Skip to content

Commit

Permalink
Extend Qt Quick GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
Martchus committed Sep 6, 2024
1 parent 97bcea6 commit 3a1ef9c
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 192 deletions.
1 change: 1 addition & 0 deletions tray/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ if (QUICK_GUI)
gui/qml/AdvancedDirConfigPage.qml
gui/qml/IgnorePatternPage.qml
gui/qml/HelpButton.qml
gui/qml/ObjectConfigPage.qml
SOURCES
gui/quick/quickicon.h
gui/quick/quickicon.cpp
Expand Down
207 changes: 17 additions & 190 deletions tray/gui/qml/AdvancedDirConfigPage.qml
Original file line number Diff line number Diff line change
@@ -1,206 +1,33 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Qt.labs.qmlmodels

Page {
ObjectConfigPage {
title: qsTr("Advanced config of folder \"%1\"").arg(dirName)
configObject: {
const folders = app.connection.rawConfig?.folders;
return Array.isArray(folders) ? folders.find((folder) => folder.id === dirId) : {};
}
configCategory: "config-option-folder"
actions: [
Action {
text: qsTr("Apply (not impleented yet)")
text: qsTr("Apply")
icon.source: app.faUrlBase + "check"
onTriggered: (source) => {
}
}
]
ListView {
id: advancedConfigListView
anchors.fill: parent
property var folderConfig: {
const folders = app.connection.rawConfig?.folders;
return Array.isArray(folders) ? folders.find((folder) => folder.id === dirId) : {};
}
model: Object.entries(folderConfig).sort().map((folderArray) => {
return {key: folderArray[0], value: folderArray[1],
type: typeof folderArray[1], label: uncamel(folderArray[0])};
})
delegate: DelegateChooser {
role: "type"
DelegateChoice {
roleValue: "string"
ItemDelegate {
width: advancedConfigListView.width
contentItem: RowLayout {
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: modelData.label
font.weight: Font.Medium
}
Label {
id: stringValue
Layout.fillWidth: true
text: modelData.value
font.weight: Font.Light
}
}
HelpButton {
id: helpButton
key: modelData.key
}
}
onClicked: stringDlg.visible = true
Dialog {
id: stringDlg
title: modelData.label
standardButtons: Dialog.Ok | Dialog.Cancel | Dialog.Help
modal: true
width: parent.width - 20
contentItem: TextField {
id: editedStringValue
text: modelData.value
onAccepted: stringDlg.accpet()
}
onAccepted: {
advancedConfigListView.folderConfig[modelData.key] = editedStringValue.text
stringValue.text = editedStringValue.text
}
onRejected: editedStringValue.text = advancedConfigListView.folderConfig[modelData.key]
onHelpRequested: helpButton.clicked()
}
required property var modelData
}
}
DelegateChoice {
roleValue: "number"
ItemDelegate {
width: advancedConfigListView.width
contentItem: RowLayout {
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: modelData.label
font.weight: Font.Medium
}
Label {
id: numberValue
Layout.fillWidth: true
text: modelData.value
font.weight: Font.Light
}
}
HelpButton {
key: modelData.key
}
}
onClicked: numberDlg.visible = true
Dialog {
id: numberDlg
title: modelData.label
standardButtons: Dialog.Ok | Dialog.Cancel | Dialog.Help
modal: true
width: parent.width - 20
contentItem: TextField {
id: editedNumberValue
text: modelData.value
validator: DoubleValidator {
id: numberValidator
locale: "en"
}
onAccepted: numberDlg.accpet()
}
onAccepted: {
const number = Number.fromLocaleString(Qt.locale(numberValidator.locale), editedNumberValue.text)
advancedConfigListView.folderConfig[modelData.key] = number
numberValue.text = number
}
onRejected: editedNumberValue.text = advancedConfigListView.folderConfig[modelData.key]
onHelpRequested: helpButton.clicked()
}
required property var modelData
}
}
DelegateChoice {
roleValue: "object"
ItemDelegate {
width: advancedConfigListView.width
contentItem: RowLayout {
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: modelData.label
font.weight: Font.Medium
}
Label {
Layout.fillWidth: true
text: "Unable to show/edit object at this point"
font.weight: Font.Light
}
}
HelpButton {
key: modelData.key
}
}
required property var modelData
const config = app.connection.rawConfig;
const folders = config.folders;
if (!Array.isArray(folders)) {
return false;
}
}
DelegateChoice {
roleValue: "boolean"
ItemDelegate {
width: advancedConfigListView.width
onClicked: booleanSwitch.toggle()
contentItem: RowLayout {
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: modelData.label
font.weight: Font.Medium
}
}
Switch {
id: booleanSwitch
checked: modelData.value
onCheckedChanged: advancedConfigListView.folderConfig[modelData.key] = booleanSwitch.checked
}
HelpButton {
key: modelData.key
}
}
required property var modelData
const index = folders.findIndex((folder) => folder.id === dirId);
if (index >= 0) {
folders[index] = configObject;
}
app.connection.postConfigFromJsonObject(config);
return true;
}
}
}
]
required property string dirName
required property string dirId
required property list<Action> actions

