From 06c3ffa6cee0a62e713acafb7cd4b32df5d4da69 Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Fri, 2 Feb 2024 17:22:46 -0500 Subject: [PATCH] testing: add a configuration tool to the dev-testing window This will allow the addition of custom parameters to a second anchored window. "Conversation ID" and "Force local preview" are implemented. Change-Id: I2366b57e6bb36efb568b06e40ef124a440a39397 --- src/app/ComponentTestWindow.qml | 142 ++++++++++++++++++++ src/app/calloverlaymodel.cpp | 32 +++-- src/app/calloverlaymodel.h | 4 +- src/app/mainview/components/MainOverlay.qml | 12 +- src/app/net/jami/Constants/JamiQmlUtils.qml | 6 + 5 files changed, 184 insertions(+), 12 deletions(-) diff --git a/src/app/ComponentTestWindow.qml b/src/app/ComponentTestWindow.qml index 7729d5863..a072ce828 100644 --- a/src/app/ComponentTestWindow.qml +++ b/src/app/ComponentTestWindow.qml @@ -17,8 +17,19 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts +import Qt.labs.qmlmodels +import net.jami.Models 1.1 import net.jami.Adapters 1.1 +import net.jami.Enums 1.1 +import net.jami.Helpers 1.1 +import net.jami.Constants 1.1 + +import "mainview" +import "mainview/components" +import "wizardview" +import "commoncomponents" // A window into which we can load a QML file for testing. ApplicationWindow { @@ -62,4 +73,135 @@ ApplicationWindow { // Closing this window should always exit the application. onClosing: Qt.quit() + + // A window to modify properties for Jamified components. + // Sometimes we need to modify properties including current conversation ID, account ID, etc. + // This window should have a simple layout: a list of editable parameters within a scroll view. + Window { + id: configTool + width: 400 + height: 400 + title: "Config tool" + + visible: true + // Cannot be closed. + flags: Qt.SplashScreen + + // Anchor the window to the right of the parent window. + x: appWindow.x + appWindow.width + y: appWindow.y + + color: "lightgray" + + Page { + anchors.fill: parent + header: Control { + contentItem: Text { + horizontalAlignment: Text.AlignHCenter + text: "Config tool" + } + background: Rectangle { color: configTool.color } + } + contentItem: Control { + background: Rectangle { color: Qt.lighter(configTool.color, 1.1) } + padding: 10 + contentItem: ListView { + // Declare types of controls. TODO: add as needed. + Component { + id: checkComponent + CheckBox { + text: label + onCheckedChanged: checkChangedCb(checked) + } + } + Component { + id: comboComponent + Control { + contentItem: RowLayout { + Text { text: label } + ComboBox { + id: comboBox + displayText: CurrentConversation.title || "undefined" + model: getDataModel() + delegate: ItemDelegate { + highlighted: comboBox.highlightedIndex === index + width: parent.width + text: JamiQmlUtils.getModelData(comboBox.model, index, displayRole) + } + onCurrentIndexChanged: onIndexChanged(model, currentIndex) + } + } + } + } + spacing: 5 + model: ListModel { + ListElement { + label: "Conversation ID" + type: "combobox" + getDataModel: () => ConversationsAdapter.convListProxyModel + displayRole: ConversationList.Title + onIndexChanged: function(model, index) { + const convUid = JamiQmlUtils.getModelData(model, index, ConversationList.UID); + LRCInstance.selectConversation(convUid); + } + } + ListElement { + label: "Force local preview" + type: "checkbox" + value: false + checkChangedCb: function(checked) { + // Find any child component of type `LocalVideo` and start it. + const localVideo = findChild(loader.item, LocalVideo, "type"); + if (localVideo) { + if (checked) { + localVideo.startWithId(VideoDevices.getDefaultDevice()); + } else { + localVideo.startWithId(""); + } + } else { + console.error("LocalVideo not found"); + } + } + } + } + delegate: DelegateChooser { + role: "type" + DelegateChoice { + roleValue: "checkbox" + delegate: checkComponent + } + DelegateChoice { + roleValue: "combobox" + delegate: comboComponent + } + } + } + } + } + } + + // From TestCase.qml, refactored to find a child by type or name. + function findChild(parent, searchValue, searchBy = "name") { + if (!parent || parent.children === undefined) { + console.error("No children found"); + return null; + } + // Search directly under the given parent + for (var i = 0; i < parent.children.length; ++i) { + var child = parent.children[i]; + var match = false; + if (searchBy === "name" && child.objectName === searchValue) { + match = true; + } else if (searchBy === "type" && child instanceof searchValue) { + match = true; + } + if (match) return child; + } + // Recursively search in child objects + for (i = 0; i < parent.children.length; ++i) { + var found = findChild(parent.children[i], searchValue, searchBy); + if (found) return found; + } + return null; + } } diff --git a/src/app/calloverlaymodel.cpp b/src/app/calloverlaymodel.cpp index 44962f205..5e6555216 100644 --- a/src/app/calloverlaymodel.cpp +++ b/src/app/calloverlaymodel.cpp @@ -19,6 +19,8 @@ #include "calloverlaymodel.h" +#include "global.h" + #include <QEvent> #include <QMouseEvent> #include <QQuickWindow> @@ -360,23 +362,37 @@ CallOverlayModel::clearControls() } void -CallOverlayModel::registerFilter(QQuickWindow* object, QQuickItem* item) +CallOverlayModel::registerFilter(QObject* object, QQuickItem* item) { - if (!object || !item || watchedItems_.contains(item)) + QQuickWindow* window = qobject_cast<QQuickWindow*>(object); + if (!window || !item) { + C_WARN << "Attempting to register an invalid object or item" << object << item; return; + } + if (watchedItems_.contains(item)) { + C_DBG << "Item already registered" << item; + } watchedItems_.push_back(item); - if (watchedItems_.size() == 1) - object->installEventFilter(this); + if (watchedItems_.size() == 1) { + window->installEventFilter(this); + } } void -CallOverlayModel::unregisterFilter(QQuickWindow* object, QQuickItem* item) +CallOverlayModel::unregisterFilter(QObject* object, QQuickItem* item) { - if (!object || !item || !watchedItems_.contains(item)) + QQuickWindow* window = qobject_cast<QQuickWindow*>(object); + if (!window || !item) { + C_WARN << "Attempting to unregister an invalid object or item" << object << item; return; + } + if (!watchedItems_.contains(item)) { + C_DBG << "Item not registered" << item; + } watchedItems_.removeOne(item); - if (watchedItems_.size() == 0) - object->removeEventFilter(this); + if (watchedItems_.size() == 0) { + window->removeEventFilter(this); + } } bool diff --git a/src/app/calloverlaymodel.h b/src/app/calloverlaymodel.h index 934802bc2..c940896ad 100644 --- a/src/app/calloverlaymodel.h +++ b/src/app/calloverlaymodel.h @@ -137,8 +137,8 @@ public: Q_INVOKABLE QVariant overflowHiddenModel(); Q_INVOKABLE QVariant pendingConferenceesModel(); - Q_INVOKABLE void registerFilter(QQuickWindow* object, QQuickItem* item); - Q_INVOKABLE void unregisterFilter(QQuickWindow* object, QQuickItem* item); + Q_INVOKABLE void registerFilter(QObject* object, QQuickItem* item); + Q_INVOKABLE void unregisterFilter(QObject* object, QQuickItem* item); bool eventFilter(QObject* object, QEvent* event) override; Q_SIGNALS: diff --git a/src/app/mainview/components/MainOverlay.qml b/src/app/mainview/components/MainOverlay.qml index 455ecb347..9bc7863ba 100644 --- a/src/app/mainview/components/MainOverlay.qml +++ b/src/app/mainview/components/MainOverlay.qml @@ -20,9 +20,11 @@ */ import QtQuick import QtQuick.Layouts + import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 + import "../../commoncomponents" Item { @@ -61,9 +63,15 @@ Item { // (un)subscribe to an app-wide mouse move event trap filtered // for the overlay's geometry - onVisibleChanged: { - visible ? CallOverlayModel.registerFilter(appWindow, this) : CallOverlayModel.unregisterFilter(appWindow, this); + function setupFilter() { + if (visible) { + CallOverlayModel.registerFilter(appWindow, this); + } else { + CallOverlayModel.unregisterFilter(appWindow, this); + } } + Component.onCompleted: setupFilter() + onVisibleChanged: setupFilter() Connections { target: CallOverlayModel diff --git a/src/app/net/jami/Constants/JamiQmlUtils.qml b/src/app/net/jami/Constants/JamiQmlUtils.qml index eb272fb93..2051903c6 100644 --- a/src/app/net/jami/Constants/JamiQmlUtils.qml +++ b/src/app/net/jami/Constants/JamiQmlUtils.qml @@ -34,6 +34,12 @@ Item { return accountCreationInputParaObject; } + // For list models (1 column). + function getModelData(model, index, role) { + const modelIndex = model.index(index, 0); + return model.data(modelIndex, role); + } + // MessageBar buttons in mainview points property var mainViewRectObj property var messageBarButtonsRowObj -- GitLab