diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d5510b3..5d6ceb5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,7 +333,6 @@ set(SRC_FILES src/ui/MxcAnimatedImage.cpp src/ui/MxcMediaProxy.cpp src/ui/NhekoCursorShape.cpp - src/ui/NhekoEventObserver.cpp src/ui/NhekoDropArea.cpp src/ui/NhekoGlobalObject.cpp src/ui/RoomSettings.cpp @@ -530,7 +529,6 @@ set(MOC_HEADERS src/ui/MxcAnimatedImage.h src/ui/MxcMediaProxy.h src/ui/NhekoCursorShape.h - src/ui/NhekoEventObserver.h src/ui/NhekoGlobalObject.h src/ui/RoomSettings.h src/ui/Theme.h @@ -645,7 +643,7 @@ qt_add_translations(nheko RESOURCE_PREFIX "/translations" TS_FILES ${LANG_TS_SRC set_property(TARGET nheko PROPERTY AUTOMOC ON) qt_add_qml_module(nheko - URI im.nheko2 + URI im.nheko RESOURCE_PREFIX "/" VERSION 1.0 SOURCES @@ -749,6 +747,10 @@ qt_target_qml_sources(nheko qml/TimelineView.qml ) +if (NOT COMPILE_QML) + set_target_properties(nheko PROPERTIES QT_QMLCACHEGEN_ARGUMENTS "--only-bytecode") +endif() + if(APPLE) target_link_libraries (nheko PRIVATE Qt5::MacExtras) @@ -764,7 +766,7 @@ else() target_compile_definitions(nheko PRIVATE NHEKO_FLATPAK) endif() endif() -target_include_directories(nheko PRIVATE src includes third_party/blurhash third_party/cpp-httplib-0.5.12 src/timeline src/ui) +target_include_directories(nheko PRIVATE src includes third_party/blurhash third_party/cpp-httplib-0.5.12 src/timeline src/ui src/encryption src/emoji src/voip) # Fixup bundled keychain include dirs if (USE_BUNDLED_QTKEYCHAIN) diff --git a/qml/Avatar.qml b/qml/Avatar.qml index 593decb7..72ebdc14 100644 --- a/qml/Avatar.qml +++ b/qml/Avatar.qml @@ -7,7 +7,7 @@ import "./ui" import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko AbstractButton { id: avatar @@ -98,7 +98,7 @@ AbstractButton { } } - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/ChatPage.qml b/qml/ChatPage.qml index 559fbc11..d8ae7feb 100644 --- a/qml/ChatPage.qml +++ b/qml/ChatPage.qml @@ -7,7 +7,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.3 import "components" -import im.nheko 1.0 +import im.nheko // this needs to be last import QtQml 2.15 diff --git a/qml/CommunitiesList.qml b/qml/CommunitiesList.qml index 64929e17..3f8163c9 100644 --- a/qml/CommunitiesList.qml +++ b/qml/CommunitiesList.qml @@ -9,7 +9,7 @@ import QtQml 2.12 import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko Page { id: communitySidebar diff --git a/qml/Completer.qml b/qml/Completer.qml index 41c28894..a45c184c 100644 --- a/qml/Completer.qml +++ b/qml/Completer.qml @@ -7,7 +7,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import im.nheko -import im.nheko2 +import im.nheko import "./ui/" diff --git a/qml/ElidedLabel.qml b/qml/ElidedLabel.qml index f5d10a21..cb2c058b 100644 --- a/qml/ElidedLabel.qml +++ b/qml/ElidedLabel.qml @@ -5,7 +5,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.5 -import im.nheko 1.0 +import im.nheko Label { id: root diff --git a/qml/EncryptionIndicator.qml b/qml/EncryptionIndicator.qml index 0b8fe089..c97b20f1 100644 --- a/qml/EncryptionIndicator.qml +++ b/qml/EncryptionIndicator.qml @@ -6,7 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.1 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko Image { id: stateImg diff --git a/qml/ForwardCompleter.qml b/qml/ForwardCompleter.qml index 07a6c548..3ff8ca19 100644 --- a/qml/ForwardCompleter.qml +++ b/qml/ForwardCompleter.qml @@ -6,7 +6,7 @@ import "./delegates/" import QtQuick 2.9 import QtQuick.Controls 2.3 -import im.nheko 1.0 +import im.nheko Popup { id: forwardMessagePopup diff --git a/qml/ImageButton.qml b/qml/ImageButton.qml index b55c423e..ff94d8b0 100644 --- a/qml/ImageButton.qml +++ b/qml/ImageButton.qml @@ -6,7 +6,7 @@ import "./ui" import QtQuick 2.3 import QtQuick.Controls 2.3 -import im.nheko 1.0 // for cursor shape +import im.nheko AbstractButton { id: button @@ -31,7 +31,7 @@ AbstractButton { fillMode: Image.PreserveAspectFit } - CursorShape { + NhekoCursorShape { id: mouseArea anchors.fill: parent diff --git a/qml/MatrixText.qml b/qml/MatrixText.qml index a3dec527..ccad597c 100644 --- a/qml/MatrixText.qml +++ b/qml/MatrixText.qml @@ -5,7 +5,7 @@ import QtQuick 2.5 import QtQuick.Controls 2.3 -import im.nheko 1.0 +import im.nheko TextEdit { id: r @@ -29,9 +29,8 @@ TextEdit { TimelineManager.fixImageRendering(r.textDocument, r); } - CursorShape { + NhekoCursorShape { id: cs - anchors.fill: parent cursorShape: hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } diff --git a/qml/MatrixTextField.qml b/qml/MatrixTextField.qml index 5563d0ab..071174ee 100644 --- a/qml/MatrixTextField.qml +++ b/qml/MatrixTextField.qml @@ -6,7 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import im.nheko 1.0 +import im.nheko ColumnLayout { diff --git a/qml/MessageInput.qml b/qml/MessageInput.qml index 8950d48b..d15185f2 100644 --- a/qml/MessageInput.qml +++ b/qml/MessageInput.qml @@ -9,7 +9,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko Rectangle { id: inputBar diff --git a/qml/MessageView.qml b/qml/MessageView.qml index c4c1acc5..1b058d7b 100644 --- a/qml/MessageView.qml +++ b/qml/MessageView.qml @@ -13,7 +13,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko Item { @@ -326,7 +326,7 @@ Item { leftPadding: 0 rightPadding: 0 - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/NhekoBusyIndicator.qml b/qml/NhekoBusyIndicator.qml index f4731d47..aec5f2c9 100644 --- a/qml/NhekoBusyIndicator.qml +++ b/qml/NhekoBusyIndicator.qml @@ -6,7 +6,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko BusyIndicator { id: control diff --git a/qml/NotificationWarning.qml b/qml/NotificationWarning.qml index fba16e93..02e64c5a 100644 --- a/qml/NotificationWarning.qml +++ b/qml/NotificationWarning.qml @@ -6,7 +6,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Item { implicitHeight: warningRect.visible ? warningDisplay.implicitHeight : 0 diff --git a/qml/PrivacyScreen.qml b/qml/PrivacyScreen.qml index 300ddc79..71159076 100644 --- a/qml/PrivacyScreen.qml +++ b/qml/PrivacyScreen.qml @@ -6,7 +6,7 @@ //import QtGraphicalEffects 1.0 import QtQuick 2.12 import QtQuick.Window 2.2 -import im.nheko 1.0 +import im.nheko Item { id: privacyScreen diff --git a/qml/QuickSwitcher.qml b/qml/QuickSwitcher.qml index e0d8d687..29fa1f4a 100644 --- a/qml/QuickSwitcher.qml +++ b/qml/QuickSwitcher.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Popup { id: quickSwitcher diff --git a/qml/Reactions.qml b/qml/Reactions.qml index 7fbf15b0..f0f7c39e 100644 --- a/qml/Reactions.qml +++ b/qml/Reactions.qml @@ -5,7 +5,7 @@ import QtQuick 2.6 import QtQuick.Controls 2.2 -import im.nheko 1.0 +import im.nheko // This class is for showing Reactions in the timeline row, not for // adding new reactions via the emoji picker diff --git a/qml/ReplyPopup.qml b/qml/ReplyPopup.qml index 68d98d63..5f685909 100644 --- a/qml/ReplyPopup.qml +++ b/qml/ReplyPopup.qml @@ -7,7 +7,7 @@ import "./delegates/" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Rectangle { id: replyPopup diff --git a/qml/RoomList.qml b/qml/RoomList.qml index 660c0edb..3474d70d 100644 --- a/qml/RoomList.qml +++ b/qml/RoomList.qml @@ -10,7 +10,7 @@ import QtQml 2.12 import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko Page { //leftPadding: Nheko.paddingSmall diff --git a/qml/Root.qml b/qml/Root.qml index da4e903e..634b09ea 100644 --- a/qml/Root.qml +++ b/qml/Root.qml @@ -15,8 +15,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.3 import QtQuick.Window 2.15 -import im.nheko 1.0 -import im.nheko.EmojiModel 1.0 +import im.nheko Pane { id: timelineRoot diff --git a/qml/SelfVerificationCheck.qml b/qml/SelfVerificationCheck.qml index 70d464e8..772eb17b 100644 --- a/qml/SelfVerificationCheck.qml +++ b/qml/SelfVerificationCheck.qml @@ -8,7 +8,7 @@ import Qt.labs.platform 1.1 as P import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko Item { visible: false diff --git a/qml/StatusIndicator.qml b/qml/StatusIndicator.qml index e1ed3b29..4290c2c4 100644 --- a/qml/StatusIndicator.qml +++ b/qml/StatusIndicator.qml @@ -5,7 +5,7 @@ import QtQuick 2.5 import QtQuick.Controls 2.1 -import im.nheko 1.0 +import im.nheko ImageButton { id: indicator diff --git a/qml/TimelineRow.qml b/qml/TimelineRow.qml index c2cfd772..a8165b1d 100644 --- a/qml/TimelineRow.qml +++ b/qml/TimelineRow.qml @@ -9,7 +9,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko AbstractButton { id: r @@ -164,7 +164,7 @@ AbstractButton { duration: r.relatedEventCacheBuster, fromModel(Room.Duration) ?? 0 roomTopic: r.relatedEventCacheBuster, fromModel(Room.RoomTopic) ?? "" roomName: r.relatedEventCacheBuster, fromModel(Room.RoomName) ?? "" - callType: r.relatedEventCacheBuster, fromModel(Room.CallType) ?? "" + callType: r.relatedEventCacheBuster, fromModel(Room.Voip) ?? "" encryptionError: r.relatedEventCacheBuster, fromModel(Room.EncryptionError) ?? 0 relatedEventCacheBuster: r.relatedEventCacheBuster, fromModel(Room.RelatedEventCacheBuster) ?? 0 } diff --git a/qml/TimelineView.qml b/qml/TimelineView.qml index 02396b82..3eb5d618 100644 --- a/qml/TimelineView.qml +++ b/qml/TimelineView.qml @@ -15,8 +15,7 @@ import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 import QtQuick.Window 2.13 import im.nheko -import im.nheko2 -import im.nheko.EmojiModel 1.0 +import im.nheko Item { id: timelineView @@ -98,7 +97,7 @@ Item { } Loader { - source: CallManager.isOnCall && CallManager.callType != CallType.VOICE ? "voip/VideoCall.qml" : "" + source: CallManager.isOnCall && CallManager.callType != Voip.VOICE ? "voip/VideoCall.qml" : "" onLoaded: TimelineManager.setVideoCallItem() } @@ -231,7 +230,7 @@ Item { horizontalAlignment: TextEdit.AlignHCenter onLinkActivated: Nheko.openLink(link) - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } diff --git a/qml/ToggleButton.qml b/qml/ToggleButton.qml index 98950b8a..40c429cf 100644 --- a/qml/ToggleButton.qml +++ b/qml/ToggleButton.qml @@ -6,7 +6,7 @@ import QtQuick 2.5 import QtQuick 2.12 import QtQuick.Controls 2.12 -import im.nheko 1.0 +import im.nheko Switch { id: toggleButton diff --git a/qml/TopBar.qml b/qml/TopBar.qml index 9aa17cf6..92a3fe78 100644 --- a/qml/TopBar.qml +++ b/qml/TopBar.qml @@ -8,7 +8,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko import "./delegates" @@ -26,7 +26,7 @@ Pane { property string directChatOtherUserId: room ? room.directChatOtherUserId : "" Layout.fillWidth: true - implicitHeight: topLayout.height + Nheko.paddingMedium * 2 + implicitHeight: topBarC.height + Nheko.paddingMedium * 2 z: 3 padding: 0 @@ -71,8 +71,7 @@ Pane { contentItem: Item { GridLayout { - id: topLayout - + id: topBarC anchors.left: parent.left anchors.right: parent.right anchors.margins: Nheko.paddingMedium @@ -344,7 +343,7 @@ Pane { } } - CursorShape { + NhekoCursorShape { anchors.fill: parent anchors.bottomMargin: (pinnedMessages.visible ? pinnedMessages.height : 0) + (widgets.visible ? widgets.height : 0) cursorShape: Qt.PointingHandCursor diff --git a/qml/TypingIndicator.qml b/qml/TypingIndicator.qml index 353369c2..64f8b02a 100644 --- a/qml/TypingIndicator.qml +++ b/qml/TypingIndicator.qml @@ -6,7 +6,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Item { implicitHeight: Math.max(fontMetrics.height * 1.2, typingDisplay.height) diff --git a/qml/UploadBox.qml b/qml/UploadBox.qml index dd7fd943..433d750a 100644 --- a/qml/UploadBox.qml +++ b/qml/UploadBox.qml @@ -8,7 +8,7 @@ import "./ui" import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko Page { id: uploadPopup diff --git a/qml/components/AdaptiveLayout.qml b/qml/components/AdaptiveLayout.qml index 8e3c0e3d..a71862ef 100644 --- a/qml/components/AdaptiveLayout.qml +++ b/qml/components/AdaptiveLayout.qml @@ -6,7 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.12 -import im.nheko 1.0 +import im.nheko Container { //Component.onCompleted: { @@ -88,7 +88,7 @@ Container { x: parent.preferredWidth z: 3 - CursorShape { + NhekoCursorShape { height: parent.height width: container.splitterGrabMargin * 2 x: -container.splitterGrabMargin diff --git a/qml/components/AvatarListTile.qml b/qml/components/AvatarListTile.qml index 93f10d06..10652fe1 100644 --- a/qml/components/AvatarListTile.qml +++ b/qml/components/AvatarListTile.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Rectangle { id: tile diff --git a/qml/components/FlatButton.qml b/qml/components/FlatButton.qml index 69f60a42..4a5ed9df 100644 --- a/qml/components/FlatButton.qml +++ b/qml/components/FlatButton.qml @@ -7,7 +7,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko // FIXME(Nico): Don't use hardcoded colors. Button { diff --git a/qml/components/MainWindowDialog.qml b/qml/components/MainWindowDialog.qml index c5abb564..dcdcebfc 100644 --- a/qml/components/MainWindowDialog.qml +++ b/qml/components/MainWindowDialog.qml @@ -7,7 +7,7 @@ import Qt.labs.platform 1.1 as P import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko Dialog { default property alias inner: scroll.data diff --git a/qml/components/TextButton.qml b/qml/components/TextButton.qml index 68299332..bd83c668 100644 --- a/qml/components/TextButton.qml +++ b/qml/components/TextButton.qml @@ -6,7 +6,7 @@ import "../ui" import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 // for cursor shape +import im.nheko // for cursor shape AbstractButton { id: button @@ -33,7 +33,7 @@ AbstractButton { horizontalAlignment: Text.AlignHCenter } - CursorShape { + NhekoCursorShape { id: mouseArea anchors.fill: parent diff --git a/qml/delegates/Encrypted.qml b/qml/delegates/Encrypted.qml index 7f16003a..37efe16c 100644 --- a/qml/delegates/Encrypted.qml +++ b/qml/delegates/Encrypted.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Rectangle { id: r diff --git a/qml/delegates/FileMessage.qml b/qml/delegates/FileMessage.qml index 42516973..d90858be 100644 --- a/qml/delegates/FileMessage.qml +++ b/qml/delegates/FileMessage.qml @@ -5,7 +5,7 @@ import QtQuick 2.12 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Item { required property string eventId @@ -51,7 +51,7 @@ Item { gesturePolicy: TapHandler.ReleaseWithinBounds } - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/delegates/ImageMessage.qml b/qml/delegates/ImageMessage.qml index 80317b0e..67131684 100644 --- a/qml/delegates/ImageMessage.qml +++ b/qml/delegates/ImageMessage.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.3 -import im.nheko 1.0 +import im.nheko AbstractButton { required property int type diff --git a/qml/delegates/MessageDelegate.qml b/qml/delegates/MessageDelegate.qml index f965b298..b159ab41 100644 --- a/qml/delegates/MessageDelegate.qml +++ b/qml/delegates/MessageDelegate.qml @@ -7,7 +7,7 @@ import QtQuick 2.6 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.2 import im.nheko -import im.nheko2 +import im.nheko Item { id: d diff --git a/qml/delegates/NoticeMessage.qml b/qml/delegates/NoticeMessage.qml index 8736c081..3aa95185 100644 --- a/qml/delegates/NoticeMessage.qml +++ b/qml/delegates/NoticeMessage.qml @@ -4,7 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import QtQuick 2.5 -import im.nheko 1.0 +import im.nheko TextMessage { diff --git a/qml/delegates/Pill.qml b/qml/delegates/Pill.qml index 87a848c2..c148a212 100644 --- a/qml/delegates/Pill.qml +++ b/qml/delegates/Pill.qml @@ -5,7 +5,7 @@ import QtQuick 2.5 import QtQuick.Controls 2.1 -import im.nheko 1.0 +import im.nheko Label { property bool isStateEvent diff --git a/qml/delegates/Placeholder.qml b/qml/delegates/Placeholder.qml index fc5e8d1f..7600ee26 100644 --- a/qml/delegates/Placeholder.qml +++ b/qml/delegates/Placeholder.qml @@ -4,7 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import ".." -import im.nheko 1.0 +import im.nheko MatrixText { required property string typeString diff --git a/qml/delegates/PlayableMediaMessage.qml b/qml/delegates/PlayableMediaMessage.qml index edd78d4b..fec49e9a 100644 --- a/qml/delegates/PlayableMediaMessage.qml +++ b/qml/delegates/PlayableMediaMessage.qml @@ -9,7 +9,7 @@ import QtMultimedia import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Item { id: content diff --git a/qml/delegates/Redacted.qml b/qml/delegates/Redacted.qml index fb881828..ff96938c 100644 --- a/qml/delegates/Redacted.qml +++ b/qml/delegates/Redacted.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Rectangle{ diff --git a/qml/delegates/Reply.qml b/qml/delegates/Reply.qml index 55607952..d9a17f18 100644 --- a/qml/delegates/Reply.qml +++ b/qml/delegates/Reply.qml @@ -8,7 +8,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko import "../" AbstractButton { @@ -43,7 +43,7 @@ AbstractButton { implicitHeight: replyContainer.height implicitWidth: visible? colorLine.width+Math.max(replyContainer.implicitWidth,userName_.fullTextWidth) : 0 // visible? seems to be causing issues - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/delegates/TextMessage.qml b/qml/delegates/TextMessage.qml index 41a56f5d..db643340 100644 --- a/qml/delegates/TextMessage.qml +++ b/qml/delegates/TextMessage.qml @@ -43,7 +43,7 @@ MatrixText { enabled: !Settings.mobileMode font.pointSize: (Settings.enlargeEmojiOnlyMessages && isOnlyEmoji > 0 && isOnlyEmoji < 4) ? Settings.fontSize * 3 : Settings.fontSize - CursorShape { + NhekoCursorShape { enabled: isReply anchors.fill: parent cursorShape: Qt.PointingHandCursor diff --git a/qml/device-verification/DeviceVerification.qml b/qml/device-verification/DeviceVerification.qml index 1ba50cd7..9d1ccf4e 100644 --- a/qml/device-verification/DeviceVerification.qml +++ b/qml/device-verification/DeviceVerification.qml @@ -6,7 +6,7 @@ import QtQuick 2.10 import QtQuick.Controls 2.3 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: dialog diff --git a/qml/device-verification/DigitVerification.qml b/qml/device-verification/DigitVerification.qml index 8c12a84b..e7c82882 100644 --- a/qml/device-verification/DigitVerification.qml +++ b/qml/device-verification/DigitVerification.qml @@ -6,7 +6,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: qsTr("Verification Code") diff --git a/qml/device-verification/EmojiVerification.qml b/qml/device-verification/EmojiVerification.qml index cbb4fd30..3131b9d2 100644 --- a/qml/device-verification/EmojiVerification.qml +++ b/qml/device-verification/EmojiVerification.qml @@ -6,7 +6,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: qsTr("Verification Code") diff --git a/qml/device-verification/Failed.qml b/qml/device-verification/Failed.qml index d640ab35..c0313cba 100644 --- a/qml/device-verification/Failed.qml +++ b/qml/device-verification/Failed.qml @@ -6,7 +6,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: qsTr("Verification failed") diff --git a/qml/device-verification/NewVerificationRequest.qml b/qml/device-verification/NewVerificationRequest.qml index 46016d61..31668a19 100644 --- a/qml/device-verification/NewVerificationRequest.qml +++ b/qml/device-verification/NewVerificationRequest.qml @@ -6,7 +6,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: flow.sender ? qsTr("Send Verification Request") : qsTr("Received Verification Request") diff --git a/qml/device-verification/Success.qml b/qml/device-verification/Success.qml index 2df1ebf6..38db3ab2 100644 --- a/qml/device-verification/Success.qml +++ b/qml/device-verification/Success.qml @@ -6,7 +6,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: qsTr("Successful Verification") diff --git a/qml/device-verification/Waiting.qml b/qml/device-verification/Waiting.qml index 0f44bd65..7f941182 100644 --- a/qml/device-verification/Waiting.qml +++ b/qml/device-verification/Waiting.qml @@ -7,7 +7,7 @@ import "../ui" import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 -import im.nheko 1.0 +import im.nheko Pane { property string title: qsTr("Waiting for other party…") diff --git a/qml/dialogs/CreateDirect.qml b/qml/dialogs/CreateDirect.qml index 72ea2f55..f68011a9 100644 --- a/qml/dialogs/CreateDirect.qml +++ b/qml/dialogs/CreateDirect.qml @@ -9,7 +9,7 @@ import QtQuick.Window 2.13 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.3 import QtQml.Models 2.15 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: createDirectRoot diff --git a/qml/dialogs/CreateRoom.qml b/qml/dialogs/CreateRoom.qml index 15cf94a8..941715c6 100644 --- a/qml/dialogs/CreateRoom.qml +++ b/qml/dialogs/CreateRoom.qml @@ -8,7 +8,7 @@ import QtQuick 2.15 import QtQuick.Window 2.13 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: createRoomRoot diff --git a/qml/dialogs/HiddenEventsDialog.qml b/qml/dialogs/HiddenEventsDialog.qml index e0e79604..1954aac4 100644 --- a/qml/dialogs/HiddenEventsDialog.qml +++ b/qml/dialogs/HiddenEventsDialog.qml @@ -6,7 +6,7 @@ import ".." import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: hiddenEventsDialog diff --git a/qml/dialogs/ImageOverlay.qml b/qml/dialogs/ImageOverlay.qml index dff96f35..31d579e1 100644 --- a/qml/dialogs/ImageOverlay.qml +++ b/qml/dialogs/ImageOverlay.qml @@ -7,7 +7,7 @@ import QtQuick.Window 2.15 import ".." -import im.nheko 1.0 +import im.nheko Window { id: imageOverlay diff --git a/qml/dialogs/ImagePackEditorDialog.qml b/qml/dialogs/ImagePackEditorDialog.qml index 93169234..cd270f9d 100644 --- a/qml/dialogs/ImagePackEditorDialog.qml +++ b/qml/dialogs/ImagePackEditorDialog.qml @@ -9,7 +9,7 @@ import Qt.labs.platform 1.1 import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: win diff --git a/qml/dialogs/ImagePackSettingsDialog.qml b/qml/dialogs/ImagePackSettingsDialog.qml index 776cd4d5..b17e4b05 100644 --- a/qml/dialogs/ImagePackSettingsDialog.qml +++ b/qml/dialogs/ImagePackSettingsDialog.qml @@ -8,7 +8,7 @@ import "../components" import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: win diff --git a/qml/dialogs/InputDialog.qml b/qml/dialogs/InputDialog.qml index 421d85bc..a383018f 100644 --- a/qml/dialogs/InputDialog.qml +++ b/qml/dialogs/InputDialog.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: inputDialog diff --git a/qml/dialogs/InviteDialog.qml b/qml/dialogs/InviteDialog.qml index 0ee00769..5b161263 100644 --- a/qml/dialogs/InviteDialog.qml +++ b/qml/dialogs/InviteDialog.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: inviteDialogRoot @@ -154,7 +154,7 @@ ApplicationWindow { } - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/dialogs/JoinRoomDialog.qml b/qml/dialogs/JoinRoomDialog.qml index d8e6bfd3..a4f77b65 100644 --- a/qml/dialogs/JoinRoomDialog.qml +++ b/qml/dialogs/JoinRoomDialog.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: joinRoomRoot diff --git a/qml/dialogs/LeaveRoomDialog.qml b/qml/dialogs/LeaveRoomDialog.qml index d64b2d31..d2ef2691 100644 --- a/qml/dialogs/LeaveRoomDialog.qml +++ b/qml/dialogs/LeaveRoomDialog.qml @@ -6,7 +6,7 @@ import Qt.labs.platform 1.1 as P import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 +import im.nheko P.MessageDialog { id: leaveRoomRoot diff --git a/qml/dialogs/LogoutDialog.qml b/qml/dialogs/LogoutDialog.qml index fb5b39f6..0589ff22 100644 --- a/qml/dialogs/LogoutDialog.qml +++ b/qml/dialogs/LogoutDialog.qml @@ -6,7 +6,7 @@ import Qt.labs.platform 1.1 as P import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 +import im.nheko P.MessageDialog { id: logoutRoot diff --git a/qml/dialogs/PhoneNumberInputDialog.qml b/qml/dialogs/PhoneNumberInputDialog.qml index 882014ee..8d88b3c5 100644 --- a/qml/dialogs/PhoneNumberInputDialog.qml +++ b/qml/dialogs/PhoneNumberInputDialog.qml @@ -8,7 +8,7 @@ import ".." import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: inputDialog diff --git a/qml/dialogs/RawMessageDialog.qml b/qml/dialogs/RawMessageDialog.qml index 8ee7d32e..e8d08543 100644 --- a/qml/dialogs/RawMessageDialog.qml +++ b/qml/dialogs/RawMessageDialog.qml @@ -5,7 +5,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: rawMessageRoot diff --git a/qml/dialogs/ReadReceipts.qml b/qml/dialogs/ReadReceipts.qml index 60eb256d..e3460dc7 100644 --- a/qml/dialogs/ReadReceipts.qml +++ b/qml/dialogs/ReadReceipts.qml @@ -7,7 +7,7 @@ import ".." import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: readReceiptsRoot @@ -110,7 +110,7 @@ ApplicationWindow { } - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/dialogs/RoomDirectory.qml b/qml/dialogs/RoomDirectory.qml index e8eebeef..4b7cb007 100644 --- a/qml/dialogs/RoomDirectory.qml +++ b/qml/dialogs/RoomDirectory.qml @@ -8,7 +8,7 @@ import "../ui" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: roomDirectoryWindow diff --git a/qml/dialogs/RoomMembers.qml b/qml/dialogs/RoomMembers.qml index 823868bb..a8137977 100644 --- a/qml/dialogs/RoomMembers.qml +++ b/qml/dialogs/RoomMembers.qml @@ -9,7 +9,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko ApplicationWindow { id: roomMembersRoot @@ -187,7 +187,7 @@ ApplicationWindow { } - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/qml/dialogs/RoomSettings.qml b/qml/dialogs/RoomSettings.qml index 0089796b..7d66913f 100644 --- a/qml/dialogs/RoomSettings.qml +++ b/qml/dialogs/RoomSettings.qml @@ -10,7 +10,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko +import im.nheko ApplicationWindow { id: roomSettingsDialog @@ -165,7 +166,7 @@ ApplicationWindow { onSingleTapped: TimelineManager.openRoomMembers(Rooms.getRoomById(roomSettings.roomId)) } - CursorShape { + NhekoCursorShape { cursorShape: Qt.PointingHandCursor anchors.fill: parent } @@ -196,7 +197,7 @@ ApplicationWindow { horizontalAlignment: TextEdit.AlignHCenter onLinkActivated: Nheko.openLink(link) - CursorShape { + NhekoCursorShape { anchors.fill: parent cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } diff --git a/qml/dialogs/UserProfile.qml b/qml/dialogs/UserProfile.qml index 46fe48f7..512c5f5f 100644 --- a/qml/dialogs/UserProfile.qml +++ b/qml/dialogs/UserProfile.qml @@ -10,7 +10,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.13 -import im.nheko 1.0 +import im.nheko +import im.nheko ApplicationWindow { id: userProfileDialog diff --git a/qml/emoji/EmojiPicker.qml b/qml/emoji/EmojiPicker.qml index fe5c505b..13bb90f2 100644 --- a/qml/emoji/EmojiPicker.qml +++ b/qml/emoji/EmojiPicker.qml @@ -8,8 +8,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import QtQuick.Window 2.15 -import im.nheko 1.0 -import im.nheko.EmojiModel 1.0 +import im.nheko Menu { id: emojiPopup @@ -203,56 +202,56 @@ Menu { // Display the normal categories Repeater { - model: ListModel { + model: [ // TODO: Would like to get 'simple' icons for the categories - ListElement { - image: ":/icons/icons/emoji-categories/people.svg" + { + image: ":/icons/icons/emoji-categories/people.svg", category: Emoji.Category.People - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/nature.svg" + { + image: ":/icons/icons/emoji-categories/nature.svg", category: Emoji.Category.Nature - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/foods.svg" + { + image: ":/icons/icons/emoji-categories/foods.svg", category: Emoji.Category.Food - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/activity.svg" + { + image: ":/icons/icons/emoji-categories/activity.svg", category: Emoji.Category.Activity - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/travel.svg" + { + image: ":/icons/icons/emoji-categories/travel.svg", category: Emoji.Category.Travel - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/objects.svg" + { + image: ":/icons/icons/emoji-categories/objects.svg", category: Emoji.Category.Objects - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/symbols.svg" + { + image: ":/icons/icons/emoji-categories/symbols.svg", category: Emoji.Category.Symbols - } + }, - ListElement { - image: ":/icons/icons/emoji-categories/flags.svg" + { + image: ":/icons/icons/emoji-categories/flags.svg", category: Emoji.Category.Flags } - } + ] delegate: AbstractButton { Layout.preferredWidth: 36 Layout.preferredHeight: 36 hoverEnabled: true ToolTip.text: { - switch (model.category) { + switch (modelData.category) { case Emoji.Category.People: return qsTr('People'); case Emoji.Category.Nature: @@ -274,7 +273,7 @@ Menu { ToolTip.visible: hovered onClicked: { //emojiPopup.model.category = model.category; - gridView.positionViewAtIndex(emojiPopup.model.sourceModel.categoryToIndex(model.category), GridView.Beginning); + gridView.positionViewAtIndex(emojiPopup.model.sourceModel.categoryToIndex(modelData.category), GridView.Beginning); } MouseArea { @@ -295,14 +294,14 @@ Menu { mipmap: true sourceSize.width: 32 * Screen.devicePixelRatio sourceSize.height: 32 * Screen.devicePixelRatio - source: "image://colorimage/" + model.image + "?" + (hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText) + source: "image://colorimage/" + modelData.image + "?" + (hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText) } background: Rectangle { anchors.fill: parent - color: emojiPopup.model.category === model.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : 'transparent' + color: emojiPopup.model.category === modelData.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : 'transparent' radius: 5 - border.color: emojiPopup.model.category === model.category ? timelineRoot.palette.highlight : 'transparent' + border.color: emojiPopup.model.category === modelData.category ? timelineRoot.palette.highlight : 'transparent' } } diff --git a/qml/emoji/StickerPicker.qml b/qml/emoji/StickerPicker.qml index 56bf4f4b..f2332af5 100644 --- a/qml/emoji/StickerPicker.qml +++ b/qml/emoji/StickerPicker.qml @@ -7,8 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 -import im.nheko 1.0 -import im.nheko.EmojiModel 1.0 +import im.nheko Menu { id: stickerPopup diff --git a/qml/pages/LoginPage.qml b/qml/pages/LoginPage.qml index 1c5a8983..1941c577 100644 --- a/qml/pages/LoginPage.qml +++ b/qml/pages/LoginPage.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko import "../components/" import "../ui/" import "../" diff --git a/qml/pages/RegisterPage.qml b/qml/pages/RegisterPage.qml index eaec2941..8054396e 100644 --- a/qml/pages/RegisterPage.qml +++ b/qml/pages/RegisterPage.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko import "../components/" import "../ui/" import "../" diff --git a/qml/pages/UserSettingsPage.qml b/qml/pages/UserSettingsPage.qml index 0602f0ef..5e74624c 100644 --- a/qml/pages/UserSettingsPage.qml +++ b/qml/pages/UserSettingsPage.qml @@ -11,7 +11,7 @@ import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.15 import im.nheko -import im.nheko2 +import im.nheko Rectangle { id: userSettingsDialog diff --git a/qml/pages/WelcomePage.qml b/qml/pages/WelcomePage.qml index 19bbba21..468e95e6 100644 --- a/qml/pages/WelcomePage.qml +++ b/qml/pages/WelcomePage.qml @@ -6,7 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.2 import QtQuick.Window 2.15 -import im.nheko 1.0 +import im.nheko import "../components/" ColumnLayout { diff --git a/qml/ui/NhekoSlider.qml b/qml/ui/NhekoSlider.qml index f8b3cd3b..4fa90304 100644 --- a/qml/ui/NhekoSlider.qml +++ b/qml/ui/NhekoSlider.qml @@ -5,7 +5,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 +import im.nheko Slider { id: control diff --git a/qml/ui/Snackbar.qml b/qml/ui/Snackbar.qml index fc6d68e4..5480d4ea 100644 --- a/qml/ui/Snackbar.qml +++ b/qml/ui/Snackbar.qml @@ -4,7 +4,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import im.nheko 1.0 +import im.nheko Popup { id: snackbar diff --git a/qml/ui/media/MediaControls.qml b/qml/ui/media/MediaControls.qml index 986b8f2e..0398b98f 100644 --- a/qml/ui/media/MediaControls.qml +++ b/qml/ui/media/MediaControls.qml @@ -9,7 +9,7 @@ import QtMultimedia 5.15 import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import im.nheko 1.0 +import im.nheko Rectangle { id: control diff --git a/qml/voip/ActiveCallBar.qml b/qml/voip/ActiveCallBar.qml index a8a65421..38f17d68 100644 --- a/qml/voip/ActiveCallBar.qml +++ b/qml/voip/ActiveCallBar.qml @@ -7,7 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Rectangle { visible: CallManager.isOnCall @@ -17,7 +17,7 @@ Rectangle { MouseArea { anchors.fill: parent onClicked: { - if (CallManager.callType != CallType.VOICE) + if (CallManager.callType != Voip.VOICE) stackLayout.currentIndex = stackLayout.currentIndex ? 0 : 1; } @@ -59,7 +59,7 @@ Rectangle { states: [ State { name: "VOICE" - when: CallManager.callType == CallType.VOICE + when: CallManager.callType == Voip.VOICE PropertyChanges { target: callTypeIcon @@ -69,7 +69,7 @@ Rectangle { }, State { name: "VIDEO" - when: CallManager.callType == CallType.VIDEO + when: CallManager.callType == Voip.VIDEO PropertyChanges { target: callTypeIcon @@ -79,7 +79,7 @@ Rectangle { }, State { name: "SCREEN" - when: CallManager.callType == CallType.SCREEN + when: CallManager.callType == Voip.SCREEN PropertyChanges { target: callTypeIcon @@ -101,7 +101,7 @@ Rectangle { states: [ State { name: "OFFERSENT" - when: CallManager.callState == WebRTCState.OFFERSENT + when: CallManager.callState == Voip.OFFERSENT PropertyChanges { target: callStateLabel @@ -111,7 +111,7 @@ Rectangle { }, State { name: "CONNECTING" - when: CallManager.callState == WebRTCState.CONNECTING + when: CallManager.callState == Voip.CONNECTING PropertyChanges { target: callStateLabel @@ -121,7 +121,7 @@ Rectangle { }, State { name: "ANSWERSENT" - when: CallManager.callState == WebRTCState.ANSWERSENT + when: CallManager.callState == Voip.ANSWERSENT PropertyChanges { target: callStateLabel @@ -131,7 +131,7 @@ Rectangle { }, State { name: "CONNECTED" - when: CallManager.callState == WebRTCState.CONNECTED + when: CallManager.callState == Voip.CONNECTED PropertyChanges { target: callStateLabel @@ -145,13 +145,13 @@ Rectangle { PropertyChanges { target: stackLayout - currentIndex: CallManager.callType != CallType.VOICE ? 1 : 0 + currentIndex: CallManager.callType != Voip.VOICE ? 1 : 0 } }, State { name: "DISCONNECTED" - when: CallManager.callState == WebRTCState.DISCONNECTED + when: CallManager.callState == Voip.DISCONNECTED PropertyChanges { target: callStateLabel @@ -177,7 +177,7 @@ Rectangle { } interval: 1000 - running: CallManager.callState == WebRTCState.CONNECTED + running: CallManager.callState == Voip.CONNECTED repeat: true onTriggered: { var d = new Date(); @@ -191,7 +191,7 @@ Rectangle { Label { Layout.leftMargin: 16 - visible: CallManager.callType == CallType.SCREEN && CallManager.callState == WebRTCState.CONNECTED + visible: CallManager.callType == Voip.SCREEN && CallManager.callState == Voip.CONNECTED text: qsTr("You are screen sharing") font.pointSize: fontMetrics.font.pointSize * 1.1 color: "#000000" diff --git a/qml/voip/CallDevices.qml b/qml/voip/CallDevices.qml index 0874cd6a..9bad6127 100644 --- a/qml/voip/CallDevices.qml +++ b/qml/voip/CallDevices.qml @@ -6,7 +6,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Popup { modal: true @@ -45,7 +45,7 @@ Popup { } RowLayout { - visible: CallManager.callType == CallType.VIDEO && CallManager.cameras.length > 0 + visible: CallManager.callType == Voip.VIDEO && CallManager.cameras.length > 0 Image { Layout.preferredWidth: 22 diff --git a/qml/voip/CallInvite.qml b/qml/voip/CallInvite.qml index b2643bac..4b811f74 100644 --- a/qml/voip/CallInvite.qml +++ b/qml/voip/CallInvite.qml @@ -7,7 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Popup { id: callInv @@ -64,7 +64,7 @@ Popup { Layout.bottomMargin: callInv.height / 25 Image { - property string image: CallManager.callType == CallType.VIDEO ? ":/icons/icons/ui/video.svg" : ":/icons/icons/ui/place-call.svg" + property string image: CallManager.callType == Voip.VIDEO ? ":/icons/icons/ui/video.svg" : ":/icons/icons/ui/place-call.svg" Layout.alignment: Qt.AlignCenter Layout.preferredWidth: callInv.height / 10 @@ -74,7 +74,7 @@ Popup { Label { Layout.alignment: Qt.AlignCenter - text: CallManager.callType == CallType.VIDEO ? qsTr("Video Call") : qsTr("Voice Call") + text: CallManager.callType == Voip.VIDEO ? qsTr("Video Call") : qsTr("Voice Call") font.pointSize: fontMetrics.font.pointSize * 2 color: timelineRoot.palette.windowText } @@ -108,7 +108,7 @@ Popup { } RowLayout { - visible: CallManager.callType == CallType.VIDEO && CallManager.cameras.length > 0 + visible: CallManager.callType == Voip.VIDEO && CallManager.cameras.length > 0 Layout.alignment: Qt.AlignCenter Image { @@ -171,7 +171,7 @@ Popup { RoundButton { id: acceptButton - property string image: CallManager.callType == CallType.VIDEO ? ":/icons/icons/ui/video.svg" : ":/icons/icons/ui/place-call.svg" + property string image: CallManager.callType == Voip.VIDEO ? ":/icons/icons/ui/video.svg" : ":/icons/icons/ui/place-call.svg" implicitWidth: buttonLayout.buttonSize implicitHeight: buttonLayout.buttonSize diff --git a/qml/voip/CallInviteBar.qml b/qml/voip/CallInviteBar.qml index 36d05160..a6a4d96d 100644 --- a/qml/voip/CallInviteBar.qml +++ b/qml/voip/CallInviteBar.qml @@ -7,7 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Rectangle { visible: CallManager.haveCallInvite && !Settings.mobileMode @@ -58,12 +58,12 @@ Rectangle { Layout.leftMargin: 4 Layout.preferredWidth: 24 Layout.preferredHeight: 24 - source: CallManager.callType == CallType.VIDEO ? "qrc:/icons/icons/ui/video.svg" : "qrc:/icons/icons/ui/place-call.svg" + source: CallManager.callType == Voip.CallType.VIDEO ? "qrc:/icons/icons/ui/video.svg" : "qrc:/icons/icons/ui/place-call.svg" } Label { font.pointSize: fontMetrics.font.pointSize * 1.1 - text: CallManager.callType == CallType.VIDEO ? qsTr("Video Call") : qsTr("Voice Call") + text: CallManager.callType == Voip.VIDEO ? qsTr("Video Call") : qsTr("Voice Call") color: "#000000" } @@ -89,7 +89,7 @@ Rectangle { Button { Layout.rightMargin: 4 - icon.source: CallManager.callType == CallType.VIDEO ? "qrc:/icons/icons/ui/video.svg" : "qrc:/icons/icons/ui/place-call.svg" + icon.source: CallManager.callType == Voip.VIDEO ? "qrc:/icons/icons/ui/video.svg" : "qrc:/icons/icons/ui/place-call.svg" text: qsTr("Accept") palette: timelineRoot.palette onClicked: { @@ -110,7 +110,7 @@ Rectangle { timelineRoot.destroyOnClose(dialog); return ; } - if (CallManager.callType == CallType.VIDEO && CallManager.cameras.length > 0 && !CallManager.cameras.includes(Settings.camera)) { + if (CallManager.callType == Voip.VIDEO && CallManager.cameras.length > 0 && !CallManager.cameras.includes(Settings.camera)) { var dialog = deviceError.createObject(timelineRoot, { "errorString": qsTr("Unknown camera: %1").arg(Settings.camera), "image": ":/icons/icons/ui/video.svg" diff --git a/qml/voip/DeviceError.qml b/qml/voip/DeviceError.qml index 48cbfc44..751d1763 100644 --- a/qml/voip/DeviceError.qml +++ b/qml/voip/DeviceError.qml @@ -6,7 +6,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Popup { property string errorString diff --git a/qml/voip/PlaceCall.qml b/qml/voip/PlaceCall.qml index 20af94df..ddbc880e 100644 --- a/qml/voip/PlaceCall.qml +++ b/qml/voip/PlaceCall.qml @@ -7,7 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Popup { modal: true @@ -83,7 +83,7 @@ Popup { onClicked: { if (buttonLayout.validateMic()) { Settings.microphone = micCombo.currentText; - CallManager.sendInvite(room.roomId, CallType.VOICE); + CallManager.sendInvite(room.roomId, Voip.VOICE); close(); } } @@ -97,7 +97,7 @@ Popup { if (buttonLayout.validateMic()) { Settings.microphone = micCombo.currentText; Settings.camera = cameraCombo.currentText; - CallManager.sendInvite(room.roomId, CallType.VIDEO); + CallManager.sendInvite(room.roomId, Voip.VIDEO); close(); } } diff --git a/qml/voip/ScreenShare.qml b/qml/voip/ScreenShare.qml index a96601f8..7ece5ddd 100644 --- a/qml/voip/ScreenShare.qml +++ b/qml/voip/ScreenShare.qml @@ -7,7 +7,7 @@ import "../" import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 -import im.nheko 1.0 +import im.nheko Popup { modal: true @@ -132,7 +132,7 @@ Popup { Settings.screenShareRemoteVideo = remoteVideoCheckBox.checked; Settings.screenShareHideCursor = hideCursorCheckBox.checked; - CallManager.sendInvite(room.roomId, CallType.SCREEN, windowCombo.currentIndex); + CallManager.sendInvite(room.roomId, Voip.SCREEN, windowCombo.currentIndex); close(); } } diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h index 6c32667e..ba27a8b4 100644 --- a/src/CacheCryptoStructs.h +++ b/src/CacheCryptoStructs.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include @@ -17,6 +18,8 @@ namespace crypto { Q_NAMESPACE +QML_NAMED_ELEMENT(Crypto) + //! How much a participant is trusted. enum Trust { diff --git a/src/Clipboard.h b/src/Clipboard.h index 65b7e4bd..9be65917 100644 --- a/src/Clipboard.h +++ b/src/Clipboard.h @@ -6,11 +6,15 @@ #pragma once #include +#include #include class Clipboard : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) public: diff --git a/src/ColorImageProvider.cpp b/src/ColorImageProvider.cpp index 74e9eff7..bbb847d0 100644 --- a/src/ColorImageProvider.cpp +++ b/src/ColorImageProvider.cpp @@ -23,10 +23,12 @@ ColorImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &) QColor color(args[1]); QPixmap colorized = source; - QPainter painter(&colorized); - painter.setCompositionMode(QPainter::CompositionMode_SourceIn); - painter.fillRect(colorized.rect(), color); - painter.end(); + if (!source.isNull()) { + QPainter painter(&colorized); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.fillRect(colorized.rect(), color); + painter.end(); + } return colorized; } diff --git a/src/ImagePackListModel.h b/src/ImagePackListModel.h index 43fbcdfb..9725b2fe 100644 --- a/src/ImagePackListModel.h +++ b/src/ImagePackListModel.h @@ -9,10 +9,14 @@ #include #include -class SingleImagePackModel; +#include "SingleImagePackModel.h" + class ImagePackListModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Needs to be instantiated from C++") + Q_PROPERTY(bool containsAccountPack READ containsAccountPack CONSTANT) public: enum Roles diff --git a/src/InviteesModel.h b/src/InviteesModel.h index ac5e215f..ad3c032e 100644 --- a/src/InviteesModel.h +++ b/src/InviteesModel.h @@ -7,6 +7,7 @@ #define INVITEESMODEL_H #include +#include #include class Invitee : public QObject @@ -30,6 +31,8 @@ private: class InviteesModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Needs to be instantiated from C++") Q_PROPERTY(int count READ rowCount NOTIFY countChanged) diff --git a/src/LoginPage.h b/src/LoginPage.h index 47896fda..3a809179 100644 --- a/src/LoginPage.h +++ b/src/LoginPage.h @@ -7,13 +7,10 @@ #pragma once #include +#include #include -namespace mtx { -namespace responses { -struct Login; -} -} +#include struct SSOProvider { @@ -35,6 +32,7 @@ public: class LoginPage : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(Login) Q_PROPERTY(QString mxid READ mxid WRITE setMxid NOTIFY matrixIdChanged) Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index f22bf908..4d2799bf 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -24,13 +24,11 @@ #include "InviteesModel.h" #include "JdenticonProvider.h" #include "Logging.h" -#include "LoginPage.h" #include "MainWindow.h" #include "MatrixClient.h" #include "MemberList.h" #include "MxcImageProvider.h" #include "ReadReceiptsModel.h" -#include "RegisterPage.h" #include "RoomDirectoryModel.h" #include "RoomsModel.h" #include "SingleImagePackModel.h" @@ -43,11 +41,6 @@ #include "encryption/DeviceVerificationFlow.h" #include "encryption/SelfVerificationStatus.h" #include "timeline/TimelineViewManager.h" -#include "ui/HiddenEvents.h" -#include "ui/MxcAnimatedImage.h" -#include "ui/MxcMediaProxy.h" -#include "ui/NhekoCursorShape.h" -#include "ui/NhekoEventObserver.h" #include "ui/NhekoGlobalObject.h" #include "ui/UIA.h" #include "voip/WebRTCSession.h" @@ -79,7 +72,7 @@ MainWindow::MainWindow(QWindow *parent) registerQmlTypes(); setColor(Theme::paletteFromTheme(userSettings_->theme()).window().color()); - setSource(QUrl(QStringLiteral("qrc:///im/nheko2/qml/Root.qml"))); + setSource(QUrl(QStringLiteral("qrc:///im/nheko/qml/Root.qml"))); trayIcon_ = new TrayIcon(QStringLiteral(":/logos/nheko.svg"), this); @@ -126,153 +119,6 @@ MainWindow::MainWindow(QWindow *parent) void MainWindow::registerQmlTypes() { - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType>(); - - qRegisterMetaType>(); - - qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject, - "im.nheko", - 1, - 0, - "MtxEvent", - QStringLiteral("Can't instantiate enum!")); - qmlRegisterUncreatableMetaObject( - olm::staticMetaObject, "im.nheko", 1, 0, "Olm", QStringLiteral("Can't instantiate enum!")); - qmlRegisterUncreatableMetaObject(crypto::staticMetaObject, - "im.nheko", - 1, - 0, - "Crypto", - QStringLiteral("Can't instantiate enum!")); - qmlRegisterUncreatableMetaObject(verification::staticMetaObject, - "im.nheko", - 1, - 0, - "VerificationStatus", - QStringLiteral("Can't instantiate enum!")); - - qmlRegisterType("im.nheko", 1, 0, "CursorShape"); - qmlRegisterType("im.nheko", 1, 0, "EventObserver"); - qmlRegisterType("im.nheko", 1, 0, "MxcAnimatedImage"); - qmlRegisterType("im.nheko", 1, 0, "MxcMedia"); - qmlRegisterType("im.nheko", 1, 0, "RoomDirectoryModel"); - qmlRegisterType("im.nheko", 1, 0, "Login"); - qmlRegisterType("im.nheko", 1, 0, "Registration"); - qmlRegisterType("im.nheko", 1, 0, "HiddenEvents"); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "DeviceVerificationFlow", - QStringLiteral("Can't create verification flow from QML!")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "UserProfileModel", - QStringLiteral("UserProfile needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "MemberList", - QStringLiteral("MemberList needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "RoomSettingsModel", - QStringLiteral("Room Settings needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", 1, 0, "Room", QStringLiteral("Room needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "ImagePackListModel", - QStringLiteral("ImagePackListModel needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "SingleImagePackModel", - QStringLiteral("SingleImagePackModel needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "InviteesModel", - QStringLiteral("InviteesModel needs to be instantiated on the C++ side")); - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "ReadReceiptsProxy", - QStringLiteral("ReadReceiptsProxy needs to be instantiated on the C++ side")); - - qmlRegisterSingletonType( - "im.nheko", 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) -> QObject * { - return new Clipboard(); - }); - qmlRegisterSingletonType( - "im.nheko", 1, 0, "Nheko", [](QQmlEngine *, QJSEngine *) -> QObject * { - return new Nheko(); - }); - qmlRegisterSingletonType( - "im.nheko", 1, 0, "UserSettingsModel", [](QQmlEngine *, QJSEngine *) -> QObject * { - return new UserSettingsModel(); - }); - - qmlRegisterSingletonInstance("im.nheko", 1, 0, "Settings", userSettings_.data()); - - qRegisterMetaType(); - qRegisterMetaType>(); - - qmlRegisterUncreatableType( - "im.nheko", - 1, - 0, - "FilteredCommunitiesModel", - QStringLiteral("Use Communities.filtered() to create a FilteredCommunitiesModel")); - - qmlRegisterType("im.nheko.EmojiModel", 1, 0, "EmojiModel"); - qmlRegisterUncreatableType( - "im.nheko.EmojiModel", 1, 0, "Emoji", QStringLiteral("Used by emoji models")); - qmlRegisterUncreatableType( - "im.nheko", 1, 0, "MediaUpload", QStringLiteral("MediaUploads can not be created in Qml")); - qmlRegisterUncreatableMetaObject(emoji::staticMetaObject, - "im.nheko.EmojiModel", - 1, - 0, - "EmojiCategory", - QStringLiteral("Error: Only enums")); - - qmlRegisterType("im.nheko", 1, 0, "RoomDirectoryModel"); - - qmlRegisterSingletonType( - "im.nheko", 1, 0, "SelfVerificationStatus", [](QQmlEngine *, QJSEngine *) -> QObject * { - auto ptr = new SelfVerificationStatus(); - QObject::connect(ChatPage::instance(), - &ChatPage::initializeEmptyViews, - ptr, - &SelfVerificationStatus::invalidate); - return ptr; - }); - qmlRegisterSingletonInstance("im.nheko", 1, 0, "MainWindow", this); - qmlRegisterSingletonInstance("im.nheko", 1, 0, "UIA", UIA::instance()); - qmlRegisterSingletonInstance( - "im.nheko", 1, 0, "CallManager", ChatPage::instance()->callManager()); - imgProvider = new MxcImageProvider(); engine()->addImageProvider(QStringLiteral("MxcImage"), imgProvider); engine()->addImageProvider(QStringLiteral("colorimage"), new ColorImageProvider()); diff --git a/src/MainWindow.h b/src/MainWindow.h index 3b1ff6f5..fd1e1174 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -40,11 +41,32 @@ class ReCaptcha; class MainWindow : public QQuickView { Q_OBJECT + QML_ELEMENT + QML_SINGLETON public: - explicit MainWindow(QWindow *parent = nullptr); + explicit MainWindow(QWindow *parent); static MainWindow *instance() { return instance_; } + static MainWindow *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } + void saveCurrentWindowSize(); void openJoinRoomDialog(std::function callback); diff --git a/src/MemberList.h b/src/MemberList.h index 2f90e5e8..7579e034 100644 --- a/src/MemberList.h +++ b/src/MemberList.h @@ -7,9 +7,9 @@ #include #include +#include #include - #include "CacheStructs.h" class MemberListBackend : public QAbstractListModel @@ -80,6 +80,8 @@ private: class MemberList : public QSortFilterProxyModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("MemberList needs to be instantiated from C++") Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(int memberCount READ memberCount NOTIFY memberCountChanged) diff --git a/src/ReadReceiptsModel.h b/src/ReadReceiptsModel.h index 23d54051..e3abfb7f 100644 --- a/src/ReadReceiptsModel.h +++ b/src/ReadReceiptsModel.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,8 @@ private: class ReadReceiptsProxy : public QSortFilterProxyModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Needs to be instantiated from C++") Q_PROPERTY(QString eventId READ eventId CONSTANT) Q_PROPERTY(QString roomId READ roomId CONSTANT) diff --git a/src/RegisterPage.h b/src/RegisterPage.h index 67e2a22e..5344ebe5 100644 --- a/src/RegisterPage.h +++ b/src/RegisterPage.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include @@ -15,6 +16,7 @@ class RegisterPage : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(Registration) Q_PROPERTY(QString error READ error NOTIFY errorChanged) Q_PROPERTY(QString hsError READ hsError NOTIFY hsErrorChanged) diff --git a/src/RoomDirectoryModel.h b/src/RoomDirectoryModel.h index 5fcc7b88..ac1c035f 100644 --- a/src/RoomDirectoryModel.h +++ b/src/RoomDirectoryModel.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ struct PublicRooms; class RoomDirectoryModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT Q_PROPERTY(bool loadingMoreRooms READ loadingMoreRooms NOTIFY loadingMoreRoomsChanged) Q_PROPERTY( diff --git a/src/SingleImagePackModel.cpp b/src/SingleImagePackModel.cpp index e0ae7a10..5fb0fa92 100644 --- a/src/SingleImagePackModel.cpp +++ b/src/SingleImagePackModel.cpp @@ -184,8 +184,7 @@ SingleImagePackModel::canEdit() const if (roomid_.empty()) return true; else - return Permissions(QString::fromStdString(roomid_)) - .canChange(qml_mtx_events::ImagePackInRoom); + return Permissions(QString::fromStdString(roomid_)).canChange(MtxEvent::ImagePackInRoom); } void diff --git a/src/SingleImagePackModel.h b/src/SingleImagePackModel.h index b732dcac..d540cac0 100644 --- a/src/SingleImagePackModel.h +++ b/src/SingleImagePackModel.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -16,6 +17,8 @@ class SingleImagePackModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Needs to be instantiated from C++") Q_PROPERTY(QString roomid READ roomid CONSTANT) Q_PROPERTY(QString statekey READ statekey WRITE setStatekey NOTIFY statekeyChanged) diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index bcc45cdc..95dc6f23 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -30,6 +31,8 @@ constexpr int LayoutBottomMargin = LayoutTopMargin; class UserSettings : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(Settings) + QML_SINGLETON Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged) Q_PROPERTY(bool messageHoverHighlight READ messageHoverHighlight WRITE setMessageHoverHighlight @@ -123,6 +126,24 @@ class UserSettings : public QObject public: static QSharedPointer instance(); static void initialize(std::optional profile); + static UserSettings *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance()); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance()->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance().get(), QJSEngine::CppOwnership); + return instance().get(); + } QSettings *qsettings() { return &settings; } @@ -388,6 +409,8 @@ private: class UserSettingsModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + QML_SINGLETON enum Indices { diff --git a/src/emoji/EmojiModel.h b/src/emoji/EmojiModel.h index 0e51eaab..396c3caa 100644 --- a/src/emoji/EmojiModel.h +++ b/src/emoji/EmojiModel.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include #include @@ -20,6 +21,8 @@ namespace emoji { class EmojiModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + public: enum Roles { diff --git a/src/emoji/Provider.h b/src/emoji/Provider.h index f994285e..8b0b0080 100644 --- a/src/emoji/Provider.h +++ b/src/emoji/Provider.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -18,6 +19,8 @@ Q_NAMESPACE struct Emoji { Q_GADGET + QML_ELEMENT + public: enum class Category { diff --git a/src/encryption/DeviceVerificationFlow.h b/src/encryption/DeviceVerificationFlow.h index e980d2ec..3a06917b 100644 --- a/src/encryption/DeviceVerificationFlow.h +++ b/src/encryption/DeviceVerificationFlow.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include @@ -62,6 +63,9 @@ using sas_ptr = std::unique_ptr; class DeviceVerificationFlow : public QObject { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Needs to be instantiated from C++") + Q_PROPERTY(QString state READ state NOTIFY stateChanged) Q_PROPERTY(Error error READ error NOTIFY errorChanged) Q_PROPERTY(QString userId READ getUserId CONSTANT) diff --git a/src/encryption/Olm.h b/src/encryption/Olm.h index 9d99bcf4..52c7a41d 100644 --- a/src/encryption/Olm.h +++ b/src/encryption/Olm.h @@ -5,6 +5,8 @@ #pragma once +#include + #include #include #include @@ -16,6 +18,7 @@ constexpr auto OLM_ALGO = "m.olm.v1.curve25519-aes-sha2"; namespace olm { Q_NAMESPACE +QML_NAMED_ELEMENT(Olm) enum DecryptionErrorCode { diff --git a/src/encryption/SelfVerificationStatus.cpp b/src/encryption/SelfVerificationStatus.cpp index 00e6be49..436d98bf 100644 --- a/src/encryption/SelfVerificationStatus.cpp +++ b/src/encryption/SelfVerificationStatus.cpp @@ -29,6 +29,10 @@ SelfVerificationStatus::SelfVerificationStatus(QObject *o) Qt::UniqueConnection); cache::client()->markUserKeysOutOfDate({http::client()->user_id().to_string()}); }); + connect(ChatPage::instance(), + &ChatPage::initializeEmptyViews, + this, + &SelfVerificationStatus::invalidate); } void diff --git a/src/encryption/SelfVerificationStatus.h b/src/encryption/SelfVerificationStatus.h index 9e20bd9d..adc7645e 100644 --- a/src/encryption/SelfVerificationStatus.h +++ b/src/encryption/SelfVerificationStatus.h @@ -6,10 +6,13 @@ #pragma once #include +#include class SelfVerificationStatus : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(bool hasSSSS READ hasSSSS NOTIFY hasSSSSChanged) diff --git a/src/encryption/VerificationManager.cpp b/src/encryption/VerificationManager.cpp index 8c775948..bb092da6 100644 --- a/src/encryption/VerificationManager.cpp +++ b/src/encryption/VerificationManager.cpp @@ -15,7 +15,9 @@ VerificationManager::VerificationManager(TimelineViewManager *o) : QObject(o) , rooms_(o->rooms()) -{} +{ + instance_ = this; +} static bool isValidTime(std::optional t) diff --git a/src/encryption/VerificationManager.h b/src/encryption/VerificationManager.h index f9844cc0..2e32e343 100644 --- a/src/encryption/VerificationManager.h +++ b/src/encryption/VerificationManager.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -21,9 +22,29 @@ class RoomlistModel; class VerificationManager : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON public: - VerificationManager(TimelineViewManager *o = nullptr); + VerificationManager(TimelineViewManager *o); + static VerificationManager *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } Q_INVOKABLE void removeVerificationFlow(DeviceVerificationFlow *flow); void verifyUser(QString userid); @@ -46,4 +67,6 @@ private: QHash> dvList; bool isInitialSync_ = false; RoomlistModel *rooms_; + + inline static VerificationManager *instance_ = nullptr; }; diff --git a/src/main.cpp b/src/main.cpp index 8067768a..7cc6e1d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -298,11 +298,7 @@ main(int argc, char *argv[]) QStringLiteral(":/translations"))) app.installTranslator(&appTranslator); - MainWindow w; - // QQuickView w; - - // Move the MainWindow to the center - // w.move(screenCenter(w.width(), w.height())); + MainWindow w(nullptr); if (!(settings.lock()->startInTray() && settings.lock()->tray())) w.show(); diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 4f650f49..1a4cb122 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -14,7 +14,9 @@ CommunitiesModel::CommunitiesModel(QObject *parent) : QAbstractListModel(parent) -{} +{ + instance_ = this; +} QHash CommunitiesModel::roleNames() const diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index 5da7d1bd..3e241a40 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,8 @@ class CommunitiesModel; class FilteredCommunitiesModel : public QSortFilterProxyModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Use Communities.filtered() to create a FilteredCommunitiesModel") public: FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent = nullptr); @@ -30,6 +33,9 @@ public: class CommunitiesModel : public QAbstractListModel { Q_OBJECT + QML_NAMED_ELEMENT(Communities) + QML_SINGLETON + Q_PROPERTY(QString currentTagId READ currentTagId WRITE setCurrentTagId NOTIFY currentTagIdChanged RESET resetCurrentTagId) Q_PROPERTY(QStringList tags READ tags NOTIFY tagsChanged) @@ -98,7 +104,26 @@ public: void restoreCollapsed(); }; - CommunitiesModel(QObject *parent = nullptr); + CommunitiesModel(QObject *parent); + static CommunitiesModel *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } + QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override { @@ -154,4 +179,6 @@ private: std::map spaces_; friend class FilteredCommunitiesModel; + + inline static CommunitiesModel *instance_ = nullptr; }; diff --git a/src/timeline/Permissions.cpp b/src/timeline/Permissions.cpp index 917495a2..86879185 100644 --- a/src/timeline/Permissions.cpp +++ b/src/timeline/Permissions.cpp @@ -52,15 +52,15 @@ bool Permissions::canChange(int eventType) { return pl.user_level(http::client()->user_id().to_string()) >= - pl.state_level(to_string( - qml_mtx_events::fromRoomEventType(static_cast(eventType)))); + pl.state_level( + to_string(MtxEvent::fromRoomEventType(static_cast(eventType)))); } bool Permissions::canSend(int eventType) { return pl.user_level(http::client()->user_id().to_string()) >= - pl.event_level(to_string( - qml_mtx_events::fromRoomEventType(static_cast(eventType)))); + pl.event_level( + to_string(MtxEvent::fromRoomEventType(static_cast(eventType)))); } bool diff --git a/src/timeline/PresenceEmitter.h b/src/timeline/PresenceEmitter.h index 6cbfa96a..38606a68 100644 --- a/src/timeline/PresenceEmitter.h +++ b/src/timeline/PresenceEmitter.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include @@ -15,11 +16,33 @@ class PresenceEmitter : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(Presence) + QML_SINGLETON public: - PresenceEmitter(QObject *p = nullptr) + PresenceEmitter(QObject *p) : QObject(p) - {} + { + instance_ = this; + } + static PresenceEmitter *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } void sync(const std::vector> &presences); @@ -28,4 +51,7 @@ public: signals: void presenceChanged(QString userid); + +private: + inline static PresenceEmitter *instance_ = nullptr; }; diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index ea4f6fa8..ca905829 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -821,6 +821,8 @@ FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *pare : QSortFilterProxyModel(parent) , roomlistmodel(model) { + instance_ = this; + this->sortByImportance = UserSettings::instance()->sortByImportance(); setSourceModel(model); setDynamicSortFilter(true); diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index 9546d434..cc751712 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -153,6 +153,9 @@ private: class FilteredRoomlistModel : public QSortFilterProxyModel { Q_OBJECT + QML_NAMED_ELEMENT(Rooms) + QML_SINGLETON + Q_PROPERTY( TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET resetCurrentRoom) Q_PROPERTY(RoomPreview currentRoomPreview READ currentRoomPreview NOTIFY currentRoomChanged @@ -162,6 +165,25 @@ public: bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override; + static FilteredRoomlistModel *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } + public slots: int roomidToIndex(QString roomid) { @@ -231,4 +253,6 @@ private: FilterBy filterType = FilterBy::Nothing; QStringList hiddenTags, hiddenSpaces; bool hideDMs = false; + + inline static FilteredRoomlistModel *instance_ = nullptr; }; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 4309fb24..e7212f31 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -48,169 +48,166 @@ namespace { struct RoomEventType { template - qml_mtx_events::EventType operator()(const mtx::events::Event &e) + MtxEvent::EventType operator()(const mtx::events::Event &e) { - return qml_mtx_events::toRoomEventType(e.type); + return MtxEvent::toRoomEventType(e.type); } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::AudioMessage; + return MtxEvent::EventType::AudioMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::EmoteMessage; + return MtxEvent::EventType::EmoteMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::FileMessage; + return MtxEvent::EventType::FileMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::ImageMessage; + return MtxEvent::EventType::ImageMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::NoticeMessage; + return MtxEvent::EventType::NoticeMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::TextMessage; + return MtxEvent::EventType::TextMessage; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::VideoMessage; + return MtxEvent::EventType::VideoMessage; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationRequest; + return MtxEvent::EventType::KeyVerificationRequest; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationStart; + return MtxEvent::EventType::KeyVerificationStart; } - qml_mtx_events::EventType - operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationMac; + return MtxEvent::EventType::KeyVerificationMac; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationAccept; + return MtxEvent::EventType::KeyVerificationAccept; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationReady; + return MtxEvent::EventType::KeyVerificationReady; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationCancel; + return MtxEvent::EventType::KeyVerificationCancel; } - qml_mtx_events::EventType - operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationKey; + return MtxEvent::EventType::KeyVerificationKey; } - qml_mtx_events::EventType + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::KeyVerificationDone; + return MtxEvent::EventType::KeyVerificationDone; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::Redacted; + return MtxEvent::EventType::Redacted; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::CallInvite; + return MtxEvent::EventType::CallInvite; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::CallAnswer; + return MtxEvent::EventType::CallAnswer; } - qml_mtx_events::EventType operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::CallHangUp; + return MtxEvent::EventType::CallHangUp; } - qml_mtx_events::EventType - operator()(const mtx::events::Event &) + MtxEvent::EventType operator()(const mtx::events::Event &) { - return qml_mtx_events::EventType::CallCandidates; + return MtxEvent::EventType::CallCandidates; } // ::EventType::Type operator()(const Event &e) { return // ::EventType::LocationMessage; } }; } -qml_mtx_events::EventType -qml_mtx_events::toRoomEventType(mtx::events::EventType e) +MtxEvent::EventType +MtxEvent::toRoomEventType(mtx::events::EventType e) { using mtx::events::EventType; switch (e) { case EventType::RoomKeyRequest: - return qml_mtx_events::EventType::KeyRequest; + return MtxEvent::EventType::KeyRequest; case EventType::Reaction: - return qml_mtx_events::EventType::Reaction; + return MtxEvent::EventType::Reaction; case EventType::RoomAliases: - return qml_mtx_events::EventType::Aliases; + return MtxEvent::EventType::Aliases; case EventType::RoomAvatar: - return qml_mtx_events::EventType::Avatar; + return MtxEvent::EventType::Avatar; case EventType::RoomCanonicalAlias: - return qml_mtx_events::EventType::CanonicalAlias; + return MtxEvent::EventType::CanonicalAlias; case EventType::RoomCreate: - return qml_mtx_events::EventType::RoomCreate; + return MtxEvent::EventType::RoomCreate; case EventType::RoomEncrypted: - return qml_mtx_events::EventType::Encrypted; + return MtxEvent::EventType::Encrypted; case EventType::RoomEncryption: - return qml_mtx_events::EventType::Encryption; + return MtxEvent::EventType::Encryption; case EventType::RoomGuestAccess: - return qml_mtx_events::EventType::RoomGuestAccess; + return MtxEvent::EventType::RoomGuestAccess; case EventType::RoomHistoryVisibility: - return qml_mtx_events::EventType::RoomHistoryVisibility; + return MtxEvent::EventType::RoomHistoryVisibility; case EventType::RoomJoinRules: - return qml_mtx_events::EventType::RoomJoinRules; + return MtxEvent::EventType::RoomJoinRules; case EventType::RoomMember: - return qml_mtx_events::EventType::Member; + return MtxEvent::EventType::Member; case EventType::RoomMessage: - return qml_mtx_events::EventType::UnknownMessage; + return MtxEvent::EventType::UnknownMessage; case EventType::RoomName: - return qml_mtx_events::EventType::Name; + return MtxEvent::EventType::Name; case EventType::RoomPowerLevels: - return qml_mtx_events::EventType::PowerLevels; + return MtxEvent::EventType::PowerLevels; case EventType::RoomTopic: - return qml_mtx_events::EventType::Topic; + return MtxEvent::EventType::Topic; case EventType::RoomTombstone: - return qml_mtx_events::EventType::Tombstone; + return MtxEvent::EventType::Tombstone; case EventType::RoomRedaction: - return qml_mtx_events::EventType::Redaction; + return MtxEvent::EventType::Redaction; case EventType::RoomPinnedEvents: - return qml_mtx_events::EventType::PinnedEvents; + return MtxEvent::EventType::PinnedEvents; case EventType::Sticker: - return qml_mtx_events::EventType::Sticker; + return MtxEvent::EventType::Sticker; case EventType::Tag: - return qml_mtx_events::EventType::Tag; + return MtxEvent::EventType::Tag; case EventType::SpaceParent: - return qml_mtx_events::EventType::SpaceParent; + return MtxEvent::EventType::SpaceParent; case EventType::SpaceChild: - return qml_mtx_events::EventType::SpaceChild; + return MtxEvent::EventType::SpaceChild; case EventType::ImagePackInRoom: - return qml_mtx_events::ImagePackInRoom; + return MtxEvent::ImagePackInRoom; case EventType::ImagePackInAccountData: - return qml_mtx_events::ImagePackInAccountData; + return MtxEvent::ImagePackInAccountData; case EventType::ImagePackRooms: - return qml_mtx_events::ImagePackRooms; + return MtxEvent::ImagePackRooms; case EventType::Unsupported: - return qml_mtx_events::EventType::Unsupported; + return MtxEvent::EventType::Unsupported; default: - return qml_mtx_events::EventType::UnknownMessage; + return MtxEvent::EventType::UnknownMessage; } } -qml_mtx_events::EventType +MtxEvent::EventType toRoomEventType(const mtx::events::collections::TimelineEvents &event) { return std::visit(RoomEventType{}, event); @@ -224,122 +221,122 @@ toRoomEventTypeString(const mtx::events::collections::TimelineEvents &event) } mtx::events::EventType -qml_mtx_events::fromRoomEventType(qml_mtx_events::EventType t) +MtxEvent::fromRoomEventType(MtxEvent::EventType t) { switch (t) { // Unsupported event - case qml_mtx_events::Unsupported: + case MtxEvent::Unsupported: return mtx::events::EventType::Unsupported; /// m.room_key_request - case qml_mtx_events::KeyRequest: + case MtxEvent::KeyRequest: return mtx::events::EventType::RoomKeyRequest; /// m.reaction: - case qml_mtx_events::Reaction: + case MtxEvent::Reaction: return mtx::events::EventType::Reaction; /// m.room.aliases - case qml_mtx_events::Aliases: + case MtxEvent::Aliases: return mtx::events::EventType::RoomAliases; /// m.room.avatar - case qml_mtx_events::Avatar: + case MtxEvent::Avatar: return mtx::events::EventType::RoomAvatar; /// m.call.invite - case qml_mtx_events::CallInvite: + case MtxEvent::CallInvite: return mtx::events::EventType::CallInvite; /// m.call.answer - case qml_mtx_events::CallAnswer: + case MtxEvent::CallAnswer: return mtx::events::EventType::CallAnswer; /// m.call.hangup - case qml_mtx_events::CallHangUp: + case MtxEvent::CallHangUp: return mtx::events::EventType::CallHangUp; /// m.call.candidates - case qml_mtx_events::CallCandidates: + case MtxEvent::CallCandidates: return mtx::events::EventType::CallCandidates; /// m.room.canonical_alias - case qml_mtx_events::CanonicalAlias: + case MtxEvent::CanonicalAlias: return mtx::events::EventType::RoomCanonicalAlias; /// m.room.create - case qml_mtx_events::RoomCreate: + case MtxEvent::RoomCreate: return mtx::events::EventType::RoomCreate; /// m.room.encrypted. - case qml_mtx_events::Encrypted: + case MtxEvent::Encrypted: return mtx::events::EventType::RoomEncrypted; /// m.room.encryption. - case qml_mtx_events::Encryption: + case MtxEvent::Encryption: return mtx::events::EventType::RoomEncryption; /// m.room.guest_access - case qml_mtx_events::RoomGuestAccess: + case MtxEvent::RoomGuestAccess: return mtx::events::EventType::RoomGuestAccess; /// m.room.history_visibility - case qml_mtx_events::RoomHistoryVisibility: + case MtxEvent::RoomHistoryVisibility: return mtx::events::EventType::RoomHistoryVisibility; /// m.room.join_rules - case qml_mtx_events::RoomJoinRules: + case MtxEvent::RoomJoinRules: return mtx::events::EventType::RoomJoinRules; /// m.room.member - case qml_mtx_events::Member: + case MtxEvent::Member: return mtx::events::EventType::RoomMember; /// m.room.name - case qml_mtx_events::Name: + case MtxEvent::Name: return mtx::events::EventType::RoomName; /// m.room.power_levels - case qml_mtx_events::PowerLevels: + case MtxEvent::PowerLevels: return mtx::events::EventType::RoomPowerLevels; /// m.room.tombstone - case qml_mtx_events::Tombstone: + case MtxEvent::Tombstone: return mtx::events::EventType::RoomTombstone; /// m.room.topic - case qml_mtx_events::Topic: + case MtxEvent::Topic: return mtx::events::EventType::RoomTopic; /// m.room.redaction - case qml_mtx_events::Redaction: + case MtxEvent::Redaction: return mtx::events::EventType::RoomRedaction; /// m.room.pinned_events - case qml_mtx_events::PinnedEvents: + case MtxEvent::PinnedEvents: return mtx::events::EventType::RoomPinnedEvents; /// m.widget - case qml_mtx_events::Widget: + case MtxEvent::Widget: return mtx::events::EventType::Widget; // m.sticker - case qml_mtx_events::Sticker: + case MtxEvent::Sticker: return mtx::events::EventType::Sticker; // m.tag - case qml_mtx_events::Tag: + case MtxEvent::Tag: return mtx::events::EventType::Tag; // m.space.parent - case qml_mtx_events::SpaceParent: + case MtxEvent::SpaceParent: return mtx::events::EventType::SpaceParent; // m.space.child - case qml_mtx_events::SpaceChild: + case MtxEvent::SpaceChild: return mtx::events::EventType::SpaceChild; /// m.room.message - case qml_mtx_events::AudioMessage: - case qml_mtx_events::EmoteMessage: - case qml_mtx_events::FileMessage: - case qml_mtx_events::ImageMessage: - case qml_mtx_events::LocationMessage: - case qml_mtx_events::NoticeMessage: - case qml_mtx_events::TextMessage: - case qml_mtx_events::VideoMessage: - case qml_mtx_events::Redacted: - case qml_mtx_events::UnknownMessage: - case qml_mtx_events::KeyVerificationRequest: - case qml_mtx_events::KeyVerificationStart: - case qml_mtx_events::KeyVerificationMac: - case qml_mtx_events::KeyVerificationAccept: - case qml_mtx_events::KeyVerificationCancel: - case qml_mtx_events::KeyVerificationKey: - case qml_mtx_events::KeyVerificationDone: - case qml_mtx_events::KeyVerificationReady: + case MtxEvent::AudioMessage: + case MtxEvent::EmoteMessage: + case MtxEvent::FileMessage: + case MtxEvent::ImageMessage: + case MtxEvent::LocationMessage: + case MtxEvent::NoticeMessage: + case MtxEvent::TextMessage: + case MtxEvent::VideoMessage: + case MtxEvent::Redacted: + case MtxEvent::UnknownMessage: + case MtxEvent::KeyVerificationRequest: + case MtxEvent::KeyVerificationStart: + case MtxEvent::KeyVerificationMac: + case MtxEvent::KeyVerificationAccept: + case MtxEvent::KeyVerificationCancel: + case MtxEvent::KeyVerificationKey: + case MtxEvent::KeyVerificationDone: + case MtxEvent::KeyVerificationReady: return mtx::events::EventType::RoomMessage; //! m.image_pack, currently im.ponies.room_emotes - case qml_mtx_events::ImagePackInRoom: + case MtxEvent::ImagePackInRoom: return mtx::events::EventType::ImagePackInRoom; //! m.image_pack, currently im.ponies.user_emotes - case qml_mtx_events::ImagePackInAccountData: + case MtxEvent::ImagePackInAccountData: return mtx::events::EventType::ImagePackInAccountData; //! m.image_pack.rooms, currently im.ponies.emote_rooms - case qml_mtx_events::ImagePackRooms: + case MtxEvent::ImagePackRooms: return mtx::events::EventType::ImagePackRooms; default: return mtx::events::EventType::Unsupported; @@ -676,13 +673,13 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r // only show read receipts for messages not from us if (acc::sender(event) != http::client()->user_id().to_string()) - return qml_mtx_events::Empty; + return MtxEvent::Empty; else if (!id.isEmpty() && id[0] == 'm') - return qml_mtx_events::Sent; + return MtxEvent::Sent; else if (read.contains(id) || containsOthers(cache::readReceipts(id, room_id_))) - return qml_mtx_events::Read; + return MtxEvent::Read; else - return qml_mtx_events::Received; + return MtxEvent::Received; } case IsEdited: return {relations(event).replaces().has_value()}; @@ -1527,14 +1524,14 @@ TimelineModel::saveMedia(const QString &eventId) const auto encryptionInfo = mtx::accessors::file(*event); - qml_mtx_events::EventType eventType = toRoomEventType(*event); + MtxEvent::EventType eventType = toRoomEventType(*event); QString dialogTitle; - if (eventType == qml_mtx_events::EventType::ImageMessage) { + if (eventType == MtxEvent::EventType::ImageMessage) { dialogTitle = tr("Save image"); - } else if (eventType == qml_mtx_events::EventType::VideoMessage) { + } else if (eventType == MtxEvent::EventType::VideoMessage) { dialogTitle = tr("Save video"); - } else if (eventType == qml_mtx_events::EventType::AudioMessage) { + } else if (eventType == MtxEvent::EventType::AudioMessage) { dialogTitle = tr("Save audio"); } else { dialogTitle = tr("Save file"); diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index c52473b1..0dcba51d 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -36,8 +37,9 @@ struct ClaimKeys; } struct RelatedInfo; -namespace qml_mtx_events { +namespace MtxEvent { Q_NAMESPACE +QML_ELEMENT enum EventType { @@ -124,8 +126,8 @@ enum EventType SpaceChild, }; Q_ENUM_NS(EventType) -mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType); -qml_mtx_events::EventType +mtx::events::EventType fromRoomEventType(MtxEvent::EventType); +MtxEvent::EventType toRoomEventType(mtx::events::EventType e); enum EventState @@ -168,6 +170,9 @@ class TimelineViewManager; class TimelineModel : public QAbstractListModel { Q_OBJECT + QML_NAMED_ELEMENT(Room) + QML_UNCREATABLE("Needs to be instantiated from C++") + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) Q_PROPERTY(std::vector typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY typingUsersChanged) diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 9499c7a0..9bd64348 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -25,15 +25,6 @@ #include "emoji/EmojiModel.h" #include "emoji/Provider.h" -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationAccept) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationCancel) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationDone) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationKey) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationMac) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationReady) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationRequest) -Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationStart) - namespace msgs = mtx::events::msg; namespace { @@ -101,32 +92,23 @@ TimelineViewManager::userColor(QString id, QColor background) TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent) : QObject(parent) , rooms_(new RoomlistModel(this)) + , frooms_(new FilteredRoomlistModel(this->rooms_)) , communities_(new CommunitiesModel(this)) , verificationManager_(new VerificationManager(this)) , presenceEmitter(new PresenceEmitter(this)) { - static auto self = this; - qmlRegisterSingletonInstance("im.nheko", 1, 0, "TimelineManager", self); - qmlRegisterSingletonType( - "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * { - auto ptr = new FilteredRoomlistModel(self->rooms_); - - connect(self->communities_, - &CommunitiesModel::currentTagIdChanged, - ptr, - &FilteredRoomlistModel::updateFilterTag); - connect(self->communities_, - &CommunitiesModel::hiddenTagsChanged, - ptr, - &FilteredRoomlistModel::updateHiddenTagsAndSpaces); - return ptr; - }); - qmlRegisterSingletonInstance("im.nheko", 1, 0, "Communities", self->communities_); - qmlRegisterSingletonInstance("im.nheko", 1, 0, "VerificationManager", verificationManager_); - qmlRegisterSingletonInstance("im.nheko", 1, 0, "Presence", presenceEmitter); + instance_ = this; updateColorPalette(); + connect(this->communities_, + &CommunitiesModel::currentTagIdChanged, + frooms_, + &FilteredRoomlistModel::updateFilterTag); + connect(this->communities_, + &CommunitiesModel::hiddenTagsChanged, + frooms_, + &FilteredRoomlistModel::updateHiddenTagsAndSpaces); connect(UserSettings::instance().get(), &UserSettings::themeChanged, this, diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 3a916853..3269708f 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include #include @@ -38,6 +39,8 @@ class ImagePackListModel; class TimelineViewManager : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(TimelineManager) + QML_SINGLETON Q_PROPERTY( bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) @@ -47,6 +50,25 @@ class TimelineViewManager : public QObject public: TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr); + static TimelineViewManager *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance_); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance_->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance_, QJSEngine::CppOwnership); + return instance_; + } + void sync(const mtx::responses::Sync &sync_); VerificationManager *verificationManager() { return verificationManager_; } @@ -118,6 +140,7 @@ private: bool isConnected_ = true; RoomlistModel *rooms_ = nullptr; + FilteredRoomlistModel *frooms_ = nullptr; CommunitiesModel *communities_ = nullptr; // don't move this above the rooms_ @@ -125,4 +148,6 @@ private: PresenceEmitter *presenceEmitter = nullptr; QHash, QColor> userColors; + + inline static TimelineViewManager *instance_ = nullptr; }; diff --git a/src/ui/HiddenEvents.cpp b/src/ui/HiddenEvents.cpp index a8da812e..fa1686c2 100644 --- a/src/ui/HiddenEvents.cpp +++ b/src/ui/HiddenEvents.cpp @@ -46,7 +46,7 @@ HiddenEvents::load() Q_INVOKABLE void HiddenEvents::toggle(int type) { - auto t = qml_mtx_events::fromRoomEventType(static_cast(type)); + auto t = MtxEvent::fromRoomEventType(static_cast(type)); if (auto it = std::find(begin(hiddenEvents_), end(hiddenEvents_), t); it != end(hiddenEvents_)) hiddenEvents_.erase(it); else @@ -59,7 +59,7 @@ HiddenEvents::hiddenEvents() const { QVariantList l; for (const auto &e : hiddenEvents_) { - l.push_back(qml_mtx_events::toRoomEventType(e)); + l.push_back(MtxEvent::toRoomEventType(e)); } return l; diff --git a/src/ui/HiddenEvents.h b/src/ui/HiddenEvents.h index 928b14ba..dbd2d0b9 100644 --- a/src/ui/HiddenEvents.h +++ b/src/ui/HiddenEvents.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -13,6 +14,8 @@ class HiddenEvents : public QObject { Q_OBJECT + QML_ELEMENT + Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged REQUIRED) Q_PROPERTY(QVariantList hiddenEvents READ hiddenEvents NOTIFY hiddenEventsChanged) public: diff --git a/src/ui/MxcAnimatedImage.h b/src/ui/MxcAnimatedImage.h index 8f4c639b..f9b01077 100644 --- a/src/ui/MxcAnimatedImage.h +++ b/src/ui/MxcAnimatedImage.h @@ -16,6 +16,8 @@ class MxcAnimatedImage : public QQuickItem { Q_OBJECT + QML_ELEMENT + Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED) Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged) Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged) diff --git a/src/ui/MxcMediaProxy.h b/src/ui/MxcMediaProxy.h index 8cb2f8d7..812d7c4b 100644 --- a/src/ui/MxcMediaProxy.h +++ b/src/ui/MxcMediaProxy.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,8 @@ class TimelineModel; class MxcMediaProxy : public QMediaPlayer { Q_OBJECT + QML_NAMED_ELEMENT(MxcMedia) + Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED) Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged) Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged) diff --git a/src/ui/NhekoCursorShape.h b/src/ui/NhekoCursorShape.h index 1f91d7de..d15f0901 100644 --- a/src/ui/NhekoCursorShape.h +++ b/src/ui/NhekoCursorShape.h @@ -8,11 +8,13 @@ // see // https://stackoverflow.com/questions/27821054/how-to-change-cursor-shape-in-qml-when-mousearea-is-covered-with-another-mousear/29382092#29382092 +#include #include class NhekoCursorShape : public QQuickItem { Q_OBJECT + QML_ELEMENT Q_PROPERTY( Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY cursorShapeChanged) diff --git a/src/ui/NhekoEventObserver.cpp b/src/ui/NhekoEventObserver.cpp deleted file mode 100644 index 5e67cec4..00000000 --- a/src/ui/NhekoEventObserver.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// SPDX-FileCopyrightText: 2022 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "NhekoEventObserver.h" - -#include - -#include "Logging.h" - -NhekoEventObserver::NhekoEventObserver(QQuickItem *parent) - : QQuickItem(parent) -{ - setFiltersChildMouseEvents(true); -} - -bool -NhekoEventObserver::childMouseEventFilter(QQuickItem * /*item*/, QEvent *event) -{ - // nhlog::ui()->debug("Touched {}", item->metaObject()->className()); - - auto setTouched = [this](bool touched) { - if (touched != this->wasTouched_) { - this->wasTouched_ = touched; - emit wasTouchedChanged(); - } - }; - - // see - // https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/quicktemplates2/qquickscrollview.cpp?id=7f29e89c26ae2babc358b1c4e6f965af6ec759f4#n471 - switch (event->type()) { - case QEvent::TouchBegin: - case QEvent::TouchEnd: - setTouched(true); - break; - - case QEvent::MouseButtonPress: - if (static_cast(event)->source() == Qt::MouseEventNotSynthesized) { - setTouched(false); - } - break; - - case QEvent::MouseMove: - case QEvent::MouseButtonRelease: - if (static_cast(event)->source() == Qt::MouseEventNotSynthesized) - setTouched(false); - break; - - case QEvent::HoverEnter: - case QEvent::HoverMove: - case QEvent::Wheel: - setTouched(false); - break; - - default: - break; - } - - return false; -} diff --git a/src/ui/NhekoEventObserver.h b/src/ui/NhekoEventObserver.h deleted file mode 100644 index 6d14f30f..00000000 --- a/src/ui/NhekoEventObserver.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -class NhekoEventObserver : public QQuickItem -{ - Q_OBJECT - - Q_PROPERTY(bool wasTouched READ wasTouched NOTIFY wasTouchedChanged) - -public: - explicit NhekoEventObserver(QQuickItem *parent = 0); - - bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; - -private: - bool wasTouched() { return wasTouched_; } - - bool wasTouched_ = false; - -signals: - void wasTouchedChanged(); -}; diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h index cfcf31fb..413ec589 100644 --- a/src/ui/NhekoGlobalObject.h +++ b/src/ui/NhekoGlobalObject.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "Theme.h" #include "UserProfile.h" @@ -15,6 +16,8 @@ class Nheko : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged) Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged) diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 9912cfd6..082023b5 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include @@ -30,6 +31,9 @@ signals: class RoomSettings : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(RoomSettingsModel) + QML_UNCREATABLE("RoomSettings needs to be instantiated from C++") + Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT) Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) diff --git a/src/ui/UIA.h b/src/ui/UIA.h index 150b595d..079e4104 100644 --- a/src/ui/UIA.h +++ b/src/ui/UIA.h @@ -6,21 +6,38 @@ #pragma once #include +#include #include class UIA : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON Q_PROPERTY(QString title READ title NOTIFY titleChanged) public: static UIA *instance(); + static UIA *create(QQmlEngine *qmlEngine, QJSEngine *) + { + // The instance has to exist before it is used. We cannot replace it. + Q_ASSERT(instance()); - UIA(QObject *parent = nullptr) - : QObject(parent) - {} + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance()->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance(), QJSEngine::CppOwnership); + return instance(); + } mtx::http::UIAHandler genericHandler(QString context); @@ -46,6 +63,10 @@ signals: void error(QString msg); private: + UIA(QObject *parent = nullptr) + : QObject(parent) + {} + std::optional currentHandler; mtx::user_interactive::Unauthorized currentStatus; QString title_; diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h index 4652a72e..2a535fbb 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -17,6 +18,7 @@ namespace verification { Q_NAMESPACE +QML_NAMED_ELEMENT(VerificationStatus) enum Status { @@ -106,6 +108,9 @@ private: class UserProfile : public QObject { Q_OBJECT + QML_NAMED_ELEMENT(UserProfileModel) + QML_UNCREATABLE("UserProfile needs to be instantiated from C++") + Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged) Q_PROPERTY(QString userid READ userid CONSTANT) Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged) diff --git a/src/voip/CallManager.cpp b/src/voip/CallManager.cpp index 529b683d..00a2b214 100644 --- a/src/voip/CallManager.cpp +++ b/src/voip/CallManager.cpp @@ -49,6 +49,27 @@ std::vector getTurnURIs(const mtx::responses::TurnServer &turnServer); } +CallManager * +CallManager::create(QQmlEngine *qmlEngine, QJSEngine *) +{ + // The instance has to exist before it is used. We cannot replace it. + auto instance = ChatPage::instance()->callManager(); + Q_ASSERT(instance); + + // The engine has to have the same thread affinity as the singleton. + Q_ASSERT(qmlEngine->thread() == instance->thread()); + + // There can only be one engine accessing the singleton. + static QJSEngine *s_engine = nullptr; + if (s_engine) + Q_ASSERT(qmlEngine == s_engine); + else + s_engine = qmlEngine; + + QJSEngine::setObjectOwnership(instance, QJSEngine::CppOwnership); + return instance; +} + CallManager::CallManager(QObject *parent) : QObject(parent) , session_(WebRTCSession::instance()) diff --git a/src/voip/CallManager.h b/src/voip/CallManager.h index a505e995..a39166d4 100644 --- a/src/voip/CallManager.h +++ b/src/voip/CallManager.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,9 @@ class QUrl; class CallManager : public QObject { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + Q_PROPERTY(bool haveCallInvite READ haveCallInvite NOTIFY newInviteState) Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY newCallState) Q_PROPERTY(webrtc::CallType callType READ callType NOTIFY newInviteState) @@ -45,6 +49,8 @@ class CallManager : public QObject public: CallManager(QObject *); + static CallManager *create(QQmlEngine *qmlEngine, QJSEngine *); + bool haveCallInvite() const { return haveCallInvite_; } bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; } webrtc::CallType callType() const { return callType_; } diff --git a/src/voip/WebRTCSession.cpp b/src/voip/WebRTCSession.cpp index 31174500..e533c46d 100644 --- a/src/voip/WebRTCSession.cpp +++ b/src/voip/WebRTCSession.cpp @@ -40,31 +40,12 @@ extern "C" // https://github.com/vector-im/riot-web/issues/10173 #define STUN_SERVER "stun://turn.matrix.org:3478" -Q_DECLARE_METATYPE(webrtc::CallType) -Q_DECLARE_METATYPE(webrtc::State) - using webrtc::CallType; using webrtc::State; WebRTCSession::WebRTCSession() : devices_(CallDevices::instance()) { - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(webrtc::staticMetaObject, - "im.nheko", - 1, - 0, - "CallType", - QStringLiteral("Can't instantiate enum")); - - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(webrtc::staticMetaObject, - "im.nheko", - 1, - 0, - "WebRTCState", - QStringLiteral("Can't instantiate enum")); - connect(this, &WebRTCSession::stateChanged, this, &WebRTCSession::setState); init(); } diff --git a/src/voip/WebRTCSession.h b/src/voip/WebRTCSession.h index 04383679..f79755db 100644 --- a/src/voip/WebRTCSession.h +++ b/src/voip/WebRTCSession.h @@ -9,6 +9,7 @@ #include #include +#include #include "mtx/events/voip.hpp" @@ -18,6 +19,7 @@ class QQuickItem; namespace webrtc { Q_NAMESPACE +QML_NAMED_ELEMENT(Voip) enum class CallType {