plasma-framework/src/plasmaquick/appletquickitem.cpp
David Edmundson 2affb1ab56 Recheck which representation we should using in setPreferredRepresentation
Summary:
Appmenu quite neatly has a config option for which should be the
preferred representation, which is needed as both things are quite
viable in a panel and can't be done automatically.

AppletQuickItem needs to update which representation to use when this is
set at runtime. We already check on every single geometry change, so
one extra check won't have a huge impact.

Test Plan:
Appmenu changes dynamically
All other applets (both compact and normal) still seem fine

Reviewers: #plasma, mart

Reviewed By: mart

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D3794
2016-12-23 13:28:32 +00:00

809 lines
26 KiB
C++

/*
* Copyright 2014 Marco Martin <mart@kde.org>
*
* 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 "appletquickitem.h"
#include "private/appletquickitem_p.h"
#include <QQmlComponent>
#include <QQmlExpression>
#include <QQmlEngine>
#include <QQmlProperty>
#include <QQmlContext>
#include <QDebug>
#include <klocalizedstring.h>
#include <Plasma/Applet>
#include <Plasma/Containment>
#include <Plasma/Corona>
#include <kdeclarative/qmlobjectsharedengine.h>
#include <packageurlinterceptor.h>
namespace PlasmaQuick
{
QHash<QObject *, AppletQuickItem *> AppletQuickItemPrivate::s_rootObjects = QHash<QObject *, AppletQuickItem *>();
AppletQuickItemPrivate::AppletQuickItemPrivate(Plasma::Applet *a, AppletQuickItem *item)
: q(item),
switchWidth(-1),
switchHeight(-1),
applet(a),
expanded(false),
activationTogglesExpanded(false)
{
}
void AppletQuickItemPrivate::init()
{
if (!applet->pluginMetaData().isValid()) {
// This `qmlObject` is used in other parts of the code
qmlObject = new KDeclarative::QmlObject(q);
return;
}
qmlObject = new KDeclarative::QmlObjectSharedEngine(q);
if (!qmlObject->engine()->urlInterceptor()) {
PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(qmlObject->engine(), Plasma::Package());
qmlObject->engine()->setUrlInterceptor(interceptor);
}
}
void AppletQuickItemPrivate::connectLayoutAttached(QObject *item)
{
QObject *layout = 0;
//Extract the representation's Layout, if any
//No Item?
if (!item) {
return;
}
//Search a child that has the needed Layout properties
//HACK: here we are not type safe, but is the only way to access to a pointer of Layout
foreach (QObject *child, item->children()) {
//find for the needed property of Layout: minimum/maximum/preferred sizes and fillWidth/fillHeight
if (child->property("minimumWidth").isValid() && child->property("minimumHeight").isValid() &&
child->property("preferredWidth").isValid() && child->property("preferredHeight").isValid() &&
child->property("maximumWidth").isValid() && child->property("maximumHeight").isValid() &&
child->property("fillWidth").isValid() && child->property("fillHeight").isValid()
) {
layout = child;
break;
}
}
if (!layout) {
return;
}
//propagate all the size hints
propagateSizeHint("minimumWidth");
propagateSizeHint("minimumHeight");
propagateSizeHint("preferredWidth");
propagateSizeHint("preferredHeight");
propagateSizeHint("maximumWidth");
propagateSizeHint("maximumHeight");
propagateSizeHint("fillWidth");
propagateSizeHint("fillHeight");
QObject *ownLayout = 0;
foreach (QObject *child, q->children()) {
//find for the needed property of Layout: minimum/maximum/preferred sizes and fillWidth/fillHeight
if (child->property("minimumWidth").isValid() && child->property("minimumHeight").isValid() &&
child->property("preferredWidth").isValid() && child->property("preferredHeight").isValid() &&
child->property("maximumWidth").isValid() && child->property("maximumHeight").isValid() &&
child->property("fillWidth").isValid() && child->property("fillHeight").isValid()
) {
ownLayout = child;
break;
}
}
//this should never happen, since we ask to create it if doesn't exists
if (!ownLayout) {
return;
}
//if the representation didn't change, don't do anything
if (representationLayout == layout) {
return;
}
if (representationLayout) {
QObject::disconnect(representationLayout, 0, q, 0);
}
//Here we can't use the new connect syntax because we can't link against QtQuick layouts
QObject::connect(layout, SIGNAL(minimumWidthChanged()),
q, SLOT(minimumWidthChanged()));
QObject::connect(layout, SIGNAL(minimumHeightChanged()),
q, SLOT(minimumHeightChanged()));
QObject::connect(layout, SIGNAL(preferredWidthChanged()),
q, SLOT(preferredWidthChanged()));
QObject::connect(layout, SIGNAL(preferredHeightChanged()),
q, SLOT(preferredHeightChanged()));
QObject::connect(layout, SIGNAL(maximumWidthChanged()),
q, SLOT(maximumWidthChanged()));
QObject::connect(layout, SIGNAL(maximumHeightChanged()),
q, SLOT(maximumHeightChanged()));
QObject::connect(layout, SIGNAL(fillWidthChanged()),
q, SLOT(fillWidthChanged()));
QObject::connect(layout, SIGNAL(fillHeightChanged()),
q, SLOT(fillHeightChanged()));
representationLayout = layout;
AppletQuickItemPrivate::ownLayout = ownLayout;
propagateSizeHint("minimumWidth");
propagateSizeHint("minimumHeight");
propagateSizeHint("preferredWidth");
propagateSizeHint("preferredHeight");
propagateSizeHint("maximumWidth");
propagateSizeHint("maximumHeight");
propagateSizeHint("fillWidth");
propagateSizeHint("fillHeight");
}
void AppletQuickItemPrivate::propagateSizeHint(const QByteArray &layoutProperty)
{
if (ownLayout && representationLayout) {
ownLayout->setProperty(layoutProperty, representationLayout->property(layoutProperty));
}
}
QQuickItem *AppletQuickItemPrivate::createCompactRepresentationItem()
{
if (!compactRepresentation) {
return 0;
}
if (compactRepresentationItem) {
return compactRepresentationItem;
}
QVariantHash initialProperties;
initialProperties[QStringLiteral("parent")] = QVariant::fromValue(q);
compactRepresentationItem = qobject_cast<QQuickItem*>(qmlObject->createObjectFromComponent(compactRepresentation, QtQml::qmlContext(qmlObject->rootObject()), initialProperties));
emit q->compactRepresentationItemChanged(compactRepresentationItem);
return compactRepresentationItem;
}
QQuickItem *AppletQuickItemPrivate::createFullRepresentationItem()
{
if (fullRepresentationItem) {
return fullRepresentationItem;
}
if (fullRepresentation && fullRepresentation != qmlObject->mainComponent()) {
QVariantHash initialProperties;
initialProperties[QStringLiteral("parent")] = QVariant::fromValue(q);
fullRepresentationItem = qobject_cast<QQuickItem*>(qmlObject->createObjectFromComponent(fullRepresentation, QtQml::qmlContext(qmlObject->rootObject()), initialProperties));
} else {
fullRepresentation = qmlObject->mainComponent();
fullRepresentationItem = qobject_cast<QQuickItem*>(qmlObject->rootObject());
emit q->fullRepresentationChanged(fullRepresentation);
}
if (!fullRepresentationItem) {
return 0;
}
emit q->fullRepresentationItemChanged(fullRepresentationItem);
return fullRepresentationItem;
}
QQuickItem *AppletQuickItemPrivate::createCompactRepresentationExpanderItem()
{
if (!compactRepresentationExpander) {
return 0;
}
if (compactRepresentationExpanderItem) {
return compactRepresentationExpanderItem;
}
compactRepresentationExpanderItem = qobject_cast<QQuickItem*>(qmlObject->createObjectFromComponent(compactRepresentationExpander, QtQml::qmlContext(qmlObject->rootObject())));
if (!compactRepresentationExpanderItem) {
return 0;
}
compactRepresentationExpanderItem->setProperty("compactRepresentation", QVariant::fromValue<QObject*>(createCompactRepresentationItem()));
return compactRepresentationExpanderItem;
}
void AppletQuickItemPrivate::compactRepresentationCheck()
{
if (!qmlObject->rootObject()) {
return;
}
//ignore 0 sizes;
if (q->width() <= 0 || q->height() <= 0) {
return;
}
bool full = false;
if (applet->isContainment()) {
full = true;
} else {
if (switchWidth > 0 && switchHeight > 0) {
full = q->width() > switchWidth && q->height() > switchHeight;
//if a size to switch wasn't set, determine what representation to always chose
} else {
//preferred representation set?
if (preferredRepresentation) {
full = preferredRepresentation == fullRepresentation;
//Otherwise, base on FormFactor
} else {
full = (applet->formFactor() != Plasma::Types::Horizontal && applet->formFactor() != Plasma::Types::Vertical);
}
}
if ((full && fullRepresentationItem && fullRepresentationItem == currentRepresentationItem) ||
(!full && compactRepresentationItem && compactRepresentationItem == currentRepresentationItem)
) {
return;
}
}
//Expanded
if (full) {
QQuickItem *item = createFullRepresentationItem();
if (item) {
//unwire with the expander
if (compactRepresentationExpanderItem) {
compactRepresentationExpanderItem->setProperty("fullRepresentation", QVariant());
compactRepresentationExpanderItem->setProperty("compactRepresentation", QVariant());
compactRepresentationExpanderItem->setVisible(false);
}
item->setParentItem(q);
{
//set anchors
QQmlExpression expr(QtQml::qmlContext(qmlObject->rootObject()), item, QStringLiteral("parent"));
QQmlProperty prop(item, QStringLiteral("anchors.fill"));
prop.write(expr.evaluate());
}
if (compactRepresentationItem) {
compactRepresentationItem->setVisible(false);
}
currentRepresentationItem = item;
connectLayoutAttached(item);
expanded = true;
emit q->expandedChanged(true);
}
//Icon
} else {
QQuickItem *compactItem = createCompactRepresentationItem();
QQuickItem *compactExpanderItem = createCompactRepresentationExpanderItem();
if (compactItem && compactExpanderItem) {
//set the root item as the main visible item
compactItem->setVisible(true);
compactExpanderItem->setParentItem(q);
compactExpanderItem->setVisible(true);
{
//set anchors
QQmlExpression expr(QtQml::qmlContext(qmlObject->rootObject()), compactExpanderItem, QStringLiteral("parent"));
QQmlProperty prop(compactExpanderItem, QStringLiteral("anchors.fill"));
prop.write(expr.evaluate());
}
if (fullRepresentationItem) {
fullRepresentationItem->setProperty("parent", QVariant());
}
compactExpanderItem->setProperty("compactRepresentation", QVariant::fromValue<QObject*>(compactItem));
//The actual full representation will be connected when created
compactExpanderItem->setProperty("fullRepresentation", QVariant());
currentRepresentationItem = compactItem;
connectLayoutAttached(compactItem);
expanded = false;
emit q->expandedChanged(false);
}
}
}
void AppletQuickItemPrivate::minimumWidthChanged()
{
propagateSizeHint("minimumWidth");
}
void AppletQuickItemPrivate::minimumHeightChanged()
{
propagateSizeHint("minimumHeight");
}
void AppletQuickItemPrivate::preferredWidthChanged()
{
propagateSizeHint("preferredWidth");
}
void AppletQuickItemPrivate::preferredHeightChanged()
{
propagateSizeHint("preferredHeight");
}
void AppletQuickItemPrivate::maximumWidthChanged()
{
propagateSizeHint("maximumWidth");
}
void AppletQuickItemPrivate::maximumHeightChanged()
{
propagateSizeHint("maximumHeight");
}
void AppletQuickItemPrivate::fillWidthChanged()
{
propagateSizeHint("fillWidth");
}
void AppletQuickItemPrivate::fillHeightChanged()
{
propagateSizeHint("fillHeight");
}
AppletQuickItem::AppletQuickItem(Plasma::Applet *applet, QQuickItem *parent)
: QQuickItem(parent),
d(new AppletQuickItemPrivate(applet, this))
{
d->init();
if (d->applet) {
d->appletPackage = d->applet->package();
if (d->applet->containment()) {
if (d->applet->containment()->corona()) {
d->coronaPackage = d->applet->containment()->corona()->package();
}
d->containmentPackage = d->applet->containment()->package();
}
if (d->applet->pluginMetaData().isValid()) {
const QString rootPath = d->applet->pluginMetaData().value(QStringLiteral("X-Plasma-RootPath"));
if (!rootPath.isEmpty()) {
d->qmlObject->setTranslationDomain(QLatin1String("plasma_applet_") + rootPath);
} else {
d->qmlObject->setTranslationDomain(QLatin1String("plasma_applet_") + d->applet->pluginMetaData().pluginId());
}
}
// set the graphicObject dynamic property on applet
d->applet->setProperty("_plasma_graphicObject", QVariant::fromValue(this));
}
d->qmlObject->setInitializationDelayed(true);
setProperty("_plasma_applet", QVariant::fromValue(d->applet));
}
AppletQuickItem::~AppletQuickItem()
{
//Here the order is important
delete d->compactRepresentationItem;
delete d->fullRepresentationItem;
delete d->compactRepresentationExpanderItem;
AppletQuickItemPrivate::s_rootObjects.remove(d->qmlObject->rootContext());
}
AppletQuickItem *AppletQuickItem::qmlAttachedProperties(QObject *object)
{
QQmlContext *context;
//is it using shared engine mode?
if (!QtQml::qmlEngine(object)->parent()) {
context = QtQml::qmlContext(object);
//search the root context of the applet in which the object is in
while (context) {
//the rootcontext of an applet is a child of the engine root context
if (context->parentContext() == QtQml::qmlEngine(object)->rootContext()) {
break;
}
context = context->parentContext();
}
//otherwise index by root context
} else {
context = QtQml::qmlEngine(object)->rootContext();
}
//at the moment of the attached object creation, the root item is the only one that hasn't a parent
//only way to avoid creation of this attached for everybody but the root item
if (!object->parent() && AppletQuickItemPrivate::s_rootObjects.contains(context)) {
return AppletQuickItemPrivate::s_rootObjects.value(context);
} else {
return 0;
}
}
Plasma::Applet *AppletQuickItem::applet() const
{
return d->applet;
}
void AppletQuickItem::init()
{
//FIXME: Plasmoid attached property should be fixed since can't be indexed by engine anymore
if (AppletQuickItemPrivate::s_rootObjects.contains(d->qmlObject->rootContext())) {
return;
}
AppletQuickItemPrivate::s_rootObjects[d->qmlObject->rootContext()] = this;
Q_ASSERT(d->applet);
//Initialize the main QML file
QQmlEngine *engine = d->qmlObject->engine();
//if the engine of the qmlObject is different from the static one, then we
//are using an old version of the api in which every applet had one engine
//so initialize a private url interceptor
if (d->applet->kPackage().isValid() && !qobject_cast<KDeclarative::QmlObjectSharedEngine *>(d->qmlObject)) {
PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(engine, d->applet->package());
interceptor->addAllowedPath(d->coronaPackage.path());
engine->setUrlInterceptor(interceptor);
}
//Force QtQuickControls to use the "Plasma" style for this engine.
//this way is possible to mix QtQuickControls and plasma components in applets
//while still having the desktop style in configuration dialogs
QQmlComponent c(engine);
c.setData(QByteArrayLiteral("import QtQuick 2.1\n\
import QtQuick.Controls 1.0\n\
import QtQuick.Controls.Private 1.0\n \
Item {\
Component.onCompleted: {\
Settings.styleName = \"Plasma\";\
}\
}"), QUrl());
QObject *o = c.create();
o->deleteLater();
d->qmlObject->setSource(QUrl::fromLocalFile(d->applet->kPackage().filePath("mainscript")));
if (!engine || !engine->rootContext() || !engine->rootContext()->isValid() || !d->qmlObject->mainComponent() || d->qmlObject->mainComponent()->isError() || d->applet->failedToLaunch()) {
QString reason;
if (d->applet->failedToLaunch()) {
reason = d->applet->launchErrorMessage();
} else if (d->applet->kPackage().isValid()) {
foreach (QQmlError error, d->qmlObject->mainComponent()->errors()) {
reason += error.toString() + '\n';
}
reason = i18n("Error loading QML file: %1", reason);
} else {
reason = i18n("Error loading Applet: package inexistent. %1", applet()->launchErrorMessage());
}
d->qmlObject->setSource(QUrl::fromLocalFile(d->coronaPackage.filePath("appleterror")));
d->qmlObject->completeInitialization();
//even the error message QML may fail
if (d->qmlObject->mainComponent()->isError()) {
return;
} else {
d->qmlObject->rootObject()->setProperty("reason", reason);
}
d->applet->setLaunchErrorMessage(reason);
}
d->qmlObject->rootContext()->setContextProperty(QStringLiteral("plasmoid"), this);
//initialize size, so an useless resize less
QVariantHash initialProperties;
//initialize with our size only if valid
if (width() > 0 && height() > 0) {
const qreal w = parentItem() ? std::min(parentItem()->width(), width()) : width();
const qreal h = parentItem() ? std::min(parentItem()->height(), height()) : height();
initialProperties[QStringLiteral("width")] = w;
initialProperties[QStringLiteral("height")] = h;
}
d->qmlObject->setInitializationDelayed(false);
d->qmlObject->completeInitialization(initialProperties);
//otherwise, initialize our size to root object's size
if (d->qmlObject->rootObject() && (width() <= 0 || height() <= 0)) {
const qreal w = d->qmlObject->rootObject()->property("width").value<qreal>();
const qreal h = d->qmlObject->rootObject()->property("height").value<qreal>();
setSize(parentItem() ? QSizeF(std::min(parentItem()->width(), w), std::min(parentItem()->height(), h)) : QSizeF(w, h));
}
//default fullrepresentation is our root main component, if none specified
if (!d->fullRepresentation) {
d->fullRepresentation = d->qmlObject->mainComponent();
d->fullRepresentationItem = qobject_cast<QQuickItem*>(d->qmlObject->rootObject());
emit fullRepresentationChanged(d->fullRepresentation);
}
//default compactRepresentation is a simple icon provided by the shell package
if (!d->compactRepresentation) {
d->compactRepresentation = new QQmlComponent(engine, this);
d->compactRepresentation->loadUrl(QUrl::fromLocalFile(d->coronaPackage.filePath("defaultcompactrepresentation")));
emit compactRepresentationChanged(d->compactRepresentation);
}
//default compactRepresentationExpander is the popup in which fullRepresentation goes
if (!d->compactRepresentationExpander) {
d->compactRepresentationExpander = new QQmlComponent(engine, this);
QString compactExpanderPath = d->containmentPackage.filePath("compactapplet");
if (compactExpanderPath.isEmpty()) {
compactExpanderPath = d->coronaPackage.filePath("compactapplet");
}
d->compactRepresentationExpander->loadUrl(QUrl::fromLocalFile(compactExpanderPath));
}
d->compactRepresentationCheck();
qmlObject()->engine()->rootContext()->setBaseUrl(qmlObject()->source());
qmlObject()->engine()->setContextForObject(this, qmlObject()->engine()->rootContext());
}
Plasma::Package AppletQuickItem::appletPackage() const
{
return d->appletPackage;
}
void AppletQuickItem::setAppletPackage(const Plasma::Package &package)
{
d->appletPackage = package;
}
Plasma::Package AppletQuickItem::coronaPackage() const
{
return d->coronaPackage;
}
void AppletQuickItem::setCoronaPackage(const Plasma::Package &package)
{
d->coronaPackage = package;
}
int AppletQuickItem::switchWidth() const
{
return d->switchWidth;
}
void AppletQuickItem::setSwitchWidth(int width)
{
if (d->switchWidth == width) {
return;
}
d->switchWidth = width;
emit switchWidthChanged(width);
}
int AppletQuickItem::switchHeight() const
{
return d->switchHeight;
}
void AppletQuickItem::setSwitchHeight(int height)
{
if (d->switchHeight == height) {
return;
}
d->switchHeight = height;
emit switchHeightChanged(height);
}
QQmlComponent *AppletQuickItem::compactRepresentation()
{
return d->compactRepresentation;
}
void AppletQuickItem::setCompactRepresentation(QQmlComponent *component)
{
if (d->compactRepresentation == component) {
return;
}
d->compactRepresentation = component;
emit compactRepresentationChanged(component);
}
QQmlComponent *AppletQuickItem::fullRepresentation()
{
return d->fullRepresentation;
}
QObject *AppletQuickItem::testItem()
{
if (!d->testItem) {
const QUrl url = QUrl::fromLocalFile(d->appletPackage.filePath("test"));
if (url.isEmpty()) {
return nullptr;
}
d->testItem = d->qmlObject->createObjectFromSource(url, QtQml::qmlContext(rootItem()));
d->testItem->setProperty("plasmoidItem", QVariant::fromValue<QObject*>(this));
}
return d->testItem;
}
void AppletQuickItem::setFullRepresentation(QQmlComponent *component)
{
if (d->fullRepresentation == component) {
return;
}
d->fullRepresentation = component;
emit fullRepresentationChanged(component);
}
QQmlComponent *AppletQuickItem::preferredRepresentation()
{
return d->preferredRepresentation;
}
void AppletQuickItem::setPreferredRepresentation(QQmlComponent *component)
{
if (d->preferredRepresentation == component) {
return;
}
d->preferredRepresentation = component;
emit preferredRepresentationChanged(component);
d->compactRepresentationCheck();
}
bool AppletQuickItem::isExpanded() const
{
return d->expanded;
}
void AppletQuickItem::setExpanded(bool expanded)
{
if (d->applet->isContainment()) {
expanded = true;
}
//if there is no compact representation it means it's always expanded
//Containments are always expanded
if (d->expanded == expanded) {
return;
}
if (expanded) {
d->createFullRepresentationItem();
if (!d->applet->isContainment() &&
(!d->preferredRepresentation ||
d->preferredRepresentation != d->fullRepresentation)) {
d->createCompactRepresentationExpanderItem();
}
if (d->compactRepresentationExpanderItem) {
d->compactRepresentationExpanderItem->setProperty("fullRepresentation", QVariant::fromValue<QObject*>(d->createFullRepresentationItem()));
} else {
d->fullRepresentationItem->setProperty("parent", QVariant::fromValue<QObject*>(this));
}
}
d->expanded = expanded;
emit expandedChanged(expanded);
}
bool AppletQuickItem::isActivationTogglesExpanded() const
{
return d->activationTogglesExpanded;
}
void AppletQuickItem::setActivationTogglesExpanded(bool activationTogglesExpanded)
{
if (d->activationTogglesExpanded == activationTogglesExpanded) {
return;
}
d->activationTogglesExpanded = activationTogglesExpanded;
emit activationTogglesExpandedChanged(activationTogglesExpanded);
}
////////////Internals
KDeclarative::QmlObject *AppletQuickItem::qmlObject()
{
return d->qmlObject;
}
QQuickItem *AppletQuickItem::compactRepresentationItem()
{
return d->compactRepresentationItem;
}
QQuickItem *AppletQuickItem::fullRepresentationItem()
{
return d->fullRepresentationItem;
}
QObject *AppletQuickItem::rootItem()
{
return d->qmlObject->rootObject();
}
void AppletQuickItem::childEvent(QChildEvent *event)
{
// Added child may be QQuickLayoutAttached
if (event->added() && !d->ownLayout && d->currentRepresentationItem) {
// Child has not yet finished initialization at this point
QTimer::singleShot(0, this, [this]() {
if (!d->ownLayout) {
d->connectLayoutAttached(d->currentRepresentationItem);
}
});
}
QQuickItem::childEvent(event);
}
void AppletQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_UNUSED(oldGeometry)
QQuickItem::geometryChanged(newGeometry, oldGeometry);
d->compactRepresentationCheck();
}
void AppletQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == QQuickItem::ItemSceneChange) {
//we have a window: create the representations if needed
if (value.window) {
init();
}
}
QQuickItem::itemChange(change, value);
}
}
#include "moc_appletquickitem.cpp"