diff --git a/src/models/statemodel.cpp b/src/models/statemodel.cpp index 7555f5f68..61f311a67 100644 --- a/src/models/statemodel.cpp +++ b/src/models/statemodel.cpp @@ -26,8 +26,7 @@ QVariant StateModel::data(const QModelIndex &index, int role) const int StateModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return m_room->currentState().events().size(); + return !m_room || parent.isValid() ? 0 : m_room->currentState().events().size(); } NeoChatRoom *StateModel::room() const @@ -37,8 +36,12 @@ NeoChatRoom *StateModel::room() const void StateModel::setRoom(NeoChatRoom *room) { + if (m_room == room) { + return; + } m_room = room; Q_EMIT roomChanged(); + beginResetModel(); m_stateEvents.clear(); m_stateEvents = m_room->currentState().events().keys(); diff --git a/src/qml/Component/Devtools/RoomData.qml b/src/qml/Component/Devtools/RoomData.qml index 42a0f2e14..e8a25b4c9 100644 --- a/src/qml/Component/Devtools/RoomData.qml +++ b/src/qml/Component/Devtools/RoomData.qml @@ -6,107 +6,122 @@ 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.kirigamiaddons.formcard 1.0 as FormCard import org.kde.kitemmodels 1.0 import org.kde.neochat 1.0 -ColumnLayout { - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormComboBoxDelegate { - text: i18n("Room") - textRole: "displayName" - valueRole: "id" - model: RoomListModel { - id: roomListModel - connection: Controller.activeConnection - } - Component.onCompleted: currentIndex = indexOfValue(room.id) - onCurrentValueChanged: room = roomListModel.roomByAliasOrId(currentValue) +FormCard.FormCardPage { + id: root + + required property var room + + FormCard.FormCard { + Layout.topMargin: Kirigami.Units.gridUnit + + FormCard.FormComboBoxDelegate { + id: roomChooser + text: i18n("Room") + textRole: "displayName" + valueRole: "roomId" + model: RoomListModel { + id: roomListModel + connection: Controller.activeConnection } - MobileForm.FormCheckDelegate { - text: i18n("Show m.room.member events") - checked: true - onToggled: { - if (checked) { - stateEventFilterModel.removeStateEventTypeFiltered("m.room.member"); - } else { - stateEventFilterModel.addStateEventTypeFiltered("m.room.member"); - } + onCurrentValueChanged: room = roomListModel.roomByAliasOrId(currentValue) + Component.onCompleted: currentIndex = indexOfValue(room.id) + } + + FormCard.FormDelegateSeparator { above: showRoomMember } + + FormCard.FormCheckDelegate { + id: showRoomMember + text: i18n("Show m.room.member events") + checked: true + onToggled: { + if (checked) { + stateEventFilterModel.removeStateEventTypeFiltered("m.room.member"); + } else { + stateEventFilterModel.addStateEventTypeFiltered("m.room.member"); } } - MobileForm.FormCheckDelegate { - id: roomAccoutnDataVisibleCheck - text: i18n("Show room account data") - checked: false - } + } + + FormCard.FormDelegateSeparator { above: roomAccoutnDataVisibleCheck; below: showRoomMember } + + FormCard.FormCheckDelegate { + id: roomAccoutnDataVisibleCheck + text: i18n("Show room account data") + checked: false + } + + FormCard.FormDelegateSeparator { below: roomAccoutnDataVisibleCheck } + + FormCard.FormTextDelegate { + text: i18n("Room id") + description: room.id } } - MobileForm.FormCard { - Layout.fillWidth: true + + FormCard.FormHeader { + title: i18n("Room Account Data for %1", room.displayName) visible: roomAccoutnDataVisibleCheck.checked - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormCardHeader { - title: i18n("Room Account Data for %1 - %2", room.displayName, room.id) - } + } - Repeater { - model: room.accountDataEventTypes - delegate: MobileForm.FormTextDelegate { - text: modelData - onClicked: applicationWindow().pageStack.pushDialogLayer("qrc:/MessageSourceSheet.qml", { - "sourceText": room.roomAcountDataJson(text) - }, { - "title": i18n("Event Source"), - "width": Kirigami.Units.gridUnit * 25 - }) - } + FormCard.FormCard { + visible: roomAccoutnDataVisibleCheck.checked + + Repeater { + model: room.accountDataEventTypes + delegate: FormCard.FormTextDelegate { + text: modelData + onClicked: applicationWindow().pageStack.pushDialogLayer("qrc:/MessageSourceSheet.qml", { + "sourceText": room.roomAcountDataJson(text) + }, { + "title": i18n("Event Source"), + "width": Kirigami.Units.gridUnit * 25 + }) } } } - MobileForm.FormCard { - Layout.fillWidth: true + + FormCard.FormHeader { + id: stateEventListHeader + title: i18n("Room State for %1", room.displayName) + } + + FormCard.FormCard { Layout.fillHeight: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormCardHeader { - id: stateEventListHeader - title: i18n("Room State for %1", room.displayName) - subtitle: room.id - } - QQC2.ScrollView { - Layout.fillWidth: true - Layout.fillHeight: true - // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) - QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff + QQC2.ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.maximumHeight: Kirigami.Units.gridUnit * 20 - ListView { - id: stateEventListView - clip: true + // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) + QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff - model: StateFilterModel { - id: stateEventFilterModel - sourceModel: StateModel { - id: stateModel - room: devtoolsPage.room - } + ListView { + id: stateEventListView + clip: true + + model: StateFilterModel { + id: stateEventFilterModel + sourceModel: StateModel { + id: stateModel + room: root.room } + } - delegate: MobileForm.FormTextDelegate { - text: model.type - description: model.stateKey - onClicked: applicationWindow().pageStack.pushDialogLayer('qrc:/MessageSourceSheet.qml', { - sourceText: stateModel.stateEventJson(stateEventFilterModel.mapToSource(stateEventFilterModel.index(model.index, 0))) - }, { - title: i18n("Event Source"), - width: Kirigami.Units.gridUnit * 25 - }); - } + delegate: FormCard.FormTextDelegate { + text: model.type + description: model.stateKey + onClicked: applicationWindow().pageStack.pushDialogLayer('qrc:/MessageSourceSheet.qml', { + sourceText: stateModel.stateEventJson(stateEventFilterModel.mapToSource(stateEventFilterModel.index(model.index, 0))) + }, { + title: i18n("Event Source"), + width: Kirigami.Units.gridUnit * 25 + }); } } } diff --git a/src/qml/Component/Devtools/ServerData.qml b/src/qml/Component/Devtools/ServerData.qml index 57369d919..1d4d9340a 100644 --- a/src/qml/Component/Devtools/ServerData.qml +++ b/src/qml/Component/Devtools/ServerData.qml @@ -6,58 +6,50 @@ 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.kirigamiaddons.formcard 1.0 as FormCard import org.kde.kitemmodels 1.0 import org.kde.neochat 1.0 -ColumnLayout { - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormCardHeader { - title: i18n("Server Capabilities") - } - MobileForm.FormTextDelegate { - text: i18n("Can change password") - description: Controller.activeConnection.canChangePassword - } - } - } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormCardHeader { - title: i18n("Default Room Version") - } - MobileForm.FormTextDelegate { - text: Controller.activeConnection.defaultRoomVersion - } - } - } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormCardHeader { - title: i18n("Available Room Versions") - } - Repeater { - model: Controller.getSupportedRoomVersions(room.connection) +FormCard.FormCardPage { + id: root - delegate: MobileForm.FormTextDelegate { - text: modelData.id - contentItem.children: QQC2.Label { - text: modelData.status - color: Kirigami.Theme.disabledTextColor - } + FormCard.FormHeader { + title: i18n("Server Capabilities") + } + + FormCard.FormCard { + FormCard.FormTextDelegate { + text: i18n("Can change password") + description: Controller.activeConnection.canChangePassword + } + } + + FormCard.FormHeader { + title: i18n("Default Room Version") + } + + FormCard.FormCard { + FormCard.FormTextDelegate { + text: Controller.activeConnection.defaultRoomVersion + } + } + + FormCard.FormHeader { + title: i18n("Available Room Versions") + } + + FormCard.FormCard { + Repeater { + model: Controller.getSupportedRoomVersions(room.connection) + + delegate: FormCard.FormTextDelegate { + text: modelData.id + contentItem.children: QQC2.Label { + text: modelData.status + color: Kirigami.Theme.disabledTextColor } } } } - Item { - Layout.fillHeight: true - } } diff --git a/src/qml/Page/DevtoolsPage.qml b/src/qml/Page/DevtoolsPage.qml index 974df9461..40f8dbcdd 100644 --- a/src/qml/Page/DevtoolsPage.qml +++ b/src/qml/Page/DevtoolsPage.qml @@ -2,41 +2,34 @@ // SPDX-License-Identifier: GPL-2.0-or-later import QtQuick 2.15 -import QtQuick.Controls 2.15 as QQC2 -import QtQuick.Layouts 1.15 import org.kde.kirigami 2.20 as Kirigami +import org.kde.kirigamiaddons.settings 1.0 as KirigamiSettings import org.kde.neochat 1.0 -Kirigami.Page { - id: devtoolsPage +KirigamiSettings.CategorizedSettings { + id: root property NeoChatRoom room - title: i18n("Developer Tools") - - leftPadding: 0 - rightPadding: 0 - - header: QQC2.TabBar { - id: tabBar - - QQC2.TabButton { - text: qsTr("Room Data") + actions: [ + KirigamiSettings.SettingAction { + actionName: "roomData" + text: i18n("Room Data") + icon.name: "datatype" + page: "qrc:/RoomData.qml" + initialProperties: { + return { + room: root.room + } + } + }, + KirigamiSettings.SettingAction { + actionName: "serverData" + text: i18n("Server Info") + icon.name: "network-server-symbolic" + page: "qrc:/ServerData.qml" } - QQC2.TabButton { - text: qsTr("Server Info") - } - } - - StackLayout { - id: swipeView - anchors.fill: parent - - currentIndex: tabBar.currentIndex - - RoomData {} - ServerData {} - } + ] } diff --git a/src/qml/RoomSettings/Permissions.qml b/src/qml/RoomSettings/Permissions.qml index 07b8a942c..9d75345e7 100644 --- a/src/qml/RoomSettings/Permissions.qml +++ b/src/qml/RoomSettings/Permissions.qml @@ -6,441 +6,439 @@ 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.kirigamiaddons.formcard 1.0 as FormCard import org.kde.kirigamiaddons.delegates 1.0 as Delegates import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.kitemmodels 1.0 import org.kde.neochat 1.0 -Kirigami.ScrollablePage { +FormCard.FormCardPage { id: root property NeoChatRoom room - title: i18nc('@title:window', 'Permissions') - topPadding: 0 - leftPadding: 0 - rightPadding: 0 + title: i18nc("@title:window", "Permissions") - UserListModel { + readonly property UserListModel userListModel: UserListModel { id: userListModel room: root.room } - ListModel { + readonly property ListModel powerLevelModel: ListModel { id: powerLevelModel } - ColumnLayout { - spacing: 0 - MobileForm.FormHeader { - Layout.fillWidth: true - title: i18n("Privileged Users") - } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - Repeater { - model: KSortFilterProxyModel { - sourceModel: userListModel - sortRole: "powerLevel" - sortOrder: Qt.DescendingOrder - filterRowCallback: function(source_row, source_parent) { - let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole) - return powerLevelRole > 0; - } - } - delegate: MobileForm.FormTextDelegate { - text: name - description: userId - contentItem.children: RowLayout { - spacing: Kirigami.Units.largeSpacing - QQC2.Label { - visible: !room.canSendState("m.room.power_levels") - text: powerLevelString - color: Kirigami.Theme.disabledTextColor - } - QQC2.ComboBox { - focusPolicy: Qt.NoFocus // provided by parent - model: powerLevelModel - textRole: "text" - valueRole: "powerLevel" - visible: room.canSendState("m.room.power_levels") - Component.onCompleted: { - /** - * This is very silly but the only way to populate the model with - * translated strings. Done here because the model needs to be filled - * before the first delegate sets it's current index. - */ - if (powerLevelModel.count == 0) { - powerLevelModel.append({"text": i18n("Member (0)"), "powerLevel": 0}); - powerLevelModel.append({"text": i18n("Moderator (50)"), "powerLevel": 50}); - powerLevelModel.append({"text": i18n("Admin (100)"), "powerLevel": 100}); - } - currentIndex = indexOfValue(powerLevel) - } - onActivated: { - room.setUserPowerLevel(userId, currentValue) - } - } - } - } + FormCard.FormHeader { + title: i18n("Privileged Users") + } + + FormCard.FormCard { + Layout.fillWidth: true + + Repeater { + model: KSortFilterProxyModel { + sourceModel: userListModel + sortRole: "powerLevel" + sortOrder: Qt.DescendingOrder + filterRowCallback: function(source_row, source_parent) { + let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole) + return powerLevelRole > 0; } - MobileForm.FormDelegateSeparator { below: userListSearchCard } - MobileForm.AbstractFormDelegate { - id: userListSearchCard - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - - contentItem: Kirigami.SearchField { - id: userListSearchField - - autoAccept: false - - Layout.fillWidth: true - - Keys.onUpPressed: userListView.decrementCurrentIndex() - Keys.onDownPressed: userListView.incrementCurrentIndex() - - onAccepted: { - let currentUser = userListView.itemAtIndex(userListView.currentIndex); - currentUser.action.trigger(); - } + } + delegate: FormCard.FormTextDelegate { + text: name + description: userId + contentItem.children: RowLayout { + spacing: Kirigami.Units.largeSpacing + QQC2.Label { + visible: !room.canSendState("m.room.power_levels") + text: powerLevelString + color: Kirigami.Theme.disabledTextColor } - QQC2.Popup { - id: userListSearchPopup - - x: userListSearchField.x - y: userListSearchField.y - height - width: userListSearchField.width - height: { - let maxHeight = userListSearchField.mapToGlobal(userListSearchField.x, userListSearchField.y).y - Kirigami.Units.largeSpacing * 3; - let minHeight = Kirigami.Units.gridUnit * 2 + userListSearchPopup.padding * 2; - let filterContentHeight = userListView.contentHeight + userListSearchPopup.padding * 2; - - return Math.max(Math.min(filterContentHeight, maxHeight), minHeight); + QQC2.ComboBox { + focusPolicy: Qt.NoFocus // provided by parent + model: root.powerLevelModel + textRole: "text" + valueRole: "powerLevel" + visible: room.canSendState("m.room.power_levels") + Component.onCompleted: { + /** + * This is very silly but the only way to populate the model with + * translated strings. Done here because the model needs to be filled + * before the first delegate sets it's current index. + */ + if (root.powerLevelModel.count == 0) { + root.powerLevelModel.append({"text": i18n("Member (0)"), "powerLevel": 0}); + root.powerLevelModel.append({"text": i18n("Moderator (50)"), "powerLevel": 50}); + root.powerLevelModel.append({"text": i18n("Admin (100)"), "powerLevel": 100}); + } + currentIndex = indexOfValue(powerLevel) } - padding: Kirigami.Units.smallSpacing - leftPadding: Kirigami.Units.smallSpacing / 2 - rightPadding: Kirigami.Units.smallSpacing / 2 - modal: false - onClosed: userListSearchField.text = "" - - background: Kirigami.ShadowedRectangle { - property color borderColor: Kirigami.Theme.textColor - - Kirigami.Theme.colorSet: Kirigami.Theme.View - Kirigami.Theme.inherit: false - - radius: 4 - color: Kirigami.Theme.backgroundColor - - border { - color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) - width: 1 - } - - shadow { - xOffset: 0 - yOffset: 4 - color: Qt.rgba(0, 0, 0, 0.3) - size: 8 - } - } - - contentItem: QQC2.ScrollView { - // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) - QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff - - ListView { - id: userListView - clip: true - - model: UserFilterModel { - id: userListFilterModel - sourceModel: userListModel - filterText: userListSearchField.text - - onFilterTextChanged: { - if (filterText.length > 0 && !userListSearchPopup.visible) { - userListSearchPopup.open() - } else if (filterText.length <= 0 && userListSearchPopup.visible) { - userListSearchPopup.close() - } - } - } - - delegate: Delegates.RoundedItemDelegate { - id: userListItem - - required property string userId - required property string avatar - required property string name - required property int powerLevel - required property string powerLevelString - - text: name - - contentItem: RowLayout { - KirigamiComponents.Avatar { - Layout.preferredWidth: Kirigami.Units.iconSizes.medium - Layout.preferredHeight: Kirigami.Units.iconSizes.medium - source: userListItem.avatar ? ("image://" + userListItem.avatar) : "" - name: userListItem.name - } - - Delegates.SubtitleContentItem { - itemDelegate: userListItem - subtitle: userListItem.userId - labelItem.textFormat: Text.PlainText - subtitleItem.textFormat: Text.PlainText - Layout.fillWidth: true - } - - QQC2.Label { - visible: userListItem.powerLevel > 0 - - text: userListItem.powerLevelString - color: Kirigami.Theme.disabledTextColor - textFormat: Text.PlainText - wrapMode: Text.NoWrap - } - } - - action: Kirigami.Action { - id: editPowerLevelAction - onTriggered: { - userListSearchPopup.close() - let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { - room: root.room, - userId: userListItem.userId, - powerLevel: userListItem.powerLevel - }); - dialog.open(); - } - } - - Component { - id: powerLevelDialog - PowerLevelDialog { - id: powerLevelDialog - } - } - } - } + onActivated: { + room.setUserPowerLevel(userId, currentValue) } } } } } + FormCard.FormDelegateSeparator { below: userListSearchCard } + FormCard.AbstractFormDelegate { + id: userListSearchCard + Layout.fillWidth: true + visible: room.canSendState("m.room.power_levels") - MobileForm.FormHeader { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - title: i18n("Default permissions") - } - MobileForm.FormCard { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormComboBoxDelegate { - text: i18n("Default user power level") - description: i18n("This is power level for all new users when joining the room") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultUserPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Default power level to set the room state") - description: i18n("This is used for all state events that do not have their own entry here") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.statePowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Default power level to send messages") - description: i18n("This is used for all message events that do not have their own entry here") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultEventPowerLevel = currentValue + contentItem: Kirigami.SearchField { + id: userListSearchField + + autoAccept: false + + Layout.fillWidth: true + + Keys.onUpPressed: userListView.decrementCurrentIndex() + Keys.onDownPressed: userListView.incrementCurrentIndex() + + onAccepted: { + let currentUser = userListView.itemAtIndex(userListView.currentIndex); + currentUser.action.trigger(); } } - } + QQC2.Popup { + id: userListSearchPopup - MobileForm.FormHeader { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - title: i18n("Basic permissions") - } - MobileForm.FormCard { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormComboBoxDelegate { - text: i18n("Invite users") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.invitePowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Kick users") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.kickPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Ban users") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.banPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Remove message sent by other users") - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.redactPowerLevel = currentValue - } - } - } + x: userListSearchField.x + y: userListSearchField.y - height + width: userListSearchField.width + height: { + let maxHeight = userListSearchField.mapToGlobal(userListSearchField.x, userListSearchField.y).y - Kirigami.Units.largeSpacing * 3; + let minHeight = Kirigami.Units.gridUnit * 2 + userListSearchPopup.padding * 2; + let filterContentHeight = userListView.contentHeight + userListSearchPopup.padding * 2; - MobileForm.FormHeader { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - title: i18n("Event permissions") - } - MobileForm.FormCard { - Layout.fillWidth: true - visible: room.canSendState("m.room.power_levels") - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormComboBoxDelegate { - text: i18n("Change user permissions") - description: "m.room.power_levels" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.powerLevelPowerLevel = currentValue + return Math.max(Math.min(filterContentHeight, maxHeight), minHeight); } - MobileForm.FormComboBoxDelegate { - text: i18n("Change the room name") - description: "m.room.name" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.namePowerLevel = currentValue + padding: Kirigami.Units.smallSpacing + leftPadding: Kirigami.Units.smallSpacing / 2 + rightPadding: Kirigami.Units.smallSpacing / 2 + modal: false + onClosed: userListSearchField.text = "" + + background: Kirigami.ShadowedRectangle { + property color borderColor: Kirigami.Theme.textColor + + Kirigami.Theme.colorSet: Kirigami.Theme.View + Kirigami.Theme.inherit: false + + radius: 4 + color: Kirigami.Theme.backgroundColor + + border { + color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) + width: 1 + } + + shadow { + xOffset: 0 + yOffset: 4 + color: Qt.rgba(0, 0, 0, 0.3) + size: 8 + } } - MobileForm.FormComboBoxDelegate { - text: i18n("Change the room avatar") - description: "m.room.avatar" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.avatarPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Change the room canonical alias") - description: "m.room.canonical_alias" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.canonicalAliasPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Change the room topic") - description: "m.room.topic" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.topicPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Enable encryption for the room") - description: "m.room.encryption" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.encryptionPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Change the room history visibility") - description: "m.room.history_visibility" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.historyVisibilityPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Set pinned events") - description: "m.room.pinned_events" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.pinnedEventsPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Upgrade the room") - description: "m.room.tombstone" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.tombstonePowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Set the room server access control list (ACL)") - description: "m.room.server_acl" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.serverAclPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - visible: room.isSpace - text: i18n("Set the children of this space") - description: "m.space.child" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceChildPowerLevel = currentValue - } - MobileForm.FormComboBoxDelegate { - text: i18n("Set the parent space of this room") - description: "m.space.parent" - textRole: "text" - valueRole: "powerLevel" - model: powerLevelModel - Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) - onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceParentPowerLevel = currentValue + + contentItem: QQC2.ScrollView { + // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) + QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff + + ListView { + id: userListView + clip: true + + model: UserFilterModel { + id: userListFilterModel + sourceModel: userListModel + filterText: userListSearchField.text + + onFilterTextChanged: { + if (filterText.length > 0 && !userListSearchPopup.visible) { + userListSearchPopup.open() + } else if (filterText.length <= 0 && userListSearchPopup.visible) { + userListSearchPopup.close() + } + } + } + + delegate: Delegates.RoundedItemDelegate { + id: userListItem + + required property string userId + required property string avatar + required property string name + required property int powerLevel + required property string powerLevelString + + text: name + + contentItem: RowLayout { + KirigamiComponents.Avatar { + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + source: userListItem.avatar ? ("image://" + userListItem.avatar) : "" + name: userListItem.name + } + + Delegates.SubtitleContentItem { + itemDelegate: userListItem + subtitle: userListItem.userId + labelItem.textFormat: Text.PlainText + subtitleItem.textFormat: Text.PlainText + Layout.fillWidth: true + } + + QQC2.Label { + visible: userListItem.powerLevel > 0 + + text: userListItem.powerLevelString + color: Kirigami.Theme.disabledTextColor + textFormat: Text.PlainText + wrapMode: Text.NoWrap + } + } + + action: Kirigami.Action { + id: editPowerLevelAction + onTriggered: { + userListSearchPopup.close() + let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { + room: root.room, + userId: userListItem.userId, + powerLevel: userListItem.powerLevel + }); + dialog.open(); + } + } + + Component { + id: powerLevelDialog + PowerLevelDialog { + id: powerLevelDialog + } + } + } + } } } } } + + FormCard.FormHeader { + visible: room.canSendState("m.room.power_levels") + title: i18n("Default permissions") + } + + FormCard.FormCard { + visible: room.canSendState("m.room.power_levels") + + FormCard.FormComboBoxDelegate { + text: i18n("Default user power level") + description: i18n("This is power level for all new users when joining the room") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultUserPowerLevel = currentValue + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormComboBoxDelegate { + text: i18n("Default power level to set the room state") + description: i18n("This is used for all state events that do not have their own entry here") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.statePowerLevel = currentValue + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormComboBoxDelegate { + text: i18n("Default power level to send messages") + description: i18n("This is used for all message events that do not have their own entry here") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultEventPowerLevel = currentValue + } + } + + FormCard.FormHeader { + visible: room.canSendState("m.room.power_levels") + title: i18n("Basic permissions") + } + + FormCard.FormCard { + visible: room.canSendState("m.room.power_levels") + + FormCard.FormComboBoxDelegate { + text: i18n("Invite users") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.invitePowerLevel = currentValue + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormComboBoxDelegate { + text: i18n("Kick users") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.kickPowerLevel = currentValue + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormComboBoxDelegate { + text: i18n("Ban users") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.banPowerLevel = currentValue + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormComboBoxDelegate { + text: i18n("Remove message sent by other users") + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.redactPowerLevel = currentValue + } + } + + FormCard.FormHeader { + visible: room.canSendState("m.room.power_levels") + title: i18n("Event permissions") + } + + FormCard.FormCard { + visible: room.canSendState("m.room.power_levels") + + FormCard.FormComboBoxDelegate { + text: i18n("Change user permissions") + description: "m.room.power_levels" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.powerLevelPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Change the room name") + description: "m.room.name" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.namePowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Change the room avatar") + description: "m.room.avatar" + textRole: "text" + valueRole: "powerLevel" + model: roo.tpowerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.avatarPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Change the room canonical alias") + description: "m.room.canonical_alias" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.canonicalAliasPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Change the room topic") + description: "m.room.topic" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.topicPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Enable encryption for the room") + description: "m.room.encryption" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.encryptionPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Change the room history visibility") + description: "m.room.history_visibility" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.historyVisibilityPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Set pinned events") + description: "m.room.pinned_events" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.pinnedEventsPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Upgrade the room") + description: "m.room.tombstone" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.tombstonePowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Set the room server access control list (ACL)") + description: "m.room.server_acl" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.serverAclPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + visible: room.isSpace + text: i18n("Set the children of this space") + description: "m.space.child" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceChildPowerLevel = currentValue + } + FormCard.FormComboBoxDelegate { + text: i18n("Set the parent space of this room") + description: "m.space.parent" + textRole: "text" + valueRole: "powerLevel" + model: root.powerLevelModel + Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) + onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceParentPowerLevel = currentValue + } + } } diff --git a/src/qml/RoomSettings/PushNotification.qml b/src/qml/RoomSettings/PushNotification.qml index e1d060117..655da5a2e 100644 --- a/src/qml/RoomSettings/PushNotification.qml +++ b/src/qml/RoomSettings/PushNotification.qml @@ -6,138 +6,123 @@ 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.kirigamiaddons.formcard 1.0 as FormCard import org.kde.kitemmodels 1.0 import org.kde.neochat 1.0 -Kirigami.ScrollablePage { +FormCard.FormCardPage { id: root property NeoChatRoom room title: i18nc('@title:window', 'Notifications') - topPadding: 0 - leftPadding: 0 - rightPadding: 0 - ColumnLayout { - spacing: 0 - MobileForm.FormHeader { - Layout.fillWidth: true - title: i18n("Room notifications setting") - } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormRadioDelegate { - text: i18n("Follow global setting") - checked: room.pushNotificationState === PushNotificationState.Default - enabled: room.pushNotificationState !== PushNotificationState.Unknown - onToggled: { - room.pushNotificationState = PushNotificationState.Default - } - } - MobileForm.FormRadioDelegate { - text: i18nc("As in 'notify for all messages'","All") - checked: room.pushNotificationState === PushNotificationState.All - enabled: room.pushNotificationState !== PushNotificationState.Unknown - onToggled: { - room.pushNotificationState = PushNotificationState.All - } - } - MobileForm.FormRadioDelegate { - text: i18nc("As in 'notify when the user is mentioned or the message contains a set keyword'","@Mentions and Keywords") - checked: room.pushNotificationState === PushNotificationState.MentionKeyword - enabled: room.pushNotificationState !== PushNotificationState.Unknown - onToggled: { - room.pushNotificationState = PushNotificationState.MentionKeyword - } - } - MobileForm.FormRadioDelegate { - text: i18nc("As in 'do not notify for any messages'","Off") - checked: room.pushNotificationState === PushNotificationState.Mute - enabled: room.pushNotificationState !== PushNotificationState.Unknown - onToggled: { - room.pushNotificationState = PushNotificationState.Mute - } - } + + FormCard.FormHeader { + title: i18n("Room notifications setting") + } + + FormCard.FormCard { + FormCard.FormRadioDelegate { + text: i18n("Follow global setting") + checked: room.pushNotificationState === PushNotificationState.Default + enabled: room.pushNotificationState !== PushNotificationState.Unknown + onToggled: { + room.pushNotificationState = PushNotificationState.Default } } + FormCard.FormRadioDelegate { + text: i18nc("As in 'notify for all messages'","All") + checked: room.pushNotificationState === PushNotificationState.All + enabled: room.pushNotificationState !== PushNotificationState.Unknown + onToggled: { + room.pushNotificationState = PushNotificationState.All + } + } + FormCard.FormRadioDelegate { + text: i18nc("As in 'notify when the user is mentioned or the message contains a set keyword'","@Mentions and Keywords") + checked: room.pushNotificationState === PushNotificationState.MentionKeyword + enabled: room.pushNotificationState !== PushNotificationState.Unknown + onToggled: { + room.pushNotificationState = PushNotificationState.MentionKeyword + } + } + FormCard.FormRadioDelegate { + text: i18nc("As in 'do not notify for any messages'","Off") + checked: room.pushNotificationState === PushNotificationState.Mute + enabled: room.pushNotificationState !== PushNotificationState.Unknown + onToggled: { + room.pushNotificationState = PushNotificationState.Mute + } + } + } - MobileForm.FormCard { + FormCard.FormHeader { + title: i18n("Keywords") + } + + FormCard.FormCard { + Repeater { + model: KSortFilterProxyModel { + sourceModel: Controller.pushRuleModel + + filterRowCallback: function(source_row, source_parent) { + let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) + let roomIdRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.RoomIdRole) + return sectionRole == PushNotificationSection.RoomKeywords && roomIdRole == root.room.id; + } + } + + delegate: ruleDelegate + } + + FormCard.AbstractFormDelegate { Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 + contentItem : RowLayout { + Kirigami.ActionTextField { + id: keywordAddField - MobileForm.FormCardHeader { - title: i18n("Keywords") - } - Repeater { - model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel - - filterRowCallback: function(source_row, source_parent) { - let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) - let roomIdRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.RoomIdRole) - return sectionRole == PushNotificationSection.RoomKeywords && roomIdRole == root.room.id; - } - } - - delegate: ruleDelegate - } - MobileForm.AbstractFormDelegate { Layout.fillWidth: true - contentItem : RowLayout { - Kirigami.ActionTextField { - id: keywordAddField + placeholderText: i18n("Keyword…") + enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown - Layout.fillWidth: true - - placeholderText: i18n("Keyword…") - enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown - - rightActions: Kirigami.Action { - icon.name: "edit-clear" - visible: keywordAddField.text.length > 0 - onTriggered: { - keywordAddField.text = "" - } - } - - onAccepted: { - Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) - keywordAddField.text = "" - } - } - QQC2.Button { - id: addButton - - text: i18n("Add keyword") - Accessible.name: text - icon.name: "list-add" - display: QQC2.AbstractButton.IconOnly - enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown - - onClicked: { - Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) - keywordAddField.text = "" - } - - QQC2.ToolTip { - text: addButton.text - delay: Kirigami.Units.toolTipDelay - } + rightActions: Kirigami.Action { + icon.name: "edit-clear" + visible: keywordAddField.text.length > 0 + onTriggered: { + keywordAddField.text = "" } } + + onAccepted: { + Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) + keywordAddField.text = "" + } + } + QQC2.Button { + id: addButton + + text: i18n("Add keyword") + icon.name: "list-add" + display: QQC2.AbstractButton.IconOnly + enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown + + onClicked: { + Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) + keywordAddField.text = "" + } + + QQC2.ToolTip.text: text + QQC2.ToolTip.visible: hovered + QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay } } } } - Component { + data: Component { id: ruleDelegate NotificationRuleItem { onDeleteRule: { diff --git a/src/qml/Settings/DeviceDelegate.qml b/src/qml/Settings/DeviceDelegate.qml index 419d63f0f..228fd3401 100644 --- a/src/qml/Settings/DeviceDelegate.qml +++ b/src/qml/Settings/DeviceDelegate.qml @@ -7,11 +7,11 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import org.kde.kirigami 2.19 as Kirigami -import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.formcard 1.0 as FormCard import org.kde.neochat 1.0 -MobileForm.AbstractFormDelegate { +FormCard.AbstractFormDelegate { id: deviceDelegate required property string id diff --git a/src/qml/Settings/NetworkProxyPage.qml b/src/qml/Settings/NetworkProxyPage.qml index 7e999e476..3f6e01d5f 100644 --- a/src/qml/Settings/NetworkProxyPage.qml +++ b/src/qml/Settings/NetworkProxyPage.qml @@ -6,104 +6,102 @@ 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.kirigamiaddons.formcard 1.0 as FormCard import org.kde.neochat 1.0 -Kirigami.ScrollablePage { - title: i18nc("@title:window", "General") +FormCard.FormCardPage { + id: root + property int currentType property bool proxyConfigChanged: false - topPadding: 0 - leftPadding: 0 - rightPadding: 0 - ColumnLayout { - spacing: 0 - MobileForm.FormHeader { - Layout.fillWidth: true - title: i18n("Network Proxy") + title: i18nc("@title:window", "General") + + FormCard.FormHeader { + title: i18n("Network Proxy") + } + + FormCard.FormCard { + FormCard.FormRadioDelegate { + text: i18n("System Default") + checked: currentType === 0 + enabled: !Config.isProxyTypeImmutable + onToggled: { + currentType = 0 + } } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormRadioDelegate { - text: i18n("System Default") - checked: currentType === 0 - enabled: !Config.isProxyTypeImmutable - onToggled: { - currentType = 0 - } - } - MobileForm.FormRadioDelegate { - text: i18n("HTTP") - checked: currentType === 1 - enabled: !Config.isProxyTypeImmutable - onToggled: { - currentType = 1 - } - } - MobileForm.FormRadioDelegate { - text: i18n("Socks5") - checked: currentType === 2 - enabled: !Config.isProxyTypeImmutable - onToggled: { - currentType = 2 - } - } + FormCard.FormRadioDelegate { + text: i18n("HTTP") + checked: currentType === 1 + enabled: !Config.isProxyTypeImmutable + onToggled: { + currentType = 1 + } + } + FormCard.FormRadioDelegate { + text: i18n("Socks5") + checked: currentType === 2 + enabled: !Config.isProxyTypeImmutable + onToggled: { + currentType = 2 + } + } + } + + FormCard.FormHeader { + title: i18n("Proxy Settings") + } + + FormCard.FormCard { + FormCard.FormTextFieldDelegate { + id: hostField + label: i18n("Host") + text: Config.proxyHost + inputMethodHints: Qt.ImhUrlCharactersOnly + onEditingFinished: { + proxyConfigChanged = true } } - MobileForm.FormHeader { - Layout.fillWidth: true - title: i18n("Proxy Settings") + FormCard.FormDelegateSeparator {} + + FormCard.FormSpinBoxDelegate { + id: portField + label: i18n("Port") + value: Config.proxyPort + from: 0 + to: 65536 + textFromValue: function(value, locale) { + return value // it will add a thousands separator if we don't do this, not sure why + } + onValueChanged: { + proxyConfigChanged = true + } } - MobileForm.FormCard { - Layout.fillWidth: true - contentItem: ColumnLayout { - spacing: 0 - MobileForm.FormTextFieldDelegate { - id: hostField - label: i18n("Host") - text: Config.proxyHost - inputMethodHints: Qt.ImhUrlCharactersOnly - onEditingFinished: { - proxyConfigChanged = true - } - } - MobileForm.FormSpinBoxDelegate { - id: portField - label: i18n("Port") - value: Config.proxyPort - from: 0 - to: 65536 - textFromValue: function(value, locale) { - return value // it will add a thousands separator if we don't do this, not sure why - } - onValueChanged: { - proxyConfigChanged = true - } - } - MobileForm.FormTextFieldDelegate { - id: userField - label: i18n("User") - text: Config.proxyUser - inputMethodHints: Qt.ImhUrlCharactersOnly - onEditingFinished: { - proxyConfigChanged = true - } - } - MobileForm.FormTextFieldDelegate { - id: passwordField - label: i18n("Password") - text: Config.proxyPassword - echoMode: TextInput.Password - inputMethodHints: Qt.ImhUrlCharactersOnly - onEditingFinished: { - proxyConfigChanged = true - } - } + + FormCard.FormDelegateSeparator {} + + FormCard.FormTextFieldDelegate { + id: userField + label: i18n("User") + text: Config.proxyUser + inputMethodHints: Qt.ImhUrlCharactersOnly + onEditingFinished: { + proxyConfigChanged = true + } + } + + FormCard.FormDelegateSeparator {} + + FormCard.FormTextFieldDelegate { + id: passwordField + label: i18n("Password") + text: Config.proxyPassword + echoMode: TextInput.Password + inputMethodHints: Qt.ImhUrlCharactersOnly + onEditingFinished: { + proxyConfigChanged = true } } }