diff --git a/imports/Spectral/Component/Timeline/FileDelegate.qml b/imports/Spectral/Component/Timeline/FileDelegate.qml
index 87186b6..966eb28 100644
--- a/imports/Spectral/Component/Timeline/FileDelegate.qml
+++ b/imports/Spectral/Component/Timeline/FileDelegate.qml
@@ -9,6 +9,7 @@ import Spectral 0.1
import Spectral.Setting 0.1
import Spectral.Component 2.0
+import Spectral.Dialog 2.0
import Spectral.Font 0.1
ColumnLayout {
@@ -111,16 +112,19 @@ ColumnLayout {
onSecondaryClicked: messageContextMenu.popup()
+ Component {
+ id: messageSourceDialog
+
+ MessageSourceDialog {}
+ }
+
Menu {
id: messageContextMenu
MenuItem {
text: "View Source"
- onTriggered: {
- sourceDialog.sourceText = toolTip
- sourceDialog.open()
- }
+ onTriggered: messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
}
MenuItem {
text: "Open Externally"
diff --git a/imports/Spectral/Component/Timeline/ImageDelegate.qml b/imports/Spectral/Component/Timeline/ImageDelegate.qml
index b92881c..cdb6395 100644
--- a/imports/Spectral/Component/Timeline/ImageDelegate.qml
+++ b/imports/Spectral/Component/Timeline/ImageDelegate.qml
@@ -9,6 +9,7 @@ import Spectral 0.1
import Spectral.Setting 0.1
import Spectral.Component 2.0
+import Spectral.Dialog 2.0
import Spectral.Effect 2.0
import Spectral.Font 0.1
@@ -133,16 +134,19 @@ ColumnLayout {
onSecondaryClicked: messageContextMenu.popup()
+ Component {
+ id: messageSourceDialog
+
+ MessageSourceDialog {}
+ }
+
Menu {
id: messageContextMenu
MenuItem {
text: "View Source"
- onTriggered: {
- sourceDialog.sourceText = toolTip
- sourceDialog.open()
- }
+ onTriggered: messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
}
MenuItem {
diff --git a/imports/Spectral/Component/Timeline/MessageDelegate.qml b/imports/Spectral/Component/Timeline/MessageDelegate.qml
index 100d062..036a756 100644
--- a/imports/Spectral/Component/Timeline/MessageDelegate.qml
+++ b/imports/Spectral/Component/Timeline/MessageDelegate.qml
@@ -7,6 +7,7 @@ import Spectral 0.1
import Spectral.Setting 0.1
import Spectral.Component 2.0
+import Spectral.Dialog 2.0
import Spectral.Effect 2.0
import Spectral.Font 0.1
@@ -84,6 +85,12 @@ ColumnLayout {
onSecondaryClicked: messageContextMenu.popup()
+ Component {
+ id: messageSourceDialog
+
+ MessageSourceDialog {}
+ }
+
Menu {
readonly property string selectedText: contentLabel.selectedText
@@ -92,10 +99,7 @@ ColumnLayout {
MenuItem {
text: "View Source"
- onTriggered: {
- sourceDialog.sourceText = toolTip
- sourceDialog.open()
- }
+ onTriggered: messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open()
}
MenuItem {
text: "Reply"
diff --git a/imports/Spectral/Dialog/CreateRoomDialog.qml b/imports/Spectral/Dialog/CreateRoomDialog.qml
new file mode 100644
index 0000000..e6efb64
--- /dev/null
+++ b/imports/Spectral/Dialog/CreateRoomDialog.qml
@@ -0,0 +1,38 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+
+Dialog {
+ anchors.centerIn: parent
+ width: 360
+
+ id: root
+
+ title: "Create a Room"
+
+ contentItem: ColumnLayout {
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: roomNameField
+
+ placeholderText: "Room Name"
+ }
+
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: roomTopicField
+
+ placeholderText: "Room Topic"
+ }
+ }
+
+ standardButtons: Dialog.Ok | Dialog.Cancel
+
+ onAccepted: spectralController.createRoom(spectralController.connection, roomNameField.text, roomTopicField.text)
+
+ onClosed: destroy()
+}
diff --git a/imports/Spectral/Dialog/InviteUserDialog.qml b/imports/Spectral/Dialog/InviteUserDialog.qml
new file mode 100644
index 0000000..f56858a
--- /dev/null
+++ b/imports/Spectral/Dialog/InviteUserDialog.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+
+Dialog {
+ property var room
+
+ anchors.centerIn: parent
+ width: 360
+
+ id: root
+
+ title: "Invite User"
+
+ modal: true
+ standardButtons: Dialog.Ok | Dialog.Cancel
+
+ contentItem: AutoTextField {
+ id: inviteUserDialogTextField
+ placeholderText: "User ID"
+ }
+
+ onAccepted: room.inviteToRoom(inviteUserDialogTextField.text)
+
+ onClosed: destroy()
+}
diff --git a/imports/Spectral/Dialog/JoinRoomDialog.qml b/imports/Spectral/Dialog/JoinRoomDialog.qml
new file mode 100644
index 0000000..e819cf5
--- /dev/null
+++ b/imports/Spectral/Dialog/JoinRoomDialog.qml
@@ -0,0 +1,38 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+
+Dialog {
+ anchors.centerIn: parent
+ width: 360
+
+ id: root
+
+ title: "Start a Chat"
+
+ contentItem: ColumnLayout {
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: identifierField
+
+ placeholderText: "Room Alias/User ID"
+ }
+ }
+
+ standardButtons: Dialog.Ok | Dialog.Cancel
+
+ onAccepted: {
+ var identifier = identifierField.text
+ var firstChar = identifier.charAt(0)
+ if (firstChar == "@") {
+ spectralController.createDirectChat(spectralController.connection, identifier)
+ } else if (firstChar == "!" || firstChar == "#") {
+ spectralController.joinRoom(spectralController.connection, identifier)
+ }
+ }
+
+ onClosed: destroy()
+}
diff --git a/imports/Spectral/Dialog/LoginDialog.qml b/imports/Spectral/Dialog/LoginDialog.qml
new file mode 100644
index 0000000..3148300
--- /dev/null
+++ b/imports/Spectral/Dialog/LoginDialog.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+
+Dialog {
+ anchors.centerIn: parent
+ width: 360
+
+ id: root
+
+ title: "Login"
+
+ standardButtons: Dialog.Ok | Dialog.Cancel
+
+ onAccepted: doLogin()
+
+ contentItem: ColumnLayout {
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: serverField
+
+ placeholderText: "Server Address"
+ text: "https://matrix.org"
+ }
+
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: usernameField
+
+ placeholderText: "Username"
+
+ onAccepted: passwordField.forceActiveFocus()
+ }
+
+ AutoTextField {
+ Layout.fillWidth: true
+
+ id: passwordField
+
+ placeholderText: "Password"
+ echoMode: TextInput.Password
+
+ onAccepted: root.doLogin()
+ }
+ }
+
+ function doLogin() {
+ spectralController.loginWithCredentials(serverField.text, usernameField.text, passwordField.text)
+ }
+
+ onClosed: root.destroy()
+}
diff --git a/imports/Spectral/Dialog/MessageSourceDialog.qml b/imports/Spectral/Dialog/MessageSourceDialog.qml
new file mode 100644
index 0000000..41ab04c
--- /dev/null
+++ b/imports/Spectral/Dialog/MessageSourceDialog.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+
+Popup {
+ property string sourceText
+
+ anchors.centerIn: parent
+ width: 480
+
+ id: root
+
+ modal: true
+ padding: 16
+
+ closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
+
+ contentItem: ScrollView {
+ clip: true
+
+ Label {
+ text: sourceText
+ }
+ }
+
+ onClosed: root.destroy()
+}
+
diff --git a/imports/Spectral/Dialog/RoomSettingsDialog.qml b/imports/Spectral/Dialog/RoomSettingsDialog.qml
new file mode 100644
index 0000000..c71db94
--- /dev/null
+++ b/imports/Spectral/Dialog/RoomSettingsDialog.qml
@@ -0,0 +1,218 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+import Spectral.Effect 2.0
+import Spectral.Setting 0.1
+
+Dialog {
+ property var room
+
+ anchors.centerIn: parent
+ width: 480
+
+ id: root
+
+ title: "Room Settings - " + (room ? room.displayName : "")
+ modal: true
+
+ contentItem: ColumnLayout {
+ RowLayout {
+ Layout.fillWidth: true
+
+ spacing: 16
+
+ Avatar {
+ Layout.preferredWidth: 72
+ Layout.preferredHeight: 72
+ Layout.alignment: Qt.AlignTop
+
+ hint: room ? room.displayName : "No name"
+ source: room ? room.avatarMediaId : null
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ Layout.margins: 4
+
+ AutoTextField {
+ Layout.fillWidth: true
+
+ text: room ? room.name : ""
+ placeholderText: "Room Name"
+ }
+
+ AutoTextField {
+ Layout.fillWidth: true
+
+ text: room ? room.topic : ""
+ placeholderText: "Room Topic"
+ }
+ }
+ }
+
+ Control {
+ Layout.fillWidth: true
+
+ visible: room ? room.predecessorId : false
+
+ padding: 8
+
+ contentItem: RowLayout {
+ MaterialIcon {
+ Layout.preferredWidth: 48
+ Layout.preferredHeight: 48
+
+ icon: "\ue8d4"
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ spacing: 0
+
+ Label {
+ Layout.fillWidth: true
+
+ font.bold: true
+ color: MPalette.foreground
+ text: "This room is a continuation of another conversation."
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ color: MPalette.lighter
+ text: "Click here to see older messages."
+ }
+ }
+ }
+
+ background: Rectangle {
+ color: MPalette.banner
+
+ RippleEffect {
+ anchors.fill: parent
+
+ onClicked: {
+ roomListForm.enteredRoom = spectralController.connection.room(room.predecessorId)
+ root.close()
+ }
+ }
+ }
+ }
+
+ Control {
+ Layout.fillWidth: true
+
+ visible: room ? room.successorId : false
+
+ padding: 8
+
+ contentItem: RowLayout {
+ MaterialIcon {
+ Layout.preferredWidth: 48
+ Layout.preferredHeight: 48
+
+ icon: "\ue8d4"
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ spacing: 0
+
+ Label {
+ Layout.fillWidth: true
+
+ font.bold: true
+ color: MPalette.foreground
+ text: "This room has been replaced and is no longer active."
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ color: MPalette.lighter
+ text: "The conversation continues here."
+ }
+ }
+ }
+
+ background: Rectangle {
+ color: MPalette.banner
+
+ RippleEffect {
+ anchors.fill: parent
+
+ onClicked: {
+ roomListForm.enteredRoom = spectralController.connection.room(room.successorId)
+ root.close()
+ }
+ }
+ }
+ }
+
+ MenuSeparator {
+ Layout.fillWidth: true
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ Label {
+ Layout.preferredWidth: 100
+
+ wrapMode: Label.Wrap
+ text: "Main Alias"
+ color: MPalette.lighter
+ }
+
+ ComboBox {
+ Layout.fillWidth: true
+
+ model: room ? room.aliases : null
+
+ currentIndex: room ? room.aliases.indexOf(room.canonicalAlias) : -1
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ Label {
+ Layout.preferredWidth: 100
+ Layout.alignment: Qt.AlignTop
+
+ wrapMode: Label.Wrap
+ text: "Aliases"
+ color: MPalette.lighter
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ Repeater {
+ model: room ? room.aliases : null
+
+ delegate: Label {
+ Layout.fillWidth: true
+
+ text: modelData
+
+ font.pixelSize: 12
+ color: MPalette.lighter
+ }
+ }
+ }
+ }
+ }
+ }
+
+ onClosed: destroy()
+}
+
diff --git a/imports/Spectral/Dialog/UserDetailDialog.qml b/imports/Spectral/Dialog/UserDetailDialog.qml
new file mode 100644
index 0000000..af59d79
--- /dev/null
+++ b/imports/Spectral/Dialog/UserDetailDialog.qml
@@ -0,0 +1,162 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Spectral.Component 2.0
+import Spectral.Effect 2.0
+import Spectral.Setting 0.1
+
+Dialog {
+ property var room
+ property var user
+
+ anchors.centerIn: parent
+ width: 360
+
+ id: root
+
+ modal: true
+
+ contentItem: ColumnLayout {
+ RowLayout {
+ Layout.fillWidth: true
+
+ spacing: 16
+
+ Avatar {
+ Layout.preferredWidth: 72
+ Layout.preferredHeight: 72
+
+ hint: user ? user.displayName : "No name"
+ source: user ? user.avatarMediaId : null
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ Label {
+ Layout.fillWidth: true
+
+ font.pixelSize: 18
+ font.bold: true
+ wrapMode: Label.Wrap
+ text: user ? user.displayName : "No Name"
+ color: MPalette.foreground
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ wrapMode: Label.Wrap
+ text: "Online"
+ color: MPalette.lighter
+ }
+ }
+ }
+
+ MenuSeparator {
+ Layout.fillWidth: true
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ spacing: 8
+
+ MaterialIcon {
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ Layout.alignment: Qt.AlignTop
+
+ icon: "\ue88f"
+ color: MPalette.lighter
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ Label {
+ Layout.fillWidth: true
+
+ wrapMode: Label.Wrap
+ text: user ? user.id : "No ID"
+ color: MPalette.accent
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ wrapMode: Label.Wrap
+ text: "User ID"
+ color: MPalette.lighter
+ }
+ }
+ }
+
+ MenuSeparator {
+ Layout.fillWidth: true
+ }
+
+ Control {
+ Layout.fillWidth: true
+
+ contentItem: RowLayout {
+ MaterialIcon {
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ Layout.alignment: Qt.AlignTop
+
+ icon: room.connection.isIgnored(user) ? "\ue7f5" : "\ue7f6"
+ color: MPalette.lighter
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ wrapMode: Label.Wrap
+ text: room.connection.isIgnored(user) ? "Unignore this user" : "Ignore this user"
+
+ color: MPalette.accent
+ }
+ }
+
+ background: RippleEffect {
+ onPrimaryClicked: {
+ room.connection.isIgnored(user) ? room.connection.removeFromIgnoredUsers(user) : room.connection.addToIgnoredUsers(user)
+ root.close()
+ }
+ }
+ }
+
+ Control {
+ Layout.fillWidth: true
+
+ contentItem: RowLayout {
+ MaterialIcon {
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ Layout.alignment: Qt.AlignTop
+
+ icon: "\ue5d9"
+ color: MPalette.lighter
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ wrapMode: Label.Wrap
+ text: "Kick this user"
+
+ color: MPalette.accent
+ }
+ }
+
+ background: RippleEffect {
+ onPrimaryClicked: room.kickMember(user.id)
+ }
+ }
+ }
+
+ onClosed: destroy()
+}
+
diff --git a/imports/Spectral/Dialog/qmldir b/imports/Spectral/Dialog/qmldir
new file mode 100644
index 0000000..0649630
--- /dev/null
+++ b/imports/Spectral/Dialog/qmldir
@@ -0,0 +1,8 @@
+module Spectral.Dialog
+RoomSettingsDialog 2.0 RoomSettingsDialog.qml
+UserDetailDialog 2.0 UserDetailDialog.qml
+MessageSourceDialog 2.0 MessageSourceDialog.qml
+LoginDialog 2.0 LoginDialog.qml
+CreateRoomDialog 2.0 CreateRoomDialog.qml
+JoinRoomDialog 2.0 JoinRoomDialog.qml
+InviteUserDialog 2.0 InviteUserDialog.qml
diff --git a/imports/Spectral/Panel/RoomDrawer.qml b/imports/Spectral/Panel/RoomDrawer.qml
index 72a1e8d..3fc90fb 100644
--- a/imports/Spectral/Panel/RoomDrawer.qml
+++ b/imports/Spectral/Panel/RoomDrawer.qml
@@ -4,6 +4,7 @@ import QtQuick.Controls.Material 2.12
import QtQuick.Layouts 1.12
import Spectral.Component 2.0
+import Spectral.Dialog 2.0
import Spectral.Effect 2.0
import Spectral.Setting 0.1
@@ -115,7 +116,7 @@ Drawer {
}
background: RippleEffect {
- onPrimaryClicked: roomDetailDialog.open()
+ onPrimaryClicked: roomSettingDialog.createObject(ApplicationWindow.overlay, {"room": room}).open()
}
}
@@ -153,7 +154,7 @@ Drawer {
color: MPalette.lighter
}
- onClicked: inviteUserDialog.open()
+ onClicked: inviteUserDialog.createObject(ApplicationWindow.overlay, {"room": room}).open()
}
}
@@ -198,6 +199,8 @@ Drawer {
RippleEffect {
anchors.fill: parent
+
+ onPrimaryClicked: userDetailDialog.createObject(ApplicationWindow.overlay, {"room": room, "user": user}).open()
}
}
@@ -205,225 +208,21 @@ Drawer {
}
}
- Dialog {
- anchors.centerIn: parent
- width: 360
+ Component {
+ id: roomSettingDialog
+ RoomSettingsDialog {}
+ }
+
+ Component {
+ id: userDetailDialog
+
+ UserDetailDialog {}
+ }
+
+ Component {
id: inviteUserDialog
- parent: ApplicationWindow.overlay
-
- title: "Invite User"
- modal: true
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- contentItem: AutoTextField {
- id: inviteUserDialogTextField
- placeholderText: "User ID"
- }
-
- onAccepted: room.inviteToRoom(inviteUserDialogTextField.text)
- }
-
- Dialog {
- anchors.centerIn: parent
- width: 480
-
- id: roomDetailDialog
-
- parent: ApplicationWindow.overlay
-
- title: "Room Settings - " + (room ? room.displayName : "")
- modal: true
-
- contentItem: ColumnLayout {
- RowLayout {
- Layout.fillWidth: true
-
- spacing: 16
-
- Avatar {
- Layout.preferredWidth: 72
- Layout.preferredHeight: 72
- Layout.alignment: Qt.AlignTop
-
- hint: room ? room.displayName : "No name"
- source: room ? room.avatarMediaId : null
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- Layout.margins: 4
-
- AutoTextField {
- Layout.fillWidth: true
-
- text: room ? room.name : ""
- placeholderText: "Room Name"
- }
-
- AutoTextField {
- Layout.fillWidth: true
-
- text: room ? room.topic : ""
- placeholderText: "Room Topic"
- }
- }
- }
-
- Control {
- Layout.fillWidth: true
-
- visible: room ? room.predecessorId : false
-
- padding: 8
-
- contentItem: RowLayout {
- MaterialIcon {
- Layout.preferredWidth: 48
- Layout.preferredHeight: 48
-
- icon: "\ue8d4"
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- Label {
- Layout.fillWidth: true
-
- font.bold: true
- color: MPalette.foreground
- text: "This room is a continuation of another conversation."
- }
-
- Label {
- Layout.fillWidth: true
-
- color: MPalette.lighter
- text: "Click here to see older messages."
- }
- }
- }
-
- background: Rectangle {
- color: MPalette.banner
-
- RippleEffect {
- anchors.fill: parent
-
- onClicked: roomListForm.enteredRoom = spectralController.connection.room(room.predecessorId)
- }
- }
- }
-
- Control {
- Layout.fillWidth: true
-
- visible: room ? room.successorId : false
-
- padding: 8
-
- contentItem: RowLayout {
- MaterialIcon {
- Layout.preferredWidth: 48
- Layout.preferredHeight: 48
-
- icon: "\ue8d4"
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- Label {
- Layout.fillWidth: true
-
- font.bold: true
- color: MPalette.foreground
- text: "This room has been replaced and is no longer active."
- }
-
- Label {
- Layout.fillWidth: true
-
- color: MPalette.lighter
- text: "The conversation continues here."
- }
- }
- }
-
- background: Rectangle {
- color: MPalette.banner
-
- RippleEffect {
- anchors.fill: parent
-
- onClicked: roomListForm.enteredRoom = spectralController.connection.room(room.successorId)
- }
- }
- }
-
- MenuSeparator {
- Layout.fillWidth: true
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- RowLayout {
- Layout.fillWidth: true
-
- Label {
- Layout.preferredWidth: 100
-
- wrapMode: Label.Wrap
- text: "Main Alias"
- color: MPalette.lighter
- }
-
- ComboBox {
- Layout.fillWidth: true
-
- model: room ? room.aliases : null
-
- currentIndex: room ? room.aliases.indexOf(room.canonicalAlias) : -1
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
-
- Label {
- Layout.preferredWidth: 100
- Layout.alignment: Qt.AlignTop
-
- wrapMode: Label.Wrap
- text: "Aliases"
- color: MPalette.lighter
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- Repeater {
- model: room ? room.aliases : null
-
- delegate: Label {
- Layout.fillWidth: true
-
- text: modelData
-
- font.pixelSize: 12
- color: MPalette.lighter
- }
- }
- }
- }
- }
- }
+ InviteUserDialog {}
}
}
diff --git a/imports/Spectral/Panel/RoomPanel.qml b/imports/Spectral/Panel/RoomPanel.qml
index b2826c8..443dc8c 100644
--- a/imports/Spectral/Panel/RoomPanel.qml
+++ b/imports/Spectral/Panel/RoomPanel.qml
@@ -88,9 +88,11 @@ Item {
sourceModel: messageEventModel
- filters: ExpressionFilter {
- expression: marks !== 0x10 && eventType !== "other"
- }
+ filters: [
+ ExpressionFilter {
+ expression: marks !== 0x10 && eventType !== "other"
+ }
+ ]
onModelReset: {
if (currentRoom) {
@@ -272,31 +274,6 @@ Item {
onClicked: messageListView.positionViewAtBeginning()
}
-
- Popup {
- property string sourceText
-
- anchors.centerIn: parent
- width: 480
-
- id: sourceDialog
-
- parent: ApplicationWindow.overlay
-
- padding: 16
-
- closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
-
- contentItem: ScrollView {
- clip: true
- TextArea {
- readOnly: true
- selectByMouse: true
-
- text: sourceDialog.sourceText
- }
- }
- }
}
Control {
diff --git a/include/libqmatrixclient b/include/libqmatrixclient
index af55d9a..52a81df 160000
--- a/include/libqmatrixclient
+++ b/include/libqmatrixclient
@@ -1 +1 @@
-Subproject commit af55d9a0f23ed48c7dcec26efe6b01fb44a8c4fc
+Subproject commit 52a81dfa8a5415be369d819837f445479b833cde
diff --git a/qml/main.qml b/qml/main.qml
index 3de3130..19f06ac 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -7,6 +7,7 @@ import Qt.labs.platform 1.0 as Platform
import Spectral.Panel 2.0
import Spectral.Component 2.0
+import Spectral.Dialog 2.0
import Spectral.Page 2.0
import Spectral.Effect 2.0
@@ -39,16 +40,14 @@ ApplicationWindow {
menu: Platform.Menu {
Platform.MenuItem {
- text: qsTr("Hide Window")
- onTriggered: hideWindow()
+ text: qsTr("Toggle Window")
+ onTriggered: window.visible ? hideWindow() : showWindow()
}
Platform.MenuItem {
text: qsTr("Quit")
onTriggered: Qt.quit()
}
}
-
- onActivated: showWindow()
}
Controller {
@@ -74,102 +73,6 @@ ApplicationWindow {
onActivated: Qt.quit()
}
- Dialog {
- property bool busy: false
-
- width: 360
- x: (window.width - width) / 2
- y: (window.height - height) / 2
-
- id: loginDialog
-
- parent: ApplicationWindow.overlay
-
- title: "Login"
-
- contentItem: ColumnLayout {
- AutoTextField {
- Layout.fillWidth: true
-
- id: serverField
-
- placeholderText: "Server Address"
- text: "https://matrix.org"
- }
-
- AutoTextField {
- Layout.fillWidth: true
-
- id: usernameField
-
- placeholderText: "Username"
-
- onAccepted: passwordField.forceActiveFocus()
- }
-
- AutoTextField {
- Layout.fillWidth: true
-
- id: passwordField
-
- placeholderText: "Password"
- echoMode: TextInput.Password
-
- onAccepted: loginDialog.doLogin()
- }
- }
-
- footer: DialogButtonBox {
- Button {
- text: "Cancel"
- flat: true
- enabled: !loginDialog.busy
-
- onClicked: loginDialog.close()
- }
-
- Button {
- text: "OK"
- flat: true
- enabled: !loginDialog.busy
-
- onClicked: loginDialog.doLogin()
- }
-
- ToolTip {
- id: loginButtonTooltip
-
- }
- }
-
- onVisibleChanged: {
- if (visible) spectralController.onErrorOccured.connect(showError)
- else spectralController.onErrorOccured.disconnect(showError)
- }
-
- function showError(error, detail) {
- loginDialog.busy = false
- loginButtonTooltip.text = error + ": " + detail
- loginButtonTooltip.open()
- }
-
- function doLogin() {
- if (!(serverField.text.startsWith("http") && serverField.text.includes("://"))) {
- loginButtonTooltip.text = "Server address should start with http(s)://"
- loginButtonTooltip.open()
- return
- }
-
- loginDialog.busy = true
- spectralController.loginWithCredentials(serverField.text, usernameField.text, passwordField.text)
-
- spectralController.connectionAdded.connect(function(conn) {
- busy = false
- loginDialog.close()
- })
- }
- }
-
Dialog {
anchors.centerIn: parent
@@ -267,7 +170,7 @@ ApplicationWindow {
color: MPalette.lighter
}
- onClicked: loginDialog.open()
+ onClicked: loginDialog.createObject(ApplicationWindow.overlay).open()
}
}
@@ -294,7 +197,7 @@ ApplicationWindow {
RippleEffect {
anchors.fill: parent
- onPrimaryClicked: joinRoomDialog.open()
+ onPrimaryClicked: joinRoomDialog.createObject(ApplicationWindow.overlay).open()
}
}
@@ -321,7 +224,7 @@ ApplicationWindow {
RippleEffect {
anchors.fill: parent
- onPrimaryClicked: createRoomDialog.open()
+ onPrimaryClicked: createRoomDialog.createObject(ApplicationWindow.overlay).open()
}
}
@@ -433,66 +336,22 @@ ApplicationWindow {
}
}
- Dialog {
- anchors.centerIn: parent
- width: 360
+ Component {
+ id: loginDialog
- id: joinRoomDialog
-
- title: "Start a Chat"
-
- contentItem: ColumnLayout {
- AutoTextField {
- Layout.fillWidth: true
-
- id: identifierField
-
- placeholderText: "Room Alias/User ID"
- }
- }
-
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- onAccepted: {
- var identifier = identifierField.text
- var firstChar = identifier.charAt(0)
- if (firstChar == "@") {
- spectralController.createDirectChat(spectralController.connection, identifier)
- } else if (firstChar == "!" || firstChar == "#") {
- spectralController.joinRoom(spectralController.connection, identifier)
- }
- }
+ LoginDialog {}
}
- Dialog {
- anchors.centerIn: parent
- width: 360
+ Component {
+ id: joinRoomDialog
+ JoinRoomDialog {}
+ }
+
+ Component {
id: createRoomDialog
- title: "Create a Room"
-
- contentItem: ColumnLayout {
- AutoTextField {
- Layout.fillWidth: true
-
- id: roomNameField
-
- placeholderText: "Room Name"
- }
-
- AutoTextField {
- Layout.fillWidth: true
-
- id: roomTopicField
-
- placeholderText: "Room Topic"
- }
- }
-
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- onAccepted: spectralController.createRoom(spectralController.connection, roomNameField.text, roomTopicField.text)
+ CreateRoomDialog {}
}
Drawer {
diff --git a/res.qrc b/res.qrc
index 63748cb..bdc2d16 100644
--- a/res.qrc
+++ b/res.qrc
@@ -44,5 +44,13 @@
imports/Spectral/Setting/Palette.qml
imports/Spectral/Component/Timeline/FileDelegate.qml
imports/Spectral/Component/FullScreenImage.qml
+ imports/Spectral/Dialog/qmldir
+ imports/Spectral/Dialog/RoomSettingsDialog.qml
+ imports/Spectral/Dialog/UserDetailDialog.qml
+ imports/Spectral/Dialog/MessageSourceDialog.qml
+ imports/Spectral/Dialog/LoginDialog.qml
+ imports/Spectral/Dialog/CreateRoomDialog.qml
+ imports/Spectral/Dialog/JoinRoomDialog.qml
+ imports/Spectral/Dialog/InviteUserDialog.qml
diff --git a/src/controller.cpp b/src/controller.cpp
index 4080262..d305f38 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -7,6 +7,7 @@
#include "events/eventcontent.h"
#include "events/roommessageevent.h"
+#include "csapi/account-data.h"
#include "csapi/joining.h"
#include "csapi/logout.h"
diff --git a/src/controller.h b/src/controller.h
index f31cc08..1dc208a 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -3,9 +3,9 @@
#include "connection.h"
#include "notifications/manager.h"
+#include "room.h"
#include "settings.h"
#include "user.h"
-#include "room.h"
#include
#include
@@ -54,13 +54,16 @@ class Controller : public QObject {
}
Connection* connection() {
- if (m_connection.isNull()) return nullptr;
+ if (m_connection.isNull())
+ return nullptr;
return m_connection;
}
void setConnection(Connection* conn) {
- if (!conn) return;
- if (conn == m_connection) return;
+ if (!conn)
+ return;
+ if (conn == m_connection)
+ return;
m_connection = conn;
emit connectionChanged();
}
@@ -100,9 +103,12 @@ class Controller : public QObject {
void createDirectChat(Connection* c, const QString& userID);
void copyToClipboard(const QString& text);
void playAudio(QUrl localFile);
- void postNotification(const QString& roomId, const QString& eventId,
- const QString& roomName, const QString& senderName,
- const QString& text, const QImage& icon);
+ void postNotification(const QString& roomId,
+ const QString& eventId,
+ const QString& roomName,
+ const QString& senderName,
+ const QString& text,
+ const QImage& icon);
};
#endif // CONTROLLER_H
diff --git a/src/main.cpp b/src/main.cpp
index fb949ef..cdee88c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,7 +23,7 @@
using namespace QMatrixClient;
-int main(int argc, char *argv[]) {
+int main(int argc, char* argv[]) {
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(Q_OS_FREEBSD)
if (qgetenv("QT_SCALE_FACTOR").size() == 0) {
QSettings settings("ENCOM", "Spectral");
@@ -59,11 +59,13 @@ int main(int argc, char *argv[]) {
"RoomMessageEvent", "ENUM");
qmlRegisterUncreatableType("Spectral", 0, 1, "RoomType", "ENUM");
- qRegisterMetaType("User*");
- qRegisterMetaType("Room*");
+ qRegisterMetaType("User*");
+ qRegisterMetaType("const User*");
+ qRegisterMetaType("Room*");
+ qRegisterMetaType("Connection*");
qRegisterMetaType("MessageEventType");
- qRegisterMetaType("SpectralRoom*");
- qRegisterMetaType("SpectralUser*");
+ qRegisterMetaType("SpectralRoom*");
+ qRegisterMetaType("SpectralUser*");
#if defined(BUNDLE_FONT)
QFontDatabase::addApplicationFont(":/assets/font/roboto.ttf");
@@ -73,12 +75,13 @@ int main(int argc, char *argv[]) {
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/imports");
- ImageProvider *m_provider = new ImageProvider();
+ ImageProvider* m_provider = new ImageProvider();
engine.rootContext()->setContextProperty("imageProvider", m_provider);
engine.addImageProvider(QLatin1String("mxc"), m_provider);
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
- if (engine.rootObjects().isEmpty()) return -1;
+ if (engine.rootObjects().isEmpty())
+ return -1;
return app.exec();
}
diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp
index 30c3eca..40c15d4 100644
--- a/src/messageeventmodel.cpp
+++ b/src/messageeventmodel.cpp
@@ -41,7 +41,7 @@ QHash MessageEventModel::roleNames() const {
return roles;
}
-MessageEventModel::MessageEventModel(QObject *parent)
+MessageEventModel::MessageEventModel(QObject* parent)
: QAbstractListModel(parent), m_currentRoom(nullptr) {
using namespace QMatrixClient;
qmlRegisterType();
@@ -52,8 +52,9 @@ MessageEventModel::MessageEventModel(QObject *parent)
MessageEventModel::~MessageEventModel() {}
-void MessageEventModel::setRoom(SpectralRoom *room) {
- if (room == m_currentRoom) return;
+void MessageEventModel::setRoom(SpectralRoom* room) {
+ if (room == m_currentRoom)
+ return;
beginResetModel();
if (m_currentRoom) {
@@ -96,8 +97,9 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
connect(m_currentRoom, &Room::pendingEventAdded, this,
&MessageEventModel::endInsertRows);
connect(m_currentRoom, &Room::pendingEventAboutToMerge, this,
- [this](RoomEvent *, int i) {
- if (i == 0) return; // No need to move anything, just refresh
+ [this](RoomEvent*, int i) {
+ if (i == 0)
+ return; // No need to move anything, just refresh
movingEvent = true;
// Reverse i because row 0 is bottommost in the model
@@ -131,7 +133,7 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
refreshEventRoles(lastReadEventId, {ReadMarkerRole});
});
connect(m_currentRoom, &Room::replacedEvent, this,
- [this](const RoomEvent *newEvent) {
+ [this](const RoomEvent* newEvent) {
refreshLastUserEvents(refreshEvent(newEvent->id()) -
timelineBaseIndex());
});
@@ -144,10 +146,15 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
connect(m_currentRoom, &Room::fileTransferCancelled, this,
&MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::readMarkerForUserMoved, this,
- [=](User *, QString fromEventId, QString toEventId) {
+ [=](User*, QString fromEventId, QString toEventId) {
refreshEventRoles(fromEventId, {UserMarkerRole});
refreshEventRoles(toEventId, {UserMarkerRole});
});
+ connect(m_currentRoom->connection(), &Connection::ignoredUsersListChanged,
+ this, [=] {
+ beginResetModel();
+ endResetModel();
+ });
qDebug() << "Connected to room" << room->id() << "as"
<< room->localUser()->id();
} else
@@ -155,23 +162,25 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
endResetModel();
}
-int MessageEventModel::refreshEvent(const QString &eventId) {
+int MessageEventModel::refreshEvent(const QString& eventId) {
return refreshEventRoles(eventId);
}
-void MessageEventModel::refreshRow(int row) { refreshEventRoles(row); }
+void MessageEventModel::refreshRow(int row) {
+ refreshEventRoles(row);
+}
int MessageEventModel::timelineBaseIndex() const {
return m_currentRoom ? int(m_currentRoom->pendingEvents().size()) : 0;
}
-void MessageEventModel::refreshEventRoles(int row, const QVector &roles) {
+void MessageEventModel::refreshEventRoles(int row, const QVector& roles) {
const auto idx = index(row);
emit dataChanged(idx, idx, roles);
}
-int MessageEventModel::refreshEventRoles(const QString &eventId,
- const QVector &roles) {
+int MessageEventModel::refreshEventRoles(const QString& eventId,
+ const QVector& roles) {
const auto it = m_currentRoom->findInTimeline(eventId);
if (it == m_currentRoom->timelineEdge()) {
qWarning() << "Trying to refresh inexistent event:" << eventId;
@@ -183,15 +192,16 @@ int MessageEventModel::refreshEventRoles(const QString &eventId,
return row;
}
-inline bool hasValidTimestamp(const QMatrixClient::TimelineItem &ti) {
+inline bool hasValidTimestamp(const QMatrixClient::TimelineItem& ti) {
return ti->timestamp().isValid();
}
QDateTime MessageEventModel::makeMessageTimestamp(
- const QMatrixClient::Room::rev_iter_t &baseIt) const {
- const auto &timeline = m_currentRoom->messageEvents();
+ const QMatrixClient::Room::rev_iter_t& baseIt) const {
+ const auto& timeline = m_currentRoom->messageEvents();
auto ts = baseIt->event()->timestamp();
- if (ts.isValid()) return ts;
+ if (ts.isValid())
+ return ts;
// The event is most likely redacted or just invalid.
// Look for the nearest date around and slap zero time to it.
@@ -210,11 +220,14 @@ QDateTime MessageEventModel::makeMessageTimestamp(
QString MessageEventModel::renderDate(QDateTime timestamp) const {
auto date = timestamp.toLocalTime().date();
- if (date == QDate::currentDate()) return tr("Today");
- if (date == QDate::currentDate().addDays(-1)) return tr("Yesterday");
+ if (date == QDate::currentDate())
+ return tr("Today");
+ if (date == QDate::currentDate().addDays(-1))
+ return tr("Yesterday");
if (date == QDate::currentDate().addDays(-2))
return tr("The day before yesterday");
- if (date > QDate::currentDate().addDays(-7)) return date.toString("dddd");
+ if (date > QDate::currentDate().addDays(-7))
+ return date.toString("dddd");
return date.toString(Qt::DefaultLocaleShortDate);
}
@@ -222,8 +235,8 @@ void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) {
if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow)
return;
- const auto &timelineBottom = m_currentRoom->messageEvents().rbegin();
- const auto &lastSender = (*(timelineBottom + baseTimelineRow))->senderId();
+ const auto& timelineBottom = m_currentRoom->messageEvents().rbegin();
+ const auto& lastSender = (*(timelineBottom + baseTimelineRow))->senderId();
const auto limit = timelineBottom + std::min(baseTimelineRow + 10,
m_currentRoom->timelineSize());
for (auto it = timelineBottom + std::max(baseTimelineRow - 10, 0);
@@ -235,12 +248,13 @@ void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) {
}
}
-int MessageEventModel::rowCount(const QModelIndex &parent) const {
- if (!m_currentRoom || parent.isValid()) return 0;
+int MessageEventModel::rowCount(const QModelIndex& parent) const {
+ if (!m_currentRoom || parent.isValid())
+ return 0;
return m_currentRoom->timelineSize();
}
-QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
+QVariant MessageEventModel::data(const QModelIndex& idx, int role) const {
const auto row = idx.row();
if (!m_currentRoom || row < 0 ||
@@ -253,7 +267,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
std::max(0, row - timelineBaseIndex());
const auto pendingIt = m_currentRoom->pendingEvents().crbegin() +
std::min(row, timelineBaseIndex());
- const auto &evt = isPending ? **pendingIt : **timelineIt;
+ const auto& evt = isPending ? **pendingIt : **timelineIt;
if (role == Qt::DisplayRole) {
return utils::removeReply(m_currentRoom->eventToString(evt, Qt::RichText));
@@ -282,7 +296,8 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
return e->hasFileContent() ? "file" : "message";
}
}
- if (evt.isStateEvent()) return "state";
+ if (evt.isStateEvent())
+ return "state";
return "other";
}
@@ -298,7 +313,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
if (role == ContentTypeRole) {
if (auto e = eventCast(&evt)) {
- const auto &contentType = e->mimeType().name();
+ const auto& contentType = e->mimeType().name();
return contentType == "text/plain" ? QStringLiteral("text/html")
: contentType;
}
@@ -323,19 +338,27 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
};
}
- if (role == HighlightRole) return m_currentRoom->isEventHighlighted(&evt);
+ if (role == HighlightRole)
+ return m_currentRoom->isEventHighlighted(&evt);
if (role == ReadMarkerRole)
return evt.id() == lastReadEventId && row > timelineBaseIndex();
if (role == SpecialMarksRole) {
- if (isPending) return pendingIt->deliveryStatus();
+ if (isPending)
+ return pendingIt->deliveryStatus();
- if (is(evt)) return EventStatus::Hidden;
- if (evt.isRedacted()) return EventStatus::Hidden;
+ if (is(evt))
+ return EventStatus::Hidden;
+ if (evt.isRedacted())
+ return EventStatus::Hidden;
if (evt.isStateEvent() &&
- static_cast(evt).repeatsState())
+ static_cast(evt).repeatsState())
+ return EventStatus::Hidden;
+
+ if (m_currentRoom->connection()->isIgnored(
+ m_currentRoom->user(evt.senderId())))
return EventStatus::Hidden;
return EventStatus::Normal;
@@ -351,7 +374,8 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
}
if (role == AnnotationRole)
- if (isPending) return pendingIt->annotation();
+ if (isPending)
+ return pendingIt->annotation();
if (role == TimeRole || role == SectionRole) {
auto ts =
@@ -361,8 +385,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
if (role == UserMarkerRole) {
QVariantList variantList;
- for (User *user : m_currentRoom->usersAtEventId(evt.id())) {
- if (user == m_currentRoom->localUser()) continue;
+ for (User* user : m_currentRoom->usersAtEventId(evt.id())) {
+ if (user == m_currentRoom->localUser())
+ continue;
variantList.append(QVariant::fromValue(user));
}
return variantList;
@@ -370,22 +395,24 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
if (role == ReplyEventIdRole || role == ReplyDisplayRole ||
role == ReplyAuthorRole) {
- const QString &replyEventId = evt.contentJson()["m.relates_to"]
+ const QString& replyEventId = evt.contentJson()["m.relates_to"]
.toObject()["m.in_reply_to"]
.toObject()["event_id"]
.toString();
- if (replyEventId.isEmpty()) return {};
+ if (replyEventId.isEmpty())
+ return {};
const auto replyIt = m_currentRoom->findInTimeline(replyEventId);
- if (replyIt == m_currentRoom->timelineEdge()) return {};
+ if (replyIt == m_currentRoom->timelineEdge())
+ return {};
const auto& replyEvt = **replyIt;
switch (role) {
case ReplyEventIdRole:
return replyEventId;
case ReplyDisplayRole:
- return utils::removeReply(m_currentRoom->eventToString(replyEvt, Qt::RichText));
+ return utils::removeReply(
+ m_currentRoom->eventToString(replyEvt, Qt::RichText));
case ReplyAuthorRole:
- return QVariant::fromValue(
- m_currentRoom->user(replyEvt.senderId()));
+ return QVariant::fromValue(m_currentRoom->user(replyEvt.senderId()));
}
return {};
}
@@ -394,7 +421,8 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
role == AboveAuthorRole || role == AboveTimeRole)
for (auto r = row + 1; r < rowCount(); ++r) {
auto i = index(r);
- if (data(i, SpecialMarksRole) != EventStatus::Hidden) switch (role) {
+ if (data(i, SpecialMarksRole) != EventStatus::Hidden)
+ switch (role) {
case AboveEventTypeRole:
return data(i, EventTypeRole);
case AboveSectionRole:
@@ -409,7 +437,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
return {};
}
-int MessageEventModel::eventIDToIndex(const QString &eventID) {
+int MessageEventModel::eventIDToIndex(const QString& eventID) {
const auto it = m_currentRoom->findInTimeline(eventID);
if (it == m_currentRoom->timelineEdge()) {
qWarning() << "Trying to find inexistent event:" << eventID;
diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp
index 7934c2a..772f709 100644
--- a/src/spectralroom.cpp
+++ b/src/spectralroom.cpp
@@ -6,6 +6,7 @@
#include "csapi/content-repo.h"
#include "csapi/leaving.h"
#include "csapi/typing.h"
+#include "events/accountdataevents.h"
#include "events/typingevent.h"
#include
diff --git a/src/userlistmodel.cpp b/src/userlistmodel.cpp
index 15cff77..ff7e697 100644
--- a/src/userlistmodel.cpp
+++ b/src/userlistmodel.cpp
@@ -14,14 +14,16 @@ UserListModel::UserListModel(QObject* parent)
: QAbstractListModel(parent), m_currentRoom(nullptr) {}
void UserListModel::setRoom(QMatrixClient::Room* room) {
- if (m_currentRoom == room) return;
+ if (m_currentRoom == room)
+ return;
using namespace QMatrixClient;
beginResetModel();
if (m_currentRoom) {
m_currentRoom->disconnect(this);
-// m_currentRoom->connection()->disconnect(this);
- for (User* user : m_users) user->disconnect(this);
+ // m_currentRoom->connection()->disconnect(this);
+ for (User* user : m_users)
+ user->disconnect(this);
m_users.clear();
}
m_currentRoom = room;
@@ -49,12 +51,14 @@ void UserListModel::setRoom(QMatrixClient::Room* room) {
}
QMatrixClient::User* UserListModel::userAt(QModelIndex index) {
- if (index.row() < 0 || index.row() >= m_users.size()) return nullptr;
+ if (index.row() < 0 || index.row() >= m_users.size())
+ return nullptr;
return m_users.at(index.row());
}
QVariant UserListModel::data(const QModelIndex& index, int role) const {
- if (!index.isValid()) return QVariant();
+ if (!index.isValid())
+ return QVariant();
if (index.row() >= m_users.count()) {
qDebug()
@@ -71,12 +75,16 @@ QVariant UserListModel::data(const QModelIndex& index, int role) const {
if (role == AvatarRole) {
return user->avatarMediaId();
}
+ if (role == ObjectRole) {
+ return QVariant::fromValue(user);
+ }
return QVariant();
}
int UserListModel::rowCount(const QModelIndex& parent) const {
- if (parent.isValid()) return 0;
+ if (parent.isValid())
+ return 0;
return m_users.count();
}
@@ -111,7 +119,8 @@ void UserListModel::refresh(QMatrixClient::User* user, QVector roles) {
void UserListModel::avatarChanged(QMatrixClient::User* user,
const QMatrixClient::Room* context) {
- if (context == m_currentRoom) refresh(user, {AvatarRole});
+ if (context == m_currentRoom)
+ refresh(user, {AvatarRole});
}
int UserListModel::findUserPos(User* user) const {
@@ -127,5 +136,6 @@ QHash UserListModel::roleNames() const {
roles[NameRole] = "name";
roles[UserIDRole] = "userId";
roles[AvatarRole] = "avatar";
+ roles[ObjectRole] = "user";
return roles;
}
diff --git a/src/userlistmodel.h b/src/userlistmodel.h
index fd01a5e..25db08a 100644
--- a/src/userlistmodel.h
+++ b/src/userlistmodel.h
@@ -17,7 +17,12 @@ class UserListModel : public QAbstractListModel {
Q_PROPERTY(
QMatrixClient::Room* room READ room WRITE setRoom NOTIFY roomChanged)
public:
- enum EventRoles { NameRole = Qt::UserRole + 1, UserIDRole, AvatarRole };
+ enum EventRoles {
+ NameRole = Qt::UserRole + 1,
+ UserIDRole,
+ AvatarRole,
+ ObjectRole
+ };
using User = QMatrixClient::User;