import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Dialogs Dialog { id: settingsDialog title: qsTr("Settings") modal: true standardButtons: Dialog.Close width: 450 height: 520 x: (parent.width - width) / 2 y: (parent.height - height) / 2 // Load the current org path from the server whenever the dialog opens. onOpened: { orgPathField.text = orkClient.orgPath() orgPathStatus.clear() } // Native folder picker. Writes the chosen local path into the field; the // user still presses Apply to send it to the server. FolderDialog { id: folderDialog title: qsTr("Select Org Directory") onAccepted: { // selectedFolder is a file:// URL; convert to a local path. orgPathField.text = decodeURIComponent( selectedFolder.toString().replace(/^file:\/\//, "")) } } // Send the field's path to the server via /cfg. On success, refresh the // document list; on failure, show the server's error message. function applyOrgPath() { var path = orgPathField.text.trim() if (path.length === 0) { orgPathStatus.ok = false orgPathStatus.text = qsTr("Path is empty.") return } if (orkClient.setOrgPath(path)) { orgPathStatus.ok = true orgPathStatus.text = qsTr("Applied. Scanning %1").arg(path) } else { orgPathStatus.ok = false orgPathStatus.text = qsTr("Failed: %1").arg(orkClient.error) } } background: Rectangle { color: theme.windowColor border.color: theme.midColor border.width: 1 radius: 6 } header: Rectangle { implicitHeight: 40 color: theme.buttonColor radius: 6 Label { anchors.centerIn: parent text: settingsDialog.title color: theme.buttonTextColor font.bold: true font.pointSize: theme.fontSize > 0 ? theme.fontSize + 1 : 13 } // Square off bottom corners Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom height: 6 color: theme.buttonColor } } contentItem: ScrollView { id: contentScroll clip: true // Only scroll vertically; the inner layout matches the viewport width. ScrollBar.horizontal.policy: ScrollBar.AlwaysOff contentWidth: availableWidth ColumnLayout { // Match the scroll viewport width so Layout.fillWidth children size // correctly and no horizontal scrolling is needed. width: contentScroll.availableWidth spacing: 16 // --- Org Path --- GroupBox { title: qsTr("Org Path") Layout.fillWidth: true background: Rectangle { color: "transparent" border.color: theme.midColor border.width: 1 radius: 4 y: 12 } label: Label { x: 8 text: parent.title color: theme.textColor font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.9 : 11 } ColumnLayout { anchors.fill: parent spacing: 8 Label { text: qsTr("Directory the server scans for .org files. A leading ~ expands to your home directory.") color: theme.placeholderTextColor font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.85 : 10 wrapMode: Text.WordWrap Layout.fillWidth: true } RowLayout { Layout.fillWidth: true spacing: 8 TextField { id: orgPathField Layout.fillWidth: true placeholderText: qsTr("e.g. ~/org") selectByMouse: true onAccepted: applyOrgPath() } Button { text: qsTr("Browse…") onClicked: folderDialog.open() } Button { text: qsTr("Apply") onClicked: applyOrgPath() } } Label { id: orgPathStatus Layout.fillWidth: true wrapMode: Text.WordWrap visible: text.length > 0 font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.85 : 10 // ok/err color set by applyOrgPath via property. property bool ok: true color: ok ? theme.doneColor : theme.deadlineColor function clear() { text = "" } } } } // --- Color Scheme --- GroupBox { title: qsTr("Color Scheme") Layout.fillWidth: true background: Rectangle { color: "transparent" border.color: theme.midColor border.width: 1 radius: 4 y: 12 } label: Label { x: 8 text: parent.title color: theme.textColor font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.9 : 11 } RowLayout { anchors.fill: parent spacing: 8 ComboBox { id: schemeCombo Layout.fillWidth: true model: theme.availableSchemes currentIndex: { let idx = model.indexOf(theme.mode) return idx >= 0 ? idx : 0 } onActivated: theme.mode = currentText } } } // --- Font --- GroupBox { title: qsTr("Font") Layout.fillWidth: true background: Rectangle { color: "transparent" border.color: theme.midColor border.width: 1 radius: 4 y: 12 } label: Label { x: 8 text: parent.title color: theme.textColor font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.9 : 11 } GridLayout { columns: 2 anchors.fill: parent columnSpacing: 12 rowSpacing: 8 Label { text: qsTr("Family:"); color: theme.textColor } ComboBox { id: fontFamilyCombo Layout.fillWidth: true model: theme.availableFamilies editable: true currentIndex: { let fam = theme.fontFamily || Qt.application.font.family let idx = model.indexOf(fam) return idx >= 0 ? idx : 0 } onActivated: theme.fontFamily = currentText onAccepted: theme.fontFamily = editText } Label { text: qsTr("Style:"); color: theme.textColor } ComboBox { id: fontStyleCombo Layout.fillWidth: true model: theme.availableStyles currentIndex: { let st = theme.fontStyle let idx = model.indexOf(st) return idx >= 0 ? idx : 0 } onActivated: theme.fontStyle = currentText } Label { text: qsTr("Size:"); color: theme.textColor } SpinBox { id: fontSizeSpin from: 6 to: 72 value: theme.fontSize > 0 ? theme.fontSize : Qt.application.font.pointSize onValueModified: theme.fontSize = value } } } // --- UI Scale --- GroupBox { title: qsTr("UI Scale") Layout.fillWidth: true background: Rectangle { color: "transparent" border.color: theme.midColor border.width: 1 radius: 4 y: 12 } label: Label { x: 8 text: parent.title color: theme.textColor font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.9 : 11 } RowLayout { anchors.fill: parent spacing: 12 Slider { id: scaleSlider Layout.fillWidth: true from: 0.5 to: 3.0 stepSize: 0.1 value: theme.uiScale onMoved: theme.uiScale = value } Label { text: (theme.uiScale * 100).toFixed(0) + "%" color: theme.textColor Layout.preferredWidth: 50 } } } // --- Reset buttons --- RowLayout { Layout.fillWidth: true spacing: 8 Button { text: qsTr("Reset Font") onClicked: theme.resetFont() } Item { Layout.fillWidth: true } } } } }