diff --git a/src/plasma/data/servicetypes/plasma-applet.desktop b/src/plasma/data/servicetypes/plasma-applet.desktop --- a/src/plasma/data/servicetypes/plasma-applet.desktop +++ b/src/plasma/data/servicetypes/plasma-applet.desktop @@ -83,6 +83,9 @@ [PropertyDef::X-Plasma-Provides] Type=QStringList +[PropertyDef::X-Plasma-PreloadWeight] +Type=int + [PropertyDef::X-Plasma-ConfigPlugins] Type=QStringList diff --git a/src/plasmaquick/CMakeLists.txt b/src/plasmaquick/CMakeLists.txt --- a/src/plasmaquick/CMakeLists.txt +++ b/src/plasmaquick/CMakeLists.txt @@ -6,6 +6,7 @@ set(plasmaquick_LIB_SRC appletquickitem.cpp + debug_p.cpp dialog.cpp dialogshadows.cpp view.cpp @@ -20,6 +21,8 @@ ../declarativeimports/core/units.cpp ) +ecm_qt_declare_logging_category(PlasmaQuick_LIB_SRCS HEADER debug_p.h IDENTIFIER LOG_PLASMAQUICK CATEGORY_NAME org.kde.plasmaquick) + add_library(KF5PlasmaQuick SHARED ${plasmaquick_LIB_SRC}) add_library(KF5::PlasmaQuick ALIAS KF5PlasmaQuick) target_include_directories(KF5PlasmaQuick PUBLIC "$") diff --git a/src/plasmaquick/appletquickitem.cpp b/src/plasmaquick/appletquickitem.cpp --- a/src/plasmaquick/appletquickitem.cpp +++ b/src/plasmaquick/appletquickitem.cpp @@ -19,6 +19,7 @@ #include "appletquickitem.h" #include "private/appletquickitem_p.h" +#include "debug_p.h" #include #include @@ -43,15 +44,24 @@ QHash AppletQuickItemPrivate::s_rootObjects = QHash(); - AppletQuickItemPrivate::AppletQuickItemPrivate(Plasma::Applet *a, AppletQuickItem *item) : q(item), switchWidth(-1), switchHeight(-1), applet(a), expanded(false), activationTogglesExpanded(false) { + if (qEnvironmentVariableIsSet("KDE_PLASMA_PRELOAD_POLICY")) { + const QByteArray policy = qgetenv("KDE_PLASMA_PRELOAD_POLICY"); + if (policy == "Aggressive") { + preloadPolicy = Aggressive; + } else if (policy == "None") { + preloadPolicy = None; + + } + //leave default as Adaptive, do nothing + } } void AppletQuickItemPrivate::init() @@ -70,6 +80,21 @@ } } +int AppletQuickItemPrivate::preloadWeight() const +{ + int defaultWeight; + const QStringList provides(KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides"))); + + //some applet types we want a bigger weight + if (provides.contains(QStringLiteral("org.kde.plasma.launchermenu"))) { + defaultWeight = DefaultLauncherPreloadWeight; + } else { + defaultWeight = DefaultPreloadWeight; + } + //default widgets to be barely preloaded + return qBound(0, applet->config().readEntry(QStringLiteral("PreloadWeight"), qMax(defaultWeight, applet->pluginMetaData().rawData().value(QStringLiteral("X-Plasma-PreloadWeight")).toInt())), 100); +} + void AppletQuickItemPrivate::connectLayoutAttached(QObject *item) { QObject *layout = 0; @@ -218,7 +243,7 @@ if (fullRepresentation && fullRepresentation != qmlObject->mainComponent()) { QVariantHash initialProperties; - initialProperties[QStringLiteral("parent")] = QVariant::fromValue(q); + initialProperties[QStringLiteral("parent")] = QVariant(); fullRepresentationItem = qobject_cast(qmlObject->createObjectFromComponent(fullRepresentation, QtQml::qmlContext(qmlObject->rootObject()), initialProperties)); } else { fullRepresentation = qmlObject->mainComponent(); @@ -437,6 +462,11 @@ AppletQuickItem::~AppletQuickItem() { + //decrease weight + if (d->preloadPolicy == AppletQuickItemPrivate::Adaptive) { + d->applet->config().writeEntry(QStringLiteral("PreloadWeight"), qMax(0, d->preloadWeight() - AppletQuickItemPrivate::PreloadWeightDecrement)); + } + //Here the order is important delete d->compactRepresentationItem; delete d->fullRepresentationItem; @@ -598,6 +628,42 @@ d->compactRepresentationCheck(); qmlObject()->engine()->rootContext()->setBaseUrl(qmlObject()->source()); qmlObject()->engine()->setContextForObject(this, qmlObject()->engine()->rootContext()); + + //if we're expanded we don't care about preloading because it will already be the case + //as well as for containments + if (d->applet->isContainment() || + d->expanded || d->preferredRepresentation == d->fullRepresentation) { + return; + } + + switch (d->preloadPolicy) { + case AppletQuickItemPrivate::Adaptive: { + const int preloadWeight = d->preloadWeight(); + qCInfo(LOG_PLASMAQUICK) << "New Applet " << d->applet->title() << "with a weight of" << preloadWeight; + + //don't preload applets less then a certain weigth + if (preloadWeight >= AppletQuickItemPrivate::DelayedPreloadWeight) { + //spread the creation over a random delay to make it look + //plasma started already, and load the popup in the background + //without big noticeable freezes, the bigger the weight the smaller is likely + //to be the delay, smaller minimum walue, smaller spread + const int min = (100 - preloadWeight) * 20; + const int max = (100 - preloadWeight) * 100; + const int delay = qrand() % ((max + 1) - min) + min; + QTimer::singleShot(delay, [this, delay]() { + qCInfo(LOG_PLASMAQUICK) << "Delayed preload of " << d->applet->title() << "after" << (qreal)delay/1000 << "seconds"; + d->createFullRepresentationItem(); + }); + } + break; + } + case AppletQuickItemPrivate::Aggressive: + d->createFullRepresentationItem(); + break; + case AppletQuickItemPrivate::None: + default: + break; + } } @@ -726,6 +792,7 @@ } if (expanded) { + qint64 time = QDateTime::currentMSecsSinceEpoch(); d->createFullRepresentationItem(); if (!d->applet->isContainment() && (!d->preferredRepresentation || @@ -738,6 +805,14 @@ } else { d->fullRepresentationItem->setProperty("parent", QVariant::fromValue(this)); } + + //increase on open, ignore containments + if (d->preloadPolicy == AppletQuickItemPrivate::Adaptive && !d->applet->isContainment()) { + const int newWeight = qMin(d->preloadWeight() + AppletQuickItemPrivate::PreloadWeightIncrement, 100); + d->applet->config().writeEntry(QStringLiteral("PreloadWeight"), newWeight); + qCInfo(LOG_PLASMAQUICK) << "Increasing score for" << d->applet->title() << "to" << newWeight; + } + qCInfo(LOG_PLASMAQUICK) << "Applet" << d->applet->title() << "opened after" << ( QDateTime::currentMSecsSinceEpoch() - time) << "msec"; } d->expanded = expanded; diff --git a/src/plasmaquick/private/appletquickitem_p.h b/src/plasmaquick/private/appletquickitem_p.h --- a/src/plasmaquick/private/appletquickitem_p.h +++ b/src/plasmaquick/private/appletquickitem_p.h @@ -55,10 +55,27 @@ class AppletQuickItemPrivate { public: + //weight values for the logic for when or if to preload + enum PreloadWeights { + DefaultPreloadWeight = 50, + DefaultLauncherPreloadWeight = 100, + DelayedPreloadWeight = 25, + PreloadWeightIncrement = 5, + PreloadWeightDecrement = 8 + }; + + enum PreloadPolicy { + None, + Adaptive, + Aggressive + }; + AppletQuickItemPrivate(Plasma::Applet *a, AppletQuickItem *item); void init(); + int preloadWeight() const; + QQuickItem *createCompactRepresentationItem(); QQuickItem *createFullRepresentationItem(); QQuickItem *createCompactRepresentationExpanderItem(); @@ -80,6 +97,7 @@ AppletQuickItem *q; + PreloadPolicy preloadPolicy = Adaptive; int switchWidth; int switchHeight;