287 lines
6.2 KiB
QML
287 lines
6.2 KiB
QML
|
import QtQuick 1.1
|
||
|
import Qt.labs.components.native 1.0
|
||
|
import com.victron.velib 1.0
|
||
|
|
||
|
/* Displays a setting and provides a submenu to select an different option */
|
||
|
MbItem {
|
||
|
id: root
|
||
|
cornerMark: !readonly
|
||
|
|
||
|
property alias description: description.text
|
||
|
property string iconId
|
||
|
property list<MbOption> possibleValues
|
||
|
property alias bind: vItem.bind
|
||
|
property alias valid: vItem.valid
|
||
|
property variant localValue: ""
|
||
|
property variant value: root.valid ? vItem.value : root.localValue
|
||
|
property bool showOldSelection;
|
||
|
property Page childPage;
|
||
|
property bool readonly: !userHasWriteAccess
|
||
|
property bool greyed: false
|
||
|
property bool magicKeys: false
|
||
|
property int upCount: 0
|
||
|
property int downCount: 0
|
||
|
property alias text: valueText.text
|
||
|
property string unknownOptionText: qsTr("Unknown")
|
||
|
property alias item: vItem
|
||
|
|
||
|
// This signal can be used when using local values
|
||
|
// and want to have a default option pre-selected
|
||
|
// when opening the option list. We can't use
|
||
|
// "onValueChanged" on such situation because value
|
||
|
// doesn't change when the default option is selected.
|
||
|
|
||
|
signal optionSelected(variant newValue)
|
||
|
|
||
|
states: [
|
||
|
State {
|
||
|
name: ""
|
||
|
},
|
||
|
State {
|
||
|
name: "closing"
|
||
|
}
|
||
|
]
|
||
|
|
||
|
MbStyle {
|
||
|
id: styleItem
|
||
|
}
|
||
|
|
||
|
MbTextDescription {
|
||
|
id: description
|
||
|
anchors {
|
||
|
left: parent.left; leftMargin: styleItem.marginDefault
|
||
|
verticalCenter: parent.verticalCenter
|
||
|
}
|
||
|
opacity: greyed ? styleItem.opacityDisabled : styleItem.opacityEnabled
|
||
|
}
|
||
|
|
||
|
MbBackgroundRect {
|
||
|
id: tag
|
||
|
color: style.backgroundColorComponent
|
||
|
height: valueText.height + 6
|
||
|
width: valueText.width + 10
|
||
|
anchors {
|
||
|
right: parent.right; rightMargin: style.marginDefault
|
||
|
verticalCenter: parent.verticalCenter
|
||
|
}
|
||
|
visible: valueText.text != "" && valueText.text != " "
|
||
|
}
|
||
|
|
||
|
MbTextValue {
|
||
|
id: valueText
|
||
|
anchors {
|
||
|
right: root.right; rightMargin: styleItem.marginDefault + 5
|
||
|
verticalCenter: parent.verticalCenter
|
||
|
}
|
||
|
|
||
|
text: getText(root.value)
|
||
|
opacity: greyed ? styleItem.opacityDisabled : styleItem.opacityEnabled
|
||
|
}
|
||
|
|
||
|
MbIcon {
|
||
|
id: statusIcon
|
||
|
iconId: root.iconId
|
||
|
anchors {
|
||
|
right: root.right; rightMargin: styleItem.marginDefault
|
||
|
verticalCenter: parent.verticalCenter
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Component {
|
||
|
id: mbPageFactory
|
||
|
MbPage {
|
||
|
id: optionPage
|
||
|
title: root.description
|
||
|
leftIcon: "icon-toolbar-cancel"
|
||
|
leftText: ""
|
||
|
rightIcon: "icon-toolbar-ok"
|
||
|
rightText: ""
|
||
|
model: VisualItemModel {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Component {
|
||
|
id: mbCheckBoxFactory
|
||
|
|
||
|
MbCheckBox {
|
||
|
property variant value
|
||
|
property bool readonly
|
||
|
property variant parentPage;
|
||
|
property bool editPassword: false
|
||
|
property string password: ""
|
||
|
property bool isCurrentItem: ListView.isCurrentItem
|
||
|
property bool isMouse
|
||
|
|
||
|
height: editPassword ? passwordBox.height : defaultHeight
|
||
|
onIsCurrentItemChanged: if (!isCurrentItem) editPassword = false
|
||
|
writeAccessLevel: root.writeAccessLevel
|
||
|
show: !readonly || parentPage.value === value
|
||
|
checked: parentPage.value === value
|
||
|
|
||
|
onEditPasswordChanged: {
|
||
|
if (editPassword)
|
||
|
return
|
||
|
|
||
|
if (passwordBox._editText == password) {
|
||
|
state = 'animate'
|
||
|
valueSelected(value)
|
||
|
} else {
|
||
|
toast.createToast(qsTr("Incorrect password"))
|
||
|
pageStack.pop()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function cancel()
|
||
|
{
|
||
|
if (root.state != "closing")
|
||
|
pageStack.pop()
|
||
|
}
|
||
|
|
||
|
function leftAction()
|
||
|
{
|
||
|
cancel()
|
||
|
}
|
||
|
|
||
|
function rightAction()
|
||
|
{
|
||
|
if (editPassword) {
|
||
|
editPassword = false;
|
||
|
} else {
|
||
|
isMouse = true
|
||
|
select();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Keys.onSpacePressed: { isMouse = false; selected() }
|
||
|
Keys.onReturnPressed: { isMouse = false; selected() }
|
||
|
Keys.onEscapePressed: cancel()
|
||
|
|
||
|
Keys.onUpPressed: {
|
||
|
if (magicKeys) {
|
||
|
if (upCount < 5) ++upCount;
|
||
|
if (downCount > 0) upCount = 0
|
||
|
downCount = 0;
|
||
|
}
|
||
|
event.accepted = false
|
||
|
}
|
||
|
|
||
|
Keys.onDownPressed: {
|
||
|
if (magicKeys) {
|
||
|
if (downCount < 5) ++downCount;
|
||
|
if (upCount == 5 && downCount == 5) {
|
||
|
valueSelected(User.AccessService)
|
||
|
upCount = 0;
|
||
|
}
|
||
|
}
|
||
|
event.accepted = false
|
||
|
}
|
||
|
|
||
|
function selected() {
|
||
|
if (password == "") {
|
||
|
state = 'animate';
|
||
|
valueSelected(value);
|
||
|
} else {
|
||
|
editPassword = true;
|
||
|
passwordBox.edit(isMouse)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MouseArea {
|
||
|
anchors.fill: parent;
|
||
|
onClicked: { isMouse = true; select(); }
|
||
|
}
|
||
|
|
||
|
MbEditBox {
|
||
|
id: passwordBox
|
||
|
description: qsTr("Password")
|
||
|
anchors.bottom: parent.bottom
|
||
|
matchString: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ~!@#$%^&*()-_=+[]{}\;:|/.,<>?"
|
||
|
show: editPassword
|
||
|
onEditModeChanged: editPassword = editMode
|
||
|
writeAccessLevel: root.writeAccessLevel
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VBusItem {
|
||
|
id: vItem
|
||
|
}
|
||
|
|
||
|
function getText(value)
|
||
|
{
|
||
|
for (var i = 0; i < possibleValues.length; i++)
|
||
|
{
|
||
|
var option = possibleValues[i];
|
||
|
if (option.value === value)
|
||
|
return option.description;
|
||
|
}
|
||
|
return root.value
|
||
|
}
|
||
|
|
||
|
function valueSelected(value)
|
||
|
{
|
||
|
// this is animation -> ignore spurious events
|
||
|
if (state != "")
|
||
|
return;
|
||
|
|
||
|
// the pagestack is animation -> ignore spurious events
|
||
|
if (pageStack.currentPage != root.childPage || childPage.status !== PageStatus.Active)
|
||
|
return
|
||
|
|
||
|
state = "closing"
|
||
|
if (root.valid) {
|
||
|
if (vItem.value !== value) {
|
||
|
vItem.setValue(value)
|
||
|
root.showOldSelection = false
|
||
|
}
|
||
|
} else {
|
||
|
if (root.localValue !== value) {
|
||
|
root.localValue = value
|
||
|
root.showOldSelection = false
|
||
|
}
|
||
|
}
|
||
|
optionSelected(value)
|
||
|
}
|
||
|
|
||
|
function edit() {
|
||
|
if (root.readonly || !pageStack.currentPage.active)
|
||
|
return
|
||
|
|
||
|
root.childPage = pageStack.push(mbPageFactory);
|
||
|
|
||
|
for (var i = 0; i < possibleValues.length; i++)
|
||
|
{
|
||
|
var option = possibleValues[i];
|
||
|
var mbCheckbox = mbCheckBoxFactory.createObject(this, {
|
||
|
"description": option.description,
|
||
|
"value": option.value,
|
||
|
"parentPage": root,
|
||
|
"readonly" : option.readonly,
|
||
|
"password" : option.password} )
|
||
|
|
||
|
mbCheckbox.toolbarHandler = mbCheckbox
|
||
|
|
||
|
childPage.model.append(mbCheckbox)
|
||
|
|
||
|
if (root.value === option.value) {
|
||
|
childPage.currentIndex = i;
|
||
|
childPage.listview.positionViewAtIndex(i, ListView.Contain)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
transitions: [
|
||
|
Transition {
|
||
|
to: "closing"
|
||
|
SequentialAnimation {
|
||
|
PauseAnimation { duration: 1000 }
|
||
|
ScriptAction {
|
||
|
script: { pageStack.pop(); state = "" }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}
|