24 #include "private/applet_p.h"
26 #include "config-plasma.h"
33 #include <QApplication>
36 #include <QGraphicsGridLayout>
37 #include <QGraphicsSceneMouseEvent>
38 #include <QGraphicsView>
42 #include <QGraphicsLinearLayout>
46 #include <QStyleOptionGraphicsItem>
47 #include <QTextDocument>
49 #include <QVBoxLayout>
53 #include <kactioncollection.h>
54 #include <kauthorized.h>
55 #include <kcolorscheme.h>
57 #include <kdesktopfile.h>
59 #include <kiconloader.h>
60 #include <kkeysequencewidget.h>
61 #include <kplugininfo.h>
62 #include <kstandarddirs.h>
64 #include <kservicetypetrader.h>
65 #include <kshortcut.h>
66 #include <kwindowsystem.h>
67 #include <kpushbutton.h>
69 #ifndef PLASMA_NO_KUTILS
70 #include <kcmoduleinfo.h>
71 #include <kcmoduleproxy.h>
76 #ifndef PLASMA_NO_SOLID
77 #include <solid/powermanagement.h>
96 #include "private/applethandle_p.h"
97 #include "private/extenderitem_p.h"
98 #include "private/framesvg_p.h"
111 #include "private/associatedapplicationmanager_p.h"
112 #include "private/authorizationmanager_p.h"
113 #include "private/containment_p.h"
114 #include "private/extenderapplet_p.h"
115 #include "private/package_p.h"
116 #include "private/packages_p.h"
117 #include "private/plasmoidservice_p.h"
118 #include "private/popupapplet_p.h"
119 #include "private/remotedataengine_p.h"
120 #include "private/service_p.h"
121 #include "ui_publish.h"
129 d(new AppletPrivate(KService::Ptr(), &info, appletId, this))
138 d(new AppletPrivate(KService::serviceByStorageId(serviceID), 0, appletId, this))
146 const QString &serviceID,
148 const QVariantList &args)
150 d(new AppletPrivate(KService::serviceByStorageId(serviceID), 0, appletId, this))
155 QVariantList &mutableArgs =
const_cast<QVariantList &
>(args);
156 if (!mutableArgs.isEmpty()) {
157 mutableArgs.removeFirst();
159 if (!mutableArgs.isEmpty()) {
160 mutableArgs.removeFirst();
164 d->args = mutableArgs;
172 KService::serviceByStorageId(args.count() > 0 ? args[0].
toString() : QString()), 0,
173 args.count() > 1 ? args[1].toInt() : 0, this))
178 QVariantList &mutableArgs =
const_cast<QVariantList &
>(args);
179 if (!mutableArgs.isEmpty()) {
180 mutableArgs.removeFirst();
182 if (!mutableArgs.isEmpty()) {
183 mutableArgs.removeFirst();
187 d->args = mutableArgs;
189 setParent(parentObject);
199 Applet::Applet(
const QString &packagePath, uint appletId,
const QVariantList &args)
201 d(new AppletPrivate(KService::Ptr(new KService(packagePath +
"/metadata.desktop")), 0, appletId, this))
204 d->
init(packagePath);
212 if (!d->transient && d->extender) {
218 d->extender.data()->saveState();
220 foreach (
ExtenderItem *item, d->extender.data()->attachedItems()) {
230 delete KConfigDialog::exists(d->configDialogId());
245 setFlag(ItemIsMovable,
true);
247 d->setupScriptSupport();
249 if (!d->script->init() && !d->failed) {
266 KConfigGroup group = g;
267 if (!group.isValid()) {
268 group = *d->mainConfigGroup();
274 group.writeEntry(
"immutability", (
int)d->immutability);
277 group.writeEntry(
"geometry",
geometry());
278 group.writeEntry(
"zvalue", zValue());
288 if (transform() == QTransform()) {
289 group.deleteEntry(
"transform");
292 QTransform t = transform();
293 m << t.m11() << t.m12() << t.m13() << t.m21() << t.m22() << t.m23() << t.m31() << t.m32() << t.m33();
294 group.writeEntry(
"transform", m);
298 KConfigGroup appletConfigGroup(&group,
"Configuration");
301 if (d->configLoader) {
304 disconnect(d->configLoader, SIGNAL(
configChanged()),
this, SLOT(propagateConfigChanged()));
305 d->configLoader->writeConfig();
306 connect(d->configLoader, SIGNAL(
configChanged()),
this, SLOT(propagateConfigChanged()));
312 QList<qreal> m = group.readEntry(
"transform", QList<qreal>());
313 if (m.count() == 9) {
314 QTransform t(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
318 qreal z = group.readEntry(
"zvalue", 0);
320 if (z >= AppletPrivate::s_maxZValue) {
321 AppletPrivate::s_maxZValue = z;
330 QRectF geom = group.readEntry(
"geometry", QRectF());
331 if (geom.isValid()) {
335 KConfigGroup shortcutConfig(&group,
"Shortcuts");
336 QString shortcutText = shortcutConfig.readEntryUntranslated(
"global", QString());
337 if (!shortcutText.isEmpty()) {
360 void AppletPrivate::setFocus()
363 q->setFocus(Qt::ShortcutFocusReason);
368 if (d->failed == failed) {
369 if (failed && !reason.isEmpty()) {
370 foreach (QGraphicsItem *item, QGraphicsItem::children()) {
373 l->
setText(d->visibleFailureText(reason));
381 prepareGeometryChange();
383 foreach (QGraphicsItem *item, childItems()) {
384 if (!dynamic_cast<AppletHandle *>(item)) {
389 d->messageOverlay = 0;
390 if (d->messageDialog) {
391 d->messageDialog.data()->deleteLater();
392 d->messageDialog.clear();
400 QGraphicsLinearLayout *failureLayout =
new QGraphicsLinearLayout(
this);
401 failureLayout->setContentsMargins(0, 0, 0, 0);
404 failureIcon->
setIcon(KIcon(
"dialog-error"));
405 failureLayout->addItem(failureIcon);
408 failureWidget->
setText(d->visibleFailureText(reason));
410 label->setWordWrap(
true);
411 failureLayout->addItem(failureWidget);
415 KIcon(
"dialog-error"));
418 setLayout(failureLayout);
420 d->background->resizeFrame(
geometry().size());
429 emit d->script->saveState(group);
432 if (group.config()->name() !=
config().config()->name()) {
435 KConfigGroup c =
config();
443 return KConfigGroup(KGlobal::config(),
"PlasmaTransientsConfig");
446 KConfigGroup cg =
config();
447 return KConfigGroup(&cg, group);
453 return KConfigGroup(KGlobal::config(),
"PlasmaTransientsConfig");
456 if (d->isContainment) {
457 return *(d->mainConfigGroup());
460 return KConfigGroup(d->mainConfigGroup(),
"Configuration");
465 KConfigGroup globalAppletConfig;
466 QString group =
isContainment() ?
"ContainmentGlobals" :
"AppletGlobals";
470 KSharedConfig::Ptr coronaConfig = corona->
config();
471 globalAppletConfig = KConfigGroup(coronaConfig, group);
473 globalAppletConfig = KConfigGroup(KGlobal::config(), group);
476 return KConfigGroup(&globalAppletConfig, d->globalName());
488 d->cleanUpAndDelete();
491 connect(zoomAnim, SIGNAL(finished()),
this, SLOT(cleanUpAndDelete()));
502 void AppletPrivate::selectItemToDestroy()
507 if (view && view->transform().isScaling() &&
508 q->scene()->focusItem() != q) {
509 QGraphicsItem *focus = q->scene()->focusItem();
525 void AppletPrivate::updateRect(
const QRectF &rect)
530 void AppletPrivate::cleanUpAndDelete()
539 if (parent && parent->layout()) {
541 for (
int i = 0; i < l->count(); ++i) {
542 if (q == l->itemAt(i)) {
550 configLoader->setDefaults();
553 resetConfigurationObject();
559 emit q->QObject::destroyed(q);
562 q->scene()->removeItem(q);
568 void AppletPrivate::createMessageOverlay(
bool usePopup)
570 if (messageOverlay) {
571 qDeleteAll(messageOverlay->children());
572 messageOverlay->setLayout(0);
577 if (!messageOverlay) {
578 if (usePopup && popup) {
579 if (popup->widget()) {
581 messageOverlayProxy->setWidget(popup->widget());
582 messageOverlay =
new AppletOverlayWidget(messageOverlayProxy);
583 }
else if (popup->graphicsWidget() &&
584 popup->graphicsWidget() !=
extender.data()) {
585 messageOverlay =
new AppletOverlayWidget(popup->graphicsWidget());
589 if (!messageOverlay) {
590 messageOverlay =
new AppletOverlayWidget(q);
594 positionMessageOverlay();
597 void AppletPrivate::positionMessageOverlay()
599 if (!messageOverlay) {
604 const bool usePopup = popup && (messageOverlay->parentItem() != q);
605 QGraphicsItem *topItem = q;
607 if (usePopup && popup->widget()) {
609 topItem = popup->d->proxy.data();
610 messageOverlay->setGeometry(popup->widget()->contentsRect());
611 }
else if (usePopup && popup->graphicsWidget() && popup->graphicsWidget() !=
extender.data()) {
613 topItem = popup->graphicsWidget();
615 messageOverlay->setGeometry(w ? w->contentsRect() : topItem->boundingRect());
618 messageOverlay->setGeometry(q->contentsRect());
623 foreach (QGraphicsItem *child, topItem->children()) {
624 if (child->zValue() > zValue) {
625 zValue = child->zValue() + 1;
628 messageOverlay->setZValue(zValue);
631 void AppletPrivate::destroyMessageOverlay()
636 messageDialog.clear();
639 if (!messageOverlay) {
643 messageOverlay->destroy();
646 if (messageOverlayProxy) {
647 messageOverlayProxy->setWidget(0);
648 delete messageOverlayProxy;
649 messageOverlayProxy = 0;
654 PushButton *button = qobject_cast<PushButton *>(q->sender());
656 if (button == messageOkButton.data()) {
659 if (button == messageYesButton.data()) {
662 if (button == messageNoButton.data()) {
665 if (button == messageCancelButton.data()) {
669 emit q->messageButtonPressed(buttonCode);
670 }
else if (q->sender() == messageOverlay) {
677 return d->configLoader;
682 if (!d->remoteLocation.isEmpty()) {
683 return d->remoteDataEngine(KUrl(d->remoteLocation), name);
684 }
else if (!
package() ||
package()->metadata().remoteLocation().isEmpty()) {
685 return d->dataEngine(name);
687 return d->remoteDataEngine(KUrl(
package()->metadata().remoteLocation()), name);
711 if (view->sceneRect().intersects(sceneBoundingRect()) ||
712 view->sceneRect().contains(scenePos())) {
714 if (view->isActiveWindow()) {
722 return found ? found : possibleFind;
728 return mapFromScene(view->mapToScene(rect)).boundingRect().adjusted(0, 0, 1, 1);
734 return view->mapFromScene(mapToScene(rect)).boundingRect().adjusted(0, 0, -1, -1);
752 d->scheduleConstraintsUpdate(constraints);
761 Q_UNUSED(constraints)
765 d->script->constraintsEvent(constraints);
774 kWarning() <<
"Missing implementation of initExtenderItem in the applet "
775 << item->
config().readEntry(
"SourceAppletPluginName",
"")
776 <<
"!\n Any applet that uses extenders should implement initExtenderItem to "
777 <<
"instantiate a widget. Destroying the item...";
785 new Extender(const_cast<Applet*>(
this));
788 return d->extender.data();
794 if (!d->busyWidget && !d->busyWidgetTimer.isActive()) {
795 d->busyWidgetTimer.start(500,
this);
798 d->busyWidgetTimer.stop();
801 d->destroyMessageOverlay();
808 return d->busyWidgetTimer.isActive() || (d->busyWidget && d->busyWidget->isVisible());
813 if (d->isContainment) {
815 if (c && c->d->isPanelContainment()) {
816 return i18n(
"Panel");
817 }
else if (!d->appletDescription.isValid()) {
818 return i18n(
"Unknown");
820 return d->appletDescription.name();
822 }
else if (!d->appletDescription.isValid()) {
823 return i18n(
"Unknown Widget");
826 return d->appletDescription.name();
831 return QApplication::font();
836 if (!d->appletDescription.isValid()) {
840 return d->appletDescription.icon();
845 if (!d->appletDescription.isValid()) {
846 return d->mainConfigGroup()->readEntry(
"plugin", QString());
849 return d->appletDescription.pluginName();
854 #ifndef PLASMA_NO_SOLID
855 return Solid::PowerManagement::appShouldConserveResources();
863 if (!d->appletDescription.isValid()) {
864 return i18nc(
"misc category",
"Miscellaneous");
867 return d->appletDescription.category();
872 return applet.property(
"X-KDE-PluginInfo-Category").toString();
877 if (appletName.isEmpty()) {
881 const QString constraint = QString(
"[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
882 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
884 if (offers.isEmpty()) {
888 return offers.first()->property(
"X-KDE-PluginInfo-Category").toString();
896 if (d->transient || (d->mainConfig && d->mainConfig->isImmutable())) {
905 upperImmutability = cont->immutability();
906 }
else if (
Corona *corona = qobject_cast<Corona*>(scene())) {
907 upperImmutability = corona->immutability();
910 if (upperImmutability !=
Mutable) {
913 return upperImmutability;
915 return d->immutability;
929 d->immutability = immutable;
935 return d->backgroundHints;
940 if (d->backgroundHints == hints) {
944 d->backgroundHints = hints;
945 d->preferredBackgroundHints = hints;
949 if (!d->background) {
951 QObject::connect(d->background, SIGNAL(repaintNeeded()),
this, SLOT(themeChanged()));
954 if ((hints & TranslucentBackground) &&
956 d->background->setImagePath(
"widgets/translucentbackground");
958 d->background->setImagePath(
"widgets/background");
962 qreal left, top, right, bottom;
963 d->background->getMargins(left, top, right, bottom);
964 setContentsMargins(left, right, top, bottom);
965 QSizeF fitSize(left + right, top + bottom);
966 d->background->resizeFrame(boundingRect().size());
969 if (d->background->hasElement(
"overlay")) {
970 QSize overlaySize = d->background->elementSize(
"overlay");
974 d->background->d->overlayPos.rx() = - (overlaySize.width() /2) + (overlaySize.width() /4) * (qrand() % (4 + 1));
975 d->background->d->overlayPos.ry() = (- (overlaySize.height() /2) + (overlaySize.height() /4) * (qrand() % (4 + 1)))/2;
977 }
else if (d->background) {
978 qreal left, top, right, bottom;
979 d->background->getMargins(left, top, right, bottom);
981 delete d->background;
983 setContentsMargins(0, 0, 0, 0);
1007 return d->needsConfig;
1012 if (d->needsConfig == needsConfig) {
1016 d->needsConfig = needsConfig;
1019 d->destroyMessageOverlay();
1023 d->createMessageOverlay(
true);
1024 d->messageOverlay->opacity = 0.4;
1026 QGraphicsGridLayout *configLayout =
new QGraphicsGridLayout(d->messageOverlay);
1027 configLayout->setContentsMargins(0, 0, 0, 0);
1030 configLayout->setColumnStretchFactor(0, 5);
1031 configLayout->setColumnStretchFactor(2, 5);
1032 configLayout->setRowStretchFactor(0, 5);
1033 configLayout->setRowStretchFactor(3, 5);
1036 if (!reason.isEmpty()) {
1037 Label *explanation =
new Label(d->messageOverlay);
1039 configLayout->addItem(explanation, row, 1);
1040 configLayout->setColumnStretchFactor(1, 5);
1042 configLayout->setAlignment(explanation, Qt::AlignBottom | Qt::AlignCenter);
1047 configWidget->
setImage(
"widgets/configuration-icons",
"configure");
1048 configWidget->setMaximumSize(24,24);
1049 configWidget->setMinimumSize(24,24);
1051 configWidget->
setText(i18n(
"Configure..."));
1054 configLayout->addItem(configWidget, row, 1);
1059 d->messageOverlay->show();
1064 if (message.isEmpty()) {
1065 d->destroyMessageOverlay();
1072 QGraphicsLinearLayout *mainLayout =
new QGraphicsLinearLayout(mainWidget);
1074 mainLayout->addStretch();
1076 QGraphicsLinearLayout *messageLayout =
new QGraphicsLinearLayout();
1079 QGraphicsLinearLayout *buttonLayout =
new QGraphicsLinearLayout();
1082 mainLayout->addItem(messageLayout);
1083 mainLayout->addItem(buttonLayout);
1084 mainLayout->addStretch();
1090 messageLayout->addStretch();
1091 messageLayout->addItem(messageIcon);
1092 messageLayout->addItem(messageText);
1093 messageLayout->addStretch();
1096 messageText->
setText(message);
1098 buttonLayout->addStretch();
1101 d->messageOkButton =
new PushButton(mainWidget);
1102 d->messageOkButton.data()->setText(i18n(
"&OK"));
1103 d->messageOkButton.data()->setIcon(KIcon(
"dialog-ok"));
1104 buttonLayout->addItem(d->messageOkButton.data());
1105 connect(d->messageOkButton.data(), SIGNAL(clicked()),
this, SLOT(destroyMessageOverlay()));
1109 d->messageYesButton =
new PushButton(mainWidget);
1110 d->messageYesButton.data()->setText(i18n(
"&Yes"));
1111 buttonLayout->addItem(d->messageYesButton.data());
1112 connect(d->messageYesButton.data(), SIGNAL(clicked()),
this, SLOT(destroyMessageOverlay()));
1116 d->messageNoButton =
new PushButton(mainWidget);
1117 d->messageNoButton.data()->setText(i18n(
"&No"));
1118 buttonLayout->addItem(d->messageNoButton.data());
1119 connect(d->messageNoButton.data(), SIGNAL(clicked()),
this, SLOT(destroyMessageOverlay()));
1123 d->messageCancelButton =
new PushButton(mainWidget);
1124 d->messageCancelButton.data()->setText(i18n(
"&Cancel"));
1125 d->messageCancelButton.data()->setIcon(KIcon(
"dialog-cancel"));
1126 buttonLayout->addItem(d->messageCancelButton.data());
1127 connect(d->messageCancelButton.data(), SIGNAL(clicked()),
this, SLOT(destroyMessageOverlay()));
1130 d->messageCloseAction =
new QAction(d->messageOverlay);
1131 d->messageCloseAction.data()->setShortcut(Qt::Key_Escape);
1132 mainWidget->addAction(d->messageCloseAction.data());
1133 connect(d->messageCloseAction.data(), SIGNAL(triggered()),
this, SLOT(destroyMessageOverlay()));
1135 buttonLayout->addStretch();
1137 mainWidget->adjustSize();
1138 QSizeF hint = mainWidget->preferredSize();
1139 if (hint.height() > size().height() || hint.width() > size().width()) {
1146 if (d->messageDialog) {
1147 delete d->messageDialog.data()->graphicsWidget();
1153 KWindowSystem::setOnAllDesktops(d->messageDialog.data()->winId(),
true);
1154 KWindowSystem::setState(d->messageDialog.data()->winId(), NET::SkipTaskbar | NET::SkipPager);
1155 d->messageDialog.data()->setGraphicsWidget(mainWidget);
1156 connect(d->messageDialog.data(), SIGNAL(
destroyed(
QObject*)), mainWidget, SLOT(deleteLater()));
1159 if (buttonLayout->count() < 1) {
1162 ok->
setIcon(KIcon(
"dialog-ok"));
1163 buttonLayout->addItem(ok);
1164 connect(ok, SIGNAL(clicked()),
this, SLOT(destroyMessageOverlay()));
1167 delete d->messageDialog.data();
1168 d->createMessageOverlay();
1169 d->messageOverlay->opacity = 0.8;
1170 mainWidget->setParentItem(d->messageOverlay);
1171 QGraphicsLinearLayout *l =
new QGraphicsLinearLayout(d->messageOverlay);
1172 l->addItem(mainWidget);
1175 if (d->messageDialog) {
1176 QPoint pos =
geometry().topLeft().toPoint();
1178 pos = corona->
popupPosition(
this, d->messageDialog.data()->size());
1181 d->messageDialog.data()->move(pos);
1184 d->messageOverlay->show();
1195 return d->itemStatus;
1210 if (d->constraintsTimer.isActive()) {
1211 d->constraintsTimer.stop();
1215 Plasma::Constraints c = d->pendingConstraints;
1221 QAction *closeApplet = d->actions->action(
"remove");
1223 closeApplet->setEnabled(unlocked);
1224 closeApplet->setVisible(unlocked);
1225 connect(closeApplet, SIGNAL(triggered(
bool)),
this, SLOT(selectItemToDestroy()), Qt::UniqueConnection);
1228 QAction *configAction = d->actions->action(
"configure");
1230 if (d->isContainment) {
1231 connect(configAction, SIGNAL(triggered(
bool)),
this, SLOT(requestConfiguration()), Qt::UniqueConnection);
1236 if (d->hasConfigurationInterface) {
1237 bool canConfig = unlocked || KAuthorized::authorize(
"plasma/allow_configure_when_locked");
1238 configAction->setVisible(canConfig);
1239 configAction->setEnabled(canConfig);
1244 if (runAssociatedApplication) {
1245 connect(runAssociatedApplication, SIGNAL(triggered(
bool)),
this, SLOT(
runAssociatedApplication()), Qt::UniqueConnection);
1248 d->updateShortcuts();
1251 connect(corona, SIGNAL(shortcutsChanged()),
this, SLOT(updateShortcuts()), Qt::UniqueConnection);
1257 QAction *
action = d->actions->action(
"remove");
1259 action->setVisible(unlocked);
1260 action->setEnabled(unlocked);
1263 action = d->actions->action(
"configure");
1264 if (action && d->hasConfigurationInterface) {
1265 bool canConfig = unlocked || KAuthorized::authorize(
"plasma/allow_configure_when_locked");
1266 action->setVisible(canConfig);
1267 action->setEnabled(canConfig);
1271 foreach (
ExtenderItem *item, d->extender.data()->attachedItems()) {
1272 item->d->setMovable(unlocked);
1276 if (!unlocked && d->handle) {
1281 if (s && h->scene() == s) {
1292 d->positionMessageOverlay();
1294 if (d->started && layout()) {
1295 layout()->updateGeometry();
1304 BackgroundHints hints = d->preferredBackgroundHints;
1306 d->preferredBackgroundHints = hints;
1311 QGraphicsLayoutItem *item = layout()->itemAt(1);
1312 layout()->removeAt(1);
1320 at.rotateRadians(0);
1325 if (d->sizeForFormFactor.contains(f)) {
1326 resize(d->sizeForFormFactor.value(f));
1330 if (!size().isEmpty() &&
1335 if (c & Plasma::SizeConstraint || c & Plasma::FormFactorConstraint) {
1339 if (d->preferredSizePolicy == QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)) {
1340 d->preferredSizePolicy = sizePolicy();
1343 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
1345 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
1346 }
else if (d->preferredSizePolicy != QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)) {
1347 setSizePolicy(d->preferredSizePolicy);
1355 if (d->isContainment && containment) {
1356 containment->d->containmentConstraintsEvent(c);
1361 popup->d->popupConstraintsEvent(c);
1369 if (d->modificationsTimer) {
1370 if (d->modificationsTimer->isActive()) {
1371 d->modificationsTimer->stop();
1374 d->modificationsTimer =
new QBasicTimer;
1387 return d->script ? d->script->contextualActions() : QList<QAction*>();
1392 return d->actions->action(name);
1397 d->actions->addAction(name, action);
1407 if (transform().isRotating()) {
1408 painter->setRenderHint(QPainter::SmoothPixmapTransform);
1409 painter->setRenderHint(QPainter::Antialiasing);
1412 if (d->background &&
1416 d->background->paintFrame(painter);
1424 qreal left, top, right, bottom;
1425 getContentsMargins(&left, &top, &right, &bottom);
1426 QRect contentsRect = QRectF(QPointF(0, 0),
1427 boundingRect().size()).adjusted(left, top, -right, -bottom).toRect();
1429 if (widget && d->isContainment) {
1431 View* v = qobject_cast<
Plasma::View*>(widget->parent());
1434 if (!v || v->isWallpaperEnabled()) {
1437 if (c && c->drawWallpaper() && c->wallpaper()) {
1438 Wallpaper *w = c->wallpaper();
1439 if (!w->isInitialized()) {
1441 KConfigGroup wallpaperConfig = c->config();
1442 wallpaperConfig = KConfigGroup(&wallpaperConfig,
"Wallpaper");
1443 wallpaperConfig = KConfigGroup(&wallpaperConfig, w->pluginName());
1444 w->restore(wallpaperConfig);
1445 disconnect(w, SIGNAL(update(QRectF)),
this, SLOT(updateRect(QRectF)));
1446 connect(w, SIGNAL(update(QRectF)),
this, SLOT(updateRect(QRectF)));
1450 c->wallpaper()->paint(painter, option->exposedRect);
1457 Containment::StyleOption coption(*option);
1473 d->script->paintInterface(painter, option, contentsRect);
1488 while (!parentApplet && pw && pw->parentWidget()) {
1490 if (!parentWidget) {
1506 if (parentApplet && parentApplet != c && c !=
this && (pa || layout())) {
1507 if (pa || (parentApplet->size().height() < layout()->effectiveSizeHint(Qt::MinimumSize).height())) {
1509 }
else if (pa || (parentApplet->size().width() < layout()->effectiveSizeHint(Qt::MinimumSize).width())) {
1520 if (d->isContainment) {
1527 QGraphicsItem *parent = parentItem();
1536 parent = parent->parentItem();
1542 QObject *objParent = this->parent();
1549 objParent = objParent->parent();
1558 if (!d->activationAction) {
1559 d->activationAction =
new KAction(
this);
1560 d->activationAction->setText(i18n(
"Activate %1 Widget",
name()));
1561 d->activationAction->setObjectName(QString(
"activate widget %1").arg(
id()));
1562 connect(d->activationAction, SIGNAL(triggered()),
this, SIGNAL(
activate()));
1563 connect(d->activationAction, SIGNAL(globalShortcutChanged(QKeySequence)),
1564 this, SLOT(globalShortcutChanged()));
1566 QList<QWidget *> widgets = d->actions->associatedWidgets();
1567 foreach (
QWidget *w, widgets) {
1568 w->addAction(d->activationAction);
1570 }
else if (d->activationAction->globalShortcut() == shortcut) {
1575 d->activationAction->setGlobalShortcut(
1577 KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut),
1578 KAction::NoAutoloading);
1579 d->globalShortcutChanged();
1582 void AppletPrivate::globalShortcutChanged()
1584 if (!activationAction) {
1588 KConfigGroup shortcutConfig(mainConfigGroup(),
"Shortcuts");
1589 shortcutConfig.writeEntry(
"global", activationAction->globalShortcut().toString());
1590 scheduleModificationNotification();
1596 if (d->activationAction) {
1597 return d->activationAction->globalShortcut();
1610 d->actions->addAssociatedWidget(widget);
1615 d->actions->removeAssociatedWidget(widget);
1628 return c->d->context();
1633 return d->aspectRatioMode;
1639 if (popup && popup->d->dialogPtr) {
1640 popup->d->dialogPtr.data()->setAspectRatioMode(mode);
1641 popup->d->savedAspectRatio = mode;
1644 d->aspectRatioMode = mode;
1649 if (!item || d->registeredAsDragHandle.contains(item)) {
1653 d->registeredAsDragHandle.insert(item);
1654 item->installSceneEventFilter(
this);
1663 if (d->registeredAsDragHandle.remove(item)) {
1665 item->removeSceneEventFilter(
this);
1672 return d->registeredAsDragHandle.contains(item);
1677 return d->hasConfigurationInterface;
1683 d->package->d->publish(methods);
1684 }
else if (d->appletDescription.isValid()) {
1686 d->service =
new PlasmoidService(
this);
1689 kDebug() <<
"publishing package under name " << resourceName;
1691 pm.
setName(d->appletDescription.name());
1693 pm.
setIcon(d->appletDescription.icon());
1694 d->service->d->publish(methods, resourceName, pm);
1696 kDebug() <<
"Can not publish invalid applets.";
1703 d->package->d->unpublish();
1706 d->service->d->unpublish();
1714 return d->package->d->isPublished();
1717 return d->service->d->isPublished();
1726 if (hasInterface == d->hasConfigurationInterface) {
1730 QAction *configAction = d->actions->action(
"configure");
1732 bool enable = hasInterface;
1735 enable = unlocked || KAuthorized::authorize(
"plasma/allow_configure_when_locked");
1737 configAction->setEnabled(enable);
1740 d->hasConfigurationInterface = hasInterface;
1743 KActionCollection* AppletPrivate::defaultActions(
QObject *parent)
1745 KActionCollection *actions =
new KActionCollection(parent);
1746 actions->setConfigGroup(
"Shortcuts-Applet");
1748 KAction *configAction = actions->addAction(
"configure");
1749 configAction->setAutoRepeat(
false);
1750 configAction->setText(i18n(
"Widget Settings"));
1751 configAction->setIcon(KIcon(
"configure"));
1752 configAction->setShortcut(KShortcut(
"alt+d, s"));
1755 KAction *closeApplet = actions->addAction(
"remove");
1756 closeApplet->setAutoRepeat(
false);
1757 closeApplet->setText(i18n(
"Remove this Widget"));
1758 closeApplet->setIcon(KIcon(
"edit-delete"));
1759 closeApplet->setShortcut(KShortcut(
"alt+d, r"));
1763 runAssociatedApplication->setAutoRepeat(
false);
1764 runAssociatedApplication->setText(i18n(
"Run the Associated Application"));
1765 runAssociatedApplication->setIcon(KIcon(
"system-run"));
1766 runAssociatedApplication->setShortcut(KShortcut(
"alt+d, t"));
1767 runAssociatedApplication->setVisible(
false);
1768 runAssociatedApplication->setEnabled(
false);
1776 return QObject::eventFilter(o, e);
1781 if (watched ==
this) {
1782 switch (event->type()) {
1783 case QEvent::GraphicsSceneHoverEnter:
1789 while ((pw = pw->parentWidget())) {
1790 if (qobject_cast<Containment *>(pw)) {
1792 }
else if (qobject_cast<Applet *>(pw)) {
1797 QGraphicsSceneHoverEvent *he =
static_cast<QGraphicsSceneHoverEvent*
>(event);
1799 d->handle.data()->setHoverPos(he->pos());
1806 handle, SLOT(appletResized()));
1812 case QEvent::GraphicsSceneHoverMove:
1814 QGraphicsSceneHoverEvent *he =
static_cast<QGraphicsSceneHoverEvent*
>(event);
1815 d->handle.data()->setHoverPos(he->pos());
1819 case QEvent::GraphicsSceneMousePress: {
1820 QGraphicsSceneMouseEvent *me =
static_cast<QGraphicsSceneMouseEvent *
>(event);
1821 if (!contentsRect().contains(me->pos())) {
1822 event->setAccepted(
false);
1834 switch (event->type()) {
1835 case QEvent::GraphicsSceneMouseMove:
1836 case QEvent::GraphicsSceneMousePress:
1837 case QEvent::GraphicsSceneMouseRelease:
1839 if (watched ==
this) {
1840 event->setAccepted(
false);
1845 if ((flags() & ItemIsMovable) && d->registeredAsDragHandle.contains(watched)) {
1848 scene()->sendEvent(
this, event);
1859 return QGraphicsItem::sceneEventFilter(watched, event);
1865 QGraphicsWidget::mouseMoveEvent(event);
1876 QGraphicsWidget::focusInEvent(event);
1881 QGraphicsWidget::resizeEvent(event);
1883 if (d->background) {
1884 d->background->resizeFrame(boundingRect().size());
1889 d->scheduleModificationNotification();
1895 return KConfigDialog::exists(d->configDialogId());
1904 if (
immutability() !=
Mutable && !KAuthorized::authorize(
"plasma/allow_configure_when_locked")) {
1908 KConfigDialog *dlg = KConfigDialog::exists(d->configDialogId());
1911 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
1913 KWindowSystem::activateWindow(dlg->winId());
1917 d->publishUI.publishCheckbox = 0;
1919 KConfigDialog *dialog = 0;
1921 const QString uiFile = d->package->filePath(
"mainconfigui");
1922 KDesktopFile df(d->package->path() +
"/metadata.desktop");
1923 const QStringList kcmPlugins = df.desktopGroup().readEntry(
"X-Plasma-ConfigPlugins", QStringList());
1924 if (!uiFile.isEmpty() || !kcmPlugins.isEmpty()) {
1926 dialog =
new AppletConfigDialog(0, d->configDialogId(), configLoader);
1928 if (!d->configLoader) {
1930 configLoader->setParent(dialog);
1933 dialog->setWindowTitle(d->configWindowTitle());
1934 dialog->setAttribute(Qt::WA_DeleteOnClose,
true);
1935 bool hasPages =
false;
1941 dialog->addPage(w, i18n(
"Settings"),
icon(), i18n(
"%1 Settings",
name()));
1945 foreach (
const QString &kcm, kcmPlugins) {
1946 #ifndef PLASMA_NO_KUTILS
1947 KCModuleProxy *module =
new KCModuleProxy(kcm);
1948 if (module->realModule()) {
1951 connect(module, SIGNAL(changed(
bool)), dialog, SLOT(settingsModified(
bool)));
1952 connect(dialog, SIGNAL(okClicked()),
1953 module->realModule(), SLOT(
save()));
1954 connect(dialog, SIGNAL(applyClicked()),
1955 module->realModule(), SLOT(
save()));
1956 dialog->addPage(module, module->moduleInfo().moduleName(), module->moduleInfo().icon());
1962 KService::Ptr service = KService::serviceByStorageId(kcm);
1965 KCModule *module = service->createInstance<KCModule>(dialog, QVariantList(), &error);
1968 connect(module, SIGNAL(changed(
bool)), dialog, SLOT(settingsModified(
bool)));
1969 connect(dialog, SIGNAL(okClicked()),
1970 module, SLOT(
save()));
1971 connect(dialog, SIGNAL(applyClicked()),
1972 module, SLOT(
save()));
1973 dialog->addPage(module, service->name(), service->icon());
1977 kDebug() <<
"failed to load kcm" << kcm <<
"for" <<
name();
1985 d->addGlobalShortcutsPage(dialog);
1993 if (!dialog && d->script) {
1994 d->script->showConfigurationInterface();
1996 }
else if (d->script) {
1997 d->script->showConfigurationInterface();
1999 KConfigDialog *dialog = d->generateGenericConfigDialog();
2000 d->addStandardConfigurationPages(dialog);
2018 QString AppletPrivate::configDialogId()
const
2020 return QString(
"%1settings%2").arg(appletId).arg(q->name());
2023 QString AppletPrivate::configWindowTitle()
const
2025 return i18nc(
"@title:window",
"%1 Settings", q->name());
2028 QSet<QString> AppletPrivate::knownCategories()
2032 QSet<QString> categories = s_customCategories;
2033 categories << QString(I18N_NOOP(
"Accessibility")).toLower()
2034 << QString(I18N_NOOP(
"Application Launchers")).toLower()
2035 << QString(I18N_NOOP(
"Astronomy")).toLower()
2036 << QString(I18N_NOOP(
"Date and Time")).toLower()
2037 << QString(I18N_NOOP(
"Development Tools")).toLower()
2038 << QString(I18N_NOOP(
"Education")).toLower()
2039 << QString(I18N_NOOP(
"Environment and Weather")).toLower()
2040 << QString(I18N_NOOP(
"Examples")).toLower()
2041 << QString(I18N_NOOP(
"File System")).toLower()
2042 << QString(I18N_NOOP(
"Fun and Games")).toLower()
2043 << QString(I18N_NOOP(
"Graphics")).toLower()
2044 << QString(I18N_NOOP(
"Language")).toLower()
2045 << QString(I18N_NOOP(
"Mapping")).toLower()
2046 << QString(I18N_NOOP(
"Miscellaneous")).toLower()
2047 << QString(I18N_NOOP(
"Multimedia")).toLower()
2048 << QString(I18N_NOOP(
"Online Services")).toLower()
2049 << QString(I18N_NOOP(
"Productivity")).toLower()
2050 << QString(I18N_NOOP(
"System Information")).toLower()
2051 << QString(I18N_NOOP(
"Utilities")).toLower()
2052 << QString(I18N_NOOP(
"Windows and Tasks")).toLower();
2056 KConfigDialog *AppletPrivate::generateGenericConfigDialog()
2059 KConfigDialog *dialog =
new AppletConfigDialog(0, configDialogId(), nullManager);
2060 nullManager->setParent(dialog);
2061 dialog->setFaceType(KPageDialog::Auto);
2062 dialog->setWindowTitle(configWindowTitle());
2063 dialog->setAttribute(Qt::WA_DeleteOnClose,
true);
2064 q->createConfigurationInterface(dialog);
2065 dialog->showButton(KDialog::Default,
false);
2066 dialog->showButton(KDialog::Help,
false);
2067 QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()));
2068 QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()));
2072 void AppletPrivate::addStandardConfigurationPages(KConfigDialog *dialog)
2074 addGlobalShortcutsPage(dialog);
2077 void AppletPrivate::addGlobalShortcutsPage(KConfigDialog *dialog)
2079 #ifndef PLASMA_NO_GLOBAL_SHORTCUTS
2085 QVBoxLayout *layout =
new QVBoxLayout(page);
2087 if (!shortcutEditor) {
2088 shortcutEditor =
new KKeySequenceWidget(page);
2089 QObject::connect(shortcutEditor.data(), SIGNAL(keySequenceChanged(QKeySequence)), dialog, SLOT(settingsModified()));
2092 shortcutEditor.data()->setKeySequence(q->globalShortcut().primary());
2093 layout->addWidget(shortcutEditor.data());
2094 layout->addStretch();
2095 dialog->addPage(page, i18n(
"Keyboard Shortcut"),
"preferences-desktop-keyboard");
2097 QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
2098 QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
2102 void AppletPrivate::publishCheckboxStateChanged(
int state)
2104 if (state == Qt::Checked) {
2105 publishUI.allUsersCheckbox->setEnabled(
true);
2107 publishUI.allUsersCheckbox->setEnabled(
false);
2111 void AppletPrivate::configDialogFinished()
2113 if (shortcutEditor) {
2114 QKeySequence sequence = shortcutEditor.data()->keySequence();
2115 if (sequence != q->globalShortcut().primary()) {
2116 q->setGlobalShortcut(KShortcut(sequence));
2117 emit q->configNeedsSaving();
2121 #ifdef ENABLE_REMOTE_WIDGETS
2122 if (KConfigDialog::exists(configDialogId()) && publishUI.publishCheckbox) {
2123 q->config().writeEntry(
"Share", publishUI.publishCheckbox->isChecked());
2125 if (publishUI.publishCheckbox->isChecked()) {
2126 QString resourceName =
2127 i18nc(
"%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
2128 "%1 on %2", q->name(), QHostInfo::localHostName());
2130 if (publishUI.allUsersCheckbox->isChecked()) {
2132 AuthorizationRule *rule =
new AuthorizationRule(resourceName,
"");
2138 AuthorizationRule *matchingRule =
2150 if (!configLoader) {
2152 propagateConfigChanged();
2153 if (KConfigDialog *dialog = qobject_cast<KConfigDialog *>(q->sender())) {
2154 dialog->enableButton(KDialog::Apply,
false);
2159 void AppletPrivate::updateShortcuts()
2164 QList<QString> names;
2165 QList<QAction*> qactions;
2166 names <<
"add sibling containment" <<
"configure shortcuts" <<
"lock widgets";
2167 foreach (
const QString &
name, names) {
2168 QAction *a = actions->action(name);
2169 actions->takeAction(a);
2173 actions->readSettings();
2175 for (
int i = 0; i < names.size(); ++i) {
2176 QAction *a = qactions.at(i);
2178 actions->addAction(names.at(i), a);
2182 actions->readSettings();
2186 void AppletPrivate::propagateConfigChanged()
2191 c->d->configChanged();
2201 if (d->configLoader) {
2202 d->configLoader->readConfig();
2204 d->script->configChanged();
2217 KConfigGroup constraintGroup(KGlobal::config(),
"Constraints");
2218 return constraintGroup.readEntry(constraint,
true);
2223 AssociatedApplicationManager::self()->setApplication(
this,
string);
2225 QAction *runAssociatedApplication = d->actions->action(
"run associated application");
2226 if (runAssociatedApplication) {
2227 bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2229 runAssociatedApplication->setVisible(valid);
2230 runAssociatedApplication->setEnabled(valid);
2236 AssociatedApplicationManager::self()->setUrls(
this, urls);
2238 QAction *runAssociatedApplication = d->actions->action(
"run associated application");
2239 if (runAssociatedApplication) {
2240 bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2242 runAssociatedApplication->setVisible(valid);
2243 runAssociatedApplication->setEnabled(valid);
2249 return AssociatedApplicationManager::self()->application(
this);
2254 return AssociatedApplicationManager::self()->urls(
this);
2260 AssociatedApplicationManager::self()->run(
this);
2266 return AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2269 void AppletPrivate::filterOffers(QList<KService::Ptr> &offers)
2271 KConfigGroup constraintGroup(KGlobal::config(),
"Constraints");
2272 foreach (
const QString &key, constraintGroup.keyList()) {
2274 if (constraintGroup.readEntry(key,
true)) {
2279 QMutableListIterator<KService::Ptr> it(offers);
2280 while (it.hasNext()) {
2281 KService::Ptr p = it.next();
2282 QString prop = QString(
"X-Plasma-Requires-").append(key);
2283 QVariant req = p->property(prop, QVariant::String);
2286 if (req.isValid()) {
2287 reqValue = req.toString();
2288 }
else if (p->property(
"X-Plasma-API").toString().toLower() ==
"javascript") {
2291 reqValue =
"Unused";
2294 if (!(reqValue ==
"Optional" || reqValue ==
"Unused")) {
2302 QString AppletPrivate::parentAppConstraint(
const QString &parentApp)
2304 if (parentApp.isEmpty()) {
2305 return QString(
"((not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '') or [X-KDE-ParentApp] == '%1')")
2306 .arg(KGlobal::mainComponent().aboutData()->appName());
2309 return QString(
"[X-KDE-ParentApp] == '%1'").arg(parentApp);
2319 QString constraint = AppletPrivate::parentAppConstraint();
2320 constraint.append(QString(
" and '%1' in [X-Plasma-DropMimeTypes]").arg(mimetype));
2322 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2323 AppletPrivate::filterOffers(offers);
2324 return KPluginInfo::fromServices(offers);
2329 QString constraint = AppletPrivate::parentAppConstraint();
2330 constraint.append(
" and exist [X-Plasma-DropUrlPatterns]");
2331 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2332 AppletPrivate::filterOffers(offers);
2334 KPluginInfo::List allApplets = KPluginInfo::fromServices(offers);
2335 KPluginInfo::List filtered;
2336 foreach (
const KPluginInfo &info, allApplets) {
2337 QStringList urlPatterns = info.property(
"X-Plasma-DropUrlPatterns").toStringList();
2338 foreach (
const QString &glob, urlPatterns) {
2340 rx.setPatternSyntax(QRegExp::Wildcard);
2341 if (rx.exactMatch(url.toString())) {
2342 kDebug() << info.name() <<
"matches" << glob << url;
2353 QString constraint = AppletPrivate::parentAppConstraint(parentApp);
2354 constraint.append(
" and exist [X-KDE-PluginInfo-Category]");
2356 KConfigGroup group(KGlobal::config(),
"General");
2357 const QStringList excluded = group.readEntry(
"ExcludeCategories", QStringList());
2358 foreach (
const QString &
category, excluded) {
2359 constraint.append(
" and [X-KDE-PluginInfo-Category] != '").append(category).append(
"'");
2362 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2363 AppletPrivate::filterOffers(offers);
2365 QStringList categories;
2366 QSet<QString> known = AppletPrivate::knownCategories();
2367 foreach (
const KService::Ptr &applet, offers) {
2368 QString appletCategory = applet->property(
"X-KDE-PluginInfo-Category").toString();
2369 if (visibleOnly && applet->noDisplay()) {
2375 if (!appletCategory.isEmpty() && !known.contains(appletCategory.toLower())) {
2376 kDebug() <<
"Unknown category: " << applet->name() <<
"says it is in the"
2377 << appletCategory <<
"category which is unknown to us";
2378 appletCategory.clear();
2381 if (appletCategory.isEmpty()) {
2382 if (!categories.contains(i18nc(
"misc category",
"Miscellaneous"))) {
2383 categories << i18nc(
"misc category",
"Miscellaneous");
2385 }
else if (!categories.contains(appletCategory)) {
2386 categories << appletCategory;
2396 AppletPrivate::s_customCategories = QSet<QString>::fromList(categories);
2401 return AppletPrivate::s_customCategories.toList();
2406 if (QFile::exists(path +
"/metadata.desktop")) {
2407 KService service(path +
"/metadata.desktop");
2408 const QStringList& types = service.serviceTypes();
2410 if (types.contains(
"Plasma/Containment")) {
2412 }
else if (types.contains(
"Plasma/PopupApplet")) {
2415 return new Applet(path, appletId, args);
2429 if (!info.isValid()) {
2433 return load(info.pluginName(), appletId, args);
2438 QVariant ret = QGraphicsWidget::itemChange(change, value);
2442 case ItemSceneHasChanged: {
2449 case ItemParentChange:
2450 if (!d->isContainment) {
2452 if (d->mainConfig && !c) {
2453 kWarning() <<
"Configuration object was requested prior to init(), which is too early. "
2454 "Please fix this item:" << parentItem() << value.value<QGraphicsItem *>()
2457 Applet *newC =
dynamic_cast<Applet*
>(value.value<QGraphicsItem *>());
2462 KConfigGroup *old = d->mainConfig;
2463 KConfigGroup appletConfig = newC->
config();
2464 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2465 d->mainConfig =
new KConfigGroup(&appletConfig, QString::number(d->appletId));
2466 old->copyTo(d->mainConfig);
2473 case ItemParentHasChanged:
2476 removeSceneEventFilter(
this);
2480 installSceneEventFilter(
this);
2482 removeSceneEventFilter(
this);
2487 case ItemPositionHasChanged:
2490 case ItemTransformHasChanged:
2491 d->scheduleModificationNotification();
2503 return d->script->shape();
2506 return QGraphicsWidget::shape();
2511 QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
2515 if (which == Qt::MinimumSize) {
2526 hint.setWidth(size().height());
2528 hint.setHeight(size().width());
2533 hint.setWidth(size().height());
2535 }
else if (ff ==
Vertical && (which == Qt::MaximumSize || size().width() <= KIconLoader::SizeLarge)) {
2536 hint.setHeight(size().width());
2556 d->constraintsTimer.stop();
2557 d->busyWidgetTimer.stop();
2558 if (d->modificationsTimer) {
2559 d->modificationsTimer->stop();
2564 if (event->timerId() == d->constraintsTimer.timerId()) {
2565 d->constraintsTimer.stop();
2572 }
else if (d->modificationsTimer && event->timerId() == d->modificationsTimer->timerId()) {
2573 d->modificationsTimer->stop();
2579 }
else if (event->timerId() == d->busyWidgetTimer.timerId()) {
2580 if (!d->busyWidget) {
2581 d->createMessageOverlay(
false);
2582 d->messageOverlay->opacity = 0;
2584 QGraphicsLinearLayout *mainLayout =
new QGraphicsLinearLayout(d->messageOverlay);
2586 d->busyWidget->setAcceptHoverEvents(
false);
2587 d->busyWidget->setAcceptedMouseButtons(Qt::NoButton);
2588 d->messageOverlay->setAcceptHoverEvents(
false);
2589 d->messageOverlay->setAcceptedMouseButtons(Qt::NoButton);
2591 mainLayout->addStretch();
2592 mainLayout->addItem(d->busyWidget);
2593 mainLayout->addStretch();
2603 QPointF bottomRight = pos();
2604 bottomRight.rx() += size().width();
2605 bottomRight.ry() += size().height();
2607 QPoint tL = v->mapToGlobal(v->mapFromScene(pos()));
2608 QPoint bR = v->mapToGlobal(v->mapFromScene(bottomRight));
2609 return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
2614 return QRect(QPoint(0, 0), QSize(0, 0));
2619 setZValue(++AppletPrivate::s_maxZValue);
2624 setZValue(--AppletPrivate::s_minZValue);
2627 void AppletPrivate::setIsContainment(
bool nowIsContainment,
bool forceUpdate)
2643 c->d->checkContainmentFurniture();
2649 return d->isContainment;
2654 AppletPrivate::AppletPrivate(KService::Ptr service,
const KPluginInfo *info,
int uniqueID,
Applet *applet)
2655 : appletId(uniqueID),
2662 appletDescription(info ? *info : KPluginInfo(service)),
2667 messageOverlayProxy(0),
2673 activationAction(0),
2675 preferredSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored),
2676 modificationsTimer(0),
2684 if (appletId == 0) {
2685 appletId = ++s_maxAppletId;
2686 }
else if (appletId > s_maxAppletId) {
2687 s_maxAppletId = appletId;
2690 publishUI.publishCheckbox = 0;
2693 AppletPrivate::~AppletPrivate()
2695 if (activationAction && activationAction->isGlobalShortcutEnabled()) {
2697 activationAction->forgetGlobalShortcut();
2700 delete extender.data();
2706 delete configLoader;
2710 delete modificationsTimer;
2713 void AppletPrivate::init(
const QString &packagePath)
2717 q->setCacheMode(Applet::DeviceCoordinateCache);
2718 q->setAcceptsHoverEvents(
true);
2719 q->setFlag(QGraphicsItem::ItemIsFocusable,
true);
2720 q->setFocusPolicy(Qt::ClickFocus);
2723 q->setLayoutDirection(qApp->layoutDirection());
2726 QSize size(200, 200);
2728 q->setHasConfigurationInterface(
true);
2730 QAction *closeApplet = actions->action(
"remove");
2732 closeApplet->setText(i18nc(
"%1 is the name of the applet",
"Remove this %1", q->name()));
2735 QAction *configAction = actions->action(
"configure");
2737 configAction->setText(i18nc(
"%1 is the name of the applet",
"%1 Settings", q->name()));
2740 QObject::connect(q, SIGNAL(activate()), q, SLOT(setFocus()));
2741 if (!appletDescription.isValid()) {
2742 kDebug() <<
"Check your constructor! "
2743 <<
"You probably want to be passing in a Service::Ptr "
2744 <<
"or a QVariantList with a valid storageid as arg[0].";
2749 QVariant s = appletDescription.property(
"X-Plasma-DefaultSize");
2756 QString api = appletDescription.property(
"X-Plasma-API").toString();
2759 if (!api.isEmpty()) {
2761 QString path = packagePath.isEmpty() ? appletDescription.pluginName() : packagePath;
2764 package = new Package(path, structure);
2767 if (package->isValid()) {
2776 q->setFailedToLaunch(
true,
2777 i18nc(
"API or programming language the widget was written in, name of the widget",
2778 "Could not create a %1 ScriptEngine for the %2 widget.",
2779 api, appletDescription.name()));
2782 q->setFailedToLaunch(
true, i18nc(
"Package file, name of the widget",
2783 "Could not open the %1 package required for the %2 widget.",
2784 appletDescription.pluginName(), appletDescription.name()));
2793 void AppletPrivate::setupScriptSupport()
2799 kDebug() <<
"setting up script support, package is in" << package->path()
2800 <<
"which is a" << package->structure()->type() <<
"package"
2801 <<
", main script is" << package->filePath(
"mainscript");
2803 QString translationsPath = package->filePath(
"translations");
2804 if (!translationsPath.isEmpty()) {
2807 KGlobal::dirs()->addResourceDir(
"locale", translationsPath);
2808 KGlobal::locale()->insertCatalog(package->metadata().pluginName());
2811 QString xmlPath = package->filePath(
"mainconfigxml");
2812 if (!xmlPath.isEmpty()) {
2813 QFile file(xmlPath);
2814 KConfigGroup config = q->config();
2816 QObject::connect(configLoader, SIGNAL(configChanged()), q, SLOT(propagateConfigChanged()));
2819 if (!package->filePath(
"mainconfigui").isEmpty()) {
2820 q->setHasConfigurationInterface(
true);
2824 QString AppletPrivate::globalName()
const
2826 if (!appletDescription.isValid()) {
2830 return appletDescription.service()->library();
2833 QString AppletPrivate::instanceName()
2835 if (!appletDescription.isValid()) {
2839 return appletDescription.service()->library() + QString::number(appletId);
2842 void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
2847 constraintsTimer.start(0, q);
2854 pendingConstraints |= c;
2857 void AppletPrivate::scheduleModificationNotification()
2860 if (modificationsTimer) {
2862 if (modificationsTimer->isActive()) {
2863 modificationsTimer->stop();
2866 modificationsTimer->start(1000, q);
2870 KConfigGroup *AppletPrivate::mainConfigGroup()
2876 bool newGroup =
false;
2877 if (isContainment) {
2878 Corona *corona = qobject_cast<Corona*>(q->scene());
2879 KConfigGroup containmentConfig;
2883 containmentConfig = KConfigGroup(corona->config(),
"Containments");
2885 containmentConfig = KConfigGroup(KGlobal::config(),
"Containments");
2888 if (package && !containmentConfig.hasGroup(QString::number(appletId))) {
2892 mainConfig =
new KConfigGroup(&containmentConfig, QString::number(appletId));
2894 KConfigGroup appletConfig;
2896 Containment *c = q->containment();
2897 Applet *parentApplet = qobject_cast<Applet *>(q->parent());
2898 if (parentApplet && parentApplet != static_cast<Applet *>(c)) {
2901 appletConfig = parentApplet->config();
2902 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2905 appletConfig = c->config();
2906 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2908 kWarning() <<
"requesting config for" << q->name() <<
"without a containment!";
2909 appletConfig = KConfigGroup(KGlobal::config(),
"Applets");
2912 if (package && !appletConfig.hasGroup(QString::number(appletId))) {
2916 mainConfig =
new KConfigGroup(&appletConfig, QString::number(appletId));
2921 const QString defaultConfigFile = q->package()->filePath(
"defaultconfig");
2922 if (!defaultConfigFile.isEmpty()) {
2923 kDebug() <<
"copying default config: " << q->package()->filePath(
"defaultconfig");
2924 KConfigGroup defaultConfig(KSharedConfig::openConfig(defaultConfigFile)->group(
"Configuration"));
2925 defaultConfig.copyTo(mainConfig);
2932 QString AppletPrivate::visibleFailureText(
const QString &reason)
2936 if (reason.isEmpty()) {
2937 text = i18n(
"This object could not be created.");
2940 r.replace(
'\n',
"<br/>");
2941 text = i18n(
"This object could not be created for the following reason:<p><b>%1</b></p>", r);
2947 void AppletPrivate::themeChanged()
2951 q->setBackgroundHints(backgroundHints);
2957 background->getMargins(left, top, right, bottom);
2958 q->setContentsMargins(left, right, top, bottom);
2963 void AppletPrivate::resetConfigurationObject()
2968 mainConfig->deleteGroup();
2972 Corona * corona = qobject_cast<Corona*>(q->scene());
2974 corona->requireConfigSync();
2978 void AppletPrivate::handleDisappeared(AppletHandle *h)
2980 if (h == handle.data()) {
2983 if (scene && h->scene() == scene) {
2984 scene->removeItem(h);
2990 void ContainmentPrivate::checkRemoveAction()
2992 q->enableAction(
"remove", q->immutability() ==
Mutable);
2996 uint AppletPrivate::s_maxAppletId = 0;
2997 int AppletPrivate::s_maxZValue = 0;
2998 int AppletPrivate::s_minZValue = 0;
3000 QSet<QString> AppletPrivate::s_customCategories;
3006 resize(parent->size());
3009 void AppletOverlayWidget::destroy()
3013 connect(anim, SIGNAL(finished()),
this, SLOT(overlayAnimationComplete()));
3014 anim->setTargetWidget(
this);
3017 overlayAnimationComplete();
3021 void AppletOverlayWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
3026 void AppletOverlayWidget::overlayAnimationComplete()
3029 scene()->removeItem(
this);
3034 void AppletOverlayWidget::paint(QPainter *painter,
3041 if (qFuzzyCompare(1, 1+opacity)) {
3046 wash.setAlphaF(opacity);
3048 Applet *applet = qobject_cast<Applet *>(parentWidget());
3051 QPainterPath backgroundShape;
3054 if (parentWidget()->contentsRect().size() != size()) {
3055 resize(parentWidget()->contentsRect().size());
3059 backgroundShape = shape();
3062 painter->setRenderHints(QPainter::Antialiasing);
3063 painter->fillPath(backgroundShape, wash);
3066 #if QT_VERSION >= 0x040700
3070 emit QGraphicsWidget::geometryChanged();
3076 #include "applet.moc"
3077 #include "private/applet_p.moc"
bool hasValidAssociatedApplication() const
virtual void destroy()
Destroys the applet; it will be removed nicely and deleted.
the size of the applet was changed
ImmutabilityType immutability
void addAction(QString name, QAction *action)
Adds the action to our collection under the given name.
The applet is constrained horizontally, but can expand vertically.
const Package * package() const
Accessor for the associated Package object if any.
void activate()
Emitted when activation is requested due to, for example, a global keyboard shortcut.
void setAssociatedApplication(const QString &string)
Sets an application associated to this applet, that will be regarded as a full view of what is repres...
A KConfigSkeleton that populates itself based on KConfigXT XML.
application startup has completed
static PluginLoader * pluginLoader()
Return the active plugin loader.
virtual void showConfigurationInterface()
Lets the user interact with the plasmoid options.
void flushPendingConstraintsEvents()
Sends all pending contraints updates to the applet.
ImmutabilityType
Defines the immutability of items like applets, corona and containments they can be free to modify...
Extends applets to allow detachable parts.
QStringList customCategories()
virtual void initExtenderItem(ExtenderItem *item)
Gets called when an extender item has to be initialized after a plasma restart.
void destroy()
Destroys this containment and all its applets (after a confirmation dialog); it will be removed nicel...
QRectF mapFromView(const QGraphicsView *view, const QRect &rect) const
Maps a QRect from a view's coordinates to local coordinates.
KConfigGroup config() const
fetch the configuration of this widget.
friend class AppletHandle
void timerEvent(QTimerEvent *event)
Reimplemented from QObject.
ConfigLoader * configScheme() const
Returns the config skeleton object from this applet's package, if any.
bool hasAuthorization(const QString &constraint) const
Returns true if the applet is allowed to perform functions covered by the given constraint eg...
virtual void restore(KConfigGroup &group)
Restores state information about this applet saved previously in save(KConfigGroup&).
the item is locked down by the system, the user can't unlock it
virtual Location location() const
Returns the location of the scene which is displaying applet.
void newStatus(Plasma::ItemStatus status)
Emitted when the applet status changes.
virtual FormFactor formFactor() const
Returns the current form factor the applet is being displayed in.
The applet is no wider (in horizontal formfactors) or no higher (in vertical ones) than a square...
Applet(QGraphicsItem *parent=0, const QString &serviceId=QString(), uint appletId=0)
virtual void constraintsEvent(Plasma::Constraints constraints)
Type containmentType() const
Returns the type of containment.
void publish(Plasma::AnnouncementMethods methods, const QString &resourceName)
Publishes and optionally announces this applet on the network for remote access.
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Reimplemented from QGraphicsLayoutItem.
void setText(const QString &text)
Sets the display text for this Label.
void geometryChanged()
Emitted whenever the applet makes a geometry change, so that views can coordinate themselves with the...
On the planar desktop layer, extending across the full screen from edge to edge.
static QStringList listCategories(const QString &parentApp=QString(), bool visibleOnly=true)
Returns a list of all the categories used by installed applets.
the immutability (locked) nature of the applet changed
void setCustomCategories(const QStringList &categories)
Sets the list of custom categories that are used in addition to the default set of categories known t...
virtual void saveState(KConfigGroup &config) const
When called, the Applet should write any information needed as part of the Applet's running state to ...
KPluginInfo::List listAppletInfo(const QString &category, const QString &parentApp=QString())
Returns a list of all known applets.
Abstract representation of a single animation.
Provides an SVG with borders.
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Reimplemented from QGraphicsLayoutItem.
KUrl::List associatedApplicationUrls() const
The applet is always a square.
Not drawing a background under the applet, the applet has its own implementation. ...
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Reimplemented from QGraphicsItem.
AppletScript * loadScriptEngine(const QString &language, Applet *applet)
Loads an Applet script engine for the given language.
The applet is constrained vertically, but can expand horizontally.
void setHasConfigurationInterface(bool hasInterface)
Sets whether or not this applet provides a user interface for configuring the applet.
static AuthorizationManager * self()
Singleton pattern accessor.
bool configurationRequired() const
virtual void paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
This method is called when the interface should be painted.
The item can be modified in any way.
void destroy()
Destroys the extender item.
virtual void configChanged()
Called when applet configuration values have changed.
ImmutabilityType immutability() const
The standard background from the theme is drawn.
QString associatedApplication() const
QPoint popupPosition(const QGraphicsItem *item, const QSize &size)
Recommended position for a popup window like a menu or a tooltip given its size.
void setGlobalShortcut(const KShortcut &shortcut)
Sets the global shorcut to associate with this widget.
KSharedConfig::Ptr config() const
Returns the config file used to store the configuration for this Corona.
bool shouldConserveResources() const
Whether the applet should conserve resources.
A dialog that uses the Plasma style.
virtual void createConfigurationInterface(KConfigDialog *parent)
Reimplement this method so provide a configuration interface, parented to the supplied widget...
static PackageStructure::Ptr packageStructure()
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
A QGraphicsView for a single Containment.
QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
Returns a nicely rounded rectanglular path for painting.
void registerAsDragHandle(QGraphicsItem *item)
Register the widgets that manage mouse clicks but you still want to be able to drag the applet around...
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
void unregisterAsDragHandle(QGraphicsItem *item)
Unregister a widget registered with registerAsDragHandle.
static KPluginInfo::List listAppletInfo(const QString &category=QString(), const QString &parentApp=QString())
Returns a list of all known applets.
Provides a plasma-themed QLabel.
void lower()
Causes this applet to lower below all the other applets.
void setStatus(const ItemStatus stat)
sets the status for this applet
static KPluginInfo::List listAppletInfoForMimetype(const QString &mimetype)
Returns a list of all known applets associated with a certain mimetype.
KShortcut globalShortcut() const
KSharedPtr< PackageStructure > Ptr
void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
Data provider for plasmoids (Plasma plugins)
void setImmutability(const ImmutabilityType immutable)
Sets the immutability type for this applet (not immutable, user immutable or system immutable) ...
FormFactor
The FormFactor enumeration describes how a Plasma::Applet should arrange itself.
The applet keeps a fixed aspect ratio.
void runAssociatedApplication()
Open the application associated to this applet, if it's not set but some urls are, open those urls with the proper application for their mimetype.
Containment * containment() const
virtual void removeAssociatedWidget(QWidget *widget)
un-associate actions from this widget, including ones added after this call.
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint=QSizeF()) const
Reimplemented from QGraphicsLayoutItem.
object representing an installed Plasmagik package
Q_INVOKABLE DataEngine * dataEngine(const QString &name) const
Loads the given DataEngine.
void raise()
Causes this applet to raise above all other applets.
Direction locationToDirection(Location location)
Converts a location to a direction.
QPainterPath shape() const
Reimplemented from QGraphicsItem.
QString icon() const
Returns the icon related to this applet.
The FormFactor for an object.
QVariantList startupArguments() const
Applet * loadApplet(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
Load an Applet plugin.
static QScriptValue toString(QScriptContext *ctx, QScriptEngine *eng)
Plasma::AspectRatioMode aspectRatioMode() const
Direction locationToInverseDirection(Location location)
Converts a location to the direction facing it.
static KPluginInfo::List listAppletInfoForUrl(const QUrl &url)
Returns a list of all known applets associated with a certain URL.
static Applet * loadPlasmoid(const QString &path, uint appletId=0, const QVariantList &args=QVariantList())
Attempts to load an applet from a package.
void focusInEvent(QFocusEvent *event)
Reimplemented from QGraphicsItem.
void resizeEvent(QGraphicsSceneResizeEvent *event)
Reimplemented from QGraphicsItem.
void setConfigurationRequired(bool needsConfiguring, const QString &reason=QString())
When the applet needs to be configured before being usable, this method can be called to show a stand...
specify that this rule is valid for all users
KConfigGroup config() const
Returns the KConfigGroup to access the applets configuration.
void setFailedToLaunch(bool failed, const QString &reason=QString())
Call this method when the applet fails to launch properly.
The applet lives in a plane and has two degrees of freedom to grow.
QGraphicsView * view() const
Returns the view this widget is visible on, or 0 if none can be found.
QRect mapToView(const QGraphicsView *view, const QRectF &rect) const
Maps a QRectF from local coordinates to a view's coordinates.
Plasma::Applet based plugins.
bool isRegisteredAsDragHandle(QGraphicsItem *item)
void extenderItemRestored(Plasma::ExtenderItem *item)
Emitted when an ExtenderItem in a scripting applet needs to be initialized.
access for messages matching this rule is allowed.
virtual bool isPopupShowing() const
QString category() const
Returns the category the applet is in, as specified in the .desktop file.
QPoint popupPosition(const QSize &s) const
Reccomended position for a popup window like a menu or a tooltip given its size.
KConfigGroup globalConfig() const
Returns a KConfigGroup object to be shared by all applets of this type.
void setBackgroundHints(const BackgroundHints hints)
Sets the BackgroundHints for this applet.
static Theme * defaultTheme()
Singleton pattern accessor.
void updateConstraints(Plasma::Constraints constraints=Plasma::AllConstraints)
Called when any of the geometry constraints have been updated.
QString name() const
Returns the user-visible name for the applet, as specified in the .desktop file.
void setAssociatedApplicationUrls(const KUrl::List &urls)
Sets a list of urls associated to this application, they will be used as parameters for the associate...
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
Extender * extender() const
void showMessage(const QIcon &icon, const QString &message, const Plasma::MessageButtons buttons)
Shows a message as an overlay of the applet: the message has an icon, text and (optional) buttons...
virtual void save(KConfigGroup &group) const
Saves state information about this applet that will be accessed when next instantiated in the restore...
void immutabilityChanged(Plasma::ImmutabilityType immutable)
Emitted when the immutability changes.
Announcements via ZeroConf.
int type() const
Reimplemented from QGraphicsItem.
virtual void addAssociatedWidget(QWidget *widget)
associate actions with this widget, including ones added after this call.
ItemStatus status() const
BackgroundHints backgroundHints() const
void setAspectRatioMode(Plasma::AspectRatioMode)
Sets the preferred aspect ratio mode for placement and resizing.
bool hasFailedToLaunch() const
If for some reason, the applet fails to get up on its feet (the library couldn't be loaded...
Q_INVOKABLE QColor color(ColorRole role) const
Returns the text color to be used by items resting on the background.
bool hasConfigurationInterface() const
void appletDestroyed(Plasma::Applet *applet)
Emitted when the applet is deleted.
bool eventFilter(QObject *o, QEvent *e)
The base class for plugins that provide backgrounds and applet grouping containers.
ImmutabilityType immutability() const
ItemStatus
Status of an applet.
void configNeedsSaving()
Emitted when an applet has changed values in its configuration and wishes for them to be saved at the...
the default background color
friend class AppletPrivate
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
An alternate version of the background is drawn, usually more translucent.
Q_INVOKABLE QAction * action(QString name) const
Returns the QAction with the given name from our collection.
bool isContainment() const
Default settings: both standard background.
virtual void init()
This method is called once the applet is loaded and added to a Corona.
Provides detachable items for an Extender.
bool isUserConfiguring() const
PackageStructure::Ptr packageStructure(const QString &language, ComponentType type)
Loads an appropriate PackageStructure for the given language and type.
Context * context() const
Returns the workspace context which the applet is operating in.
QRect screenRect() const
This method returns screen coordinates for the widget; this method can be somewhat expensive and shou...
void setBusy(bool busy)
Shows a busy indicator that overlays the applet.
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void releaseVisualFocus()
This signal indicates that an application launch, window creation or window focus event was triggered...
No constraint; never passed in to Applet::constraintsEvent on its own.
virtual QList< QAction * > contextualActions()
Returns a list of context-related QAction instances.
QString pluginName() const
Returns the plugin name for the applet.
void setTargetWidget(QGraphicsWidget *widget)
Set the widget on which the animation is to be performed.
A QGraphicsScene for Plasma::Applets.
AspectRatioMode
Defines the aspect ratio used when scaling an applet.
static Applet * load(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
Attempts to load an applet.