From 075937aa008a298fa9937712649b4612194bb079 Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Fri, 18 Oct 2024 16:33:55 +0200 Subject: [PATCH] wait for core is on before displaying ui Use directly accountProxy and react to signals. --- Linphone/core/App.cpp | 28 +++++++++++++++++-- Linphone/core/App.hpp | 6 ++++ Linphone/core/account/AccountList.cpp | 25 ++++++++++++----- Linphone/core/account/AccountList.hpp | 8 ++++-- Linphone/core/account/AccountProxy.cpp | 20 +++++++++++-- Linphone/core/account/AccountProxy.hpp | 7 ++++- Linphone/core/proxy/LimitProxy.cpp | 8 ++++-- .../view/Page/Main/Contact/ContactPage.qml | 2 +- Linphone/view/Page/Window/Main/MainWindow.qml | 27 ++++++++++++------ 9 files changed, 104 insertions(+), 27 deletions(-) diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp index 3bbebf29..ebd946bf 100644 --- a/Linphone/core/App.cpp +++ b/Linphone/core/App.cpp @@ -341,6 +341,13 @@ void App::setSelf(QSharedPointer(me)) { } }); }); + mCoreModelConnection->makeConnectToModel( + &CoreModel::globalStateChanged, + [this](const std::shared_ptr &core, linphone::GlobalState gstate, const std::string &message) { + if (gstate == linphone::GlobalState::On) { + mCoreModelConnection->invokeToCore([this] { setCoreStarted(true); }); + } + }); mCoreModelConnection->makeConnectToModel( &CoreModel::authenticationRequested, [this](const std::shared_ptr &core, const std::shared_ptr &authInfo, @@ -424,9 +431,10 @@ void App::initCore() { mLinphoneThread->getThreadId(), [this]() mutable { CoreModel::getInstance()->start(); + auto coreStarted = CoreModel::getInstance()->getCore()->getGlobalState() == linphone::GlobalState::On; SettingsModel::create(); auto settings = SettingsCore::create(); - QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings] { + QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings, coreStarted] { // QML mEngine = new QQmlApplicationEngine(this); assert(mEngine); @@ -473,6 +481,7 @@ void App::initCore() { mNotifier = new Notifier(mEngine); mSettings = settings; mEngine->setObjectOwnership(mSettings.get(), QQmlEngine::CppOwnership); + mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership); mAccountList = AccountList::create(); mCallList = CallList::create(); setAutoStart(mSettings->getAutoStart()); @@ -484,7 +493,7 @@ void App::initCore() { const QUrl url(u"qrc:/qt/qml/Linphone/view/Page/Window/Main/MainWindow.qml"_qs); QObject::connect( mEngine, &QQmlApplicationEngine::objectCreated, this, - [this, url](QObject *obj, const QUrl &objUrl) { + [this, url, coreStarted](QObject *obj, const QUrl &objUrl) { if (url == objUrl) { if (!obj) { lCritical() << log().arg("MainWindow.qml couldn't be load. The app will exit"); @@ -492,7 +501,7 @@ void App::initCore() { } auto window = qobject_cast(obj); setMainWindow(window); - QMetaObject::invokeMethod(obj, "initStackViewItem"); + setCoreStarted(coreStarted); #ifndef __APPLE__ // Enable TrayIconSystem. if (!QSystemTrayIcon::isSystemTrayAvailable()) @@ -523,6 +532,8 @@ void App::initCore() { } void App::initCppInterfaces() { + qmlRegisterSingletonType(Constants::MainQmlUri, 1, 0, "AppCpp", + [](QQmlEngine *engine, QJSEngine *) -> QObject * { return App::getInstance(); }); qmlRegisterSingletonType( Constants::MainQmlUri, 1, 0, "LoginPageCpp", [](QQmlEngine *engine, QJSEngine *) -> QObject * { static auto loginPage = new LoginPage(); @@ -698,6 +709,17 @@ void App::sendCommand() { } } +bool App::getCoreStarted() const { + return mCoreStarted; +} + +void App::setCoreStarted(bool started) { + if (mCoreStarted != started) { + mCoreStarted = started; + emit coreStartedChanged(mCoreStarted); + } +} + bool App::notify(QObject *receiver, QEvent *event) { bool done = true; try { diff --git a/Linphone/core/App.hpp b/Linphone/core/App.hpp index 1a762b95..0e227572 100644 --- a/Linphone/core/App.hpp +++ b/Linphone/core/App.hpp @@ -38,6 +38,7 @@ class QSystemTrayIcon; class App : public SingleApplication, public AbstractObject { Q_OBJECT + Q_PROPERTY(bool coreStarted READ getCoreStarted WRITE setCoreStarted NOTIFY coreStartedChanged) public: App(int &argc, char *argv[]); ~App(); @@ -113,6 +114,9 @@ public: void onLoggerInitialized(); void sendCommand(); + bool getCoreStarted() const; + void setCoreStarted(bool started); + QQuickWindow *getCallsWindow(QVariant callGui = QVariant()); void setCallsWindowProperty(const char *id, QVariant property); void closeCallsWindow(); @@ -141,6 +145,7 @@ public: signals: void mainWindowChanged(); + void coreStartedChanged(bool coreStarted); // void executeCommand(QString command); private: @@ -160,6 +165,7 @@ private: QSharedPointer> mCoreModelConnection; QSharedPointer> mCliModelConnection; bool mAutoStart = false; + bool mCoreStarted = false; QLocale mLocale = QLocale::system(); DECLARE_ABSTRACT_OBJECT diff --git a/Linphone/core/account/AccountList.cpp b/Linphone/core/account/AccountList.cpp index a11ceb7d..09f3b6a7 100644 --- a/Linphone/core/account/AccountList.cpp +++ b/Linphone/core/account/AccountList.cpp @@ -50,8 +50,8 @@ void AccountList::setSelf(QSharedPointer me) { mModelConnection = QSharedPointer>( new SafeConnection(me, CoreModel::getInstance()), &QObject::deleteLater); - mModelConnection->makeConnectToCore(&AccountList::lUpdate, [this]() { - mModelConnection->invokeToModel([this]() { + mModelConnection->makeConnectToCore(&AccountList::lUpdate, [this](bool isInitialization) { + mModelConnection->invokeToModel([this, isInitialization]() { // Avoid copy to lambdas QList> *accounts = new QList>(); mustBeInLinphoneThread(getClassName()); @@ -63,11 +63,12 @@ void AccountList::setSelf(QSharedPointer me) { if (it == defaultAccount) defaultAccountCore = AccountCore::create(defaultAccount); accounts->push_back(model); } - mModelConnection->invokeToCore([this, accounts, defaultAccountCore]() { + mModelConnection->invokeToCore([this, accounts, defaultAccountCore, isInitialization]() { mustBeInMainThread(getClassName()); resetData(*accounts); setHaveAccount(accounts->size() > 0); setDefaultAccount(defaultAccountCore); + if (isInitialization) setInitialized(true); delete accounts; }); }); @@ -80,11 +81,10 @@ void AccountList::setSelf(QSharedPointer me) { mModelConnection->invokeToCore([this, model]() { setDefaultAccount(model); }); } else mModelConnection->invokeToCore([this]() { setDefaultAccount(nullptr); }); }); - mModelConnection->makeConnectToModel(&CoreModel::accountRemoved, &AccountList::lUpdate); - mModelConnection->makeConnectToModel(&CoreModel::accountAdded, &AccountList::lUpdate); + mModelConnection->makeConnectToModel(&CoreModel::accountRemoved, [this] { emit lUpdate(); }); + mModelConnection->makeConnectToModel(&CoreModel::accountAdded, [this] { emit lUpdate(); }); - lUpdate(); - emit initialized(); + lUpdate(true); } QSharedPointer AccountList::getDefaultAccountCore() const { @@ -135,6 +135,17 @@ void AccountList::setHaveAccount(bool haveAccount) { } } +bool AccountList::isInitialized() const { + return mIsInitialized; +} + +void AccountList::setInitialized(bool init) { + if (mIsInitialized != init) { + mIsInitialized = init; + emit initializedChanged(mIsInitialized); + } +} + QVariant AccountList::data(const QModelIndex &index, int role) const { int row = index.row(); if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant(); diff --git a/Linphone/core/account/AccountList.hpp b/Linphone/core/account/AccountList.hpp index 5fc983e9..c32a78d0 100644 --- a/Linphone/core/account/AccountList.hpp +++ b/Linphone/core/account/AccountList.hpp @@ -49,15 +49,19 @@ public: bool getHaveAccount() const; void setHaveAccount(bool haveAccount); + bool isInitialized() const; + void setInitialized(bool init); + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; signals: - void lUpdate(); + void lUpdate(bool isInitialization = false); void haveAccountChanged(); void defaultAccountChanged(); - void initialized(); + void initializedChanged(bool init); private: bool mHaveAccount = false; + bool mIsInitialized = false; QSharedPointer mDefaultAccount; QSharedPointer> mModelConnection; DECLARE_ABSTRACT_OBJECT diff --git a/Linphone/core/account/AccountProxy.cpp b/Linphone/core/account/AccountProxy.cpp index 8af029ff..d9f4e27b 100644 --- a/Linphone/core/account/AccountProxy.cpp +++ b/Linphone/core/account/AccountProxy.cpp @@ -24,7 +24,7 @@ #include "core/App.hpp" AccountProxy::AccountProxy(QObject *parent) : LimitProxy(parent) { - setSourceModels(new SortFilterList(App::getInstance()->getAccountList().get(), Qt::AscendingOrder)); + setSourceModel(App::getInstance()->getAccountList().get()); } AccountProxy::~AccountProxy() { @@ -59,6 +59,17 @@ bool AccountProxy::getHaveAccount() const { return getListModel()->getHaveAccount(); } +bool AccountProxy::isInitialized() const { + return mInitialized; +} + +void AccountProxy::setInitialized(bool init) { + if (mInitialized != init) { + mInitialized = init; + emit initializedChanged(); + } +} + void AccountProxy::setSourceModel(QAbstractItemModel *model) { auto oldAccountList = getListModel(); if (oldAccountList) { @@ -66,6 +77,11 @@ void AccountProxy::setSourceModel(QAbstractItemModel *model) { } auto newAccountList = dynamic_cast(model); if (newAccountList) { + connect(newAccountList, &AccountList::initializedChanged, this, [this](bool init) { + qDebug() << "AccountProxy initialized"; + setInitialized(init); + }); + setInitialized(newAccountList->isInitialized()); connect(newAccountList, &AccountList::countChanged, this, &AccountProxy::resetDefaultAccount, Qt::QueuedConnection); connect(newAccountList, &AccountList::defaultAccountChanged, this, &AccountProxy::resetDefaultAccount, @@ -73,7 +89,7 @@ void AccountProxy::setSourceModel(QAbstractItemModel *model) { connect(newAccountList, &AccountList::haveAccountChanged, this, &AccountProxy::haveAccountChanged, Qt::QueuedConnection); } - QSortFilterProxyModel::setSourceModel(model); + setSourceModels(new SortFilterList(model, Qt::AscendingOrder)); } //------------------------------------------------------------------------------------------ diff --git a/Linphone/core/account/AccountProxy.hpp b/Linphone/core/account/AccountProxy.hpp index 601baa2b..e3fcf917 100644 --- a/Linphone/core/account/AccountProxy.hpp +++ b/Linphone/core/account/AccountProxy.hpp @@ -33,6 +33,7 @@ class AccountProxy : public LimitProxy { Q_PROPERTY(AccountGui *defaultAccount READ getDefaultAccount WRITE setDefaultAccount NOTIFY defaultAccountChanged) Q_PROPERTY(bool haveAccount READ getHaveAccount NOTIFY haveAccountChanged) + Q_PROPERTY(bool isInitialized READ isInitialized NOTIFY initializedChanged) public: DECLARE_SORTFILTER_CLASS() @@ -48,14 +49,18 @@ public: bool getHaveAccount() const; + bool isInitialized() const; + void setInitialized(bool init); + void setSourceModel(QAbstractItemModel *sourceModel) override; signals: void defaultAccountChanged(); void haveAccountChanged(); - void initialized(); + void initializedChanged(); protected: + bool mInitialized = false; QSharedPointer mDefaultAccount; // When null, a new UI object is build from List }; diff --git a/Linphone/core/proxy/LimitProxy.cpp b/Linphone/core/proxy/LimitProxy.cpp index 2c2e7bee..4f493f29 100644 --- a/Linphone/core/proxy/LimitProxy.cpp +++ b/Linphone/core/proxy/LimitProxy.cpp @@ -38,9 +38,11 @@ bool LimitProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent void LimitProxy::setSourceModels(SortFilterProxy *firstList) { auto secondList = firstList->sourceModel(); - connect(secondList, &QAbstractItemModel::rowsInserted, this, &LimitProxy::onAdded); - connect(secondList, &QAbstractItemModel::rowsRemoved, this, &LimitProxy::onRemoved); - connect(secondList, &QAbstractItemModel::modelReset, this, &LimitProxy::invalidateRowsFilter); + if (secondList) { + connect(secondList, &QAbstractItemModel::rowsInserted, this, &LimitProxy::onAdded); + connect(secondList, &QAbstractItemModel::rowsRemoved, this, &LimitProxy::onRemoved); + connect(secondList, &QAbstractItemModel::modelReset, this, &LimitProxy::invalidateRowsFilter); + } connect(firstList, &SortFilterProxy::filterTextChanged, this, &LimitProxy::filterTextChanged); connect(firstList, &SortFilterProxy::filterTypeChanged, this, &LimitProxy::filterTypeChanged); diff --git a/Linphone/view/Page/Main/Contact/ContactPage.qml b/Linphone/view/Page/Main/Contact/ContactPage.qml index 6f6b13cb..f88a996e 100644 --- a/Linphone/view/Page/Main/Contact/ContactPage.qml +++ b/Linphone/view/Page/Main/Contact/ContactPage.qml @@ -201,7 +201,7 @@ AbstractMainPage { spacing: 38 * DefaultStyle.dp SearchBar { id: searchBar - visible: contactList.model.sourceModel.count != 0 + visible: contactList.count != 0 Layout.leftMargin: leftPanel.leftMargin Layout.rightMargin: leftPanel.rightMargin Layout.topMargin: 18 * DefaultStyle.dp diff --git a/Linphone/view/Page/Window/Main/MainWindow.qml b/Linphone/view/Page/Window/Main/MainWindow.qml index 873d9cf2..b340a735 100644 --- a/Linphone/view/Page/Window/Main/MainWindow.qml +++ b/Linphone/view/Page/Window/Main/MainWindow.qml @@ -17,7 +17,8 @@ AbstractWindow { color: DefaultStyle.grey_0 signal callCreated() - + property var accountProxy: accountProxyLoader.item + // TODO : use this to make the border transparent // flags: Qt.Window | Qt.FramelessWindowHint | Qt.WindowTitleHint // menuBar: Rectangle { @@ -25,6 +26,7 @@ AbstractWindow { // height: 40 * DefaultStyle.dp // color: DefaultStyle.grey_100 // } + function openMainPage(){ if (mainWindowStackView.currentItem.objectName !== "mainPage") mainWindowStackView.replace(mainPage, StackView.Immediate) } @@ -45,10 +47,12 @@ AbstractWindow { UtilsCpp.showInformationPopup(qsTr("Appel transféré"), qsTr("Votre correspondant a été transféré au contact sélectionné")) } function initStackViewItem() { - if (accountProxy.haveAccount) openMainPage() - else if (SettingsCpp.getFirstLaunch()) mainWindowStackView.replace(welcomePage, StackView.Immediate) - else if (SettingsCpp.assistantGoDirectlyToThirdPartySipAccountLogin) mainWindowStackView.replace(sipLoginPage, StackView.Immediate) - else mainWindowStackView.replace(loginPage, StackView.Immediate) + if(accountProxy && accountProxy.isInitialized) { + if (accountProxy.haveAccount) openMainPage() + else if (SettingsCpp.getFirstLaunch()) mainWindowStackView.replace(welcomePage, StackView.Immediate) + else if (SettingsCpp.assistantGoDirectlyToThirdPartySipAccountLogin) mainWindowStackView.replace(sipLoginPage, StackView.Immediate) + else mainWindowStackView.replace(loginPage, StackView.Immediate) + } } function goToLogin() { @@ -90,9 +94,16 @@ AbstractWindow { } } - AccountProxy { - id: accountProxy - onInitialized: initStackViewItem() + Loader { + id: accountProxyLoader + active: AppCpp.coreStarted + sourceComponent: AccountProxy { + Component.onCompleted: { + mainWindow.accountProxy = this + mainWindow.initStackViewItem() + } + onInitializedChanged: mainWindow.initStackViewItem() + } } StackView {