function uncamel(input) {
input = input.replace(/(.)([A-Z][a-z]+)/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2');
const parts = input.split(' ');
const lastPart = parts.splice(-1)[0];
switch (lastPart) {
case "S":
parts.push('(seconds)');
break;
case "M":
parts.push('(minutes)');
break;
case "H":
parts.push('(hours)');
break;
case "Ms":
parts.push('(milliseconds)');
break;
default:
parts.push(lastPart);
break;
}
input = parts.join(' ');
return input.charAt(0).toUpperCase() + input.slice(1);
}
}
2 changes: 1 addition & 1 deletion tray/gui/qml/DirDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ ExpandableDelegate {
Action {
text: qsTr("Advanced config")
icon.source: app.faUrlBase + "cogs"
onTriggered: (source) => mainView.stackView.push("AdvancedDirConfigPage.qml", {dirName: modelData.name, dirId: modelData.dirId}, StackView.PushTransition)
onTriggered: (source) => mainView.stackView.push("AdvancedDirConfigPage.qml", {dirName: modelData.name, dirId: modelData.dirId, stackView: mainView.stackView}, StackView.PushTransition)
}
]
}
Expand Down
12 changes: 12 additions & 0 deletions tray/gui/qml/FilesPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,25 @@ Page {
ToolTip.toolTip.onAboutToShow: ToolTip.text = toolTipData ?? ''
}
}
TapHandler {
acceptedButtons: Qt.LeftButton
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
onTapped: treeView.toggleExpanded(row)
}
TapHandler {
acceptedButtons: Qt.RightButton
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
onTapped: contextMenu.open()
}
TapHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
onLongPressed: treeView.model.triggerAction("toggle-selection-single", treeView.index(row, 0))
}
TapHandler {
acceptedDevices: PointerDevice.TouchScreen
onTapped: treeView.toggleExpanded(row)
onLongPressed: contextMenu.open()
}
Menu {
id: contextMenu
MenuItem {
Expand Down
4 changes: 3 additions & 1 deletion tray/gui/qml/HelpButton.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts

RoundButton {
visible: configCategory.length > 0
hoverEnabled: true
Layout.preferredWidth: 36
Layout.preferredHeight: 36
Expand All @@ -12,6 +13,7 @@ RoundButton {
icon.source: app.faUrlBase + "question"
icon.width: 20
icon.height: 20
onClicked: Qt.openUrlExternally("https://docs.syncthing.net/users/config#config-option-folder." + key.toLowerCase())
onClicked: Qt.openUrlExternally(`https://docs.syncthing.net/users/config#${configCategory}.${key.toLowerCase()}`)
property string configCategory
required property string key
}
Loading

0 comments on commit 3a1ef9c

Please sign in to comment.