From eb53a622b7f51160a2204fefa9c6a2e019bd9aff Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Thu, 3 Sep 2020 09:24:49 -0400 Subject: [PATCH] qml interop: start replacing QMetaObject::invokeMethod with signals It seems concurrent calls to invokeMethod using qml component object pointers can lead to access violations. These method invocations can be replaced with a signal/slot mechanism. This patch replaces only the invocations in conversationsadapter and accountsadapter that are known to be problematic for now. Some code cleanup is done for QmlAdapterBase derived classes. Gitlab: #61 Change-Id: I72f47c9229a9bf42299ae52822c3a1a8c04eb423 --- jami-qt.pro | 1 - src/accountadapter.cpp | 6 +- src/accountadapter.h | 11 +- src/avadapter.cpp | 6 - src/avadapter.h | 9 +- src/calladapter.cpp | 8 +- src/calladapter.h | 11 +- src/contactadapter.cpp | 8 +- src/contactadapter.h | 13 ++- src/conversationsadapter.cpp | 22 ++-- src/conversationsadapter.h | 17 ++- src/mainview/MainView.qml | 4 - src/mainview/components/AccountComboBox.qml | 14 ++- .../components/ConversationSmartListView.qml | 105 +++++++++--------- src/mainview/components/SidePanel.qml | 2 +- src/mediahandleradapter.cpp | 6 - src/mediahandleradapter.h | 14 +-- src/messagesadapter.cpp | 10 +- src/messagesadapter.h | 11 +- src/qmladapterbase.cpp | 35 ------ src/qmladapterbase.h | 17 ++- src/qmlregister.cpp | 2 +- 22 files changed, 144 insertions(+), 188 deletions(-) delete mode 100644 src/qmladapterbase.cpp diff --git a/jami-qt.pro b/jami-qt.pro index 84817dc65..6ac56315f 100644 --- a/jami-qt.pro +++ b/jami-qt.pro @@ -174,7 +174,6 @@ SOURCES += ./src/bannedlistmodel.cpp \ ./src/conversationsadapter.cpp \ ./src/distantrenderer.cpp \ ./src/previewrenderer.cpp \ - ./src/qmladapterbase.cpp \ ./src/avadapter.cpp \ ./src/contactadapter.cpp \ ./src/mediahandleradapter.cpp \ diff --git a/src/accountadapter.cpp b/src/accountadapter.cpp index 00923de5e..d924bff90 100644 --- a/src/accountadapter.cpp +++ b/src/accountadapter.cpp @@ -30,8 +30,6 @@ AccountAdapter::AccountAdapter(QObject *parent) : QmlAdapterBase(parent) {} -AccountAdapter::~AccountAdapter() {} - AccountAdapter & AccountAdapter::instance() { @@ -40,7 +38,7 @@ AccountAdapter::instance() } void -AccountAdapter::initQmlObject() +AccountAdapter::safeInit() { setSelectedAccount(LRCInstance::getCurrAccId()); } @@ -334,7 +332,7 @@ void AccountAdapter::backToWelcomePage() { deselectConversation(); - QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage"); + emit navigateToWelcomePageRequested(); } void diff --git a/src/accountadapter.h b/src/accountadapter.h index d2e9844d7..e28cec893 100644 --- a/src/accountadapter.h +++ b/src/accountadapter.h @@ -27,13 +27,18 @@ #include "lrcinstance.h" #include "utils.h" -class AccountAdapter : public QmlAdapterBase +class AccountAdapter final : public QmlAdapterBase { Q_OBJECT public: explicit AccountAdapter(QObject *parent = 0); - ~AccountAdapter(); + ~AccountAdapter() = default; + +protected: + void safeInit() override; + +public: //Singleton static AccountAdapter &instance(); @@ -94,9 +99,9 @@ signals: */ void reportFailure(); void accountAdded(bool showBackUp, int index); + void navigateToWelcomePageRequested(); private: - void initQmlObject() override final; void setSelectedAccount(const QString &accountId); void backToWelcomePage(); void deselectConversation(); diff --git a/src/avadapter.cpp b/src/avadapter.cpp index b7a256449..5306fda3f 100644 --- a/src/avadapter.cpp +++ b/src/avadapter.cpp @@ -28,12 +28,6 @@ AvAdapter::AvAdapter(QObject *parent) : QmlAdapterBase(parent) {} -AvAdapter::~AvAdapter() {} - -void -AvAdapter::initQmlObject() -{} - QVariantMap AvAdapter::populateVideoDeviceContextMenuItem() { diff --git a/src/avadapter.h b/src/avadapter.h index 1c300e883..ec64067af 100644 --- a/src/avadapter.h +++ b/src/avadapter.h @@ -24,13 +24,16 @@ #include <QVariant> #include <QString> -class AvAdapter : public QmlAdapterBase +class AvAdapter final : public QmlAdapterBase { Q_OBJECT public: explicit AvAdapter(QObject *parent = nullptr); - ~AvAdapter(); + ~AvAdapter() = default; + +protected: + void safeInit() override {}; /* * Return needed info for populating video device context menu item. @@ -62,6 +65,4 @@ public: */ Q_INVOKABLE void shareScreenArea(int screenNumber, int x, int y, int width, int height); -private: - void initQmlObject() override; }; diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 962a5a783..098efacd1 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -30,12 +30,6 @@ CallAdapter::CallAdapter(QObject* parent) : QmlAdapterBase(parent) , oneSecondTimer_(new QTimer(this)) -{} - -CallAdapter::~CallAdapter() {} - -void -CallAdapter::initQmlObject() { connectCallModel(LRCInstance::getCurrAccId()); @@ -676,4 +670,4 @@ CallAdapter::setTime(const QString& accountId, const QString& convUid) auto timeString = LRCInstance::getCurrentCallModel()->getFormattedCallDuration(callId); emit updateTimeText(timeString); } -} \ No newline at end of file +} diff --git a/src/calladapter.h b/src/calladapter.h index bd7871d79..d39d8427c 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -26,19 +26,18 @@ #include <QString> #include <QVariant> -class CallAdapter : public QmlAdapterBase +class CallAdapter final : public QmlAdapterBase { Q_OBJECT public: explicit CallAdapter(QObject* parent = nullptr); - ~CallAdapter(); + ~CallAdapter() = default; - /* - * This is needed to be public since it has to be recognized by qml. - */ - Q_INVOKABLE void initQmlObject() override; +protected: + void safeInit() override {}; +public: Q_INVOKABLE void placeAudioOnlyCall(); Q_INVOKABLE void placeCall(); Q_INVOKABLE void hangUpACall(const QString& accountId, const QString& convUid); diff --git a/src/contactadapter.cpp b/src/contactadapter.cpp index e08a6dee8..9514d852c 100644 --- a/src/contactadapter.cpp +++ b/src/contactadapter.cpp @@ -1,4 +1,4 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> @@ -28,8 +28,6 @@ ContactAdapter::ContactAdapter(QObject *parent) selectableProxyModel_.reset(new SelectableProxyModel(smartListModel_.get())); } -ContactAdapter::~ContactAdapter() {} - QVariant ContactAdapter::getContactSelectableModel(int type) { @@ -175,7 +173,3 @@ ContactAdapter::setCalleeDisplayName(const QString &name) { calleeDisplayName_ = name; } - -void -ContactAdapter::initQmlObject() -{} diff --git a/src/contactadapter.h b/src/contactadapter.h index 4b694770d..9f3aae432 100644 --- a/src/contactadapter.h +++ b/src/contactadapter.h @@ -1,4 +1,4 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * @@ -34,7 +34,7 @@ * * Additionally, user need to setFilterRegExp to be able to get input QRegExp from FilterPredicate. */ -class SelectableProxyModel : public QSortFilterProxyModel +class SelectableProxyModel final : public QSortFilterProxyModel { public: using FilterPredicate = std::function<bool(const QModelIndex &, const QRegExp &)>; @@ -68,13 +68,16 @@ private: std::function<bool(const QModelIndex &, const QRegExp &)> filterPredicate_; }; -class ContactAdapter : public QmlAdapterBase +class ContactAdapter final : public QmlAdapterBase { Q_OBJECT public: explicit ContactAdapter(QObject *parent = nullptr); - ~ContactAdapter(); + ~ContactAdapter() = default; + +protected: + void safeInit() override {}; Q_INVOKABLE QVariant getContactSelectableModel(int type); Q_INVOKABLE void setSearchFilter(const QString &filter); @@ -82,8 +85,6 @@ public: Q_INVOKABLE void setCalleeDisplayName(const QString &name); private: - void initQmlObject() override; - SmartListModel::Type listModeltype_; /* diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp index 69d46f919..1c979a547 100644 --- a/src/conversationsadapter.cpp +++ b/src/conversationsadapter.cpp @@ -1,4 +1,4 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com> @@ -29,15 +29,12 @@ ConversationsAdapter::ConversationsAdapter(QObject *parent) : QmlAdapterBase(parent) {} -ConversationsAdapter::~ConversationsAdapter() {} - void -ConversationsAdapter::initQmlObject() +ConversationsAdapter::safeInit() { conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this); - QMetaObject::invokeMethod(qmlObj_, "setModel", - Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_))); + emit modelChanged(QVariant::fromValue(conversationSmartListModel_)); connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView, @@ -57,7 +54,7 @@ void ConversationsAdapter::backToWelcomePage() { deselectConversation(); - QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage"); + emit navigateToWelcomePageRequested(); } void @@ -198,7 +195,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) [this]() { conversationSmartListModel_->fillConversationsList(); updateConversationsFilterWidget(); - QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + emit updateListViewRequested(); auto* convModel = LRCInstance::getCurrentConversationModel(); const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid()); @@ -211,7 +208,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) == lrc::api::profile::Type::TEMPORARY) { return; } - QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI)); + emit modelSorted(QVariant::fromValue(contactURI)); }); modelUpdatedConnection_ = QObject::connect(currentConversationModel, @@ -219,7 +216,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) [this](const QString &convUid) { conversationSmartListModel_->updateConversation(convUid); updateConversationsFilterWidget(); - QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + emit updateListViewRequested(); }); filterChangedConnection_ = QObject::connect(currentConversationModel, @@ -228,7 +225,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) conversationSmartListModel_->fillConversationsList(); conversationSmartListModel_->setAccount(LRCInstance::getCurrAccId()); updateConversationsFilterWidget(); - QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + emit updateListViewRequested(); }); newConversationConnection_ = QObject::connect(currentConversationModel, @@ -265,9 +262,10 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) searchResultUpdatedConnection_ = QObject::connect(currentConversationModel, &lrc::api::ConversationModel::searchResultUpdated, [this]() { + conversationSmartListModel_->fillConversationsList(); conversationSmartListModel_->setAccount(LRCInstance::getCurrAccId()); - QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + emit updateListViewRequested(); }); if (updateFilter) currentConversationModel->setFilter(""); diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h index 19cad97f4..56f346268 100644 --- a/src/conversationsadapter.h +++ b/src/conversationsadapter.h @@ -1,4 +1,4 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * @@ -25,14 +25,17 @@ #include <QObject> #include <QString> -class ConversationsAdapter : public QmlAdapterBase +class ConversationsAdapter final : public QmlAdapterBase { Q_OBJECT - public: explicit ConversationsAdapter(QObject *parent = nullptr); - ~ConversationsAdapter(); + ~ConversationsAdapter() = default; + +protected: + void safeInit() override; +public: Q_INVOKABLE bool connectConversationModel(bool updateFilter = true); Q_INVOKABLE void disconnectConversationModel(); Q_INVOKABLE void selectConversation(const QString &accountId, @@ -50,8 +53,12 @@ signals: void showConversationTabs(bool visible); void showSearchStatus(const QString &status); + void modelChanged(const QVariant& model); + void modelSorted(const QVariant& uri); + void updateListViewRequested(); + void navigateToWelcomePageRequested(); + private: - void initQmlObject() override; void setConversationFilter(lrc::api::profile::Type filter); void backToWelcomePage(); bool selectConversation(const lrc::api::conversation::Info &item, diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml index 1ab5a3fc0..bfd2f7f66 100644 --- a/src/mainview/MainView.qml +++ b/src/mainview/MainView.qml @@ -704,10 +704,6 @@ Window { height: userProfile.contentHeight } - Component.onCompleted: { - CallAdapter.initQmlObject() - } - onClosing: { close.accepted = false mainViewWindow.hide() diff --git a/src/mainview/components/AccountComboBox.qml b/src/mainview/components/AccountComboBox.qml index 0252b8d7f..b1bc5029f 100644 --- a/src/mainview/components/AccountComboBox.qml +++ b/src/mainview/components/AccountComboBox.qml @@ -27,14 +27,10 @@ ComboBox { id: accountComboBox signal accountChanged(int index) - signal needToBackToWelcomePage() + signal needToBackToWelcomePage signal newAccountButtonClicked signal settingBtnClicked - function backToWelcomePage() { - needToBackToWelcomePage() - } - // Reset accountListModel. function resetAccountListModel() { accountListModel.reset() @@ -53,6 +49,14 @@ ComboBox { } } + Connections { + target: ClientWrapper.accountAdaptor + + function onNavigateToWelcomePageRequested() { + needToBackToWelcomePage() + } + } + Image { id: userImageRoot diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml index f850c1173..1d61c5bb3 100644 --- a/src/mainview/components/ConversationSmartListView.qml +++ b/src/mainview/components/ConversationSmartListView.qml @@ -1,7 +1,7 @@ - /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,13 +16,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ + import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import net.jami.Models 1.0 ListView { - id: conversationSmartListView + id: root signal needToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, int callState) signal needToSelectItems(string conversationUid) @@ -34,60 +35,59 @@ ListView { signal currentIndexIsChanged signal forceUpdatePotentialInvalidItem + // Refresh all items within the model. + function updateListView() { + root.model.dataChanged( + root.model.index(0, 0), + root.model.index( + root.model.rowCount() - 1, 0)) + root.forceUpdatePotentialInvalidItem() + } - /* - * When model is sorted, we need to reset to focus (currentIndex) - * to the real conversation that we focused. - */ - function modelSorted(contactURIToCompare) { - var conversationSmartListViewModel = conversationSmartListView.model - conversationSmartListView.currentIndex = -1 - updateConversationSmartListView() - for (var i = 0; i < count; i++) { - if (conversationSmartListViewModel.data( - conversationSmartListViewModel.index(i, 0), - 261) === contactURIToCompare) { - conversationSmartListView.currentIndex = i - break - } - } + ConversationSmartListContextMenu { + id: smartListContextMenu } + Connections { + target: ConversationsAdapter - /* - * Refresh all item within model. - */ - function updateConversationSmartListView() { - var conversationSmartListViewModel = conversationSmartListView.model - conversationSmartListViewModel.dataChanged( - conversationSmartListViewModel.index(0, 0), - conversationSmartListViewModel.index( - conversationSmartListViewModel.rowCount() - 1, 0)) - conversationSmartListView.forceUpdatePotentialInvalidItem() - } + function onModelChanged(model) { + root.model = model + } - function setModel(model) { - conversationSmartListView.model = model - } + // When the model has been sorted, we need to adjust the focus (currentIndex) + // to the previously focused conversation item. + function onModelSorted(uri) { + root.currentIndex = -1 + updateListView() + for (var i = 0; i < count; i++) { + if (root.model.data( + root.model.index(i, 0), 261) === uri) { + root.currentIndex = i + break + } + } + } - function backToWelcomePage() { - conversationSmartListView.needToBackToWelcomePage() - } + function onUpdateListViewRequested() { + updateListView() + } - ConversationSmartListContextMenu { - id: smartListContextMenu + function onNavigateToWelcomePageRequested() { + root.needToBackToWelcomePage() + } } Connections { target: CallAdapter function onUpdateConversationSmartList() { - updateConversationSmartListView() + updateListView() } } onCurrentIndexChanged: { - conversationSmartListView.currentIndexIsChanged() + root.currentIndexIsChanged() } clip: true @@ -101,7 +101,7 @@ ListView { Shortcut { sequence: "Ctrl+Shift+X" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { CallAdapter.placeCall() } @@ -110,7 +110,7 @@ ListView { Shortcut { sequence: "Ctrl+Shift+C" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { CallAdapter.placeAudioOnlyCall() } @@ -119,7 +119,7 @@ ListView { Shortcut { sequence: "Ctrl+Shift+L" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { ClientWrapper.utilsAdaptor.clearConversationHistory(ClientWrapper.utilsAdaptor.getCurrAccId(), ClientWrapper.utilsAdaptor.getCurrConvId()) @@ -129,18 +129,18 @@ ListView { Shortcut { sequence: "Ctrl+Shift+B" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(), ClientWrapper.utilsAdaptor.getCurrConvId(), true) - conversationSmartListView.needToBackToWelcomePage() + root.needToBackToWelcomePage() } } Shortcut { sequence: "Ctrl+Shift+Delete" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(), ClientWrapper.utilsAdaptor.getCurrConvId(), false) @@ -150,21 +150,22 @@ ListView { Shortcut { sequence: "Ctrl+Down" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { - if (currentIndex + 1 >= count) return - conversationSmartListView.currentIndex += 1 + if (currentIndex + 1 >= count) + return + root.currentIndex += 1 } } Shortcut { sequence: "Ctrl+Up" context: Qt.ApplicationShortcut - enabled: conversationSmartListView.visible + enabled: root.visible onActivated: { - if (currentIndex <= 0) return - conversationSmartListView.currentIndex -= 1 + if (currentIndex <= 0) + return + root.currentIndex -= 1 } } - } diff --git a/src/mainview/components/SidePanel.qml b/src/mainview/components/SidePanel.qml index 01d13b5b5..bf2d6ffb7 100644 --- a/src/mainview/components/SidePanel.qml +++ b/src/mainview/components/SidePanel.qml @@ -91,7 +91,7 @@ Rectangle { } function forceUpdateConversationSmartListView() { - conversationSmartListView.updateConversationSmartListView() + conversationSmartListView.updateListView() } /* diff --git a/src/mediahandleradapter.cpp b/src/mediahandleradapter.cpp index 120a55e7d..d35117d59 100644 --- a/src/mediahandleradapter.cpp +++ b/src/mediahandleradapter.cpp @@ -24,8 +24,6 @@ MediaHandlerAdapter::MediaHandlerAdapter(QObject* parent) : QmlAdapterBase(parent) {} -MediaHandlerAdapter::~MediaHandlerAdapter() {} - QVariant MediaHandlerAdapter::getMediaHandlerSelectableModel() { @@ -61,7 +59,3 @@ MediaHandlerAdapter::getMediaHandlerPreferencesSelectableModel(QString pluginId) return QVariant::fromValue(mediaHandlerListPreferenceModel_.get()); } - -void -MediaHandlerAdapter::initQmlObject() -{} diff --git a/src/mediahandleradapter.h b/src/mediahandleradapter.h index 6681ada13..57837a68f 100644 --- a/src/mediahandleradapter.h +++ b/src/mediahandleradapter.h @@ -1,4 +1,4 @@ -/** +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * @@ -19,7 +19,6 @@ #pragma once #include "qmladapterbase.h" -//#include "smartlistmodel.h" #include "mediahandleritemlistmodel.h" #include "mediahandlerlistpreferencemodel.h" #include "preferenceitemlistmodel.h" @@ -28,22 +27,23 @@ #include <QSortFilterProxyModel> #include <QString> -class MediaHandlerAdapter : public QmlAdapterBase +class MediaHandlerAdapter final : public QmlAdapterBase { Q_OBJECT - public: explicit MediaHandlerAdapter(QObject* parent = nullptr); - ~MediaHandlerAdapter(); + ~MediaHandlerAdapter() = default; + +protected: + void safeInit() override {}; Q_INVOKABLE QVariant getMediaHandlerSelectableModel(); Q_INVOKABLE QVariant getMediaHandlerPreferencesModel(QString pluginId, QString mediaHandlerName); Q_INVOKABLE QVariant getMediaHandlerPreferencesSelectableModel(QString pluginId); private: - void initQmlObject(); - std::unique_ptr<MediaHandlerItemListModel> mediaHandlerListModel_; std::unique_ptr<PreferenceItemListModel> mediaHandlerPreferenceItemListModel_; std::unique_ptr<MediaHandlerListPreferenceModel> mediaHandlerListPreferenceModel_; + }; diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp index f61c90ede..8b7cd94d0 100644 --- a/src/messagesadapter.cpp +++ b/src/messagesadapter.cpp @@ -1,7 +1,7 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> - * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com> + * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> @@ -22,9 +22,9 @@ */ #include "messagesadapter.h" -#include "webchathelpers.h" #include "utils.h" +#include "webchathelpers.h" #include <QDesktopServices> #include <QFileInfo> @@ -36,10 +36,8 @@ MessagesAdapter::MessagesAdapter(QObject *parent) : QmlAdapterBase(parent) {} -MessagesAdapter::~MessagesAdapter() {} - void -MessagesAdapter::initQmlObject() { +MessagesAdapter::safeInit() { connect(&LRCInstance::instance(), &LRCInstance::currentAccountChanged, [this](){ diff --git a/src/messagesadapter.h b/src/messagesadapter.h index 352cc3eec..5f066a538 100644 --- a/src/messagesadapter.h +++ b/src/messagesadapter.h @@ -1,4 +1,4 @@ -/* +/*! * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * @@ -24,13 +24,15 @@ #include <QObject> #include <QString> -class MessagesAdapter : public QmlAdapterBase +class MessagesAdapter final : public QmlAdapterBase { Q_OBJECT - public: explicit MessagesAdapter(QObject *parent = 0); - ~MessagesAdapter(); + ~MessagesAdapter() = default; + +protected: + void safeInit() override; Q_INVOKABLE void setupChatView(const QString &uid); Q_INVOKABLE void connectConversationModel(); @@ -93,7 +95,6 @@ public slots: void slotMessagesLoaded(); private: - void initQmlObject() override final; void setConversationProfileData(const lrc::api::conversation::Info &convInfo); void newInteraction(const QString &accountId, const QString &convUid, diff --git a/src/qmladapterbase.cpp b/src/qmladapterbase.cpp deleted file mode 100644 index 6b8d3f68b..000000000 --- a/src/qmladapterbase.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "qmladapterbase.h" - -QmlAdapterBase::QmlAdapterBase(QObject *parent) - : QObject(parent) -{ - qmlObj_ = nullptr; -} - -QmlAdapterBase::~QmlAdapterBase() {} - -void -QmlAdapterBase::setQmlObject(QObject *obj) -{ - qmlObj_ = obj; - - initQmlObject(); -} diff --git a/src/qmladapterbase.h b/src/qmladapterbase.h index e476359ea..750c09e60 100644 --- a/src/qmladapterbase.h +++ b/src/qmladapterbase.h @@ -28,20 +28,27 @@ class QmlAdapterBase : public QObject { Q_OBJECT public: - explicit QmlAdapterBase(QObject *parent = nullptr); - ~QmlAdapterBase(); + explicit QmlAdapterBase(QObject *parent = nullptr) + : QObject(parent) + , qmlObj_(nullptr) {}; + + virtual ~QmlAdapterBase() = default; /* * This function should be called in the Component.onCompleted slot * in the qml component that this adapter should attach to. */ - Q_INVOKABLE void setQmlObject(QObject *obj); + Q_INVOKABLE void setQmlObject(QObject *obj) + { + qmlObj_ = obj; + safeInit(); + }; protected: /* - *Once the qml object is set, custom actions can be done in this function. + * Once the qml object is set, Qml method invokation can be done */ - virtual void initQmlObject() = 0; + virtual void safeInit() = 0; /* * Object pointer. diff --git a/src/qmlregister.cpp b/src/qmlregister.cpp index 11301adf1..02694a684 100644 --- a/src/qmlregister.cpp +++ b/src/qmlregister.cpp @@ -135,6 +135,7 @@ void registerTypes() QML_REGISTERSINGLETONTYPE_URL(QStringLiteral("qrc:/src/constant/JamiQmlUtils.qml"), JamiQmlUtils, 1, 0); + QML_REGISTERSINGLETONTYPE("net.jami.Models", AccountAdapter, 1, 0); QML_REGISTERSINGLETONTYPE("net.jami.Models", CallAdapter, 1, 0); QML_REGISTERSINGLETONTYPE("net.jami.Models", MessagesAdapter, 1, 0); QML_REGISTERSINGLETONTYPE("net.jami.Models", ConversationsAdapter, 1, 0); @@ -167,7 +168,6 @@ void registerTypes() * qmlRegisterUncreatableType & Q_DECLARE_METATYPE to expose models in qml. */ QML_REGISTERUNCREATABLE("net.jami.Models", RenderManager, 1, 0); - QML_REGISTERUNCREATABLE("net.jami.Models", AccountAdapter, 1, 0); QML_REGISTERUNCREATABLE("net.jami.Models", UtilsAdapter, 1, 0); QML_REGISTERUNCREATABLE("net.jami.Models", NameDirectory, 1, 0); QML_REGISTERUNCREATABLE("net.jami.Models", LRCInstance, 1, 0); -- GitLab