8#include "sharedqmlengine_p.h"
10#include <KLocalizedQmlContext>
14#include <QQmlIncubator>
15#include <QQmlNetworkAccessManagerFactory>
20#include "kcmutils_debug.h"
22using namespace Qt::StringLiterals;
24class SharedQmlEnginePrivate
27 SharedQmlEnginePrivate(
const std::shared_ptr<QQmlEngine> &engine, SharedQmlEngine *parent)
33 executionEndTimer.setInterval(0);
34 executionEndTimer.setSingleShot(
true);
36 scheduleExecutionEnd();
40 ~SharedQmlEnginePrivate()
42 delete incubator.object();
45 void errorPrint(QQmlComponent *component, QQmlIncubator *incubator =
nullptr);
46 void execute(
const QUrl &source);
47 void scheduleExecutionEnd();
48 void minimumWidthChanged();
49 void minimumHeightChanged();
50 void maximumWidthChanged();
51 void maximumHeightChanged();
52 void preferredWidthChanged();
53 void preferredHeightChanged();
54 void checkInitializationCompleted();
60 QQmlIncubator incubator;
61 QQmlComponent *component;
62 QTimer executionEndTimer;
63 KLocalizedQmlContext *context{
nullptr};
64 QQmlContext *rootContext;
66 std::shared_ptr<QQmlEngine> m_engine;
71 QList<QQmlError> errors;
72 if (component && component->isError()) {
73 errors = component->errors();
74 }
else if (incubator && incubator->isError()) {
75 errors = incubator->errors();
80 qCWarning(KCMUTILS_LOG).noquote() <<
"Error loading QML file" << component->url().toString();
81 for (
const auto &error : errors) {
82 constexpr const QLatin1String indent(
" ");
83 qCWarning(KCMUTILS_LOG).noquote().nospace() << indent <<
error;
87void SharedQmlEnginePrivate::execute(
const QUrl &source)
89 Q_ASSERT(!source.isEmpty());
91 component =
new QQmlComponent(m_engine.get(), q);
92 delete incubator.object();
94 m_engine->addImportPath(QStringLiteral(
"qrc:/"));
95 component->loadUrl(source);
98 executionEndTimer.start(0);
100 scheduleExecutionEnd();
104void SharedQmlEnginePrivate::scheduleExecutionEnd()
106 if (component->isReady() || component->isError()) {
107 q->completeInitialization();
110 q->completeInitialization();
115SharedQmlEngine::SharedQmlEngine(
const std::shared_ptr<QQmlEngine> &engine,
QObject *parent)
117 , d(new SharedQmlEnginePrivate(engine, this))
120 d->rootContext->setParent(
this);
123 d->rootContext->setContextObject(d->context);
126SharedQmlEngine::~SharedQmlEngine() =
default;
128void SharedQmlEngine::setTranslationDomain(
const QString &translationDomain)
130 d->context->setTranslationDomain(translationDomain);
133QString SharedQmlEngine::translationDomain()
const
135 return d->context->translationDomain();
138void SharedQmlEngine::setSource(
const QUrl &source)
144QUrl SharedQmlEngine::source()
const
149void SharedQmlEngine::setInitializationDelayed(
const bool delay)
154bool SharedQmlEngine::isInitializationDelayed()
const
159std::shared_ptr<QQmlEngine> SharedQmlEngine::engine()
164QObject *SharedQmlEngine::rootObject()
const
166 if (d->incubator.isLoading()) {
167 qCWarning(KCMUTILS_LOG) <<
"Trying to use rootObject before initialization is completed, whilst using setInitializationDelayed. Forcing completion";
168 d->incubator.forceCompletion();
170 return d->incubator.object();
180 return d->rootContext;
183bool SharedQmlEngine::isError()
const
185 return !d->m_engine || !d->component || d->component->isError() || d->incubator.isError();
191 for (
const auto &e : errors) {
197QString SharedQmlEngine::errorString()
const
199 if (d->component && d->component->isError()) {
200 return d->component->errorString();
201 }
else if (d->incubator.isError()) {
202 return qmlErrorsToString(d->incubator.errors());
208void SharedQmlEnginePrivate::checkInitializationCompleted()
210 if (!incubator.isReady() && !incubator.isError()) {
212 checkInitializationCompleted();
217 if (!incubator.object()) {
218 errorPrint(component, &incubator);
221 Q_EMIT q->finished();
224void SharedQmlEngine::completeInitialization(
const QVariantMap &initialProperties)
226 d->executionEndTimer.stop();
227 if (d->incubator.object()) {
232 qCWarning(KCMUTILS_LOG) <<
"No component for" << source();
236 if (!d->component->isReady()) {
237 d->errorPrint(d->component);
241 d->incubator.setInitialProperties(initialProperties);
242 d->component->create(d->incubator, d->rootContext);
245 d->checkInitializationCompleted();
247 d->incubator.forceCompletion();
249 if (!d->incubator.object()) {
250 d->errorPrint(d->component, &d->incubator);
256QObject *SharedQmlEngine::createObjectFromSource(
const QUrl &source,
QQmlContext *context,
const QVariantMap &initialProperties)
261 return createObjectFromComponent(component, context, initialProperties);
268 if (!component->
isError() &&
object) {
270 const auto root = rootObject();
271 object->setParent(root);
275 if (!initialProperties.contains(
QLatin1String(
"parent")) && root && root->isQuickItemType()) {
280 d->errorPrint(component);
286#include "moc_sharedqmlengine_p.cpp"
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setParent(QObject *parent)
QObject * createWithInitialProperties(const QVariantMap &initialProperties, QQmlContext *context)
bool isError() const const
void loadUrl(const QUrl &url)
void statusChanged(QQmlComponent::Status status)
QString number(double n, char format, int precision)
QVariant fromValue(T &&value)