Compare commits

...

3 Commits

Author SHA1 Message Date
Carl Schwan
8177c1f1bc Port About page to FormCard 2023-08-22 22:03:35 +00:00
Carl Schwan
80171748d8 Port more MobileForm to FormCard
- DevTools
- Network settings
- Push notification
- Permissions
2023-08-22 22:03:35 +00:00
Carl Schwan
6aa2e586de Port to form card 2023-08-22 22:03:35 +00:00
12 changed files with 1104 additions and 1126 deletions

View File

@@ -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();

View File

@@ -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
});
}
}
}

View File

@@ -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
}
}

View File

@@ -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 {}
}
]
}

View File

@@ -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
}
}
}

View File

@@ -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: {

View File

@@ -4,10 +4,10 @@
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
MobileForm.AboutPage {
FormCard.AboutPage {
title: i18nc("@title:window", "About NeoChat")
aboutData: About
}

View File

@@ -1,8 +1,8 @@
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
MobileForm.AboutKDE {
FormCard.AboutKDE {
title: i18nc("@title:window", "About KDE")
}

View File

@@ -7,344 +7,337 @@ 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.labs.components 1.0 as KirigamiComponents
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
import org.kde.kirigamiaddons.components 1.0 as KirigamiComponents
import org.kde.neochat 1.0
Kirigami.ScrollablePage {
FormCard.FormCardPage {
id: root
title: i18nc("@title:window", "Appearance")
topPadding: 0
leftPadding: 0
rightPadding: 0
ColumnLayout {
spacing: 0
MobileForm.FormHeader {
FormCard.FormHeader {
Layout.fillWidth: true
title: i18n("General theme")
}
FormCard.FormCard {
Layout.fillWidth: true
FormCard.AbstractFormDelegate {
id: timelineModeSetting
Layout.fillWidth: true
title: i18n("General theme")
}
MobileForm.FormCard {
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.AbstractFormDelegate {
id: timelineModeSetting
background: Item {}
contentItem: RowLayout {
Layout.alignment: Qt.AlignCenter
spacing: Kirigami.Units.largeSpacing
Item {
Layout.fillWidth: true
background: Item {}
contentItem: RowLayout {
Layout.alignment: Qt.AlignCenter
spacing: Kirigami.Units.largeSpacing
Item {
Layout.fillWidth: true
}
QQC2.ButtonGroup { id: themeGroup }
ThemeRadioButton {
thin: timelineModeSetting.width < Kirigami.Units.gridUnit * 22
innerObject: [
RowLayout {
Layout.fillWidth: true
KirigamiComponents.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
KirigamiComponents.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();
}
}
ThemeRadioButton {
// Layout.alignment: Qt.AlignRight
thin: timelineModeSetting.width < Kirigami.Units.gridUnit * 22
innerObject: [
RowLayout {
Layout.fillWidth: true
KirigamiComponents.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
KirigamiComponents.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();
}
}
Item {
Layout.fillWidth: true
}
}
}
QQC2.ButtonGroup { id: themeGroup }
ThemeRadioButton {
thin: timelineModeSetting.width < Kirigami.Units.gridUnit * 22
innerObject: [
RowLayout {
Layout.fillWidth: true
KirigamiComponents.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
KirigamiComponents.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
}
}
}
]
MobileForm.FormDelegateSeparator { below: compactRoomListDelegate }
text: i18n("Bubbles")
checked: !Config.compactLayout
QQC2.ButtonGroup.group: themeGroup
enabled: !Config.isCompactLayoutImmutable
MobileForm.FormCheckDelegate {
id: compactRoomListDelegate
text: i18n("Use compact room list")
checked: Config.compactRoomList
onToggled: {
Config.compactRoomList = checked;
Config.compactLayout = !checked;
Config.save();
}
}
MobileForm.FormDelegateSeparator { above: compactRoomListDelegate ; below: colorSchemeDelegate.item ; visible: colorSchemeDelegate.visible }
Loader {
id: colorSchemeDelegate
visible: item !== null && Qt.platform.os !== "android"
source: "qrc:/ColorScheme.qml"
ThemeRadioButton {
// Layout.alignment: Qt.AlignRight
thin: timelineModeSetting.width < Kirigami.Units.gridUnit * 22
innerObject: [
RowLayout {
Layout.fillWidth: true
KirigamiComponents.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
KirigamiComponents.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();
}
}
Item {
Layout.fillWidth: true
}
}
}
MobileForm.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
FormCard.FormDelegateSeparator { below: compactRoomListDelegate }
FormCard.FormCheckDelegate {
id: compactRoomListDelegate
text: i18n("Use compact room list")
checked: Config.compactRoomList
onToggled: {
Config.compactRoomList = checked;
Config.save();
}
}
FormCard.FormDelegateSeparator { above: compactRoomListDelegate ; below: colorSchemeDelegate.item ; visible: colorSchemeDelegate.visible }
Loader {
id: colorSchemeDelegate
visible: item !== null && Qt.platform.os !== "android"
source: "qrc:/ColorScheme.qml"
Layout.fillWidth: true
}
}
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing * 2
Layout.fillWidth: true
FormCard.FormCheckDelegate {
id: showFancyEffectsDelegate
text: i18n("Show fancy effects in chat")
checked: Config.showFancyEffects
enabled: !Config.isShowFancyEffectsImmutable
onToggled: {
Config.showFancyEffects = checked;
Config.save();
}
}
FormCard.FormDelegateSeparator { above: showFancyEffectsDelegate ; below: hasWindowSystemDelegate }
FormCard.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();
}
}
FormCard.FormDelegateSeparator { above: hasWindowSystemDelegate; below: transparencyDelegate }
FormCard.AbstractFormDelegate {
id: transparencyDelegate
Layout.fillWidth: true
visible: Controller.hasWindowSystem && Config.blur
enabled: !Config.isTransparancyImmutable
background: Item {}
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCheckDelegate {
id: showFancyEffectsDelegate
text: i18n("Show fancy effects in chat")
checked: Config.showFancyEffects
enabled: !Config.isShowFancyEffectsImmutable
onToggled: {
Config.showFancyEffects = checked;
Config.save();
}
}
MobileForm.FormDelegateSeparator { above: showFancyEffectsDelegate ; below: hasWindowSystemDelegate }
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();
}
}
MobileForm.FormDelegateSeparator { above: hasWindowSystemDelegate; below: transparencyDelegate }
MobileForm.AbstractFormDelegate {
id: transparencyDelegate
QQC2.Label {
text: i18n("Transparency")
Layout.fillWidth: true
visible: Controller.hasWindowSystem && Config.blur
enabled: !Config.isTransparancyImmutable
background: Item {}
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()
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.")
}
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()
}
QQC2.Label {
text: Math.round(Config.transparency * 100) + "%"
Layout.fillWidth: true
}
}
}
MobileForm.FormHeader {
Layout.fillWidth: true
title: i18n("Show Avatar")
}
MobileForm.FormCard {
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
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()
}
}
FormCard.FormDelegateSeparator { above: transparencyDelegate; below: showLocalMessagesOnRightDelegate; visible: transparencyDelegate.visible }
FormCard.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()
}
}
FormCard.FormDelegateSeparator { above: showLocalMessagesOnRightDelegate; below: showLinkPreviewDelegate }
FormCard.FormCheckDelegate {
id: showLinkPreviewDelegate
text: i18n("Show links preview in the chat messages")
checked: Config.showLinkPreview
onToggled: {
Config.showLinkPreview = checked
Config.save()
}
}
}
FormCard.FormHeader {
Layout.fillWidth: true
title: i18n("Show Avatar")
}
FormCard.FormCard {
Layout.fillWidth: true
FormCard.FormCheckDelegate {
text: i18n("In chat")
checked: Config.showAvatarInTimeline
onToggled: {
Config.showAvatarInTimeline = checked
Config.save()
}
enabled: !Config.isShowAvatarInTimelineImmutable
}
FormCard.FormCheckDelegate {
text: i18n("In sidebar")
checked: Config.showAvatarInRoomDrawer
enabled: !Config.isShowAvatarInRoomDrawerImmutable
onToggled: {
Config.showAvatarInRoomDrawer = checked
Config.save()
}
}
}

View File

@@ -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

View File

@@ -7,80 +7,81 @@ 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
Kirigami.ScrollablePage {
FormCard.FormCardPage {
id: root
title: i18n("Devices")
property alias connection: devicesModel.connection
leftPadding: 0
rightPadding: 0
DevicesModel {
id: devicesModel
DevicesCard {
title: i18n("This Device")
type: DevicesModel.This
showVerifyButton: false
}
DevicesCard {
title: i18n("Verified Devices")
type: DevicesModel.Verified
showVerifyButton: true
}
DevicesCard {
title: i18n("Unverified Devices")
type: DevicesModel.Unverified
showVerifyButton: true
}
DevicesCard {
title: i18n("Devices without Encryption Support")
type: DevicesModel.Unencrypted
showVerifyButton: false
}
ColumnLayout {
DevicesCard {
title: i18n("This Device")
type: DevicesModel.This
showVerifyButton: false
}
DevicesCard {
title: i18n("Verified Devices")
type: DevicesModel.Verified
showVerifyButton: true
}
DevicesCard {
title: i18n("Unverified Devices")
type: DevicesModel.Unverified
showVerifyButton: true
}
DevicesCard {
title: i18n("Devices without Encryption Support")
type: DevicesModel.Unencrypted
showVerifyButton: false
}
MobileForm.AbstractFormDelegate {
Layout.fillWidth: true
visible: Controller.activeConnection && devicesModel.count === 0 // We can assume 0 means loading since there is at least one device
contentItem: Kirigami.LoadingPlaceholder { }
}
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
Layout.alignment: Qt.AlignHCenter
text: i18n("Please login to view the signed-in devices for your account.")
type: Kirigami.MessageType.Information
visible: !Controller.activeConnection
}
FormCard.AbstractFormDelegate {
Layout.fillWidth: true
visible: Controller.activeConnection && devicesModel.count === 0 // We can assume 0 means loading since there is at least one device
contentItem: Kirigami.LoadingPlaceholder { }
}
Kirigami.OverlaySheet {
id: passwordSheet
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
Layout.alignment: Qt.AlignHCenter
text: i18n("Please login to view the signed-in devices for your account.")
type: Kirigami.MessageType.Information
visible: !Controller.activeConnection
}
property string deviceId
data: [
DevicesModel {
id: devicesModel
},
Kirigami.PromptDialog {
id: passwordSheet
title: i18n("Remove device")
Kirigami.FormLayout {
QQC2.TextField {
property string deviceId
parent: applicationWindow().overlay
title: i18n("Remove device")
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
onAccepted: {
devicesModel.logout(passwordSheet.deviceId, passwordField.text)
passwordField.text = ""
passwordSheet.close()
}
FormCard.FormTextFieldDelegate {
id: passwordField
Kirigami.FormData.label: i18n("Password:")
label: i18n("Password:")
echoMode: TextInput.Password
}
QQC2.Button {
text: i18n("Confirm")
onClicked: {
devicesModel.logout(passwordSheet.deviceId, passwordField.text)
passwordField.text = ""
passwordSheet.close()
}
}
}
}
]
}

View File

@@ -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
}
}
}