Commit 873f9df4 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(src/app/App): remove usage of async creation of calls/settings window

parent a067245e
......@@ -83,7 +83,6 @@ endif()
set(SOURCES
src/app/App.cpp
src/app/logger/Logger.cpp
src/app/object-builders/AsyncObjectBuilder.cpp
src/app/paths/Paths.cpp
src/app/providers/AvatarProvider.cpp
src/app/providers/ThumbnailProvider.cpp
......@@ -121,7 +120,6 @@ set(SOURCES
set(HEADERS
src/app/App.hpp
src/app/logger/Logger.hpp
src/app/object-builders/AsyncObjectBuilder.hpp
src/app/paths/Paths.hpp
src/app/providers/AvatarProvider.hpp
src/app/providers/ThumbnailProvider.hpp
......
......@@ -215,8 +215,11 @@ void App::tryToUsePreferredLocale () {
// -----------------------------------------------------------------------------
QQuickWindow *App::getCallsWindow () const {
return qobject_cast<QQuickWindow *>(m_calls_window.getObject());
QQuickWindow *App::getCallsWindow () {
if (!m_calls_window)
m_calls_window = createSubWindow(this, QML_VIEW_CALLS_WINDOW);
return m_calls_window;
}
QQuickWindow *App::getMainWindow () const {
......@@ -225,14 +228,27 @@ QQuickWindow *App::getMainWindow () const {
);
}
QQuickWindow *App::getSettingsWindow () const {
return qobject_cast<QQuickWindow *>(m_settings_window.getObject());
QQuickWindow *App::getSettingsWindow () {
if (!m_settings_window) {
m_settings_window = createSubWindow(this, QML_VIEW_SETTINGS_WINDOW);
QObject::connect(
m_settings_window, &QWindow::visibilityChanged, this, [](QWindow::Visibility visibility) {
if (visibility == QWindow::Hidden) {
qInfo() << "Update nat policy.";
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
core->setNatPolicy(core->getNatPolicy());
}
}
);
}
return m_settings_window;
}
// -----------------------------------------------------------------------------
bool App::hasFocus () const {
return getMainWindow()->isActive() || (m_calls_window.isCreated() && getCallsWindow()->isActive());
return getMainWindow()->isActive() || (m_calls_window && m_calls_window->isActive());
}
// -----------------------------------------------------------------------------
......@@ -379,23 +395,6 @@ void App::openAppAfterInit () {
#else
getMainWindow()->showNormal();
#endif // ifndef __APPLE__
m_calls_window.createObject(&m_engine, QML_VIEW_CALLS_WINDOW);
m_settings_window.createObject(
&m_engine, QML_VIEW_SETTINGS_WINDOW, [this](QObject *object) {
QQuickWindow *window = qobject_cast<QQuickWindow *>(object);
QObject::connect(
window, &QWindow::visibilityChanged, this, [](QWindow::Visibility visibility) {
if (visibility == QWindow::Hidden) {
qInfo() << "Update nat policy.";
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
core->setNatPolicy(core->getNatPolicy());
}
}
);
}
);
}
// -----------------------------------------------------------------------------
......
......@@ -25,7 +25,6 @@
#include "../components/notifier/Notifier.hpp"
#include "../externals/single-application/SingleApplication.hpp"
#include "object-builders/AsyncObjectBuilder.hpp"
#include <QCommandLineParser>
#include <QQmlApplicationEngine>
......@@ -59,12 +58,12 @@ public:
return m_notifier;
}
QQuickWindow *getCallsWindow () const;
QQuickWindow *getCallsWindow ();
QQuickWindow *getMainWindow () const;
bool hasFocus () const;
Q_INVOKABLE QQuickWindow *getSettingsWindow () const;
Q_INVOKABLE QQuickWindow *getSettingsWindow ();
static App *getInstance () {
return static_cast<App *>(QApplication::instance());
......@@ -101,8 +100,8 @@ private:
DefaultTranslator *m_translator = nullptr;
Notifier *m_notifier = nullptr;
AsyncObjectBuilder m_calls_window;
AsyncObjectBuilder m_settings_window;
QQuickWindow *m_calls_window = nullptr;
QQuickWindow *m_settings_window = nullptr;
};
#endif // APP_H_
/*
* AsyncObjectBuilder.cpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: March 27, 2017
* Author: Ronan Abhamon
*/
#include <QCoreApplication>
#include <QDebug>
#include <QQmlIncubator>
#include "AsyncObjectBuilder.hpp"
using namespace std;
// =============================================================================
class AsyncObjectBuilder::ObjectIncubator : public QQmlIncubator {
public:
// FIXME: At this moment, asynchronous loading is unstable.
// In the future, use `IncubationMode::Asynchronous` instead in Qt 5.9.
//
// See: https://bugreports.qt.io/browse/QTBUG-49416 and
// https://bugreports.qt.io/browse/QTBUG-50992
ObjectIncubator (AsyncObjectBuilder *builder) : QQmlIncubator(IncubationMode::Synchronous) {
Q_ASSERT(builder != nullptr);
m_builder = builder;
}
protected:
void statusChanged (Status status) override {
if (status == Error) {
qWarning() << "ObjectIncubator failed to build component:" << errors();
abort();
}
if (status == Ready) {
QObject *object = QQmlIncubator::object();
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
object->setParent(m_builder);
// Call user decorator.
if (m_builder->m_decorator)
m_builder->m_decorator(object);
qInfo() << QStringLiteral("Creation of component instance is successful:") << m_builder->m_component;
m_builder->m_object = object;
emit m_builder->objectCreated(object);
Q_ASSERT(m_builder->m_component != nullptr);
Q_ASSERT(m_builder->m_incubator != nullptr);
// Optimization: Delete unused component now.
m_builder->m_component->deleteLater();
// Optimization: Delete unused incubator.
m_builder->m_incubator = nullptr;
delete this; // Very courageous but works.
}
}
private:
AsyncObjectBuilder *m_builder;
};
// -----------------------------------------------------------------------------
AsyncObjectBuilder::AsyncObjectBuilder (QObject *parent) : QObject(parent) {}
AsyncObjectBuilder::~AsyncObjectBuilder () {
delete m_incubator;
}
void AsyncObjectBuilder::createObject (QQmlEngine *engine, const char *path, Decorator decorator) {
#ifdef QT_DEBUG
Q_ASSERT(!m_block_creation);
m_block_creation = true;
Q_ASSERT(engine != nullptr);
Q_ASSERT(path != nullptr);
#endif // ifdef QT_DEBUG
m_component = new QQmlComponent(engine, QUrl(path), QQmlComponent::Asynchronous, this);
m_decorator = decorator;
qInfo() << QStringLiteral("Start async creation of: `%1`. Component:").arg(path) << m_component;
QObject::connect(
m_component, &QQmlComponent::statusChanged,
this, &AsyncObjectBuilder::handleComponentCreation,
Qt::DirectConnection
);
}
QObject *AsyncObjectBuilder::getObject () const {
while (!m_object)
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
return m_object;
}
void AsyncObjectBuilder::handleComponentCreation (QQmlComponent::Status status) {
if (status == QQmlComponent::Ready) {
qInfo() << QStringLiteral("Component built:") << m_component;
m_incubator = new ObjectIncubator(this);
qInfo() << QStringLiteral("Start creation of component instance:") << m_component;
m_component->create(*m_incubator);
} else if (status == QQmlComponent::Error) {
qWarning() << "AsyncObjectBuilder failed to build component:" << m_component->errors();
abort();
}
}
/*
* AsyncObjectBuilder.hpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: March 27, 2017
* Author: Ronan Abhamon
*/
#ifndef ASYNC_OBJECT_BUILDER_H_
#define ASYNC_OBJECT_BUILDER_H_
#include <functional>
#include <QQmlComponent>
#include <QQmlEngine>
// =============================================================================
class AsyncObjectBuilder : public QObject {
Q_OBJECT;
class ObjectIncubator;
typedef std::function<void (QObject *)> Decorator;
public:
AsyncObjectBuilder (QObject *parent = Q_NULLPTR);
~AsyncObjectBuilder ();
void createObject (QQmlEngine *engine, const char *path, Decorator decorator = nullptr);
QObject *getObject () const;
bool isCreated () const {
return !!m_object;
}
signals:
void objectCreated (QObject *object);
private:
void handleComponentCreation (QQmlComponent::Status status);
ObjectIncubator *m_incubator = nullptr;
QQmlComponent *m_component = nullptr;
Decorator m_decorator;
QObject *m_object = nullptr;
#ifdef QT_DEBUG
bool m_block_creation = false;
#endif // ifdef QT_DEBUG
};
#endif // ASYNC_OBJECT_BUILDER_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment