From 05c4d6d90cae2873bcbdccb8b1c4dc74b671453b Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 16 Nov 2022 09:52:40 +0000 Subject: [PATCH] Port Settings to new Kirigami Form components --- CMakeLists.txt | 2 + src/qml/Settings/AccountEditorPage.qml | 297 +++++++---- src/qml/Settings/AccountsPage.qml | 130 +++-- src/qml/Settings/AppearanceSettingsPage.qml | 522 +++++++++++--------- src/qml/Settings/ColorScheme.qml | 8 +- src/qml/Settings/GeneralSettingsPage.qml | 280 ++++++----- 6 files changed, 734 insertions(+), 505 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd5fefa77..1e5198113 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,8 @@ else() ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0) endif() +ecm_find_qmlmodule(org.kde.kirigamiaddons.labs.mobileform 0.1) + if (NOT ANDROID AND NOT WIN32 AND NOT APPLE) find_package(KF5DBusAddons ${KF5_MIN_VERSION} REQUIRED) endif() diff --git a/src/qml/Settings/AccountEditorPage.qml b/src/qml/Settings/AccountEditorPage.qml index 8d6cdf0a9..7e72f48ab 100644 --- a/src/qml/Settings/AccountEditorPage.qml +++ b/src/qml/Settings/AccountEditorPage.qml @@ -8,7 +8,7 @@ import QtQuick.Layouts 1.15 import Qt.labs.platform 1.1 import org.kde.kirigami 2.15 as Kirigami - +import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm import org.kde.neochat 1.0 Kirigami.ScrollablePage { @@ -16,115 +16,218 @@ Kirigami.ScrollablePage { title: i18n("Edit Account") property var connection + readonly property bool compact: width > Kirigami.Units.gridUnit * 30 ? 2 : 1 + ColumnLayout { - Kirigami.FormLayout { - RowLayout { - Kirigami.Avatar { - id: avatar - source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : "" - name: root.connection.localUser.displayName ?? root.connection.localUser.id + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("User information") + } + MobileForm.AbstractFormDelegate { + Layout.fillWidth: true + contentItem: RowLayout { + Kirigami.Avatar { + id: avatar + source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : "" + name: root.connection.localUser.displayName ?? root.connection.localUser.id - MouseArea { - id: mouseArea - anchors.fill: parent - property var fileDialog: null; - onClicked: { - if (fileDialog != null) { - return; - } + MouseArea { + id: mouseArea + anchors.fill: parent + property var fileDialog: null; + onClicked: { + if (fileDialog != null) { + return; + } - fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.Overlay) - - fileDialog.chosen.connect(function(receivedSource) { - mouseArea.fileDialog = null; - if (!receivedSource) { - return; + fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.Overlay) + fileDialog.chosen.connect(function(receivedSource) { + mouseArea.fileDialog = null; + if (!receivedSource) { + return; + } + parent.source = receivedSource; + }); + fileDialog.onRejected.connect(function() { + mouseArea.fileDialog = null; + }); + fileDialog.open(); } - parent.source = receivedSource; - }); - fileDialog.onRejected.connect(function() { - mouseArea.fileDialog = null; - }); - fileDialog.open(); + } + } + QQC2.Button { + visible: avatar.source.toString().length !== 0 + icon.name: "edit-clear" + + onClicked: avatar.source = "" + } + Item { + Layout.fillWidth: true } } } - QQC2.Button { - visible: avatar.source.toString().length !== 0 - icon.name: "edit-clear" - - onClicked: avatar.source = "" + MobileForm.FormTextFieldDelegate { + id: name + label: i18n("Name:") + text: root.connection ? root.connection.localUser.displayName : "" } - Kirigami.FormData.label: i18n("Avatar:") - } - QQC2.TextField { - id: name - text: root.connection ? root.connection.localUser.displayName : "" - Kirigami.FormData.label: i18n("Name:") - } - QQC2.TextField { - id: accountLabel - text: root.connection ? root.connection.localUser.accountLabel : "" - Kirigami.FormData.label: i18n("Label:") - } - QQC2.TextField { - id: currentPassword - Kirigami.FormData.label: i18n("Current Password:") - enabled: root.connection !== undefined && root.connection.canChangePassword !== false - echoMode: TextInput.Password - } - QQC2.TextField { - id: newPassword - Kirigami.FormData.label: i18n("New Password:") - enabled: root.connection !== undefined && root.connection.canChangePassword !== false - echoMode: TextInput.Password - - } - QQC2.TextField { - id: confirmPassword - Kirigami.FormData.label: i18n("Confirm new Password:") - enabled: root.connection !== undefined && root.connection.canChangePassword !== false - echoMode: TextInput.Password - } - } - } - - footer: RowLayout { - Item { - Layout.fillWidth: true - } - - QQC2.Button { - text: i18n("Save") - Layout.bottomMargin: Kirigami.Units.smallSpacing - Layout.topMargin: Kirigami.Units.smallSpacing - onClicked: { - if (!Controller.setAvatar(root.connection, avatar.source)) { - showPassiveNotification("The Avatar could not be set"); + MobileForm.FormTextFieldDelegate { + id: accountLabel + label: i18n("Label:") + text: root.connection ? root.connection.localUser.accountLabel : "" } - if (root.connection.localUser.displayName !== name.text) { - root.connection.localUser.rename(name.text); - } - if (root.connection.localUser.accountLabel !== accountLabel.text) { - root.connection.localUser.setAccountLabel(accountLabel.text); - } - if(currentPassword.text !== "" && newPassword.text !== "" && confirmPassword.text !== "") { - if(newPassword.text === confirmPassword.text) { - Controller.changePassword(root.connection, currentPassword.text, newPassword.text); - } else { - showPassiveNotification(i18n("Passwords do not match")); - return; + MobileForm.AbstractFormDelegate { + Layout.fillWidth: true + background: Item {} + contentItem: RowLayout { + Item { + Layout.fillWidth: true + } + QQC2.Button { + text: i18n("Save") + Layout.bottomMargin: Kirigami.Units.smallSpacing + Layout.topMargin: Kirigami.Units.smallSpacing + onClicked: { + if (!Controller.setAvatar(root.connection, avatar.source)) { + showPassiveNotification("The Avatar could not be set"); + } + if (root.connection.localUser.displayName !== name.text) { + root.connection.localUser.rename(name.text); + } + if (root.connection.localUser.accountLabel !== accountLabel.text) { + root.connection.localUser.setAccountLabel(accountLabel.text); + } + } + } } } - root.closeDialog(); } } - QQC2.Button { - text: i18n("Cancel") - Layout.rightMargin: Kirigami.Units.smallSpacing - Layout.bottomMargin: Kirigami.Units.smallSpacing - Layout.topMargin: Kirigami.Units.smallSpacing - onClicked: root.closeDialog(); + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Password") + } + MobileForm.FormTextDelegate { + visible: root.connection !== undefined && root.connection.canChangePassword === false + text: i18n("Your server doesn't support changing your password") + } + MobileForm.FormTextFieldDelegate { + id: currentPassword + label: i18n("Current Password:") + enabled: root.connection !== undefined && root.connection.canChangePassword !== false + echoMode: TextInput.Password + } + MobileForm.FormTextFieldDelegate { + id: newPassword + label: i18n("New Password:") + enabled: root.connection !== undefined && root.connection.canChangePassword !== false + echoMode: TextInput.Password + } + MobileForm.FormTextFieldDelegate { + id: confirmPassword + label: i18n("Confirm new Password:") + enabled: root.connection !== undefined && root.connection.canChangePassword !== false + echoMode: TextInput.Password + onTextChanged: if (newPassword.text !== confirmPassword.text && confirmPassword.text.length > 0) { + confirmPassword.status = MobileForm.AbstractFormDelegate.Status.Error; + confirmPassword.statusMessage = i18n("Passwords don't match"); + } else { + confirmPassword.status = MobileForm.AbstractFormDelegate.Status.Default; + confirmPassword.statusMessage = ''; + } + } + MobileForm.AbstractFormDelegate { + Layout.fillWidth: true + background: Item {} + contentItem: RowLayout { + Item { + Layout.fillWidth: true + } + QQC2.Button { + text: i18n("Save") + Layout.bottomMargin: Kirigami.Units.smallSpacing + Layout.topMargin: Kirigami.Units.smallSpacing + enabled: currentPassword.text.length > 0 && newPassword.text.length > 0 && confirmPassword.text.length > 0 + onClicked: { + if (newPassword.text === confirmPassword.text) { + Controller.changePassword(root.connection, currentPassword.text, newPassword.text); + } else { + showPassiveNotification(i18n("Passwords do not match")); + } + } + } + QQC2.Button { + text: i18n("Cancel") + Layout.rightMargin: Kirigami.Units.smallSpacing + Layout.bottomMargin: Kirigami.Units.smallSpacing + Layout.topMargin: Kirigami.Units.smallSpacing + onClicked: root.closeDialog(); + } + } + } + } + } + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Server Information") + } + MobileForm.FormTextDelegate { + text: i18n("Homeserver url") + description: root.connection.homeserver + } + + /** TODO but needs first some api in Quotient + MobileForm.FormTextDelegate { + text: i18n("Server file upload limit") + description: root.connection.homeserver + } + + MobileForm.FormTextDelegate { + text: i18n("Server name") + description: root.connection.homeserver + } + + MobileForm.FormTextDelegate { + text: i18n("Server version") + description: root.connection.homeserver + }*/ + } + } + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Sign out") + } + MobileForm.FormButtonDelegate { + Layout.fillWidth: true + text: i18n("Sign out") + onClicked: { + Controller.logout(model.connection, true); + root.closeDialog(); + if (Controller.accountCount === 1) { + pageStack.layers.pop(); + } + } + } + } } } Component { diff --git a/src/qml/Settings/AccountsPage.qml b/src/qml/Settings/AccountsPage.qml index f24ca1860..13e204d2e 100644 --- a/src/qml/Settings/AccountsPage.qml +++ b/src/qml/Settings/AccountsPage.qml @@ -6,86 +6,83 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import Qt.labs.platform 1.1 -import org.kde.kirigami 2.15 as Kirigami +import org.kde.kirigami 2.19 as Kirigami +import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm import org.kde.neochat 1.0 Kirigami.ScrollablePage { title: i18n("Accounts") + leftPadding: 0 + rightPadding: 0 - actions.main: Kirigami.Action { - text: i18n("Add an account") - icon.name: "list-add-user" - onTriggered: pageStack.layers.push("qrc:/WelcomePage.qml") - visible: !pageSettingStack.wideMode - } + ColumnLayout { + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Accounts") + } - ListView { - model: AccountRegistry - anchors.fill: parent - delegate: Kirigami.BasicListItem { - text: model.connection.localUser.displayName - labelItem.textFormat: Text.PlainText - subtitle: model.connection.localUserId - - leading: Kirigami.Avatar { - name: model.connection.localUser.displayName ?? model.connection.localUser.id - source: model.connection.localUser.avatarMediaId ? ("image://mxc/" + model.connection.localUser.avatarMediaId) : "" - width: height - } - - onClicked: { - Controller.activeConnection = model.connection; - pageStack.layers.pop(); - } - - trailing: RowLayout { - QQC2.ToolButton { - display: QQC2.AbstractButton.IconOnly - QQC2.ToolTip { - text: parent.action.text - } - action: Kirigami.Action { - text: i18n("Edit this account") - iconName: "document-edit" - onTriggered: pageSettingStack.pushDialogLayer(Qt.resolvedUrl('./AccountEditorPage.qml'), { + Repeater { + model: AccountRegistry + delegate: MobileForm.FormButtonDelegate { + onClicked: pageSettingStack.pushDialogLayer("qrc:/AccountEditorPage.qml", { connection: model.connection }, { title: i18n("Account editor") - }); - } - } - QQC2.ToolButton { - display: QQC2.AbstractButton.IconOnly - QQC2.ToolTip { - text: parent.action.text - } - action: Kirigami.Action { - text: i18n("Logout") - iconName: "im-kick-user" - onTriggered: { - Controller.logout(model.connection, true); - if (Controller.accountCount === 1) { - pageStack.layers.pop(); + }) + + contentItem: RowLayout { + Kirigami.Avatar { + name: model.connection.localUser.displayName ?? model.connection.localUser.id + source: model.connection.localUser.avatarMediaId ? ("image://mxc/" + model.connection.localUser.avatarMediaId) : "" + + Layout.rightMargin: Kirigami.Units.largeSpacing + implicitWidth: Kirigami.Units.iconSizes.medium + implicitHeight: Kirigami.Units.iconSizes.medium + } + + ColumnLayout { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + QQC2.Label { + Layout.fillWidth: true + text: model.connection.localUser.displayName + textFormat: Text.PlainText + elide: Text.ElideRight + wrapMode: Text.Wrap + maximumLineCount: 2 + color: Kirigami.Theme.textColor + } + + QQC2.Label { + Layout.fillWidth: true + text: model.connection.localUserId + color: Kirigami.Theme.disabledTextColor + font: Kirigami.Theme.smallFont + elide: Text.ElideRight + } + } + + MobileForm.FormArrow { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + direction: MobileForm.FormArrow.Right } } } } - } - } - } + MobileForm.FormDelegateSeparator { below: addAccountDelegate } - footer: QQC2.ToolBar { - Kirigami.Theme.colorSet: Kirigami.Theme.Window - Kirigami.ActionToolBar { - alignment: Qt.AlignRight - rightPadding: Kirigami.Units.smallSpacing - width: parent.width - flat: false - actions: Kirigami.Action { - text: i18n("Add an account") - icon.name: "list-add-user" - onTriggered: pageStack.layers.push("qrc:/WelcomePage.qml") + MobileForm.FormButtonDelegate { + id: addAccountDelegate + text: i18n("Add Account") + icon.name: "list-add" + onClicked: pageStack.layers.push("qrc:/WelcomePage.qml") + } } } } @@ -93,8 +90,9 @@ Kirigami.ScrollablePage { Connections { target: Controller function onConnectionAdded() { - if (pageStack.layers.depth > 2) + if (pageStack.layers.depth > 2) { pageStack.layers.pop() + } } function onPasswordStatus(status) { if (status === Controller.Success) { diff --git a/src/qml/Settings/AppearanceSettingsPage.qml b/src/qml/Settings/AppearanceSettingsPage.qml index 7c5b87944..bdeecdd6d 100644 --- a/src/qml/Settings/AppearanceSettingsPage.qml +++ b/src/qml/Settings/AppearanceSettingsPage.qml @@ -7,256 +7,322 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami +import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm import org.kde.neochat 1.0 Kirigami.ScrollablePage { title: i18nc("@title:window", "Appearance") + leftPadding: 0 + rightPadding: 0 ColumnLayout { - RowLayout { - Layout.alignment: Qt.AlignCenter - spacing: Kirigami.Units.gridUnit * 2 - QQC2.ButtonGroup { id: themeGroup } - ThemeRadioButton { - innerObject: [ - RowLayout { - Layout.fillWidth: true - Kirigami.Avatar { - color: "#4a5bcc" - Layout.alignment: Qt.AlignTop - visible: Config.showAvatarInTimeline - Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 - Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 - } - QQC2.Control { - Layout.fillWidth: true - contentItem: ColumnLayout { - QQC2.Label { - Layout.fillWidth: true - font.weight: Font.Bold - font.pixelSize: 7 - text: "Paul Müller" - color: "#4a5bcc" - wrapMode: Text.Wrap - } - QQC2.Label { - Layout.fillWidth: true - text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta mauris, quis finibus sem suscipit tincidunt." - wrapMode: Text.Wrap - font.pixelSize: 7 - } - } - background: Kirigami.ShadowedRectangle { - color: Kirigami.Theme.backgroundColor - radius: Kirigami.Units.smallSpacing - shadow.size: Kirigami.Units.smallSpacing - shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10) - border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15) - border.width: 1 - } - } - }, - RowLayout { - Layout.fillWidth: true - Kirigami.Avatar { - color: "#9f244b" - Layout.alignment: Qt.AlignTop - visible: Config.showAvatarInTimeline - Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 - Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 - } - QQC2.Control { - Layout.fillWidth: true - contentItem: ColumnLayout { - QQC2.Label { - Layout.fillWidth: true - font.weight: Font.Bold - font.pixelSize: 7 - text: "Jean Paul" - color: "#9f244b" - wrapMode: Text.Wrap - } - QQC2.Label { - Layout.fillWidth: true - text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta , quis sem suscipit tincidunt." - wrapMode: Text.Wrap - font.pixelSize: 7 - } - } - background: Kirigami.ShadowedRectangle { - color: Kirigami.Theme.backgroundColor - radius: Kirigami.Units.smallSpacing - shadow.size: Kirigami.Units.smallSpacing - shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10) - border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15) - border.width: 1 - } - } - } - ] - - text: i18n("Bubbles") - checked: !Config.compactLayout - QQC2.ButtonGroup.group: themeGroup - enabled: !Config.isCompactLayoutImmutable - - onToggled: { - Config.compactLayout = !checked; - Config.save(); + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("General theme") } - } - ThemeRadioButton { - innerObject: [ - RowLayout { - Layout.fillWidth: true - Kirigami.Avatar { - color: "#4a5bcc" - Layout.alignment: Qt.AlignTop - visible: Config.showAvatarInTimeline - Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 - Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 - } - ColumnLayout { - Layout.fillWidth: true - QQC2.Label { - Layout.fillWidth: true - font.weight: Font.Bold - font.pixelSize: 7 - text: "Paul Müller" - color: "#4a5bcc" - wrapMode: Text.Wrap - } - QQC2.Label { - Layout.fillWidth: true - text: "Lorem ipsum dolor sit amet, consectetur elit. Vivamus facilisis porta mauris, finibus sem suscipit tincidunt." - wrapMode: Text.Wrap - font.pixelSize: 7 + + MobileForm.AbstractFormDelegate { + Layout.fillWidth: true + background: Item {} + contentItem: RowLayout { + Layout.alignment: Qt.AlignCenter + spacing: Kirigami.Units.gridUnit * 2 + QQC2.ButtonGroup { id: themeGroup } + ThemeRadioButton { + innerObject: [ + RowLayout { + Layout.fillWidth: true + Kirigami.Avatar { + color: "#4a5bcc" + Layout.alignment: Qt.AlignTop + visible: Config.showAvatarInTimeline + Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 + Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 + } + QQC2.Control { + Layout.fillWidth: true + contentItem: ColumnLayout { + QQC2.Label { + Layout.fillWidth: true + font.weight: Font.Bold + font.pixelSize: 7 + text: "Paul Müller" + color: "#4a5bcc" + wrapMode: Text.Wrap + } + QQC2.Label { + Layout.fillWidth: true + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta mauris, quis finibus sem suscipit tincidunt." + wrapMode: Text.Wrap + font.pixelSize: 7 + } + } + background: Kirigami.ShadowedRectangle { + color: Kirigami.Theme.backgroundColor + radius: Kirigami.Units.smallSpacing + shadow.size: Kirigami.Units.smallSpacing + shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10) + border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15) + border.width: 1 + } + } + }, + RowLayout { + Layout.fillWidth: true + Kirigami.Avatar { + color: "#9f244b" + Layout.alignment: Qt.AlignTop + visible: Config.showAvatarInTimeline + Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 + Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 + } + QQC2.Control { + Layout.fillWidth: true + contentItem: ColumnLayout { + QQC2.Label { + Layout.fillWidth: true + font.weight: Font.Bold + font.pixelSize: 7 + text: "Jean Paul" + color: "#9f244b" + wrapMode: Text.Wrap + } + QQC2.Label { + Layout.fillWidth: true + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta , quis sem suscipit tincidunt." + wrapMode: Text.Wrap + font.pixelSize: 7 + } + } + background: Kirigami.ShadowedRectangle { + color: Kirigami.Theme.backgroundColor + radius: Kirigami.Units.smallSpacing + shadow.size: Kirigami.Units.smallSpacing + shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10) + border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15) + border.width: 1 + } + } + } + ] + + text: i18n("Bubbles") + checked: !Config.compactLayout + QQC2.ButtonGroup.group: themeGroup + enabled: !Config.isCompactLayoutImmutable + + onToggled: { + Config.compactLayout = !checked; + Config.save(); } } - }, - RowLayout { - Layout.fillWidth: true - Kirigami.Avatar { - color: "#9f244b" - Layout.alignment: Qt.AlignTop - visible: Config.showAvatarInTimeline - Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 - Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 - } - ColumnLayout { - Layout.fillWidth: true - QQC2.Label { - Layout.fillWidth: true - font.weight: Font.Bold - font.pixelSize: 7 - text: "Jean Paul" - color: "#9f244b" - wrapMode: Text.Wrap - } - QQC2.Label { - Layout.fillWidth: true - text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta mauris, quis finibus sem suscipit tincidunt." - wrapMode: Text.Wrap - font.pixelSize: 7 + ThemeRadioButton { + Layout.alignment: Qt.AlignRight + innerObject: [ + RowLayout { + Layout.fillWidth: true + Kirigami.Avatar { + color: "#4a5bcc" + Layout.alignment: Qt.AlignTop + visible: Config.showAvatarInTimeline + Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 + Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 + } + ColumnLayout { + Layout.fillWidth: true + QQC2.Label { + Layout.fillWidth: true + font.weight: Font.Bold + font.pixelSize: 7 + text: "Paul Müller" + color: "#4a5bcc" + wrapMode: Text.Wrap + } + QQC2.Label { + Layout.fillWidth: true + text: "Lorem ipsum dolor sit amet, consectetur elit. Vivamus facilisis porta mauris, finibus sem suscipit tincidunt." + wrapMode: Text.Wrap + font.pixelSize: 7 + } + } + }, + RowLayout { + Layout.fillWidth: true + Kirigami.Avatar { + color: "#9f244b" + Layout.alignment: Qt.AlignTop + visible: Config.showAvatarInTimeline + Layout.preferredWidth: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing * 2 : 0 + Layout.preferredHeight: Kirigami.Units.largeSpacing * 2 + } + ColumnLayout { + Layout.fillWidth: true + QQC2.Label { + Layout.fillWidth: true + font.weight: Font.Bold + font.pixelSize: 7 + text: "Jean Paul" + color: "#9f244b" + wrapMode: Text.Wrap + } + QQC2.Label { + Layout.fillWidth: true + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus facilisis porta mauris, quis finibus sem suscipit tincidunt." + wrapMode: Text.Wrap + font.pixelSize: 7 + } + } + } + ] + text: i18n("Compact") + checked: Config.compactLayout + QQC2.ButtonGroup.group: themeGroup + enabled: !Config.isCompactLayoutImmutable + + onToggled: { + Config.compactLayout = checked; + Config.save(); } } } - ] - text: i18n("Compact") - checked: Config.compactLayout - QQC2.ButtonGroup.group: themeGroup - enabled: !Config.isCompactLayoutImmutable - - onToggled: { - Config.compactLayout = checked; - Config.save(); } } } - Kirigami.FormLayout { - Layout.maximumWidth: parent.width - QQC2.CheckBox { - Kirigami.FormData.label: i18n("Show Avatar:") - text: i18n("In Chat") - checked: Config.showAvatarInTimeline - onToggled: { - Config.showAvatarInTimeline = checked - Config.save() + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Timeline") } - enabled: !Config.isShowAvatarInTimelineImmutable - } - QQC2.CheckBox { - text: i18n("In Sidebar") - checked: Config.showAvatarInRoomDrawer - enabled: !Config.isShowAvatarInRoomDrawerImmutable - onToggled: { - Config.showAvatarInRoomDrawer = checked - Config.save() - } - } - QQC2.CheckBox { - text: i18n("Show Fancy Effects") - checked: Config.showFancyEffects - enabled: !Config.isShowFancyEffectsImmutable - onToggled: { - Config.showFancyEffects = checked; - Config.save(); - } - } - Loader { - visible: item !== null - Kirigami.FormData.label: item ? i18n("Theme:") : "" - source: "qrc:/ColorScheme.qml" - } - QQC2.CheckBox { - visible: Controller.hasWindowSystem - text: i18n("Use transparent chat page") - enabled: !Config.compactLayout && !Config.isBlurImmutable - checked: Config.blur - onToggled: { - Config.blur = checked; - Config.save(); - } - } - RowLayout { - visible: Controller.hasWindowSystem && Config.blur - enabled: !Config.isTransparancyImmutable - Kirigami.FormData.label: i18n("Transparency:") - QQC2.Slider { - enabled: !Config.compactLayout && Config.blur - from: 0 - to: 1 - stepSize: 0.05 - value: Config.transparency - onMoved: { - Config.transparency = value; + MobileForm.FormCheckDelegate { + id: showFancyEffectsDelegate + text: i18n("Show Fancy Effects") + checked: Config.showFancyEffects + enabled: !Config.isShowFancyEffectsImmutable + onToggled: { + Config.showFancyEffects = checked; Config.save(); } + } - HoverHandler { id: sliderHover } - QQC2.ToolTip.visible: sliderHover.hovered && !enabled - QQC2.ToolTip.text: i18n("Only enabled if the transparent chat page is enabled.") - QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay + MobileForm.FormDelegateSeparator { above: showFancyEffectsDelegate ; below: colorSchemeDelegate } + + Loader { + id: colorSchemeDelegate + visible: item !== null + source: "qrc:/ColorScheme.qml" + Layout.fillWidth: true } - QQC2.Label { - text: Math.round(Config.transparency * 100) + "%" + + MobileForm.FormDelegateSeparator { + above: colorSchemeDelegate + below: hasWindowSystemDelegate + visible: colorSchemeDelegate.visible } - } - QQC2.CheckBox { - text: i18n("Show your messages on the right") - checked: Config.showLocalMessagesOnRight - enabled: !Config.isShowLocalMessagesOnRightImmutable && !Config.compactLayout - onToggled: { - Config.showLocalMessagesOnRight = checked - Config.save() + + MobileForm.FormCheckDelegate { + id: hasWindowSystemDelegate + visible: Controller.hasWindowSystem + text: i18n("Use transparent chat page") + enabled: !Config.compactLayout && !Config.isBlurImmutable + checked: Config.blur + onToggled: { + Config.blur = checked; + Config.save(); + } } - } - QQC2.CheckBox { - text: i18n("Show links preview in the chat messages") - checked: Config.showLinkPreview - onToggled: { - Config.showLinkPreview = checked - Config.save() + + MobileForm.FormDelegateSeparator { above: hasWindowSystemDelegate; below: transparencyDelegate } + + MobileForm.AbstractFormDelegate { + id: transparencyDelegate + Layout.fillWidth: true + visible: Controller.hasWindowSystem && Config.blur + enabled: !Config.isTransparancyImmutable + contentItem: ColumnLayout { + QQC2.Label { + text: i18n("Transparency") + Layout.fillWidth: true + } + QQC2.Slider { + enabled: !Config.compactLayout && Config.blur + from: 0 + to: 1 + stepSize: 0.05 + value: Config.transparency + onMoved: { + Config.transparency = value; + Config.save(); + } + Layout.fillWidth: true + + HoverHandler { id: sliderHover } + QQC2.ToolTip.visible: sliderHover.hovered && !enabled + QQC2.ToolTip.text: i18n("Only enabled if the transparent chat page is enabled.") + } + QQC2.Label { + text: Math.round(Config.transparency * 100) + "%" + Layout.fillWidth: true + } + } + } + + MobileForm.FormDelegateSeparator { above: transparencyDelegate; below: showLocalMessagesOnRightDelegate; visible: transparencyDelegate.visible } + + MobileForm.FormCheckDelegate { + id: showLocalMessagesOnRightDelegate + text: i18n("Show your messages on the right") + checked: Config.showLocalMessagesOnRight + enabled: !Config.isShowLocalMessagesOnRightImmutable && !Config.compactLayout + onToggled: { + Config.showLocalMessagesOnRight = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: showLocalMessagesOnRightDelegate; below: showLinkPreviewDelegate } + + MobileForm.FormCheckDelegate { + id: showLinkPreviewDelegate + text: i18n("Show links preview in the chat messages") + checked: Config.showLinkPreview + onToggled: { + Config.showLinkPreview = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: showLinkPreviewDelegate; below: showAvatarDelegate } + + MobileForm.FormSectionText { + id: showAvatarDelegate + text: i18n("Show Avatar") + } + + MobileForm.FormCheckDelegate { + text: i18n("In Chat") + checked: Config.showAvatarInTimeline + onToggled: { + Config.showAvatarInTimeline = checked + Config.save() + } + enabled: !Config.isShowAvatarInTimelineImmutable + } + + MobileForm.FormCheckDelegate { + text: i18n("In Sidebar") + checked: Config.showAvatarInRoomDrawer + enabled: !Config.isShowAvatarInRoomDrawerImmutable + onToggled: { + Config.showAvatarInRoomDrawer = checked + Config.save() + } } } } diff --git a/src/qml/Settings/ColorScheme.qml b/src/qml/Settings/ColorScheme.qml index 6f61b9455..056ed995c 100644 --- a/src/qml/Settings/ColorScheme.qml +++ b/src/qml/Settings/ColorScheme.qml @@ -6,14 +6,18 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami +import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm import org.kde.neochat 1.0 -QQC2.ComboBox { +MobileForm.FormComboBoxDelegate { + Layout.fillWidth: true + text: i18n("Themes") textRole: "display" + valueRole: "display" model: ColorSchemer.model Component.onCompleted: currentIndex = ColorSchemer.indexForScheme(Config.colorScheme); - onActivated: { + onCurrentValueChanged: { ColorSchemer.apply(currentIndex); Config.colorScheme = ColorSchemer.nameForIndex(currentIndex); Config.save(); diff --git a/src/qml/Settings/GeneralSettingsPage.qml b/src/qml/Settings/GeneralSettingsPage.qml index 8736d89b7..10b6bca4a 100644 --- a/src/qml/Settings/GeneralSettingsPage.qml +++ b/src/qml/Settings/GeneralSettingsPage.qml @@ -7,129 +7,185 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami +import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm import org.kde.neochat 1.0 Kirigami.ScrollablePage { title: i18nc("@title:window", "General") + leftPadding: 0 + rightPadding: 0 ColumnLayout { - Kirigami.FormLayout { + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing Layout.fillWidth: true - QQC2.CheckBox { - Kirigami.FormData.label: i18n("General settings:") - text: i18n("Close to system tray") - checked: Config.systemTray - visible: Controller.supportSystemTray - enabled: !Config.isSystemTrayImmutable - onToggled: { - Config.systemTray = checked - Config.save() - } - } - QQC2.CheckBox { - text: i18n("Minimize to system tray on startup") - checked: Config.minimizeToSystemTrayOnStartup - visible: Controller.supportSystemTray && !Kirigami.Settings.isMobile - enabled: Config.systemTray && !Config.isMinimizeToSystemTrayOnStartupImmutable - onToggled: { - Config.minimizeToSystemTrayOnStartup = checked - Config.save() - } - } - QQC2.CheckBox { - // TODO: When there are enough notification and timeline event - // settings, make 2 separate groups with FormData labels. - Kirigami.FormData.label: i18n("Notifications and events:") - text: i18n("Show notifications") - checked: Config.showNotifications - enabled: !Config.isShowNotificationsImmutable - onToggled: { - Config.showNotifications = checked - Config.save() - NotificationsManager.globalNotificationsEnabled = checked - } - } - QQC2.CheckBox { - text: i18n("Show leave and join events") - checked: Config.showLeaveJoinEvent - enabled: !Config.isShowLeaveJoinEventImmutable - onToggled: { - Config.showLeaveJoinEvent = checked - Config.save() - } - } - QQC2.CheckBox { - text: i18n("Show name change events") - checked: Config.showRename - enabled: !Config.isShowRenameImmutable - onToggled: { - Config.showRename = checked - Config.save() - } - } - QQC2.CheckBox { - text: i18n("Show avatar update events") - checked: Config.showAvatarUpdate - enabled: !Config.isShowAvatarUpdateImmutable - onToggled: { - Config.showAvatarUpdate = checked - Config.save() - } - } - QQC2.RadioButton { - Kirigami.FormData.label: i18n("Rooms and private chats:") - text: i18n("Separated") - checked: !Config.mergeRoomList - enabled: !Config.isMergeRoomListImmutable - onToggled: { - Config.mergeRoomList = false - Config.save() - } - } - QQC2.RadioButton { - text: i18n("Intermixed") - checked: Config.mergeRoomList - enabled: !Config.isMergeRoomListImmutable - onToggled: { - Config.mergeRoomList = true - Config.save() - } - } - QQC2.CheckBox { - id: quickEditCheckbox - Layout.maximumWidth: parent.width - text: i18n("Use s/text/replacement syntax to edit your last message") - checked: Config.allowQuickEdit - enabled: !Config.isAllowQuickEditImmutable - onToggled: { - Config.allowQuickEdit = checked - Config.save() + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("General settings") } - // TODO KF5.97 remove this line - Component.onCompleted: this.contentItem.wrap = QQC2.Label.Wrap - } - QQC2.CheckBox { - text: i18n("Send Typing Notifications") - checked: Config.typingNotifications - enabled: !Config.isTypingNotificationsImmutable - onToggled: { - Config.typingNotifications = checked - Config.save() - } - } - QQC2.CheckBox { - text: i18n("Automatically hide/unhide the room information when resizing the window") - Layout.maximumWidth: parent.width - checked: Config.autoRoomInfoDrawer - enabled: !Config.isAutoRoomInfoDrawerImmutable - onToggled: { - Config.autoRoomInfoDrawer = checked - Config.save() + MobileForm.FormCheckDelegate { + id: closeDelegate + text: i18n("Close to system tray") + checked: Config.systemTray + visible: Controller.supportSystemTray + enabled: !Config.isSystemTrayImmutable + onToggled: { + Config.systemTray = checked + Config.save() + } } - // TODO KF5.97 remove this line - Component.onCompleted: this.contentItem.wrap = QQC2.Label.Wrap + MobileForm.FormDelegateSeparator { above: closeDelegate; below: minimizeDelegate } + + MobileForm.FormCheckDelegate { + id: minimizeDelegate + text: i18n("Minimize to system tray on startup") + checked: Config.minimizeToSystemTrayOnStartup + visible: Controller.supportSystemTray && !Kirigami.Settings.isMobile + enabled: Config.systemTray && !Config.isMinimizeToSystemTrayOnStartupImmutable + onToggled: { + Config.minimizeToSystemTrayOnStartup = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: minimizeDelegate; below: automaticallyDelegate } + + MobileForm.FormCheckDelegate { + id: automaticallyDelegate + text: i18n("Automatically hide/unhide the room information when resizing the window") + checked: Config.autoRoomInfoDrawer + enabled: !Config.isAutoRoomInfoDrawerImmutable + onToggled: { + Config.autoRoomInfoDrawer = checked + Config.save() + } + } + } + } + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Notifications and events") + } + MobileForm.FormCheckDelegate { + id: showNotificationsDelegate + // TODO: When there are enough notification and timeline event + // settings, make 2 separate groups with FormData labels. + text: i18n("Show notifications") + checked: Config.showNotifications + enabled: !Config.isShowNotificationsImmutable + onToggled: { + Config.showNotifications = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: showNotificationsDelegate; below: showLeaveJoinEventDelegate } + + MobileForm.FormCheckDelegate { + id: showLeaveJoinEventDelegate + text: i18n("Show leave and join events") + checked: Config.showLeaveJoinEvent + enabled: !Config.isShowLeaveJoinEventImmutable + onToggled: { + Config.showLeaveJoinEvent = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: showLeaveJoinEventDelegate; below: showNameDelegate } + + MobileForm.FormCheckDelegate { + id: showNameDelegate + text: i18n("Show name change events") + checked: Config.showRename + enabled: !Config.isShowRenameImmutable + onToggled: { + Config.showRename = checked + Config.save() + } + } + + MobileForm.FormDelegateSeparator { above: showNameDelegate; below: showAvatarChangeDelegate } + + MobileForm.FormCheckDelegate { + id: showAvatarChangeDelegate + text: i18n("Show avatar update events") + checked: Config.showAvatarUpdate + enabled: !Config.isShowAvatarUpdateImmutable + onToggled: { + Config.showAvatarUpdate = checked + Config.save() + } + } + } + } + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18n("Rooms and private chats") + } + MobileForm.FormRadioDelegate { + text: i18n("Separated") + checked: !Config.mergeRoomList + enabled: !Config.isMergeRoomListImmutable + onToggled: { + Config.mergeRoomList = false + Config.save() + } + } + MobileForm.FormRadioDelegate { + text: i18n("Intermixed") + checked: Config.mergeRoomList + enabled: !Config.isMergeRoomListImmutable + onToggled: { + Config.mergeRoomList = true + Config.save() + } + } + } + } + + MobileForm.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormCardHeader { + title: i18nc("Chat Editor", "Editor:") + } + MobileForm.FormCheckDelegate { + id: quickEditCheckbox + text: i18n("Use s/text/replacement syntax to edit your last message") + checked: Config.allowQuickEdit + enabled: !Config.isAllowQuickEditImmutable + onToggled: { + Config.allowQuickEdit = checked + Config.save() + } + } + MobileForm.FormDelegateSeparator { above: quickEditCheckbox; below: typingNotificationsDelegate } + MobileForm.FormCheckDelegate { + id: typingNotificationsDelegate + text: i18n("Send Typing Notifications") + checked: Config.typingNotifications + enabled: !Config.isTypingNotificationsImmutable + onToggled: { + Config.typingNotifications = checked + Config.save() + } + } } } }