Fix crash on exit.

Add Async/Sync functions to post lambda on model thread.
Fix missing defines on headers.
Move Login c++ logic into core for MVVM.
Write async login.
Auto core iterate (30ms).
Clean exit by stopping core before deletion.
This commit is contained in:
Julien Wadel 2023-10-11 11:53:23 +02:00
parent 1adbfa6f98
commit 99ebfd2f7b
20 changed files with 465 additions and 38 deletions

View file

@ -23,9 +23,9 @@
#include <QCoreApplication>
#include "core/logger/QtLogger.hpp"
#include "core/login/LoginPage.hpp"
#include "core/singleapplication/singleapplication.h"
#include "tool/Constants.hpp"
#include "view/Page/LoginPage.hpp"
App::App(int &argc, char *argv[])
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
@ -35,14 +35,18 @@ App::App(int &argc, char *argv[])
mLinphoneThread->start();
}
App *App::getInstance() {
return dynamic_cast<App *>(QApplication::instance());
}
//-----------------------------------------------------------
// Initializations
//-----------------------------------------------------------
void App::init() {
// Core. Manage the logger so it must be instantiate at first.
mCoreModel = QSharedPointer<CoreModel>::create("", mLinphoneThread);
auto coreModel = CoreModel::create("", mLinphoneThread);
connect(mLinphoneThread, &QThread::started, coreModel.get(), &CoreModel::start);
// Console Commands
createCommandParser();
mParser->parse(this->arguments());
@ -54,7 +58,6 @@ void App::init() {
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
connect(mLinphoneThread, &QThread::started, mCoreModel.get(), &CoreModel::start);
// QML
mEngine = new QQmlApplicationEngine(this);
mEngine->addImportPath(":/");
@ -78,6 +81,13 @@ void App::initCppInterfaces() {
}
//------------------------------------------------------------
void App::clean() {
mLinphoneThread->exit();
mLinphoneThread->wait();
delete mLinphoneThread;
}
void App::createCommandParser() {
if (!mParser) delete mParser;

View file

@ -29,18 +29,35 @@
class App : public SingleApplication {
public:
App(int &argc, char *argv[]);
static App* getInstance();
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
template<typename Func, typename... Args>
static auto postModelAsync(Func&& callable, Args&& ...args) {
QMetaObject::invokeMethod(CoreModel::getInstance().get(), callable, args...);
}
template<typename Func>
static auto postModelAsync(Func&& callable) {
QMetaObject::invokeMethod(CoreModel::getInstance().get(), callable);
}
template<typename Func>
static auto postModelSync(Func&& callable) {
QMetaObject::invokeMethod(CoreModel::getInstance().get(), callable
, QThread::currentThread() != CoreModel::getInstance()->thread() ? Qt::BlockingQueuedConnection : Qt::DirectConnection);
}
void clean();
void init();
void initCppInterfaces();
void onLoggerInitialized();
QQmlApplicationEngine *mEngine = nullptr;
Thread *mLinphoneThread = nullptr;
QSharedPointer<CoreModel> mCoreModel;
private:
void createCommandParser();
QCommandLineParser *mParser = nullptr;
Thread *mLinphoneThread = nullptr;
};

View file

@ -1,6 +1,7 @@
list(APPEND _LINPHONEAPP_SOURCES
core/App.cpp
core/logger/QtLogger.cpp
core/login/LoginPage.cpp
core/path/Paths.cpp
core/setting/Settings.cpp
core/thread/Thread.cpp

View file

@ -18,8 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOGGER_STATIC_MODEL_H_
#define LOGGER_STATIC_MODEL_H_
#ifndef QT_LOGGER_H_
#define QT_LOGGER_H_
#include <QMetaMethod>
#include <QObject>

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* 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 "LoginPage.hpp"
#include <QTimer>
#include "core/App.hpp"
#include "model/account/AccountManager.hpp"
LoginPage::LoginPage(QObject *parent) : QObject(parent) {
}
bool LoginPage::isLogged() const {
// View thread
return mIsLogged;
}
void LoginPage::setIsLogged(bool status) {
// Should be view thread only because of object updates.
if (mIsLogged != status) {
mIsLogged = status;
emit isLoggedChanged();
}
}
void LoginPage::login(const QString &username, const QString &password) {
App::postModelAsync([=]() {
// Create on Model thread.
AccountManager *accountManager = new AccountManager();
connect(accountManager, &AccountManager::logged, this, [accountManager, this](bool isLoggued) mutable {
// View thread
setIsLogged(isLoggued);
accountManager->deleteLater();
});
accountManager->login(username, password);
});
}

View file

@ -27,9 +27,14 @@ public:
LoginPage(QObject *parent = nullptr);
Q_PROPERTY(bool isLogged READ isLogged NOTIFY isLoggedChanged)
Q_INVOKABLE void login(const QString& username, const QString& password);
bool isLogged();
bool isLogged() const;
void setIsLogged(bool status);
signals:
void isLoggedChanged();
};
private:
bool mIsLogged = false;
};

View file

@ -27,6 +27,6 @@ void Thread::run() {
int toExit = false;
while (!toExit) {
int result = exec();
if (result < 0) toExit = true;
if (result <= 0) toExit = true;
}
}
}

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">1</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>
<entry name="publish" overwrite="true">1</entry>
<entry name="publish_expires" overwrite="true">120</entry>
<entry name="quality_reporting_collector" overwrite="true">sip:voip-metrics@sip.linphone.org;transport=tls</entry>
<entry name="quality_reporting_enabled" overwrite="true">1</entry>
<entry name="quality_reporting_interval" overwrite="true">180</entry>
<entry name="reg_expires" overwrite="true">600</entry>
<entry name="reg_identity" overwrite="true">sip:?@sip.linphone.org</entry>
<entry name="reg_proxy" overwrite="true">&lt;sip:sip.linphone.org;transport=tls&gt;</entry>
<entry name="reg_sendregister" overwrite="true">1</entry>
<entry name="nat_policy_ref" overwrite="true">default_nat_policy_values</entry>
<entry name="realm" overwrite="true">sip.linphone.org</entry>
<entry name="contact_parameters" overwrite="true">message-expires=2419200</entry>
<entry name="conference_factory_uri" overwrite="true">sip:conference-factory@sip.linphone.org</entry>
<entry name="audio_video_conference_factory_uri" overwrite="true">sip:videoconference-factory@sip.linphone.org</entry>
<entry name="cpim_in_basic_chat_rooms_enabled" overwrite="true">1</entry>
<entry name="rtp_bundle" overwrite="true">1</entry>
<entry name="lime_server_url" overwrite="true">https://lime.linphone.org/lime-server/lime-server.php</entry>
</section>
<section name="default_nat_policy_values">
<entry name="stun_server" overwrite="true">stun.linphone.org</entry>
<entry name="protocols" overwrite="true">stun,ice</entry>
</section>
<section name="misc">
<entry name="file_transfer_server_url" overwrite="true">https://www.linphone.org:444/lft.php</entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true">sips:rls@sip.linphone.org</entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="algorithm" overwrite="true">SHA-256</entry>
<entry name="password_max_length" overwrite="true">-1</entry>
<entry name="password_min_length" overwrite="true">1</entry>
<entry name="username_length" overwrite="true">-1</entry>
<entry name="username_max_length" overwrite="true">64</entry>
<entry name="username_min_length" overwrite="true">1</entry>
<entry name="username_regex" overwrite="true">^[a-z0-9+_.\-]*$</entry>
<entry name="xmlrpc_url" overwrite="true">https://subscribe.linphone.org:444/wizard.php</entry>
</section>
<section name="account_creator">
<entry name="backend" overwrite="true">1</entry>
<entry name="url" overwrite="true">https://subscribe.linphone.org/api/</entry>
</section>
</config>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">1</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>
<entry name="publish" overwrite="true">1</entry>
<entry name="publish_expires" overwrite="true">120</entry>
<entry name="quality_reporting_collector" overwrite="true">sip:voip-metrics@sip.linphone.org;transport=tls</entry>
<entry name="quality_reporting_enabled" overwrite="true">1</entry>
<entry name="quality_reporting_interval" overwrite="true">180</entry>
<entry name="reg_expires" overwrite="true">600</entry>
<entry name="reg_identity" overwrite="true">sip:?@sip.linphone.org</entry>
<entry name="reg_proxy" overwrite="true">&lt;sip:sip.linphone.org;transport=tls&gt;</entry>
<entry name="reg_sendregister" overwrite="true">1</entry>
<entry name="nat_policy_ref" overwrite="true">default_nat_policy_values</entry>
<entry name="realm" overwrite="true">sip.linphone.org</entry>
<entry name="contact_parameters" overwrite="true">message-expires=2419200</entry>
<entry name="conference_factory_uri" overwrite="true">sip:conference-factory@sip.linphone.org</entry>
<entry name="audio_video_conference_factory_uri" overwrite="true">sip:videoconference-factory@sip.linphone.org</entry>
<entry name="cpim_in_basic_chat_rooms_enabled" overwrite="true">1</entry>
<entry name="rtp_bundle" overwrite="true">1</entry>
<entry name="lime_server_url" overwrite="true">https://lime.linphone.org/lime-server/lime-server.php</entry>
</section>
<section name="default_nat_policy_values">
<entry name="stun_server" overwrite="true">stun.linphone.org</entry>
<entry name="protocols" overwrite="true">stun,ice</entry>
</section>
<section name="misc">
<entry name="file_transfer_server_url" overwrite="true">https://www.linphone.org:444/lft.php</entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true">sips:rls@sip.linphone.org</entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="algorithm" overwrite="true">SHA-256</entry>
<entry name="password_max_length" overwrite="true">-1</entry>
<entry name="password_min_length" overwrite="true">1</entry>
<entry name="username_length" overwrite="true">-1</entry>
<entry name="username_max_length" overwrite="true">64</entry>
<entry name="username_min_length" overwrite="true">1</entry>
<entry name="username_regex" overwrite="true">^[a-z0-9+_.\-]*$</entry>
<entry name="xmlrpc_url" overwrite="true">https://subscribe.linphone.org:444/wizard.php</entry>
</section>
<section name="account_creator">
<entry name="backend" overwrite="true">1</entry>
<entry name="url" overwrite="true">https://subscribe.linphone.org/api/</entry>
</section>
</config>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">0</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>
<entry name="publish" overwrite="true">0</entry>
<entry name="quality_reporting_collector" overwrite="true"></entry>
<entry name="quality_reporting_enabled" overwrite="true">0</entry>
<entry name="quality_reporting_interval" overwrite="true">0</entry>
<entry name="reg_expires" overwrite="true">3600</entry>
<entry name="reg_identity" overwrite="true"></entry>
<entry name="reg_proxy" overwrite="true"></entry>
<entry name="reg_route" overwrite="true"></entry>
<entry name="reg_sendregister" overwrite="true">1</entry>
<entry name="nat_policy_ref" overwrite="true"></entry>
<entry name="refkey" overwrite="true"></entry>
<entry name="realm" overwrite="true"></entry>
<entry name="conference_factory_uri" overwrite="true"></entry>
<entry name="audio_video_conference_factory_uri" overwrite="true"></entry>
<entry name="lime_server_url" overwrite="true"></entry>
</section>
<section name="default_nat_policy_values">
<entry name="stun_server" overwrite="true"></entry>
<entry name="protocols" overwrite="true"></entry>
</section>
<section name="sip">
<entry name="use_rls_presence" overwrite="true"></entry>
<entry name="rls_uri" overwrite="true"></entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true"></entry>
<entry name="algorithm" overwrite="true">MD5</entry>
<entry name="password_max_length" overwrite="true">-1</entry>
<entry name="password_min_length" overwrite="true">0</entry>
<entry name="username_length" overwrite="true">-1</entry>
<entry name="username_max_length" overwrite="true">128</entry>
<entry name="username_min_length" overwrite="true">1</entry>
<entry name="username_regex" overwrite="true">^[a-zA-Z0-9+_.\-]*$</entry>
</section>
</config>

View file

@ -20,5 +20,6 @@ int main(int argc, char *argv[]) {
}
int result = app.exec();
app.clean();
return result;
}

