diff --git a/src/kdeclarative/CMakeLists.txt b/src/kdeclarative/CMakeLists.txt index da2e673..014b400 100644 --- a/src/kdeclarative/CMakeLists.txt +++ b/src/kdeclarative/CMakeLists.txt @@ -1,68 +1,67 @@ set(kdeclarative_SRCS configpropertymap.cpp qmlobject.cpp qmlobjectsharedengine.cpp kdeclarative.cpp private/kiconprovider.cpp private/kioaccessmanagerfactory.cpp - private/qmlobject_p.h ) add_library(KF5Declarative ${kdeclarative_SRCS}) generate_export_header(KF5Declarative EXPORT_FILE_NAME ${KDeclarative_BINARY_DIR}/kdeclarative/kdeclarative_export.h BASE_NAME KDeclarative) add_library(KF5::Declarative ALIAS KF5Declarative) # Apps must include or target_include_directories(KF5Declarative INTERFACE "$") target_link_libraries(KF5Declarative PUBLIC KF5::ConfigCore # KCoreConfigSkeleton, in ConfigPropertyMap Qt5::Qml KF5::Package PRIVATE Qt5::Quick #QQuickImageProvider KF5::I18n #i18n bindings KF5::KIOWidgets #KIO::AccessManager KF5::IconThemes #KIconProvider ) target_include_directories(KF5Declarative PUBLIC "$") set_target_properties(KF5Declarative PROPERTIES VERSION ${KDECLARATIVE_VERSION_STRING} SOVERSION ${KDECLARATIVE_SOVERSION} EXPORT_NAME Declarative ) # Install files ecm_generate_headers(KDeclarative_CamelCase_HEADERS HEADER_NAMES KDeclarative QmlObject QmlObjectSharedEngine ConfigPropertyMap PREFIX KDeclarative REQUIRED_HEADERS KDeclarative_HEADERS ) install(FILES ${KDeclarative_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KDeclarative/KDeclarative COMPONENT Devel) install(TARGETS KF5Declarative EXPORT KF5DeclarativeTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ) install(FILES ${KDeclarative_BINARY_DIR}/kdeclarative/kdeclarative_export.h ${KDeclarative_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KDeclarative/kdeclarative COMPONENT Devel ) # make available to ecm_add_qch in parent folder set(KDeclarative_QCH_SOURCES ${KDeclarative_HEADERS} PARENT_SCOPE) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KDeclarative LIB_NAME KF5Declarative DEPS "qml" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KDeclarative) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/kdeclarative/private/qmlobject_p.h b/src/kdeclarative/private/qmlobject_p.h deleted file mode 100644 index 74c51d0..0000000 --- a/src/kdeclarative/private/qmlobject_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2013 Marco Martin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2, 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 Library 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. - */ - -#ifndef QMLOBJECT_P_H -#define QMLOBJECT_P_H - -#include -#include - -#include -#include -#include -#include - -class QQmlEngine; -class QQmlComponent; - -namespace KDeclarative { - -class QmlObjectIncubationController : public QObject, public QQmlIncubationController -{ - Q_OBJECT - -public: - QmlObjectIncubationController(QObject *parent) - : QObject(parent), - QQmlIncubationController() - { - // Allow incubation for 1/3 of a frame. - m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3); - } - -protected: - bool event(QEvent *e) Q_DECL_OVERRIDE - { - if (e->type() == QEvent::User) { - incubate(); - return true; - } - return QObject::event(e); - } - -public Q_SLOTS: - void incubate() - { - if (incubatingObjectCount()) { - incubateFor(m_incubation_time * 2); - if (incubatingObjectCount()) { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - } - } - } - - void animationStopped() - { - incubate(); - } - -protected: - void incubatingObjectCountChanged(int count) Q_DECL_OVERRIDE - { - if (count) { - incubate(); - } - QQmlIncubationController::incubatingObjectCountChanged(count); - } -private: - int m_incubation_time; -}; - -} - -#endif // multiple inclusion guard diff --git a/src/kdeclarative/qmlobject.cpp b/src/kdeclarative/qmlobject.cpp index 4bf24ed..18a858e 100644 --- a/src/kdeclarative/qmlobject.cpp +++ b/src/kdeclarative/qmlobject.cpp @@ -1,377 +1,373 @@ /* * Copyright 2013 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "qmlobject.h" -#include "private/qmlobject_p.h" #include "private/kdeclarative_p.h" #include #include #include #include #include #include #include #include #include #include //#include "packageaccessmanagerfactory.h" //#include "private/declarative/dataenginebindings_p.h" namespace KDeclarative { class QmlObjectIncubator : public QQmlIncubator { public: QVariantHash m_initialProperties; protected: void setInitialState(QObject *object) Q_DECL_OVERRIDE { QHashIterator i(m_initialProperties); while (i.hasNext()) { i.next(); object->setProperty(i.key().toLatin1().data(), i.value()); } } }; class QmlObjectPrivate { public: QmlObjectPrivate(QmlObject *parent) : q(parent), engine(nullptr), component(nullptr), delay(false) { executionEndTimer = new QTimer(q); executionEndTimer->setInterval(0); executionEndTimer->setSingleShot(true); QObject::connect(executionEndTimer, SIGNAL(timeout()), q, SLOT(scheduleExecutionEnd())); } ~QmlObjectPrivate() { delete incubator.object(); } void errorPrint(QQmlComponent *component); void execute(const QUrl &source); void scheduleExecutionEnd(); void minimumWidthChanged(); void minimumHeightChanged(); void maximumWidthChanged(); void maximumHeightChanged(); void preferredWidthChanged(); void preferredHeightChanged(); void checkInitializationCompleted(); QmlObject *q; QUrl source; QQmlEngine *engine; QmlObjectIncubator incubator; QQmlComponent *component; QTimer *executionEndTimer; KDeclarative kdeclarative; KPackage::Package package; QQmlContext *rootContext; bool delay : 1; }; void QmlObjectPrivate::errorPrint(QQmlComponent *component) { QString errorStr = QStringLiteral("Error loading QML file.\n"); if (component->isError()) { QList errors = component->errors(); foreach (const QQmlError &error, errors) { errorStr += (error.line() > 0 ? QString(QString::number(error.line()) + QLatin1String(": ")) : QLatin1String("")) + error.description() + QLatin1Char('\n'); } } qWarning() << component->url().toString() << '\n' << errorStr; } void QmlObjectPrivate::execute(const QUrl &source) { if (source.isEmpty()) { qWarning() << "File name empty!"; return; } delete component; component = new QQmlComponent(engine, q); QObject::connect(component, &QQmlComponent::statusChanged, q, &QmlObject::statusChanged, Qt::QueuedConnection); delete incubator.object(); component->loadUrl(source); if (delay) { executionEndTimer->start(0); } else { scheduleExecutionEnd(); } } void QmlObjectPrivate::scheduleExecutionEnd() { if (component->isReady() || component->isError()) { q->completeInitialization(); } else { QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)), q, SLOT(completeInitialization())); } } QmlObject::QmlObject(QObject *parent) : QObject(parent), d(new QmlObjectPrivate(this)) { d->engine = new QQmlEngine(this); d->rootContext = d->engine->rootContext(); d->kdeclarative.setDeclarativeEngine(d->engine); d->kdeclarative.d->qmlObj = this; //binds things like kconfig and icons d->kdeclarative.setupBindings(); - d->engine->setIncubationController(new QmlObjectIncubationController(this)); } QmlObject::QmlObject(QQmlEngine *engine, QObject *parent) : QObject(parent), d(new QmlObjectPrivate(this)) { if (engine) { d->engine = engine; } else { d->engine = new QQmlEngine(this); - d->engine->setIncubationController(new QmlObjectIncubationController(this)); } d->rootContext = d->engine->rootContext(); d->kdeclarative.setDeclarativeEngine(d->engine); d->kdeclarative.d->qmlObj = this; //binds things like kconfig and icons d->kdeclarative.setupBindings(); } QmlObject::QmlObject(QQmlEngine *engine, QQmlContext *rootContext, QObject *parent) : QObject(parent), d(new QmlObjectPrivate(this)) { if (engine) { d->engine = engine; } else { d->engine = new QQmlEngine(this); - d->engine->setIncubationController(new QmlObjectIncubationController(0)); } if (rootContext) { d->rootContext = rootContext; } else { d->rootContext = d->engine->rootContext(); } d->kdeclarative.setDeclarativeEngine(d->engine); d->kdeclarative.d->qmlObj = this; //binds things like kconfig and icons d->kdeclarative.setupBindings(); } QmlObject::~QmlObject() { // QDeclarativeNetworkAccessManagerFactory *factory = d->engine->networkAccessManagerFactory(); // d->engine->setNetworkAccessManagerFactory(0); // delete factory; delete d; } void QmlObject::setTranslationDomain(const QString &translationDomain) { d->kdeclarative.setTranslationDomain(translationDomain); } QString QmlObject::translationDomain() const { return d->kdeclarative.translationDomain(); } void QmlObject::setSource(const QUrl &source) { d->source = source; d->execute(source); } QUrl QmlObject::source() const { return d->source; } void QmlObject::loadPackage(const QString &packageName) { d->package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("KPackage/GenericQML")); d->package.setPath(packageName); setSource(QUrl::fromLocalFile(d->package.filePath("mainscript"))); } void QmlObject::setPackage(const KPackage::Package &package) { d->package = package; setSource(QUrl::fromLocalFile(package.filePath("mainscript"))); } KPackage::Package QmlObject::package() const { return d->package; } void QmlObject::setInitializationDelayed(const bool delay) { d->delay = delay; } bool QmlObject::isInitializationDelayed() const { return d->delay; } QQmlEngine *QmlObject::engine() { return d->engine; } QObject *QmlObject::rootObject() const { if (d->incubator.status() == QQmlIncubator::Loading) { qWarning() << "Trying to use rootObject before initialization is completed, whilst using setInitializationDelayed. Forcing completion"; d->incubator.forceCompletion(); } return d->incubator.object(); } QQmlComponent *QmlObject::mainComponent() const { return d->component; } QQmlContext *QmlObject::rootContext() const { return d->rootContext; } QQmlComponent::Status QmlObject::status() const { if (!d->engine) { return QQmlComponent::Error; } if (!d->component) { return QQmlComponent::Null; } return QQmlComponent::Status(d->component->status()); } void QmlObjectPrivate::checkInitializationCompleted() { if (!incubator.isReady() && incubator.status() != QQmlIncubator::Error) { QTimer::singleShot(0, q, SLOT(checkInitializationCompleted())); return; } if (!incubator.object()) { errorPrint(component); } emit q->finished(); } void QmlObject::completeInitialization(const QVariantHash &initialProperties) { d->executionEndTimer->stop(); if (d->incubator.object()) { return; } if (!d->component) { qWarning() << "No component for" << source(); return; } if (d->component->status() != QQmlComponent::Ready || d->component->isError()) { d->errorPrint(d->component); return; } d->incubator.m_initialProperties = initialProperties; d->component->create(d->incubator, d->rootContext); if (d->delay) { d->checkInitializationCompleted(); } else { d->incubator.forceCompletion(); if (!d->incubator.object()) { d->errorPrint(d->component); } emit finished(); } } QObject *QmlObject::createObjectFromSource(const QUrl &source, QQmlContext *context, const QVariantHash &initialProperties) { QQmlComponent *component = new QQmlComponent(d->engine, this); component->loadUrl(source); return createObjectFromComponent(component, context, initialProperties); } QObject *QmlObject::createObjectFromComponent(QQmlComponent *component, QQmlContext *context, const QVariantHash &initialProperties) { QmlObjectIncubator incubator; incubator.m_initialProperties = initialProperties; component->create(incubator, context ? context : d->rootContext); incubator.forceCompletion(); QObject *object = incubator.object(); if (!component->isError() && object) { //memory management component->setParent(object); //reparent to root object if wasn't specified otherwise by initialProperties if (!initialProperties.contains(QStringLiteral("parent"))) { if (qobject_cast(rootObject())) { object->setProperty("parent", QVariant::fromValue(rootObject())); } else { object->setParent(rootObject()); } } return object; } else { d->errorPrint(component); delete object; return nullptr; } } } #include "moc_qmlobject.cpp" diff --git a/src/kdeclarative/qmlobjectsharedengine.cpp b/src/kdeclarative/qmlobjectsharedengine.cpp index 0c8a184..8bfb91f 100644 --- a/src/kdeclarative/qmlobjectsharedengine.cpp +++ b/src/kdeclarative/qmlobjectsharedengine.cpp @@ -1,84 +1,82 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "qmlobjectsharedengine.h" -#include "private/qmlobject_p.h" #include #include #include #include #include #include namespace KDeclarative { class QmlObjectSharedEnginePrivate { public: QmlObjectSharedEnginePrivate() { //ensure the engine is present, then ref it engine(); engineRef = s_engine; } ~QmlObjectSharedEnginePrivate() { //when the only remaining are out two refs, reset the pointers, causing deletion //when the refcount is 2, we are sure that the only refs are s_engine and our copy //of engineRef if (engineRef.use_count() == 2) { s_engine.reset(); } } static QQmlEngine *engine() { if (!s_engine) { s_engine = std::make_shared(); - s_engine->setIncubationController(new QmlObjectIncubationController(0)); } return s_engine.get(); } //used to delete it std::shared_ptr engineRef; static std::shared_ptr s_engine; }; std::shared_ptr QmlObjectSharedEnginePrivate::s_engine = std::shared_ptr(); QmlObjectSharedEngine::QmlObjectSharedEngine(QObject *parent) : QmlObject(QmlObjectSharedEnginePrivate::engine(), new QQmlContext(QmlObjectSharedEnginePrivate::engine()), parent), d(new QmlObjectSharedEnginePrivate()) { } QmlObjectSharedEngine::~QmlObjectSharedEngine() { rootContext()->deleteLater(); } } #include "moc_qmlobjectsharedengine.cpp"