Merge branch 'mart/AppletAttached'

Conflicts:
	src/declarativeimports/core/dialog.cpp
	src/scriptengines/qml/plasmoid/containmentinterface.cpp
This commit is contained in:
Marco Martin 2014-02-06 13:16:11 +01:00
commit 3858044d25
34 changed files with 1196 additions and 606 deletions

View File

@ -19,13 +19,14 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents
Item { Item {
property int minimumWidth: 200 Layout.minimumWidth: 200
property int minimumHeight: 300 Layout.minimumHeight: 300
property Component compactRepresentation: Component { Plasmoid.compactRepresentation: Component {
PlasmaComponents.Button { PlasmaComponents.Button {
text: i18n("Click me") text: i18n("Click me")
onClicked: plasmoid.expanded = !plasmoid.expanded onClicked: plasmoid.expanded = !plasmoid.expanded

View File

@ -17,6 +17,7 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
@ -30,10 +31,10 @@ Rectangle {
height: 100 height: 100
radius: 10 radius: 10
smooth: true smooth: true
property int minimumWidth: units.gridUnit * 20 Layout.minimumWidth: units.gridUnit * 20
property int minimumHeight: column.implicitHeight Layout.minimumHeight: column.implicitHeight
property Component compactRepresentation: Component { Plasmoid.compactRepresentation: Component {
Rectangle { Rectangle {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View File

@ -26,8 +26,8 @@ Item {
id: root id: root
width: 100 width: 100
height: 100 height: 100
property int minimumWidth: units.gridUnit * 20 Layout.minimumWidth: units.gridUnit * 20
property int minimumHeight: column.implicitHeight Layout.minimumHeight: column.implicitHeight
ColumnLayout { ColumnLayout {

View File

@ -19,6 +19,7 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.extras 2.0 as PlasmaExtras
@ -26,8 +27,8 @@ import org.kde.plasma.extras 2.0 as PlasmaExtras
Column { Column {
width: 500 width: 500
height: 500 height: 500
property int minimumWidth: 200 Layout.minimumWidth: 200
property int minimumHeight: 300 Layout.minimumHeight: 300
PlasmaCore.DataSource { PlasmaCore.DataSource {
id: source id: source

View File

@ -19,12 +19,13 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents
Item { Item {
property int minimumWidth: 200 Layout.minimumWidth: 200
property int minimumHeight: 300 Layout.minimumHeight: 300
PlasmaComponents.Label { PlasmaComponents.Label {
text: i18n("Hello world") text: i18n("Hello world")

View File

@ -18,12 +18,13 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents
PlasmaCore.SvgItem { PlasmaCore.SvgItem {
property int minimumWidth: 150 Layout.minimumWidth: 150
property int minimumHeight: 150 Layout.minimumHeight: 150
svg: PlasmaCore.Svg("widgets/notes") svg: PlasmaCore.Svg("widgets/notes")
elementId: "yellow-notes" elementId: "yellow-notes"

View File

@ -27,8 +27,8 @@ Item {
width: 400 width: 400
height: 32 height: 32
property bool fillWidth: true Layout.fillWidth: true
property bool fillHeight: true Layout.fillHeight: true
implicitWidth: tasksModel.count * 50 implicitWidth: tasksModel.count * 50
PlasmaCore.DataSource { PlasmaCore.DataSource {

View File

@ -28,8 +28,8 @@ Item {
width: 100 width: 100
height: 100 height: 100
clip: true clip: true
property int minimumWidth: units.gridUnit * 20 Layout.minimumWidth: units.gridUnit * 20
property int minimumHeight: units.gridUnit * 30 Layout.minimumHeight: units.gridUnit * 30
property int _s: units.iconSizes.small property int _s: units.iconSizes.small
property int _h: units.iconSizes.desktop property int _h: units.iconSizes.desktop

View File

@ -28,8 +28,8 @@ Item {
width: 400 width: 400
height: 400 height: 400
property int minimumWidth: units.gridUnit * 20 Layout.minimumWidth: units.gridUnit * 20
property int minimumHeight: units.gridUnit * 30 Layout.minimumHeight: units.gridUnit * 30
property int _s: units.iconSizes.small property int _s: units.iconSizes.small
property int _h: units.iconSizes.desktop property int _h: units.iconSizes.desktop
property int _m: 12 property int _m: 12

View File

@ -28,8 +28,8 @@ Item {
width: 300 width: 300
height: 400 height: 400
clip: true clip: true
property int minimumWidth: units.gridUnit * 10 Layout.minimumWidth: units.gridUnit * 10
property int minimumHeight: units.gridUnit * 10 Layout.minimumHeight: units.gridUnit * 10
property int _s: units.iconSizes.small property int _s: units.iconSizes.small
property int _h: units.iconSizes.medium property int _h: units.iconSizes.medium

View File

@ -18,15 +18,22 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.components 2.0 import org.kde.plasma.components 2.0
Item { Item {
property int minimumWidth: 300 Plasmoid.switchWidth: 300
property int minimumHeight: 400 Plasmoid.switchHeight: 400
Plasmoid.fullRepresentation: Item {
Layout.minimumWidth: 300
Layout.minimumHeight: 400
ToolBar { ToolBar {
id: toolBar id: toolBar
z: 10 z: 10
//AppletInterface.title: "bah"
anchors { anchors {
top: parent.top top: parent.top
left: parent.left left: parent.left
@ -34,7 +41,6 @@ Item {
} }
} }
PageStack { PageStack {
id: pageStack id: pageStack
toolBar: toolBar toolBar: toolBar
@ -47,4 +53,5 @@ Item {
} }
initialPage: Qt.createComponent("Menu.qml") initialPage: Qt.createComponent("Menu.qml")
} }
}
} }

View File

@ -18,11 +18,12 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.components 2.0 import org.kde.plasma.components 2.0
Image { Image {
property int minimumWidth: 300 Layout.minimumWidth: 300
property int minimumHeight: 400 Layout.minimumHeight: 400
source: "image://appbackgrounds/standard" source: "image://appbackgrounds/standard"
fillMode: Image.Tile fillMode: Image.Tile
asynchronous: true asynchronous: true

View File

@ -20,6 +20,7 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.extras 2.0 as PlasmaExtras
@ -28,8 +29,8 @@ Item {
width: 400 width: 400
height: 32 height: 32
property bool fillWidth: true Layout.fillWidth: true
property bool fillHeight: true Layout.fillHeight: true
PlasmaCore.DataSource { PlasmaCore.DataSource {
id: tasksSource id: tasksSource

View File

@ -44,6 +44,10 @@
#include <xcb/shape.h> #include <xcb/shape.h>
#endif #endif
//Unfortunately QWINDOWSIZE_MAX is not exported
#define DIALOGSIZE_MAX ((1<<24)-1)
DialogProxy::DialogProxy(QQuickItem *parent) DialogProxy::DialogProxy(QQuickItem *parent)
: QQuickWindow(parent ? parent->window() : 0), : QQuickWindow(parent ? parent->window() : 0),
m_location(Plasma::Types::BottomEdge), m_location(Plasma::Types::BottomEdge),
@ -114,6 +118,36 @@ void DialogProxy::setMainItem(QQuickItem *mainItem)
}); });
} }
requestSyncToMainItemSize(); requestSyncToMainItemSize();
//Extract the representation's Layout, if any
QObject *layout = 0;
//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, mainItem->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;
}
}
m_mainItemLayout = layout;
if (layout) {
connect(layout, SIGNAL(minimumWidthChanged()), this, SLOT(updateMinimumWidth()));
connect(layout, SIGNAL(minimumHeightChanged()), this, SLOT(updateMinimumHeight()));
connect(layout, SIGNAL(maximumWidthChanged()), this, SLOT(updatemaximumWidth()));
connect(layout, SIGNAL(maximumHeightChanged()), this, SLOT(updatemaximumHeight()));
updateMinimumWidth();
updateMinimumHeight();
updateMaximumWidth();
updateMaximumHeight();
}
} }
//if this is called in Component.onCompleted we have to wait a loop the item is added to a scene //if this is called in Component.onCompleted we have to wait a loop the item is added to a scene
@ -604,6 +638,7 @@ void DialogProxy::updateInputShape()
#endif #endif
} }
//find the screen which contains the item //find the screen which contains the item
QScreen* DialogProxy::screenForItem(QQuickItem* item) const QScreen* DialogProxy::screenForItem(QQuickItem* item) const
{ {
@ -616,5 +651,51 @@ QScreen* DialogProxy::screenForItem(QQuickItem* item) const
return QGuiApplication::primaryScreen(); return QGuiApplication::primaryScreen();
} }
void DialogProxy::updateMinimumWidth()
{
if (m_mainItemLayout) {
setMinimumWidth(m_mainItemLayout.data()->property("minimumWidth").toInt());
} else {
setMinimumWidth(-1);
}
}
void DialogProxy::updateMinimumHeight()
{
if (m_mainItemLayout) {
setMinimumHeight(m_mainItemLayout.data()->property("minimumHeight").toInt());
} else {
setMinimumHeight(-1);
}
}
void DialogProxy::updateMaximumWidth()
{
if (m_mainItemLayout) {
const int hint = m_mainItemLayout.data()->property("maximumWidth").toInt();
if (hint > 0) {
setMaximumWidth(hint);
} else {
setMaximumWidth(DIALOGSIZE_MAX);
}
} else {
setMaximumWidth(DIALOGSIZE_MAX);
}
}
void DialogProxy::updateMaximumHeight()
{
if (m_mainItemLayout) {
const int hint = m_mainItemLayout.data()->property("maximumHeight").toInt();
if (hint > 0) {
setMaximumWidth(hint);
} else {
setMaximumWidth(DIALOGSIZE_MAX);
}
} else {
setMaximumHeight(DIALOGSIZE_MAX);
}
}
#include "dialog.moc" #include "dialog.moc"

View File

@ -172,6 +172,11 @@ private Q_SLOTS:
void updateVisibility(bool visible); void updateVisibility(bool visible);
void updateMinimumWidth();
void updateMinimumHeight();
void updateMaximumWidth();
void updateMaximumHeight();
private: private:
QScreen* screenForItem(QQuickItem *item) const; QScreen* screenForItem(QQuickItem *item) const;
@ -180,6 +185,9 @@ private:
bool m_hideOnWindowDeactivate; bool m_hideOnWindowDeactivate;
bool m_outputOnly; bool m_outputOnly;
Plasma::Theme m_theme; Plasma::Theme m_theme;
//Attached Layout property of mainItem, if any
QWeakPointer <QObject> m_mainItemLayout;
}; };
#endif #endif

View File

@ -415,6 +415,21 @@ class PLASMA_EXPORT Applet : public QObject
public Q_SLOTS: public Q_SLOTS:
//BOOKKEEPING //BOOKKEEPING
/**
* Call this method when the applet fails to launch properly. An
* optional reason can be provided.
*
* Not that all children items will be deleted when this method is
* called. If you have pointers to these items, you will need to
* reset them after calling this method.
*
* @param failed true when the applet failed, false when it succeeded
* @param reason an optional reason to show the user why the applet
* failed to launch
* @since 5.0
**/
void setLaunchErrorMessage(const QString &reason = QString());
/** /**
* Sets the immutability type for this applet (not immutable, * Sets the immutability type for this applet (not immutable,
* user immutable or system immutable) * user immutable or system immutable)
@ -488,22 +503,6 @@ class PLASMA_EXPORT Applet : public QObject
*/ */
Applet(QObject *parent, const QVariantList &args); Applet(QObject *parent, const QVariantList &args);
//BOOKEEPING
/**
* Call this method when the applet fails to launch properly. An
* optional reason can be provided.
*
* Not that all children items will be deleted when this method is
* called. If you have pointers to these items, you will need to
* reset them after calling this method.
*
* @param failed true when the applet failed, false when it succeeded
* @param reason an optional reason to show the user why the applet
* failed to launch
* @since 5.0
**/
void setLaunchErrorMessage(const QString &reason = QString());
//CONFIGURATION //CONFIGURATION
/** /**
* When called, the Applet should write any information needed as part * When called, the Applet should write any information needed as part

View File

@ -358,12 +358,21 @@ KConfigGroup *AppletPrivate::mainConfigGroup()
return mainConfig; return mainConfig;
} }
Containment *c = q->containment();
Plasma::Applet *parentApplet = 0;
if (c) {
parentApplet = qobject_cast<Plasma::Applet *>(c->parent());
}
if (q->isContainment()) { if (q->isContainment()) {
Corona *corona = static_cast<Containment*>(q)->corona(); Corona *corona = static_cast<Containment*>(q)->corona();
KConfigGroup containmentConfig; KConfigGroup containmentConfig;
//qDebug() << "got a corona, baby?" << (QObject*)corona << (QObject*)q; //qDebug() << "got a corona, baby?" << (QObject*)corona << (QObject*)q;
if (corona) { if (parentApplet) {
containmentConfig = parentApplet->config();
containmentConfig = KConfigGroup(&containmentConfig, "Containments");
} else if (corona) {
containmentConfig = KConfigGroup(corona->config(), "Containments"); containmentConfig = KConfigGroup(corona->config(), "Containments");
} else { } else {
containmentConfig = KConfigGroup(KSharedConfig::openConfig(), "Containments"); containmentConfig = KConfigGroup(KSharedConfig::openConfig(), "Containments");
@ -373,14 +382,7 @@ KConfigGroup *AppletPrivate::mainConfigGroup()
} else { } else {
KConfigGroup appletConfig; KConfigGroup appletConfig;
Containment *c = q->containment(); if (c) {
Applet *parentApplet = qobject_cast<Applet *>(q->parent());
if (parentApplet && parentApplet != static_cast<Applet *>(c)) {
// this applet is nested inside another applet! use it's config
// as the parent group in the config
appletConfig = parentApplet->config();
appletConfig = KConfigGroup(&appletConfig, "Applets");
} else if (c) {
// applet directly in a Containment, as usual // applet directly in a Containment, as usual
appletConfig = c->config(); appletConfig = c->config();
appletConfig = KConfigGroup(&appletConfig, "Applets"); appletConfig = KConfigGroup(&appletConfig, "Applets");

View File

@ -1,6 +1,7 @@
project(PlasmaQuick) project(PlasmaQuick)
set(plasmaquick_LIB_SRC set(plasmaquick_LIB_SRC
appletquickitem.cpp
plasmaquickview.cpp plasmaquickview.cpp
configmodel.cpp configmodel.cpp
configview.cpp configview.cpp
@ -36,6 +37,7 @@ generate_export_header(KF5PlasmaQuick BASE_NAME PlasmaQuick)
set(plasmaquick_LIB_INCLUDES set(plasmaquick_LIB_INCLUDES
${CMAKE_CURRENT_BINARY_DIR}/plasmaquick_export.h ${CMAKE_CURRENT_BINARY_DIR}/plasmaquick_export.h
appletquickitem.h
plasmaquickview.h plasmaquickview.h
configview.h configview.h
configmodel.h configmodel.h

View File

@ -0,0 +1,648 @@
/*
* 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/qmlobject.h>
#include <plasma/scripting/appletscript.h>
#include <packageurlinterceptor.h>
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)
{
}
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;
}
}
if (!layout) {
return;
}
//propagate all the size hints
propagateSizeHint("minimumWidth");
propagateSizeHint("minimumHeight");
propagateSizeHint("preferredWidth");
propagateSizeHint("preferredHeight");
propagateSizeHint("maximumWidth");
propagateSizeHint("maximumHeight");
propagateSizeHint("fillWidth");
propagateSizeHint("fillHeight");
//HACK: check the Layout properties we wrote
QQmlProperty p(q, "Layout.minimumWidth", QtQml::qmlContext(qmlObject->rootObject()));
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;
}
}
//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.data() == layout) {
return;
}
if (representationLayout) {
QObject::disconnect(representationLayout.data(), 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.data()->setProperty(layoutProperty, representationLayout.data()->property(layoutProperty));
}
}
QObject *AppletQuickItemPrivate::createCompactRepresentationItem()
{
if (!compactRepresentation) {
return 0;
}
if (compactRepresentationItem) {
return compactRepresentationItem.data();
}
compactRepresentationItem = qmlObject->createObjectFromComponent(compactRepresentation.data(), QtQml::qmlContext(qmlObject->rootObject()));
emit q->compactRepresentationItemChanged(compactRepresentationItem.data());
return compactRepresentationItem.data();
}
QObject *AppletQuickItemPrivate::createFullRepresentationItem()
{
if (fullRepresentationItem) {
return fullRepresentationItem.data();
}
if (fullRepresentation) {
fullRepresentationItem = qmlObject->createObjectFromComponent(fullRepresentation.data(), QtQml::qmlContext(qmlObject->rootObject()));
} else {
fullRepresentation = qmlObject->mainComponent();
fullRepresentationItem = qmlObject->rootObject();
emit q->fullRepresentationChanged(fullRepresentation.data());
}
QQuickItem *graphicsObj = qobject_cast<QQuickItem *>(fullRepresentationItem.data());
QObject::connect (graphicsObj, &QQuickItem::widthChanged, [=]() {
fullRepresentationResizeTimer.start();
});
QObject::connect (graphicsObj, &QQuickItem::heightChanged, [=]() {
fullRepresentationResizeTimer.start();
});
emit q->fullRepresentationItemChanged(fullRepresentationItem.data());
return fullRepresentationItem.data();
}
QObject *AppletQuickItemPrivate::createCompactRepresentationExpanderItem()
{
if (!compactRepresentationExpander) {
return 0;
}
if (compactRepresentationExpanderItem) {
return compactRepresentationExpanderItem.data();
}
compactRepresentationExpanderItem = qmlObject->createObjectFromComponent(compactRepresentationExpander.data(), QtQml::qmlContext(qmlObject->rootObject()));
compactRepresentationExpanderItem.data()->setProperty("compactRepresentation", QVariant::fromValue(createCompactRepresentationItem()));
compactRepresentationExpanderItem.data()->setProperty("fullRepresentation", QVariant::fromValue(createFullRepresentationItem()));
return compactRepresentationExpanderItem.data();
}
void AppletQuickItemPrivate::compactRepresentationCheck()
{
//ignore 0,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.data() == fullRepresentation.data();
//Otherwise, base on FormFactor
} else {
full = (applet->formFactor() != Plasma::Types::Horizontal && applet->formFactor() != Plasma::Types::Vertical);
}
}
if ((full && fullRepresentationItem && fullRepresentationItem.data() == currentRepresentationItem.data()) ||
(!full && compactRepresentationItem && compactRepresentationItem.data() == currentRepresentationItem.data())
) {
return;
}
}
//Expanded
if (full) {
QQuickItem *item = qobject_cast<QQuickItem *>(createFullRepresentationItem());
if (item) {
item->setParentItem(q);
{
//set anchors
QQmlExpression expr(QtQml::qmlContext(qmlObject->rootObject()), item, "parent");
QQmlProperty prop(item, "anchors.fill");
prop.write(expr.evaluate());
}
if (compactRepresentationItem) {
compactRepresentationItem.data()->setProperty("visible", false);
}
if (compactRepresentationExpanderItem) {
compactRepresentationExpanderItem.data()->setProperty("compactRepresentation", QVariant());
compactRepresentationExpanderItem.data()->setProperty("fullRepresentation", QVariant());
}
currentRepresentationItem = item;
connectLayoutAttached(item);
}
//Icon
} else {
QQuickItem *compactItem = qobject_cast<QQuickItem *>(createCompactRepresentationItem());
if (compactItem) {
//set the root item as the main visible item
compactItem->setParentItem(q);
compactItem->setVisible(true);
{
//set anchors
QQmlExpression expr(QtQml::qmlContext(qmlObject->rootObject()), compactItem, "parent");
QQmlProperty prop(compactItem, "anchors.fill");
prop.write(expr.evaluate());
}
if (fullRepresentationItem) {
fullRepresentationItem.data()->setProperty("parent", QVariant());
}
if (compactRepresentationExpanderItem) {
compactRepresentationExpanderItem.data()->setProperty("compactRepresentation", QVariant::fromValue(compactItem));
compactRepresentationExpanderItem.data()->setProperty("fullRepresentation", QVariant::fromValue(createFullRepresentationItem()));
}
currentRepresentationItem = compactItem;
connectLayoutAttached(compactItem);
}
}
}
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))
{
if (d->applet) {
d->appletPackage = d->applet->package();
}
if (d->applet && d->applet->containment() && d->applet->containment()->corona()) {
d->coronaPackage = d->applet->containment()->corona()->package();
}
d->compactRepresentationCheckTimer.setSingleShot(true);
d->compactRepresentationCheckTimer.setInterval(250);
connect (&d->compactRepresentationCheckTimer, SIGNAL(timeout()),
this, SLOT(compactRepresentationCheck()));
d->compactRepresentationCheckTimer.start();
d->fullRepresentationResizeTimer.setSingleShot(true);
d->fullRepresentationResizeTimer.setInterval(250);
connect (&d->fullRepresentationResizeTimer, &QTimer::timeout,
[=]() {
KConfigGroup cg = d->applet->config();
cg = KConfigGroup(&cg, "PopupApplet");
cg.writeEntry("DialogWidth", d->fullRepresentationItem.data()->property("width").toInt());
cg.writeEntry("DialogHeight", d->fullRepresentationItem.data()->property("height").toInt());
}
);
d->qmlObject = new KDeclarative::QmlObject(this);
d->qmlObject->setInitializationDelayed(true);
// set the graphicObject dynamic property on applet
d->applet->setProperty("_plasma_graphicObject", QVariant::fromValue(this));
setProperty("_plasma_applet", QVariant::fromValue(applet));
}
AppletQuickItem::~AppletQuickItem()
{
//Here the order is important
delete d->compactRepresentationItem.data();
delete d->fullRepresentationItem.data();
delete d->compactRepresentationExpanderItem.data();
AppletQuickItemPrivate::s_rootObjects.remove(d->qmlObject->engine());
}
AppletQuickItem *AppletQuickItem::qmlAttachedProperties(QObject *object)
{
//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(QtQml::qmlEngine(object))) {
return AppletQuickItemPrivate::s_rootObjects.value(QtQml::qmlEngine(object));
} else {
return 0;
}
}
Plasma::Applet *AppletQuickItem::applet() const
{
return d->applet;
}
void AppletQuickItem::init()
{
if (AppletQuickItemPrivate::s_rootObjects.contains(this)) {
return;
}
AppletQuickItemPrivate::s_rootObjects[d->qmlObject->engine()] = this;
Q_ASSERT(d->applet);
//Initialize the main QML file
QQmlEngine *engine = d->qmlObject->engine();
PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(engine, d->applet->package());
interceptor->addAllowedPath(d->coronaPackage.path());
engine->setUrlInterceptor(interceptor);
d->qmlObject->setSource(QUrl::fromLocalFile(d->applet->package().filePath("mainscript")));
if (!engine || !engine->rootContext() || !engine->rootContext()->isValid() || d->qmlObject->mainComponent()->isError()) {
QString reason;
foreach (QQmlError error, d->qmlObject->mainComponent()->errors()) {
reason += error.toString()+'\n';
}
reason = i18n("Error loading QML file: %1", reason);
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);
}
engine->rootContext()->setContextProperty("plasmoid", this);
//initialize size, so an useless resize less
QVariantHash initialProperties;
initialProperties["width"] = width();
initialProperties["height"] = height();
d->qmlObject->completeInitialization(initialProperties);
//default fullrepresentation is our root main component, if none specified
if (!d->fullRepresentation) {
d->fullRepresentation = d->qmlObject->mainComponent();
d->fullRepresentationItem = d->qmlObject->rootObject();
emit fullRepresentationChanged(d->fullRepresentation.data());
}
//default d->compactRepresentation is a simple icon provided by the shell package
if (!d->compactRepresentation) {
d->compactRepresentation = new QQmlComponent(engine, this);
d->compactRepresentation.data()->loadUrl(QUrl::fromLocalFile(d->coronaPackage.filePath("defaultcompactrepresentation")));
emit compactRepresentationChanged(d->compactRepresentation.data());
}
//default d->compactRepresentationExpander is the popup in which fullRepresentation goes
if (!d->compactRepresentationExpander) {
d->compactRepresentationExpander = new QQmlComponent(engine, this);
d->compactRepresentationExpander.data()->loadUrl(QUrl::fromLocalFile(d->coronaPackage.filePath("compactapplet")));
}
}
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 width)
{
if (d->switchHeight == width) {
return;
}
d->switchHeight = width;
emit switchHeightChanged(width);
}
QQmlComponent *AppletQuickItem::compactRepresentation()
{
return d->compactRepresentation.data();
}
void AppletQuickItem::setCompactRepresentation(QQmlComponent *component)
{
if (d->compactRepresentation.data() == component) {
return;
}
d->compactRepresentation = component;
emit compactRepresentationChanged(component);
}
QQmlComponent *AppletQuickItem::fullRepresentation()
{
return d->fullRepresentation.data();
}
void AppletQuickItem::setFullRepresentation(QQmlComponent *component)
{
if (d->fullRepresentation.data() == component) {
return;
}
d->fullRepresentation = component;
emit fullRepresentationChanged(component);
}
QQmlComponent *AppletQuickItem::preferredRepresentation()
{
return d->preferredRepresentation.data();
}
void AppletQuickItem::setPreferredRepresentation(QQmlComponent *component)
{
if (d->preferredRepresentation.data() == component) {
return;
}
d->preferredRepresentation = component;
emit preferredRepresentationChanged(component);
}
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
//Containnments are always expanded
if (d->expanded == expanded) {
return;
}
d->createFullRepresentationItem();
d->createCompactRepresentationExpanderItem();
d->expanded = expanded;
emit expandedChanged(expanded);
}
////////////Internals
KDeclarative::QmlObject *AppletQuickItem::qmlObject()
{
return d->qmlObject;
}
QObject *AppletQuickItem::compactRepresentationItem()
{
return d->compactRepresentationItem.data();
}
QObject *AppletQuickItem::fullRepresentationItem()
{
return d->fullRepresentationItem.data();
}
void AppletQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_UNUSED(oldGeometry)
QQuickItem::geometryChanged(newGeometry, oldGeometry);
d->compactRepresentationCheckTimer.start();
}
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"

View File

@ -0,0 +1,151 @@
/*
* 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.
*/
#ifndef APPLETQUICKITEM_H
#define APPLETQUICKITEM_H
#include <QQuickItem>
#include <QWeakPointer>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QTimer>
#include <Plasma/Package>
#include <plasmaquick/plasmaquick_export.h>
namespace Plasma {
class Applet;
}
namespace KDeclarative {
class QmlObject;
}
class AppletQuickItemPrivate;
class PLASMAQUICK_EXPORT AppletQuickItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(int switchWidth READ switchWidth WRITE setSwitchWidth NOTIFY switchWidthChanged)
Q_PROPERTY(int switchHeight READ switchHeight WRITE setSwitchHeight NOTIFY switchHeightChanged)
Q_PROPERTY(QQmlComponent *compactRepresentation READ compactRepresentation WRITE setCompactRepresentation NOTIFY compactRepresentationChanged)
Q_PROPERTY(QObject *compactRepresentationItem READ compactRepresentationItem NOTIFY compactRepresentationItemChanged)
Q_PROPERTY(QQmlComponent *fullRepresentation READ fullRepresentation WRITE setFullRepresentation NOTIFY fullRepresentationChanged)
Q_PROPERTY(QObject *fullRepresentationItem READ fullRepresentationItem NOTIFY fullRepresentationItemChanged)
/**
* this is supposed to be either one between compactRepresentation or fullRepresentation
*/
Q_PROPERTY(QQmlComponent *preferredRepresentation READ preferredRepresentation WRITE setPreferredRepresentation NOTIFY preferredRepresentationChanged)
/**
* True when the applet is showing its full representation. either as the main only view, or in a popup.
* Setting it will open or close the popup if the plasmoid is iconified, however it won't have effect if the applet is open
*/
Q_PROPERTY(bool expanded WRITE setExpanded READ isExpanded NOTIFY expandedChanged)
public:
AppletQuickItem(Plasma::Applet *applet, QQuickItem *parent = 0);
~AppletQuickItem();
////API NOT SUPPOSED TO BE USED BY QML
Plasma::Applet *applet() const;
//Make the constructor lighter and delay the actual instantiation of the qml in the applet
virtual void init();
Plasma::Package appletPackage() const;
void setAppletPackage(const Plasma::Package &package);
Plasma::Package coronaPackage() const;
void setCoronaPackage(const Plasma::Package &package);
QObject *compactRepresentationItem();
QObject *fullRepresentationItem();
////PROPERTY ACCESSORS
int switchWidth() const;
void setSwitchWidth(int width);
int switchHeight() const;
void setSwitchHeight(int width);
QQmlComponent *compactRepresentation();
void setCompactRepresentation(QQmlComponent *component);
QQmlComponent *fullRepresentation();
void setFullRepresentation(QQmlComponent *component);
QQmlComponent *preferredRepresentation();
void setPreferredRepresentation(QQmlComponent *component);
bool isExpanded() const;
void setExpanded(bool expanded);
////NEEDED BY QML TO CREATE ATTACHED PROPERTIES
static AppletQuickItem *qmlAttachedProperties(QObject *object);
Q_SIGNALS:
//Property signals
void switchWidthChanged(int width);
void switchHeightChanged(int height);
void expandedChanged(bool expanded);
void compactRepresentationChanged(QQmlComponent *compactRepresentation);
void fullRepresentationChanged(QQmlComponent *fullRepresentation);
void preferredRepresentationChanged(QQmlComponent *preferredRepresentation);
void compactRepresentationItemChanged(QObject *compactRepresentationItem);
void fullRepresentationItemChanged(QObject *fullRepresentationItem);
protected:
KDeclarative::QmlObject *qmlObject();
//Reimplementation
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
virtual void itemChange(ItemChange change, const ItemChangeData &value);
private:
AppletQuickItemPrivate *const d;
Q_PRIVATE_SLOT(d, void compactRepresentationCheck())
Q_PRIVATE_SLOT(d, void minimumWidthChanged())
Q_PRIVATE_SLOT(d, void minimumHeightChanged())
Q_PRIVATE_SLOT(d, void preferredWidthChanged())
Q_PRIVATE_SLOT(d, void preferredHeightChanged())
Q_PRIVATE_SLOT(d, void maximumWidthChanged())
Q_PRIVATE_SLOT(d, void maximumHeightChanged())
Q_PRIVATE_SLOT(d, void fillWidthChanged())
Q_PRIVATE_SLOT(d, void fillHeightChanged())
};
QML_DECLARE_TYPEINFO(AppletQuickItem, QML_HAS_ATTACHED_PROPERTIES)
#endif

View File

@ -92,7 +92,7 @@ void ConfigViewPrivate::init()
delete object; delete object;
} }
q->engine()->rootContext()->setContextProperty("plasmoid", applet->property("graphicObject").value<QObject*>()); q->engine()->rootContext()->setContextProperty("plasmoid", applet->property("_plasma_graphicObject").value<QObject*>());
q->engine()->rootContext()->setContextProperty("configDialog", q); q->engine()->rootContext()->setContextProperty("configDialog", q);
component->completeCreate(); component->completeCreate();
delete component; delete component;

View File

@ -67,7 +67,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont)
if (containment) { if (containment) {
QObject::disconnect(containment.data(), 0, q, 0); QObject::disconnect(containment.data(), 0, q, 0);
QObject *oldGraphicObject = containment.data()->property("graphicObject").value<QObject *>(); QObject *oldGraphicObject = containment.data()->property("_plasma_graphicObject").value<QObject *>();
if (oldGraphicObject) { if (oldGraphicObject) {
qDebug() << "Old graphics Object:" << oldGraphicObject << "Old containment" << containment.data(); qDebug() << "Old graphics Object:" << oldGraphicObject << "Old containment" << containment.data();
//make sure the graphic object won't die with us //make sure the graphic object won't die with us
@ -100,7 +100,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont)
return; return;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(containment.data()->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(containment.data()->property("_plasma_graphicObject").value<QObject *>());
if (graphicObject) { if (graphicObject) {

View File

@ -0,0 +1,93 @@
/*
* 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.
*/
#ifndef APPLETQUICKITEM_P_H
#define APPLETQUICKITEM_P_H
#include <QQmlComponent>
namespace Plasma {
class Applet;
}
namespace KDeclarative {
class QmlObject;
}
class AppletQuickItem;
class AppletQuickItemPrivate
{
public:
AppletQuickItemPrivate(Plasma::Applet *a, AppletQuickItem *item);
QObject *createCompactRepresentationItem();
QObject *createFullRepresentationItem();
QObject *createCompactRepresentationExpanderItem();
//look into item, and return the Layout attached property, if found
void connectLayoutAttached(QObject *item);
void propagateSizeHint(const QByteArray &layoutProperty);
//handlers of Layout signals, private slots
void compactRepresentationCheck();
void minimumWidthChanged();
void minimumHeightChanged();
void preferredWidthChanged();
void preferredHeightChanged();
void maximumWidthChanged();
void maximumHeightChanged();
void fillWidthChanged();
void fillHeightChanged();
AppletQuickItem *q;
int switchWidth;
int switchHeight;
QWeakPointer<QQmlComponent> compactRepresentation;
QWeakPointer<QQmlComponent> fullRepresentation;
QWeakPointer<QQmlComponent> preferredRepresentation;
QWeakPointer<QQmlComponent> compactRepresentationExpander;
QWeakPointer<QObject> compactRepresentationItem;
QWeakPointer<QObject> fullRepresentationItem;
QWeakPointer<QObject> compactRepresentationExpanderItem;
QWeakPointer<QObject> currentRepresentationItem;
//Attached layout objects: own and the representation's one
QWeakPointer<QObject> representationLayout;
QWeakPointer<QObject> ownLayout;
QTimer compactRepresentationCheckTimer;
QTimer fullRepresentationResizeTimer;
Plasma::Applet *applet;
KDeclarative::QmlObject *qmlObject;
Plasma::Package appletPackage;
Plasma::Package coronaPackage;
bool expanded : 1;
static QHash<QObject *, AppletQuickItem *> s_rootObjects;
};
#endif

View File

@ -8,6 +8,8 @@ endif()
#DECLARATIVE APPLET #DECLARATIVE APPLET
set(declarative_appletscript_SRCS set(declarative_appletscript_SRCS
plasmoid/declarativeappletscript.cpp
plasmoid/appletinterface.cpp plasmoid/appletinterface.cpp
plasmoid/containmentinterface.cpp plasmoid/containmentinterface.cpp
plasmoid/declarativeappletscript.cpp plasmoid/declarativeappletscript.cpp

View File

@ -48,20 +48,18 @@
#include <kdeclarative/configpropertymap.h> #include <kdeclarative/configpropertymap.h>
#include <kdeclarative/qmlobject.h> #include <kdeclarative/qmlobject.h>
#include <packageurlinterceptor.h>
Q_DECLARE_METATYPE(AppletInterface*) Q_DECLARE_METATYPE(AppletInterface*)
AppletInterface::AppletInterface(DeclarativeAppletScript *script, QQuickItem *parent) AppletInterface::AppletInterface(DeclarativeAppletScript *script, QQuickItem *parent)
: QQuickItem(parent), : AppletQuickItem(script->applet(), parent),
m_appletScriptEngine(script),
m_actionSignals(0), m_actionSignals(0),
m_appletScriptEngine(script),
m_backgroundHints(Plasma::Types::StandardBackground), m_backgroundHints(Plasma::Types::StandardBackground),
m_busy(false), m_busy(false),
m_expanded(false),
m_hideOnDeactivate(true) m_hideOnDeactivate(true)
{ {
qmlRegisterType<AppletInterface>();
qmlRegisterType<QAction>(); qmlRegisterType<QAction>();
connect(this, &AppletInterface::configNeedsSaving, connect(this, &AppletInterface::configNeedsSaving,
@ -74,80 +72,39 @@ AppletInterface::AppletInterface(DeclarativeAppletScript *script, QQuickItem *pa
connect(applet(), &Plasma::Applet::statusChanged, connect(applet(), &Plasma::Applet::statusChanged,
this, &AppletInterface::statusChanged); this, &AppletInterface::statusChanged);
connect(m_appletScriptEngine, &DeclarativeAppletScript::formFactorChanged, connect(appletScript(), &DeclarativeAppletScript::formFactorChanged,
this, &AppletInterface::formFactorChanged); this, &AppletInterface::formFactorChanged);
connect(m_appletScriptEngine, &DeclarativeAppletScript::locationChanged, connect(appletScript(), &DeclarativeAppletScript::locationChanged,
this, &AppletInterface::locationChanged); this, &AppletInterface::locationChanged);
connect(m_appletScriptEngine, &DeclarativeAppletScript::contextChanged, connect(appletScript(), &DeclarativeAppletScript::contextChanged,
this, &AppletInterface::contextChanged); this, &AppletInterface::contextChanged);
if (applet()->containment()) { if (applet()->containment()) {
connect(applet()->containment(), &Plasma::Containment::screenChanged, connect(applet()->containment(), &Plasma::Containment::screenChanged,
this, &ContainmentInterface::screenChanged); this, &ContainmentInterface::screenChanged);
} }
m_qmlObject = new KDeclarative::QmlObject(this);
m_qmlObject->setInitializationDelayed(true);
m_collapseTimer = new QTimer(this);
m_collapseTimer->setSingleShot(true);
connect(m_collapseTimer, &QTimer::timeout, this, &AppletInterface::compactRepresentationCheck);
} }
AppletInterface::~AppletInterface() AppletInterface::~AppletInterface()
{ {
} }
DeclarativeAppletScript *AppletInterface::appletScript() const
{
return m_appletScriptEngine;
}
void AppletInterface::init() void AppletInterface::init()
{ {
if (m_qmlObject->rootObject()) { if (qmlObject()->rootObject() && m_configuration) {
return; return;
} }
m_configuration = new KDeclarative::ConfigPropertyMap(applet()->configScheme(), this); m_configuration = new KDeclarative::ConfigPropertyMap(applet()->configScheme(), this);
//use our own custom network access manager that will access Plasma packages and to manage security (i.e. deny access to remote stuff when the proper extension isn't enabled AppletQuickItem::init();
QQmlEngine *engine = m_qmlObject->engine();
//Hook generic url resolution to the applet package as well qDebug() << "Graphic object created:" << applet() << this;
//TODO: same thing will have to be done for every qqmlengine: PackageUrlInterceptor is material for plasmaquick?
PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(engine, m_appletScriptEngine->package());
interceptor->addAllowedPath(applet()->containment()->corona()->package().path());
engine->setUrlInterceptor(interceptor);
m_qmlObject->setSource(QUrl::fromLocalFile(m_appletScriptEngine->mainScript()));
if (!m_qmlObject->engine() || !m_qmlObject->engine()->rootContext() || !m_qmlObject->engine()->rootContext()->isValid() || m_qmlObject->mainComponent()->isError()) {
QString reason;
foreach (QQmlError error, m_qmlObject->mainComponent()->errors()) {
reason += error.toString()+'\n';
}
reason = i18n("Error loading QML file: %1", reason);
m_qmlObject->setSource(QUrl::fromLocalFile(applet()->containment()->corona()->package().filePath("appleterror")));
m_qmlObject->completeInitialization();
//even the error message QML may fail
if (m_qmlObject->mainComponent()->isError()) {
return;
} else {
m_qmlObject->rootObject()->setProperty("reason", reason);
}
m_appletScriptEngine->setLaunchErrorMessage(reason);
}
m_qmlObject->engine()->rootContext()->setContextProperty("plasmoid", this);
//initialize size, so an useless resize less
QVariantHash initialProperties;
initialProperties["width"] = width();
initialProperties["height"] = height();
m_qmlObject->completeInitialization(initialProperties);
qDebug() << "Graphic object created:" << applet() << applet()->property("graphicObject");
geometryChanged(QRectF(), QRectF(x(), y(), width(), height())); geometryChanged(QRectF(), QRectF(x(), y(), width(), height()));
emit busyChanged(); emit busyChanged();
@ -167,7 +124,11 @@ Plasma::Types::Location AppletInterface::location() const
QString AppletInterface::currentActivity() const QString AppletInterface::currentActivity() const
{ {
if (applet()->containment()) {
return applet()->containment()->activity(); return applet()->containment()->activity();
} else {
return QString();
}
} }
QObject* AppletInterface::configuration() const QObject* AppletInterface::configuration() const
@ -212,7 +173,7 @@ void AppletInterface::setTitle(const QString &title)
bool AppletInterface::isBusy() const bool AppletInterface::isBusy() const
{ {
return !m_qmlObject->rootObject() || m_busy; return m_busy;
} }
void AppletInterface::setBusy(bool busy) void AppletInterface::setBusy(bool busy)
@ -225,23 +186,6 @@ void AppletInterface::setBusy(bool busy)
emit busyChanged(); emit busyChanged();
} }
bool AppletInterface::isExpanded() const
{
return m_expanded;
}
void AppletInterface::setExpanded(bool expanded)
{
//if there is no compact representation it means it's always expanded
//Containnments are always expanded
if (!m_compactUiObject || qobject_cast<ContainmentInterface *>(this) || m_expanded == expanded) {
return;
}
m_expanded = expanded;
emit expandedChanged();
}
Plasma::Types::BackgroundHints AppletInterface::backgroundHints() const Plasma::Types::BackgroundHints AppletInterface::backgroundHints() const
{ {
return m_backgroundHints; return m_backgroundHints;
@ -259,7 +203,7 @@ void AppletInterface::setBackgroundHints(Plasma::Types::BackgroundHints hint)
void AppletInterface::setConfigurationRequired(bool needsConfiguring, const QString &reason) void AppletInterface::setConfigurationRequired(bool needsConfiguring, const QString &reason)
{ {
m_appletScriptEngine->setConfigurationRequired(needsConfiguring, reason); appletScript()->setConfigurationRequired(needsConfiguring, reason);
} }
QString AppletInterface::activeConfig() const QString AppletInterface::activeConfig() const
@ -277,7 +221,7 @@ void AppletInterface::setActiveConfig(const QString &name)
Plasma::ConfigLoader *loader = m_configs.value(name, 0); Plasma::ConfigLoader *loader = m_configs.value(name, 0);
if (!loader) { if (!loader) {
QString path = m_appletScriptEngine->filePath("config", name + ".xml"); QString path = appletScript()->filePath("config", name + ".xml");
if (path.isEmpty()) { if (path.isEmpty()) {
return; return;
} }
@ -307,7 +251,7 @@ void AppletInterface::writeConfig(const QString &entry, const QVariant &value)
config->blockSignals(true); config->blockSignals(true);
config->writeConfig(); config->writeConfig();
config->blockSignals(false); config->blockSignals(false);
m_appletScriptEngine->configNeedsSaving(); appletScript()->configNeedsSaving();
} }
} else } else
qWarning() << "Couldn't find a configuration entry"; qWarning() << "Couldn't find a configuration entry";
@ -333,12 +277,12 @@ QVariant AppletInterface::readConfig(const QString &entry) const
QString AppletInterface::file(const QString &fileType) QString AppletInterface::file(const QString &fileType)
{ {
return m_appletScriptEngine->filePath(fileType, QString()); return appletScript()->filePath(fileType, QString());
} }
QString AppletInterface::file(const QString &fileType, const QString &filePath) QString AppletInterface::file(const QString &fileType, const QString &filePath)
{ {
return m_appletScriptEngine->filePath(fileType, filePath); return appletScript()->filePath(fileType, filePath);
} }
QList<QAction*> AppletInterface::contextualActions() const QList<QAction*> AppletInterface::contextualActions() const
@ -392,7 +336,7 @@ void AppletInterface::setAction(const QString &name, const QString &text, const
if (!m_actionSignals) { if (!m_actionSignals) {
m_actionSignals = new QSignalMapper(this); m_actionSignals = new QSignalMapper(this);
connect(m_actionSignals, SIGNAL(mapped(QString)), connect(m_actionSignals, SIGNAL(mapped(QString)),
m_appletScriptEngine, SLOT(executeAction(QString))); appletScript(), SLOT(executeAction(QString)));
} }
connect(action, SIGNAL(triggered()), m_actionSignals, SLOT(map())); connect(action, SIGNAL(triggered()), m_actionSignals, SLOT(map()));
@ -452,92 +396,6 @@ int AppletInterface::apiVersion() const
return offers.first()->property("X-KDE-PluginInfo-Version", QVariant::Int).toInt(); return offers.first()->property("X-KDE-PluginInfo-Version", QVariant::Int).toInt();
} }
bool AppletInterface::fillWidth() const
{
if (!m_qmlObject->rootObject()) {
return false;
}
QVariant prop;
if (m_compactUiObject) {
prop = m_compactUiObject.data()->property("fillWidth");
} else {
prop = m_qmlObject->rootObject()->property("fillWidth");
}
if (prop.isValid() && prop.canConvert<bool>()) {
return prop.toBool();
} else {
return false;
}
}
bool AppletInterface::fillHeight() const
{
if (!m_qmlObject->rootObject()) {
return false;
}
QVariant prop;
if (m_compactUiObject) {
prop = m_compactUiObject.data()->property("fillHeight");
} else {
prop = m_qmlObject->rootObject()->property("fillHeight");
}
if (prop.isValid() && prop.canConvert<bool>()) {
return prop.toBool();
} else {
return false;
}
}
//private api, just an helper
qreal AppletInterface::readGraphicsObjectSizeHint(const char *hint) const
{
if (!m_qmlObject->rootObject()) {
return -1;
}
QVariant prop;
if (m_compactUiObject) {
prop = m_compactUiObject.data()->property(hint);
} else {
prop = m_qmlObject->rootObject()->property(hint);
}
if (prop.isValid() && prop.canConvert<qreal>()) {
return prop.toReal();
} else {
return -1;
}
}
qreal AppletInterface::minimumWidth() const
{
return readGraphicsObjectSizeHint("minimumWidth");
}
qreal AppletInterface::minimumHeight() const
{
return readGraphicsObjectSizeHint("minimumHeight");
}
qreal AppletInterface::maximumWidth() const
{
return readGraphicsObjectSizeHint("maximumWidth");
}
qreal AppletInterface::maximumHeight() const
{
return readGraphicsObjectSizeHint("maximumHeight");
}
void AppletInterface::setAssociatedApplication(const QString &string) void AppletInterface::setAssociatedApplication(const QString &string)
{ {
@ -601,245 +459,11 @@ QStringList AppletInterface::downloadedFiles() const
return dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::Readable); return dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::Readable);
} }
void AppletInterface::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) void AppletInterface::executeAction(const QString &name)
{ {
Q_UNUSED(oldGeometry) if (qmlObject()->rootObject()) {
QMetaObject::invokeMethod(qmlObject()->rootObject(), QString("action_" + name).toLatin1(), Qt::DirectConnection);
QQuickItem::geometryChanged(newGeometry, oldGeometry);
m_collapseTimer->start(100);
}
void AppletInterface::compactRepresentationCheck()
{
if (width() <= 0 || height() <= 0 || !m_qmlObject->rootObject() ||
qobject_cast<ContainmentInterface *>(this)) {
return;
} }
//Read the minimum width of the full representation, not our own, since we could be in collapsed mode
QSizeF minHint(-1, -1);
if (m_qmlObject->rootObject()->property("minimumWidth").canConvert<qreal>()) {
minHint.setWidth(m_qmlObject->rootObject()->property("minimumWidth").toReal());
}
if (m_qmlObject->rootObject()->property("minimumHeight").canConvert<qreal>()) {
minHint.setHeight(m_qmlObject->rootObject()->property("minimumHeight").toReal());
}
//Make it an icon
if (width() < minHint.width() || height() < minHint.height()) {
m_expanded = false;
//we are already an icon: nothing to do
if (m_compactUiObject) {
return;
}
m_compactUiObject = m_qmlObject->createObjectFromSource(QUrl::fromLocalFile(applet()->containment()->corona()->package().filePath("compactapplet")));
QObject *compactRepresentation = 0;
//build the icon representation
if (m_compactUiObject) {
QQmlComponent *compactComponent = m_qmlObject->rootObject()->property("compactRepresentation").value<QQmlComponent *>();
if (compactComponent) {
compactRepresentation = compactComponent->create(compactComponent->creationContext());
} else {
compactRepresentation = m_qmlObject->createObjectFromSource(QUrl::fromLocalFile(applet()->containment()->corona()->package().filePath("defaultcompactrepresentation")));
}
if (compactRepresentation && compactComponent) {
compactComponent->setParent(compactRepresentation);
} else {
delete compactComponent;
}
}
if (m_compactUiObject && compactRepresentation) {
//put compactRepresentation in the icon place
compactRepresentation->setProperty("parent", QVariant::fromValue(m_compactUiObject.data()));
m_compactUiObject.data()->setProperty("compactRepresentation", QVariant::fromValue(compactRepresentation));
//replace the full applet with the collapsed view
m_compactUiObject.data()->setProperty("visible", true);
m_compactUiObject.data()->setProperty("parent", QVariant::fromValue(this));
{
//set anchors
QQmlExpression expr(m_qmlObject->engine()->rootContext(), m_compactUiObject.data(), "parent");
QQmlProperty prop(m_compactUiObject.data(), "anchors.fill");
prop.write(expr.evaluate());
}
m_qmlObject->rootObject()->setProperty("parent", QVariant::fromValue(m_compactUiObject.data()));
{
//reset all the anchors
QQmlExpression expr(m_qmlObject->engine()->rootContext(), m_qmlObject->rootObject(), "anchors.fill=undefined;anchors.left=undefined;anchors.right=undefined;anchors.top=undefined;anchors.bottom=undefined;");
expr.evaluate();
}
KConfigGroup cg = applet()->config();
cg = KConfigGroup(&cg, "PopupApplet");
int width = cg.readEntry("DialogWidth", 0);
int height = cg.readEntry("DialogHeight", 0);
m_qmlObject->rootObject()->setProperty("width", width);
m_qmlObject->rootObject()->setProperty("height", height);
m_compactUiObject.data()->setProperty("applet", QVariant::fromValue(m_qmlObject->rootObject()));
//hook m_compactUiObject size hints to this size hint
//Here we have to use the old connect syntax, because we don't have access to the class type
if (m_qmlObject->rootObject()) {
disconnect(m_qmlObject->rootObject(), 0, this, 0);
}
//resize of the root object means popup resize when iconified
connect(m_qmlObject->rootObject(), SIGNAL(widthChanged()),
this, SLOT(updatePopupSize()));
connect(m_qmlObject->rootObject(), SIGNAL(heightChanged()),
this, SLOT(updatePopupSize()));
if (m_compactUiObject.data()->property("minimumWidth").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(minimumWidthChanged()),
this, SIGNAL(minimumWidthChanged()));
}
if (m_compactUiObject.data()->property("minimumHeight").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(minimumHeightChanged()),
this, SIGNAL(minimumHeightChanged()));
}
if (m_compactUiObject.data()->property("maximumWidth").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(maximumWidthChanged()),
this, SIGNAL(maximumWidthChanged()));
}
if (m_compactUiObject.data()->property("maximumHeight").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(maximumHeightChanged()),
this, SIGNAL(maximumHeightChanged()));
}
if (m_compactUiObject.data()->property("implicitWidth").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(implicitWidthChanged()),
this, SIGNAL(implicitWidthChanged()));
}
if (m_compactUiObject.data()->property("implicitHeight").isValid()) {
connect(m_compactUiObject.data(), SIGNAL(implicitHeightChanged()),
this, SIGNAL(implicitHeightChanged()));
}
emit fillWidthChanged();
emit fillHeightChanged();
emit minimumWidthChanged();
emit minimumHeightChanged();
emit implicitWidthChanged();
emit implicitHeightChanged();
emit maximumWidthChanged();
emit maximumHeightChanged();
//failed to create UI, don't do anything, return in expanded status
} else {
m_expanded = true;
}
emit expandedChanged();
//show the full UI
} else {
m_expanded = true;
emit expandedChanged();
//we are already expanded: nothing to do
if (m_compactUiObject) {
disconnect(m_compactUiObject.data(), 0, this, 0);
}
disconnect(m_qmlObject->rootObject(), SIGNAL(widthChanged()),
this, SLOT(updatePopupSize()));
disconnect(m_qmlObject->rootObject(), SIGNAL(heightChanged()),
this, SLOT(updatePopupSize()));
//Here we have to use the old connect syntax, because we don't have access to the class type
if (m_qmlObject->rootObject()->property("minimumWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(minimumWidthChanged()),
this, SIGNAL(minimumWidthChanged()));
}
if (m_qmlObject->rootObject()->property("minimumHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(minimumHeightChanged()),
this, SIGNAL(minimumHeightChanged()));
}
if (m_qmlObject->rootObject()->property("maximumWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(maximumWidthChanged()),
this, SIGNAL(maximumWidthChanged()));
}
if (m_qmlObject->rootObject()->property("maximumHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(maximumHeightChanged()),
this, SIGNAL(maximumHeightChanged()));
}
if (m_qmlObject->rootObject()->property("implicitWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(implicitWidthChanged()),
this, SLOT(updateImplicitWidth()));
}
if (m_qmlObject->rootObject()->property("implicitHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(implicitHeightChanged()),
this, SLOT(updateImplicitHeight()));
}
emit fillWidthChanged();
emit fillHeightChanged();
emit minimumWidthChanged();
emit minimumHeightChanged();
emit maximumWidthChanged();
emit maximumHeightChanged();
m_qmlObject->rootObject()->setProperty("parent", QVariant::fromValue(this));
if (m_compactUiObject) {
m_compactUiObject.data()->deleteLater();
}
//set anchors
QQmlExpression expr(m_qmlObject->engine()->rootContext(), m_qmlObject->rootObject(), "parent");
QQmlProperty prop(m_qmlObject->rootObject(), "anchors.fill");
prop.write(expr.evaluate());
}
}
void AppletInterface::updateImplicitWidth()
{
setImplicitWidth(readGraphicsObjectSizeHint("implicitWidth"));
}
void AppletInterface::updateImplicitHeight()
{
setImplicitHeight(readGraphicsObjectSizeHint("implicitHeight"));
}
void AppletInterface::updatePopupSize()
{
KConfigGroup cg = applet()->config();
cg = KConfigGroup(&cg, "PopupApplet");
cg.writeEntry("DialogWidth", m_qmlObject->rootObject()->property("width").toInt());
cg.writeEntry("DialogHeight", m_qmlObject->rootObject()->property("height").toInt());
}
void AppletInterface::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == QQuickItem::ItemSceneChange) {
//we have a window: create the
if (value.window && !m_qmlObject->rootObject()) {
init();
}
}
QQuickItem::itemChange(change, value);
}
KDeclarative::QmlObject *AppletInterface::qmlObject()
{
return m_qmlObject;
} }
#include "moc_appletinterface.cpp" #include "moc_appletinterface.cpp"

View File

@ -29,6 +29,7 @@
#include <Plasma/Applet> #include <Plasma/Applet>
#include <Plasma/Theme> #include <Plasma/Theme>
#include <appletquickitem.h>
#include "declarativeappletscript.h" #include "declarativeappletscript.h"
class QAction; class QAction;
@ -48,7 +49,7 @@ namespace Plasma
class ConfigLoader; class ConfigLoader;
} // namespace Plasma } // namespace Plasma
class AppletInterface : public QQuickItem class AppletInterface : public AppletQuickItem
{ {
Q_OBJECT Q_OBJECT
@ -107,12 +108,6 @@ class AppletInterface : public QQuickItem
*/ */
Q_PROPERTY(bool busy WRITE setBusy READ isBusy NOTIFY busyChanged) Q_PROPERTY(bool busy WRITE setBusy READ isBusy NOTIFY busyChanged)
/**
* True when the applet is showing its full representation. either as the main only view, or in a popup.
* Setting it will open or close the popup if the plasmoid is iconified, however it won't have effect if the applet is open
*/
Q_PROPERTY(bool expanded WRITE setExpanded READ isExpanded NOTIFY expandedChanged)
/** /**
* How the applet wants its background to be drawn. The containment may chose to ignore this hint. * How the applet wants its background to be drawn. The containment may chose to ignore this hint.
*/ */
@ -145,22 +140,6 @@ class AppletInterface : public QQuickItem
// would be preferrable if found. // would be preferrable if found.
Q_PROPERTY(int screen READ screen NOTIFY screenChanged) Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
//Size hints. Note that the containments may chose to not respect them.
Q_PROPERTY(qreal minimumWidth READ minimumWidth NOTIFY minimumWidthChanged)
Q_PROPERTY(qreal minimumHeight READ minimumHeight NOTIFY minimumHeightChanged)
Q_PROPERTY(qreal maximumWidth READ maximumWidth NOTIFY maximumWidthChanged)
Q_PROPERTY(qreal maximumHeight READ maximumHeight NOTIFY maximumHeightChanged)
/**
* If the plasmoid is in a linear layout, such as a panel, it indicates to take as much horizontal space as possible
*/
Q_PROPERTY(bool fillWidth READ fillWidth NOTIFY fillWidthChanged)
/**
* If the plasmoid is in a linear layout, such as a panel, it indicates to take as much vertical space as possible
*/
Q_PROPERTY(bool fillHeight READ fillHeight NOTIFY fillHeightChanged)
/** /**
* Whether the dialog should be hidden when the dialog loses focus. * Whether the dialog should be hidden when the dialog loses focus.
* *
@ -174,11 +153,12 @@ public:
~AppletInterface(); ~AppletInterface();
//API not intended for the QML part //API not intended for the QML part
KDeclarative::QmlObject *qmlObject();
DeclarativeAppletScript *appletScript() const;
QList<QAction*> contextualActions() const; QList<QAction*> contextualActions() const;
inline Plasma::Applet *applet() const { return m_appletScriptEngine->applet(); } void executeAction(const QString &name);
//QML API------------------------------------------------------------------- //QML API-------------------------------------------------------------------
@ -238,6 +218,10 @@ public:
*/ */
Q_INVOKABLE void writeConfig(const QString &entry, const QVariant &value); Q_INVOKABLE void writeConfig(const QString &entry, const QVariant &value);
static AppletInterface *qmlAttachedProperties(QObject *object)
{
return qobject_cast<AppletInterface *>(AppletQuickItem::qmlAttachedProperties(object));
}
//PROPERTY ACCESSORS------------------------------------------------------------------- //PROPERTY ACCESSORS-------------------------------------------------------------------
QString icon() const; QString icon() const;
@ -259,9 +243,6 @@ public:
bool isBusy() const; bool isBusy() const;
void setBusy(bool busy); void setBusy(bool busy);
bool isExpanded() const;
void setExpanded(bool expanded);
Plasma::Types::BackgroundHints backgroundHints() const; Plasma::Types::BackgroundHints backgroundHints() const;
void setBackgroundHints(Plasma::Types::BackgroundHints hint); void setBackgroundHints(Plasma::Types::BackgroundHints hint);
@ -283,13 +264,6 @@ public:
bool hideOnWindowDeactivate() const; bool hideOnWindowDeactivate() const;
void setHideOnWindowDeactivate(bool hide); void setHideOnWindowDeactivate(bool hide);
bool fillWidth() const;
bool fillHeight() const;
qreal minimumWidth() const;
qreal minimumHeight() const;
qreal maximumWidth() const;
qreal maximumHeight() const;
Q_SIGNALS: Q_SIGNALS:
/** /**
* somebody else, usually the containment sent some data to the applet * somebody else, usually the containment sent some data to the applet
@ -311,36 +285,15 @@ Q_SIGNALS:
void statusChanged(); void statusChanged();
void backgroundHintsChanged(); void backgroundHintsChanged();
void busyChanged(); void busyChanged();
void expandedChanged();
void screenChanged(); void screenChanged();
void hideOnWindowDeactivateChanged(); void hideOnWindowDeactivateChanged();
void minimumWidthChanged();
void minimumHeightChanged();
void maximumWidthChanged();
void maximumHeightChanged();
void fillWidthChanged();
void fillHeightChanged();
void userConfiguringChanged(); void userConfiguringChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
void itemChange(ItemChange change, const ItemChangeData &value);
DeclarativeAppletScript *m_appletScriptEngine;
protected Q_SLOTS: protected Q_SLOTS:
virtual void init(); virtual void init();
private Q_SLOTS:
void compactRepresentationCheck();
void updatePopupSize();
void updateImplicitWidth();
void updateImplicitHeight();
private: private:
//Helper for minimumWidth etc.
qreal readGraphicsObjectSizeHint(const char *hint) const;
QStringList m_actions; QStringList m_actions;
QSignalMapper *m_actionSignals; QSignalMapper *m_actionSignals;
@ -349,18 +302,17 @@ private:
KDeclarative::ConfigPropertyMap *m_configuration; KDeclarative::ConfigPropertyMap *m_configuration;
DeclarativeAppletScript *m_appletScriptEngine;
//UI-specific members ------------------ //UI-specific members ------------------
KDeclarative::QmlObject *m_qmlObject;
QWeakPointer<QObject> m_compactUiObject;
QTimer *m_collapseTimer;
Plasma::Types::BackgroundHints m_backgroundHints; Plasma::Types::BackgroundHints m_backgroundHints;
bool m_busy : 1; bool m_busy : 1;
bool m_expanded : 1;
bool m_hideOnDeactivate : 1; bool m_hideOnDeactivate : 1;
friend class ContainmentInterface; friend class ContainmentInterface;
}; };
QML_DECLARE_TYPEINFO(AppletInterface, QML_HAS_ATTACHED_PROPERTIES)
#endif #endif

View File

@ -59,8 +59,6 @@ ContainmentInterface::ContainmentInterface(DeclarativeAppletScript *parent)
{ {
setAcceptedMouseButtons(Qt::AllButtons); setAcceptedMouseButtons(Qt::AllButtons);
qmlRegisterType<ContainmentInterface>();
connect(containment(), &Plasma::Containment::appletRemoved, connect(containment(), &Plasma::Containment::appletRemoved,
this, &ContainmentInterface::appletRemovedForward); this, &ContainmentInterface::appletRemovedForward);
connect(containment(), &Plasma::Containment::appletAdded, connect(containment(), &Plasma::Containment::appletAdded,
@ -117,15 +115,15 @@ void ContainmentInterface::init()
pkg.setPath("org.kde.desktoptoolbox"); pkg.setPath("org.kde.desktoptoolbox");
} }
PackageUrlInterceptor *interceptor = dynamic_cast<PackageUrlInterceptor *>(m_qmlObject->engine()->urlInterceptor()); PackageUrlInterceptor *interceptor = dynamic_cast<PackageUrlInterceptor *>(qmlObject()->engine()->urlInterceptor());
if (interceptor) { if (interceptor) {
interceptor->addAllowedPath(pkg.path()); interceptor->addAllowedPath(pkg.path());
} }
if (pkg.isValid()) { if (pkg.isValid()) {
QObject *toolBoxObject = m_qmlObject->createObjectFromSource(QUrl::fromLocalFile(pkg.filePath("mainscript"))); QObject *toolBoxObject = qmlObject()->createObjectFromSource(QUrl::fromLocalFile(pkg.filePath("mainscript")));
QObject *containmentGraphicObject = m_qmlObject->rootObject(); QObject *containmentGraphicObject = qmlObject()->rootObject();
if (containmentGraphicObject && toolBoxObject) { if (containmentGraphicObject && toolBoxObject) {
toolBoxObject->setProperty("parent", QVariant::fromValue(containmentGraphicObject)); toolBoxObject->setProperty("parent", QVariant::fromValue(containmentGraphicObject));
@ -142,50 +140,14 @@ void ContainmentInterface::init()
//set parent, both as object hyerarchy and visually //set parent, both as object hyerarchy and visually
//do this only for containments, applets will do it in compactrepresentationcheck //do this only for containments, applets will do it in compactrepresentationcheck
if (m_qmlObject->rootObject()) { if (qmlObject()->rootObject()) {
m_qmlObject->rootObject()->setProperty("parent", QVariant::fromValue(this)); qmlObject()->rootObject()->setProperty("parent", QVariant::fromValue(this));
//set anchors //set anchors
QQmlExpression expr(m_qmlObject->engine()->rootContext(), m_qmlObject->rootObject(), "parent"); QQmlExpression expr(qmlObject()->engine()->rootContext(), qmlObject()->rootObject(), "parent");
QQmlProperty prop(m_qmlObject->rootObject(), "anchors.fill"); QQmlProperty prop(qmlObject()->rootObject(), "anchors.fill");
prop.write(expr.evaluate()); prop.write(expr.evaluate());
} }
if (m_qmlObject->rootObject()->property("minimumWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(minimumWidthChanged()),
this, SIGNAL(minimumWidthChanged()));
}
if (m_qmlObject->rootObject()->property("minimumHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(minimumHeightChanged()),
this, SIGNAL(minimumHeightChanged()));
}
if (m_qmlObject->rootObject()->property("maximumWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(maximumWidthChanged()),
this, SIGNAL(maximumWidthChanged()));
}
if (m_qmlObject->rootObject()->property("maximumHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(maximumHeightChanged()),
this, SIGNAL(maximumHeightChanged()));
}
if (m_qmlObject->rootObject()->property("implicitWidth").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(implicitWidthChanged()),
this, SIGNAL(implicitWidthChanged()));
}
if (m_qmlObject->rootObject()->property("implicitHeight").isValid()) {
connect(m_qmlObject->rootObject(), SIGNAL(implicitHeightChanged()),
this, SIGNAL(implicitHeightChanged()));
}
emit fillWidthChanged();
emit fillHeightChanged();
emit minimumWidthChanged();
emit minimumHeightChanged();
emit implicitWidthChanged();
emit implicitHeightChanged();
emit maximumWidthChanged();
emit maximumHeightChanged();
} }
QList <QObject *> ContainmentInterface::applets() QList <QObject *> ContainmentInterface::applets()
@ -195,12 +157,12 @@ QList <QObject *> ContainmentInterface::applets()
Plasma::Types::ContainmentType ContainmentInterface::containmentType() const Plasma::Types::ContainmentType ContainmentInterface::containmentType() const
{ {
return m_appletScriptEngine->containmentType(); return appletScript()->containmentType();
} }
void ContainmentInterface::setContainmentType(Plasma::Types::ContainmentType type) void ContainmentInterface::setContainmentType(Plasma::Types::ContainmentType type)
{ {
m_appletScriptEngine->setContainmentType(type); appletScript()->setContainmentType(type);
} }
void ContainmentInterface::lockWidgets(bool locked) void ContainmentInterface::lockWidgets(bool locked)
@ -242,7 +204,7 @@ Plasma::Applet *ContainmentInterface::addApplet(const QString &plugin, const QVa
if (applet) { if (applet) {
QObject *appletGraphicObject = applet->property("graphicObject").value<QObject *>(); QObject *appletGraphicObject = applet->property("_plasma_graphicObject").value<QObject *>();
blockSignals(false); blockSignals(false);
@ -259,7 +221,7 @@ void ContainmentInterface::setAppletArgs(Plasma::Applet *applet, const QString &
return; return;
} }
AppletInterface *appletInterface = applet->property("graphicObject").value<AppletInterface *>(); AppletInterface *appletInterface = applet->property("_plasma_graphicObject").value<AppletInterface *>();
if (appletInterface) { if (appletInterface) {
emit appletInterface->externalData(mimetype, data); emit appletInterface->externalData(mimetype, data);
} }
@ -526,8 +488,8 @@ void ContainmentInterface::appletAddedForward(Plasma::Applet *applet)
return; return;
} }
QObject *appletGraphicObject = applet->property("graphicObject").value<QObject *>(); QObject *appletGraphicObject = applet->property("_plasma_graphicObject").value<QObject *>();
QObject *contGraphicObject = containment()->property("graphicObject").value<QObject *>(); QObject *contGraphicObject = containment()->property("_plasma_graphicObject").value<QObject *>();
qDebug() << "Applet added on containment:" << containment()->title() << contGraphicObject qDebug() << "Applet added on containment:" << containment()->title() << contGraphicObject
<< "Applet: " << applet << applet->title() << appletGraphicObject; << "Applet: " << applet << applet->title() << appletGraphicObject;
@ -555,7 +517,7 @@ void ContainmentInterface::appletAddedForward(Plasma::Applet *applet)
void ContainmentInterface::appletRemovedForward(Plasma::Applet *applet) void ContainmentInterface::appletRemovedForward(Plasma::Applet *applet)
{ {
QObject *appletGraphicObject = applet->property("graphicObject").value<QObject *>(); QObject *appletGraphicObject = applet->property("_plasma_graphicObject").value<QObject *>();
m_appletInterfaces.removeAll(appletGraphicObject); m_appletInterfaces.removeAll(appletGraphicObject);
emit appletRemoved(appletGraphicObject); emit appletRemoved(appletGraphicObject);
emit appletsChanged(); emit appletsChanged();

View File

@ -70,7 +70,7 @@ class ContainmentInterface : public AppletInterface
public: public:
ContainmentInterface(DeclarativeAppletScript *parent); ContainmentInterface(DeclarativeAppletScript *parent);
//Not for QML //Not for QML
inline Plasma::Containment *containment() const { return static_cast<Plasma::Containment *>(m_appletScriptEngine->applet()->containment()); } Plasma::Containment *containment() const { return static_cast<Plasma::Containment *>(appletScript()->applet()->containment()); }
inline WallpaperInterface *wallpaperInterface() const { return m_wallpaperInterface;} inline WallpaperInterface *wallpaperInterface() const { return m_wallpaperInterface;}
@ -105,6 +105,11 @@ public:
*/ */
Q_INVOKABLE void processMimeData(QMimeData *data, int x, int y); Q_INVOKABLE void processMimeData(QMimeData *data, int x, int y);
static ContainmentInterface *qmlAttachedProperties(QObject *object)
{
return qobject_cast<ContainmentInterface *>(AppletQuickItem::qmlAttachedProperties(object));
}
protected: protected:
void init(); void init();
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event);
@ -159,4 +164,6 @@ private:
KActivities::Info *m_activityInfo; KActivities::Info *m_activityInfo;
}; };
QML_DECLARE_TYPEINFO(ContainmentInterface, QML_HAS_ATTACHED_PROPERTIES)
#endif #endif

View File

@ -42,6 +42,7 @@
#include "plasmoid/appletinterface.h" #include "plasmoid/appletinterface.h"
#include "plasmoid/containmentinterface.h" #include "plasmoid/containmentinterface.h"
#include "plasmoid/wallpaperinterface.h"
#include <kdeclarative/qmlobject.h> #include <kdeclarative/qmlobject.h>
#include <kdeclarative/configpropertymap.h> #include <kdeclarative/configpropertymap.h>
@ -54,7 +55,18 @@ DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariant
: Plasma::AppletScript(parent), : Plasma::AppletScript(parent),
m_interface(0) m_interface(0)
{ {
qmlRegisterType<AppletInterface>(); //qmlRegisterType<AppletInterface>();
//FIXME: use this if/when will be possible to have properties of attached items subclasses on the left hand of expressions
/*qmlRegisterUncreatableType<AppletLoader>("org.kde.plasma.plasmoid", 2, 0, "Plasmoid",
QLatin1String("Do not create objects of type Plasmoid"));*/
qmlRegisterUncreatableType<AppletInterface>("org.kde.plasma.plasmoid", 2, 0, "Plasmoid",
QLatin1String("Do not create objects of type Plasmoid"));
qmlRegisterUncreatableType<ContainmentInterface>("org.kde.plasma.plasmoid", 2, 0, "Containment",
QLatin1String("Do not create objects of type Containment"));
qmlRegisterUncreatableType<WallpaperInterface>("org.kde.plasma.plasmoid", 2, 0, "Wallpaper",
QLatin1String("Do not create objects of type Wallpaper"));
qmlRegisterType<KDeclarative::ConfigPropertyMap>(); qmlRegisterType<KDeclarative::ConfigPropertyMap>();
Q_UNUSED(args); Q_UNUSED(args);
} }
@ -81,8 +93,6 @@ bool DeclarativeAppletScript::init()
} }
m_interface->setParent(this); m_interface->setParent(this);
// set the graphicObject dynamic property on applet
a->setProperty("graphicObject", QVariant::fromValue(m_interface));
return true; return true;
} }
@ -109,9 +119,7 @@ void DeclarativeAppletScript::constraintsEvent(Plasma::Types::Constraints constr
void DeclarativeAppletScript::executeAction(const QString &name) void DeclarativeAppletScript::executeAction(const QString &name)
{ {
if (m_interface->qmlObject()->rootObject()) { m_interface->executeAction(name);
QMetaObject::invokeMethod(m_interface->qmlObject()->rootObject(), QString("action_" + name).toLatin1(), Qt::DirectConnection);
}
} }
QList<QAction*> DeclarativeAppletScript::contextualActions() QList<QAction*> DeclarativeAppletScript::contextualActions()

View File

@ -56,6 +56,7 @@ Q_SIGNALS:
private: private:
AppletInterface *m_interface; AppletInterface *m_interface;
friend class AppletLoader;
friend class AppletInterface; friend class AppletInterface;
friend class ContainmentInterface; friend class ContainmentInterface;
}; };

View File

@ -36,6 +36,8 @@
#include <Plasma/ConfigLoader> #include <Plasma/ConfigLoader>
#include <Plasma/PluginLoader> #include <Plasma/PluginLoader>
QHash<QObject *, WallpaperInterface *> WallpaperInterface::s_rootObjects = QHash<QObject *, WallpaperInterface *>();
WallpaperInterface::WallpaperInterface(ContainmentInterface *parent) WallpaperInterface::WallpaperInterface(ContainmentInterface *parent)
: QQuickItem(parent), : QQuickItem(parent),
m_containmentInterface(parent), m_containmentInterface(parent),
@ -55,7 +57,9 @@ WallpaperInterface::WallpaperInterface(ContainmentInterface *parent)
} }
WallpaperInterface::~WallpaperInterface() WallpaperInterface::~WallpaperInterface()
{} {
s_rootObjects.remove(m_qmlObject->engine());
}
KPluginInfo::List WallpaperInterface::listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor) KPluginInfo::List WallpaperInterface::listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor)
{ {
@ -109,6 +113,7 @@ void WallpaperInterface::syncWallpaperPackage()
if (!m_qmlObject) { if (!m_qmlObject) {
m_qmlObject = new KDeclarative::QmlObject(this); m_qmlObject = new KDeclarative::QmlObject(this);
s_rootObjects[m_qmlObject->engine()] = this;
m_qmlObject->setInitializationDelayed(true); m_qmlObject->setInitializationDelayed(true);
} }
@ -142,6 +147,7 @@ void WallpaperInterface::syncWallpaperPackage()
} else if (m_qmlObject->mainComponent()) { } else if (m_qmlObject->mainComponent()) {
qWarning() << "Error loading the wallpaper" << m_qmlObject->mainComponent()->errors(); qWarning() << "Error loading the wallpaper" << m_qmlObject->mainComponent()->errors();
s_rootObjects.remove(m_qmlObject->engine());
m_qmlObject->deleteLater(); m_qmlObject->deleteLater();
m_qmlObject = 0; m_qmlObject = 0;

View File

@ -21,6 +21,7 @@
#define WALLPAPERINTERFACE_H #define WALLPAPERINTERFACE_H
#include <QQuickItem> #include <QQuickItem>
#include <QQmlEngine>
#include <Plasma/Package> #include <Plasma/Package>
@ -78,6 +79,17 @@ public:
Q_INVOKABLE QAction *action(QString name) const; Q_INVOKABLE QAction *action(QString name) const;
static WallpaperInterface *qmlAttachedProperties(QObject *object)
{
//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() && s_rootObjects.contains(QtQml::qmlEngine(object))) {
return s_rootObjects.value(QtQml::qmlEngine(object));
} else {
return 0;
}
}
Q_SIGNALS: Q_SIGNALS:
void packageChanged(); void packageChanged();
void configurationChanged(); void configurationChanged();
@ -95,6 +107,10 @@ private:
Plasma::ConfigLoader *m_configLoader; Plasma::ConfigLoader *m_configLoader;
KActionCollection *m_actions; KActionCollection *m_actions;
QSignalMapper *m_actionSignals; QSignalMapper *m_actionSignals;
static QHash<QObject *, WallpaperInterface *> s_rootObjects;
}; };
QML_DECLARE_TYPEINFO(WallpaperInterface, QML_HAS_ATTACHED_PROPERTIES)
#endif #endif

View File

@ -182,7 +182,7 @@ void Panel::setOffset(int pixels)
return; return;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("_plasma_graphicObject").value<QObject *>());
if (!graphicObject) { if (!graphicObject) {
return; return;
@ -222,7 +222,7 @@ int Panel::length() const
if (!c) { if (!c) {
return 0; return 0;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("_plasma_graphicObject").value<QObject *>());
if (!graphicObject) { if (!graphicObject) {
return 0; return 0;
@ -242,7 +242,7 @@ void Panel::setLength(int pixels)
return; return;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("_plasma_graphicObject").value<QObject *>());
if (!graphicObject) { if (!graphicObject) {
return; return;
@ -279,7 +279,7 @@ int Panel::height() const
return 0; return 0;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("_plasma_graphicObject").value<QObject *>());
if (!graphicObject) { if (!graphicObject) {
return 0; return 0;
@ -296,7 +296,7 @@ void Panel::setHeight(int height)
return; return;
} }
QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("graphicObject").value<QObject *>()); QQuickItem *graphicObject = qobject_cast<QQuickItem *>(c->property("_plasma_graphicObject").value<QObject *>());
if (!graphicObject) { if (!graphicObject) {
return; return;

View File

@ -138,5 +138,19 @@ for FS in `find $PWD -name '*.h' -o -name '*.cpp'`; do
perl -p -i -e 's/Plasma\:\:AcceptingInputStatus/Plasma::Types::AcceptingInputStatus/g' $FS perl -p -i -e 's/Plasma\:\:AcceptingInputStatus/Plasma::Types::AcceptingInputStatus/g' $FS
done done
# make compactrepresentation come from Plasmoid.*
# size hints come from Layout
for FS in `find $PWD -type f -name '*.qml'`; do
perl -p -i -e 's/property Component compactRepresentation/Plasmoid.compactRepresentation/g' $FS
perl -p -i -e 's/property int minimumWidth/Layout.minimumWidth/g' $FS
perl -p -i -e 's/property int minimumHeight/Layout.minimumHeight/g' $FS
perl -p -i -e 's/property int maximumWidth/Layout.maximumWidth/g' $FS
perl -p -i -e 's/property int maximumHeight/Layout.maximumHeight/g' $FS
perl -p -i -e 's/property bool fillWidth/Layout.fillWidth/g' $FS
perl -p -i -e 's/property bool fillHeight/Layout.fillHeight/g' $FS
done
for FS in `find $PWD -type f -name '*main.qml'`; do
perl -p -i -e 's/QtQuick 2.0/QtQuick 2.0\nimport org.kde.plasma.plasmoid 2.0/g' $FS
done