View file

@ -1,4 +1,7 @@
list(APPEND _LINPHONEAPP_SOURCES
model/account/AccountListener.cpp
model/account/AccountManager.cpp
model/core/CoreModel.cpp
model/core/CoreListener.cpp

View file

@ -18,17 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LoginPage.hpp"
#include <QTimer>
#include "AccountListener.hpp"
LoginPage::LoginPage(QObject *parent) : QObject(parent) {
#include <QDebug>
AccountListener::AccountListener(QObject *parent) : QObject(parent) {
}
bool LoginPage::isLogged() {
static bool testLog = false;
QTimer::singleShot(2000, [&]() mutable {
testLog = true;
emit isLoggedChanged();
});
return testLog;
}
void AccountListener::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
linphone::RegistrationState state,
const std::string &message) {
emit registrationStateChanged(account, state, message);
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* 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/>.
*/
#ifndef ACCOUNT_LISTENER_H_
#define ACCOUNT_LISTENER_H_
#include <QObject>
#include <linphone++/linphone.hh>
class AccountListener : public QObject, public linphone::AccountListener {
Q_OBJECT
public:
AccountListener(QObject *parent = nullptr);
virtual void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
linphone::RegistrationState state,
const std::string &message) override;
signals:
void registrationStateChanged(const std::shared_ptr<linphone::Account> & account, linphone::RegistrationState state, const std::string & message);
};
#endif

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* 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 "AccountManager.hpp"
#include <QDebug>
#include "core/path/Paths.hpp"
#include "model/core/CoreModel.hpp"
#include "tool/Utils.hpp"
AccountManager::AccountManager(QObject *parent) : QObject(parent) {
}
std::shared_ptr<linphone::Account> AccountManager::createAccount(const QString &assistantFile) {
auto core = CoreModel::getInstance()->getCore();
QString assistantPath = Paths::getAssistantConfigDirPath() + assistantFile;
qInfo() << QStringLiteral("[AccountManager] Set config on assistant: `%1`.").arg(assistantPath);
core->getConfig()->loadFromXmlFile(Utils::appStringToCoreString(assistantPath));
return core->createAccount(core->createAccountParams());
}
bool AccountManager::login(QString username, QString password) {
auto core = CoreModel::getInstance()->getCore();
auto factory = linphone::Factory::get();
auto account = createAccount("use-app-sip-account.rc");
auto params = account->getParams()->clone();
// Sip address.
auto identity = params->getIdentityAddress()->clone();
if (mAccountListener) return false;
identity->setUsername(Utils::appStringToCoreString(username));
if (params->setIdentityAddress(identity)) {
qWarning() << QStringLiteral("[AccountManager] Unable to set identity address: `%1`.")
.arg(Utils::coreStringToAppString(identity->asStringUriOnly()));
return false;
}
core->addAuthInfo(factory->createAuthInfo(Utils::appStringToCoreString(username), // Username.
"", // User ID.
Utils::appStringToCoreString(password), // Password.
"", // HA1.
"", // Realm.
identity->getDomain() // Domain.
));
mAccountListener = std::make_shared<AccountListener>(this);
account->addListener(mAccountListener);
connect(mAccountListener.get(), &AccountListener::registrationStateChanged, this,
&AccountManager::onRegistrationStateChanged);
core->addAccount(account);
return true;
}
void AccountManager::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
linphone::RegistrationState state,
const std::string &message) {
auto core = CoreModel::getInstance()->getCore();
switch (state) {
case linphone::RegistrationState::Failed:
core->removeAccount(account);
account->removeListener(mAccountListener);
mAccountListener = nullptr;
emit logged(false);
break;
case linphone::RegistrationState::Ok:
account->removeListener(mAccountListener);
mAccountListener = nullptr;
emit logged(true);
break;
default: {
}
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* 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/>.
*/
#ifndef ACCOUNT_MANAGER_H_
#define ACCOUNT_MANAGER_H_
#include <QObject>
#include <linphone++/linphone.hh>
#include "AccountListener.hpp"
class AccountManager: public QObject {
Q_OBJECT
public:
AccountManager(QObject *parent = nullptr);
bool login(QString username, QString password);
std::shared_ptr<linphone::Account> createAccount(const QString& assistantFile);
void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> & account, linphone::RegistrationState state, const std::string & message);
signals:
void logged(bool isLoggued);
private:
std::shared_ptr<AccountListener> mAccountListener;
};
#endif

View file

@ -27,21 +27,39 @@
#include <QSysInfo>
#include <QTimer>
#include "core/App.hpp"
#include "core/path/Paths.hpp"
#include "tool/Utils.hpp"
// =============================================================================
CoreModel::CoreModel(const QString &configPath, QObject *parent) : QObject(parent) {
QSharedPointer<CoreModel> CoreModel::gCoreModel;
CoreModel::CoreModel(const QString &configPath, QThread *parent) : QObject() {
connect(parent, &QThread::finished, this, [this]() {
// Model thread
if (mCore && mCore->getGlobalState() == linphone::GlobalState::On) mCore->stop();
gCoreModel = nullptr;
});
mConfigPath = configPath;
mLogger = std::make_shared<LoggerModel>(this);
mLogger->init();
moveToThread(parent);
}
CoreModel::~CoreModel() {
}
QSharedPointer<CoreModel> CoreModel::create(const QString &configPath, QThread *parent) {
auto model = QSharedPointer<CoreModel>::create(configPath, parent);
gCoreModel = model;
return model;
}
void CoreModel::start() {
mIterateTimer = new QTimer(this);
mIterateTimer->setInterval(30);
connect(mIterateTimer, &QTimer::timeout, [this]() { mCore->iterate(); });
setPathBeforeCreation();
mCore =
linphone::Factory::get()->createCore(Utils::appStringToCoreString(Paths::getConfigFilePath(mConfigPath)),
@ -49,12 +67,12 @@ void CoreModel::start() {
setPathsAfterCreation();
mCore->start();
setPathAfterStart();
mCore->enableAutoIterate(true);
mIterateTimer->start();
}
// -----------------------------------------------------------------------------
CoreModel *CoreModel::getInstance() {
return nullptr;
QSharedPointer<CoreModel> CoreModel::getInstance() {
return gCoreModel;
}
std::shared_ptr<linphone::Core> CoreModel::getCore() {

View file

@ -25,6 +25,7 @@
#include <QSharedPointer>
#include <QString>
#include <QThread>
#include <QTimer>
#include <linphone++/linphone.hh>
#include "model/logger/LoggerModel.hpp"
@ -34,15 +35,14 @@
class CoreModel : public QObject {
Q_OBJECT
public:
CoreModel(const QString &configPath, QObject *parent);
CoreModel(const QString &configPath, QThread * parent);
~CoreModel();
static QSharedPointer<CoreModel> create(const QString &configPath, QThread * parent);
static QSharedPointer<CoreModel> getInstance();
std::shared_ptr<linphone::Core> getCore();
void start();
static CoreModel *getInstance();
void setConfigPath(QString path);
@ -55,11 +55,13 @@ signals:
void loggerInitialized();
private:
QString mConfigPath;
QTimer *mIterateTimer = nullptr;
void setPathBeforeCreation();
void setPathsAfterCreation();
void setPathAfterStart();
static QSharedPointer<CoreModel> gCoreModel;
};
#endif

View file

@ -7,9 +7,4 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Page/LoginPage.qml
)
list(APPEND _LINPHONEAPP_SOURCES
view/Page/LoginPage.cpp
)
set(_LINPHONEAPP_QML_FILES ${_LINPHONEAPP_QML_FILES} PARENT_SCOPE)
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)

View file

@ -13,7 +13,7 @@ Item{
RowLayout{
Button{
text: 'Sign In'
onClicked: console.log("Click!")
onClicked: LoginPageCpp.login("myusername", "passy")
}
Button{
text: 'Sign Out'
@ -22,4 +22,4 @@ Item{
}
}
}