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);
1986 d->addPublishPage(dialog);
1994 if (!dialog && d->script) {
1995 d->script->showConfigurationInterface();
1997 }
else if (d->script) {
1998 d->script->showConfigurationInterface();
2000 KConfigDialog *dialog = d->generateGenericConfigDialog();
2001 d->addStandardConfigurationPages(dialog);
2019 QString AppletPrivate::configDialogId()
const
2021 return QString(
"%1settings%2").arg(appletId).arg(q->name());
2024 QString AppletPrivate::configWindowTitle()
const
2026 return i18nc(
"@title:window",
"%1 Settings", q->name());
2029 QSet<QString> AppletPrivate::knownCategories()
2033 QSet<QString> categories = s_customCategories;
2034 categories << QString(I18N_NOOP(
"Accessibility")).toLower()
2035 << QString(I18N_NOOP(
"Application Launchers")).toLower()
2036 << QString(I18N_NOOP(
"Astronomy")).toLower()
2037 << QString(I18N_NOOP(
"Date and Time")).toLower()
2038 << QString(I18N_NOOP(
"Development Tools")).toLower()
2039 << QString(I18N_NOOP(
"Education")).toLower()
2040 << QString(I18N_NOOP(
"Environment and Weather")).toLower()
2041 << QString(I18N_NOOP(
"Examples")).toLower()
2042 << QString(I18N_NOOP(
"File System")).toLower()
2043 << QString(I18N_NOOP(
"Fun and Games")).toLower()
2044 << QString(I18N_NOOP(
"Graphics")).toLower()
2045 << QString(I18N_NOOP(
"Language")).toLower()
2046 << QString(I18N_NOOP(
"Mapping")).toLower()
2047 << QString(I18N_NOOP(
"Miscellaneous")).toLower()
2048 << QString(I18N_NOOP(
"Multimedia")).toLower()
2049 << QString(I18N_NOOP(
"Online Services")).toLower()
2050 << QString(I18N_NOOP(
"Productivity")).toLower()
2051 << QString(I18N_NOOP(
"System Information")).toLower()
2052 << QString(I18N_NOOP(
"Utilities")).toLower()
2053 << QString(I18N_NOOP(
"Windows and Tasks")).toLower();
2057 KConfigDialog *AppletPrivate::generateGenericConfigDialog()
2060 KConfigDialog *dialog =
new AppletConfigDialog(0, configDialogId(), nullManager);
2061 nullManager->setParent(dialog);
2062 dialog->setFaceType(KPageDialog::Auto);
2063 dialog->setWindowTitle(configWindowTitle());
2064 dialog->setAttribute(Qt::WA_DeleteOnClose,
true);
2065 q->createConfigurationInterface(dialog);
2066 dialog->showButton(KDialog::Default,
false);
2067 dialog->showButton(KDialog::Help,
false);
2068 QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()));
2069 QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()));
2073 void AppletPrivate::addStandardConfigurationPages(KConfigDialog *dialog)
2075 addGlobalShortcutsPage(dialog);
2076 addPublishPage(dialog);
2079 void AppletPrivate::addGlobalShortcutsPage(KConfigDialog *dialog)
2081 #ifndef PLASMA_NO_GLOBAL_SHORTCUTS
2087 QVBoxLayout *layout =
new QVBoxLayout(page);
2089 if (!shortcutEditor) {
2090 shortcutEditor =
new KKeySequenceWidget(page);
2091 QObject::connect(shortcutEditor.data(), SIGNAL(keySequenceChanged(QKeySequence)), dialog, SLOT(settingsModified()));
2094 shortcutEditor.data()->setKeySequence(q->globalShortcut().primary());
2095 layout->addWidget(shortcutEditor.data());
2096 layout->addStretch();
2097 dialog->addPage(page, i18n(
"Keyboard Shortcut"),
"preferences-desktop-keyboard");
2099 QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
2100 QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
2104 void AppletPrivate::addPublishPage(KConfigDialog *dialog)
2106 #ifdef ENABLE_REMOTE_WIDGETS
2108 publishUI.setupUi(page);
2109 publishUI.publishCheckbox->setChecked(q->isPublished());
2110 QObject::connect(publishUI.publishCheckbox, SIGNAL(clicked(
bool)), dialog, SLOT(settingsModified()));
2111 publishUI.allUsersCheckbox->setEnabled(q->isPublished());
2112 QObject::connect(publishUI.allUsersCheckbox, SIGNAL(clicked(
bool)), dialog, SLOT(settingsModified()));
2114 QString resourceName =
2115 i18nc(
"%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
2116 "%1 on %2", q->name(), QHostInfo::localHostName());
2118 publishUI.allUsersCheckbox->setChecked(
true);
2120 publishUI.allUsersCheckbox->setChecked(
false);
2123 q->connect(publishUI.publishCheckbox, SIGNAL(stateChanged(
int)),
2124 q, SLOT(publishCheckboxStateChanged(
int)));
2125 dialog->addPage(page, i18n(
"Share"),
"applications-internet");
2129 void AppletPrivate::publishCheckboxStateChanged(
int state)
2131 if (state == Qt::Checked) {
2132 publishUI.allUsersCheckbox->setEnabled(
true);
2134 publishUI.allUsersCheckbox->setEnabled(
false);
2138 void AppletPrivate::configDialogFinished()
2140 if (shortcutEditor) {
2141 QKeySequence sequence = shortcutEditor.data()->keySequence();
2142 if (sequence != q->globalShortcut().primary()) {
2143 q->setGlobalShortcut(KShortcut(sequence));
2144 emit q->configNeedsSaving();
2148 #ifdef ENABLE_REMOTE_WIDGETS
2149 if (KConfigDialog::exists(configDialogId()) && publishUI.publishCheckbox) {
2150 q->config().writeEntry(
"Share", publishUI.publishCheckbox->isChecked());
2152 if (publishUI.publishCheckbox->isChecked()) {
2153 QString resourceName =
2154 i18nc(
"%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
2155 "%1 on %2", q->name(), QHostInfo::localHostName());
2157 if (publishUI.allUsersCheckbox->isChecked()) {
2159 AuthorizationRule *rule =
new AuthorizationRule(resourceName,
"");
2165 AuthorizationRule *matchingRule =
2177 if (!configLoader) {
2179 propagateConfigChanged();
2180 if (KConfigDialog *dialog = qobject_cast<KConfigDialog *>(q->sender())) {
2181 dialog->enableButton(KDialog::Apply,
false);
2186 void AppletPrivate::updateShortcuts()
2191 QList<QString> names;
2192 QList<QAction*> qactions;
2193 names <<
"add sibling containment" <<
"configure shortcuts" <<
"lock widgets";
2194 foreach (
const QString &
name, names) {
2195 QAction *a = actions->action(name);
2196 actions->takeAction(a);
2200 actions->readSettings();
2202 for (
int i = 0; i < names.size(); ++i) {
2203 QAction *a = qactions.at(i);
2205 actions->addAction(names.at(i), a);
2209 actions->readSettings();
2213 void AppletPrivate::propagateConfigChanged()
2218 c->d->configChanged();
2228 if (d->configLoader) {
2229 d->configLoader->readConfig();
2231 d->script->configChanged();
2244 KConfigGroup constraintGroup(KGlobal::config(),
"Constraints");
2245 return constraintGroup.readEntry(constraint,
true);
2250 AssociatedApplicationManager::self()->setApplication(
this,
string);
2252 QAction *runAssociatedApplication = d->actions->action(
"run associated application");
2253 if (runAssociatedApplication) {
2254 bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2256 runAssociatedApplication->setVisible(valid);
2257 runAssociatedApplication->setEnabled(valid);
2263 AssociatedApplicationManager::self()->setUrls(
this, urls);
2265 QAction *runAssociatedApplication = d->actions->action(
"run associated application");
2266 if (runAssociatedApplication) {
2267 bool valid = AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2269 runAssociatedApplication->setVisible(valid);
2270 runAssociatedApplication->setEnabled(valid);
2276 return AssociatedApplicationManager::self()->application(
this);
2281 return AssociatedApplicationManager::self()->urls(
this);
2287 AssociatedApplicationManager::self()->run(
this);
2293 return AssociatedApplicationManager::self()->appletHasValidAssociatedApplication(
this);
2296 void AppletPrivate::filterOffers(QList<KService::Ptr> &offers)
2298 KConfigGroup constraintGroup(KGlobal::config(),
"Constraints");
2299 foreach (
const QString &key, constraintGroup.keyList()) {
2301 if (constraintGroup.readEntry(key,
true)) {
2306 QMutableListIterator<KService::Ptr> it(offers);
2307 while (it.hasNext()) {
2308 KService::Ptr p = it.next();
2309 QString prop = QString(
"X-Plasma-Requires-").append(key);
2310 QVariant req = p->property(prop, QVariant::String);
2313 if (req.isValid()) {
2314 reqValue = req.toString();
2315 }
else if (p->property(
"X-Plasma-API").toString().toLower() ==
"javascript") {
2318 reqValue =
"Unused";
2321 if (!(reqValue ==
"Optional" || reqValue ==
"Unused")) {
2329 QString AppletPrivate::parentAppConstraint(
const QString &parentApp)
2331 if (parentApp.isEmpty()) {
2332 return QString(
"((not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '') or [X-KDE-ParentApp] == '%1')")
2333 .arg(KGlobal::mainComponent().aboutData()->appName());
2336 return QString(
"[X-KDE-ParentApp] == '%1'").arg(parentApp);
2346 QString constraint = AppletPrivate::parentAppConstraint();
2347 constraint.append(QString(
" and '%1' in [X-Plasma-DropMimeTypes]").arg(mimetype));
2349 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2350 AppletPrivate::filterOffers(offers);
2351 return KPluginInfo::fromServices(offers);
2356 QString constraint = AppletPrivate::parentAppConstraint();
2357 constraint.append(
" and exist [X-Plasma-DropUrlPatterns]");
2358 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2359 AppletPrivate::filterOffers(offers);
2361 KPluginInfo::List allApplets = KPluginInfo::fromServices(offers);
2362 KPluginInfo::List filtered;
2363 foreach (
const KPluginInfo &info, allApplets) {
2364 QStringList urlPatterns = info.property(
"X-Plasma-DropUrlPatterns").toStringList();
2365 foreach (
const QString &glob, urlPatterns) {
2367 rx.setPatternSyntax(QRegExp::Wildcard);
2368 if (rx.exactMatch(url.toString())) {
2369 kDebug() << info.name() <<
"matches" << glob << url;
2380 QString constraint = AppletPrivate::parentAppConstraint(parentApp);
2381 constraint.append(
" and exist [X-KDE-PluginInfo-Category]");
2383 KConfigGroup group(KGlobal::config(),
"General");
2384 const QStringList excluded = group.readEntry(
"ExcludeCategories", QStringList());
2385 foreach (
const QString &
category, excluded) {
2386 constraint.append(
" and [X-KDE-PluginInfo-Category] != '").append(category).append(
"'");
2389 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Applet", constraint);
2390 AppletPrivate::filterOffers(offers);
2392 QStringList categories;
2393 QSet<QString> known = AppletPrivate::knownCategories();
2394 foreach (
const KService::Ptr &applet, offers) {
2395 QString appletCategory = applet->property(
"X-KDE-PluginInfo-Category").toString();
2396 if (visibleOnly && applet->noDisplay()) {
2402 if (!appletCategory.isEmpty() && !known.contains(appletCategory.toLower())) {
2403 kDebug() <<
"Unknown category: " << applet->name() <<
"says it is in the"
2404 << appletCategory <<
"category which is unknown to us";
2405 appletCategory.clear();
2408 if (appletCategory.isEmpty()) {
2409 if (!categories.contains(i18nc(
"misc category",
"Miscellaneous"))) {
2410 categories << i18nc(
"misc category",
"Miscellaneous");
2412 }
else if (!categories.contains(appletCategory)) {
2413 categories << appletCategory;
2423 AppletPrivate::s_customCategories = QSet<QString>::fromList(categories);
2428 return AppletPrivate::s_customCategories.toList();
2433 if (QFile::exists(path +
"/metadata.desktop")) {
2434 KService service(path +
"/metadata.desktop");
2435 const QStringList& types = service.serviceTypes();
2437 if (types.contains(
"Plasma/Containment")) {
2439 }
else if (types.contains(
"Plasma/PopupApplet")) {
2442 return new Applet(path, appletId, args);
2456 if (!info.isValid()) {
2460 return load(info.pluginName(), appletId, args);
2465 QVariant ret = QGraphicsWidget::itemChange(change, value);
2469 case ItemSceneHasChanged: {
2476 case ItemParentChange:
2477 if (!d->isContainment) {
2479 if (d->mainConfig && !c) {
2480 kWarning() <<
"Configuration object was requested prior to init(), which is too early. "
2481 "Please fix this item:" << parentItem() << value.value<QGraphicsItem *>()
2484 Applet *newC =
dynamic_cast<Applet*
>(value.value<QGraphicsItem *>());
2489 KConfigGroup *old = d->mainConfig;
2490 KConfigGroup appletConfig = newC->
config();
2491 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2492 d->mainConfig =
new KConfigGroup(&appletConfig, QString::number(d->appletId));
2493 old->copyTo(d->mainConfig);
2500 case ItemParentHasChanged:
2503 removeSceneEventFilter(
this);
2507 installSceneEventFilter(
this);
2509 removeSceneEventFilter(
this);
2514 case ItemPositionHasChanged:
2517 case ItemTransformHasChanged:
2518 d->scheduleModificationNotification();
2530 return d->script->shape();
2533 return QGraphicsWidget::shape();
2538 QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
2542 if (which == Qt::MinimumSize) {
2553 hint.setWidth(size().height());
2555 hint.setHeight(size().width());
2560 hint.setWidth(size().height());
2562 }
else if (ff ==
Vertical && (which == Qt::MaximumSize || size().width() <= KIconLoader::SizeLarge)) {
2563 hint.setHeight(size().width());
2583 d->constraintsTimer.stop();
2584 d->busyWidgetTimer.stop();
2585 if (d->modificationsTimer) {
2586 d->modificationsTimer->stop();
2591 if (event->timerId() == d->constraintsTimer.timerId()) {
2592 d->constraintsTimer.stop();
2599 }
else if (d->modificationsTimer && event->timerId() == d->modificationsTimer->timerId()) {
2600 d->modificationsTimer->stop();
2606 }
else if (event->timerId() == d->busyWidgetTimer.timerId()) {
2607 if (!d->busyWidget) {
2608 d->createMessageOverlay(
false);
2609 d->messageOverlay->opacity = 0;
2611 QGraphicsLinearLayout *mainLayout =
new QGraphicsLinearLayout(d->messageOverlay);
2613 d->busyWidget->setAcceptHoverEvents(
false);
2614 d->busyWidget->setAcceptedMouseButtons(Qt::NoButton);
2615 d->messageOverlay->setAcceptHoverEvents(
false);
2616 d->messageOverlay->setAcceptedMouseButtons(Qt::NoButton);
2618 mainLayout->addStretch();
2619 mainLayout->addItem(d->busyWidget);
2620 mainLayout->addStretch();
2630 QPointF bottomRight = pos();
2631 bottomRight.rx() += size().width();
2632 bottomRight.ry() += size().height();
2634 QPoint tL = v->mapToGlobal(v->mapFromScene(pos()));
2635 QPoint bR = v->mapToGlobal(v->mapFromScene(bottomRight));
2636 return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
2641 return QRect(QPoint(0, 0), QSize(0, 0));
2646 setZValue(++AppletPrivate::s_maxZValue);
2651 setZValue(--AppletPrivate::s_minZValue);
2654 void AppletPrivate::setIsContainment(
bool nowIsContainment,
bool forceUpdate)
2670 c->d->checkContainmentFurniture();
2676 return d->isContainment;
2681 AppletPrivate::AppletPrivate(KService::Ptr service,
const KPluginInfo *info,
int uniqueID,
Applet *applet)
2682 : appletId(uniqueID),
2689 appletDescription(info ? *info : KPluginInfo(service)),
2694 messageOverlayProxy(0),
2700 activationAction(0),
2702 preferredSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored),
2703 modificationsTimer(0),
2711 if (appletId == 0) {
2712 appletId = ++s_maxAppletId;
2713 }
else if (appletId > s_maxAppletId) {
2714 s_maxAppletId = appletId;
2717 publishUI.publishCheckbox = 0;
2720 AppletPrivate::~AppletPrivate()
2722 if (activationAction && activationAction->isGlobalShortcutEnabled()) {
2724 activationAction->forgetGlobalShortcut();
2727 delete extender.data();
2733 delete configLoader;
2737 delete modificationsTimer;
2740 void AppletPrivate::init(
const QString &packagePath)
2744 q->setCacheMode(Applet::DeviceCoordinateCache);
2745 q->setAcceptsHoverEvents(
true);
2746 q->setFlag(QGraphicsItem::ItemIsFocusable,
true);
2747 q->setFocusPolicy(Qt::ClickFocus);
2750 q->setLayoutDirection(qApp->layoutDirection());
2753 QSize size(200, 200);
2755 q->setHasConfigurationInterface(
true);
2757 QAction *closeApplet = actions->action(
"remove");
2759 closeApplet->setText(i18nc(
"%1 is the name of the applet",
"Remove this %1", q->name()));
2762 QAction *configAction = actions->action(
"configure");
2764 configAction->setText(i18nc(
"%1 is the name of the applet",
"%1 Settings", q->name()));
2767 QObject::connect(q, SIGNAL(activate()), q, SLOT(setFocus()));
2768 if (!appletDescription.isValid()) {
2769 kDebug() <<
"Check your constructor! "
2770 <<
"You probably want to be passing in a Service::Ptr "
2771 <<
"or a QVariantList with a valid storageid as arg[0].";
2776 QVariant s = appletDescription.property(
"X-Plasma-DefaultSize");
2783 QString api = appletDescription.property(
"X-Plasma-API").toString();
2786 if (!api.isEmpty()) {
2788 QString path = packagePath.isEmpty() ? appletDescription.pluginName() : packagePath;
2791 package = new Package(path, structure);
2794 if (package->isValid()) {
2803 q->setFailedToLaunch(
true,
2804 i18nc(
"API or programming language the widget was written in, name of the widget",
2805 "Could not create a %1 ScriptEngine for the %2 widget.",
2806 api, appletDescription.name()));
2809 q->setFailedToLaunch(
true, i18nc(
"Package file, name of the widget",
2810 "Could not open the %1 package required for the %2 widget.",
2811 appletDescription.pluginName(), appletDescription.name()));
2820 void AppletPrivate::setupScriptSupport()
2826 kDebug() <<
"setting up script support, package is in" << package->path()
2827 <<
"which is a" << package->structure()->type() <<
"package"
2828 <<
", main script is" << package->filePath(
"mainscript");
2830 QString translationsPath = package->filePath(
"translations");
2831 if (!translationsPath.isEmpty()) {
2834 KGlobal::dirs()->addResourceDir(
"locale", translationsPath);
2835 KGlobal::locale()->insertCatalog(package->metadata().pluginName());
2838 QString xmlPath = package->filePath(
"mainconfigxml");
2839 if (!xmlPath.isEmpty()) {
2840 QFile file(xmlPath);
2841 KConfigGroup config = q->config();
2843 QObject::connect(configLoader, SIGNAL(configChanged()), q, SLOT(propagateConfigChanged()));
2846 if (!package->filePath(
"mainconfigui").isEmpty()) {
2847 q->setHasConfigurationInterface(
true);
2851 QString AppletPrivate::globalName()
const
2853 if (!appletDescription.isValid()) {
2857 return appletDescription.service()->library();
2860 QString AppletPrivate::instanceName()
2862 if (!appletDescription.isValid()) {
2866 return appletDescription.service()->library() + QString::number(appletId);
2869 void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
2874 constraintsTimer.start(0, q);
2881 pendingConstraints |= c;
2884 void AppletPrivate::scheduleModificationNotification()
2887 if (modificationsTimer) {
2889 if (modificationsTimer->isActive()) {
2890 modificationsTimer->stop();
2893 modificationsTimer->start(1000, q);
2897 KConfigGroup *AppletPrivate::mainConfigGroup()
2903 bool newGroup =
false;
2904 if (isContainment) {
2905 Corona *corona = qobject_cast<Corona*>(q->scene());
2906 KConfigGroup containmentConfig;
2910 containmentConfig = KConfigGroup(corona->config(),
"Containments");
2912 containmentConfig = KConfigGroup(KGlobal::config(),
"Containments");
2915 if (package && !containmentConfig.hasGroup(QString::number(appletId))) {
2919 mainConfig =
new KConfigGroup(&containmentConfig, QString::number(appletId));
2921 KConfigGroup appletConfig;
2923 Containment *c = q->containment();
2924 Applet *parentApplet = qobject_cast<Applet *>(q->parent());
2925 if (parentApplet && parentApplet != static_cast<Applet *>(c)) {
2928 appletConfig = parentApplet->config();
2929 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2932 appletConfig = c->config();
2933 appletConfig = KConfigGroup(&appletConfig,
"Applets");
2935 kWarning() <<
"requesting config for" << q->name() <<
"without a containment!";
2936 appletConfig = KConfigGroup(KGlobal::config(),
"Applets");
2939 if (package && !appletConfig.hasGroup(QString::number(appletId))) {
2943 mainConfig =
new KConfigGroup(&appletConfig, QString::number(appletId));
2948 const QString defaultConfigFile = q->package()->filePath(
"defaultconfig");
2949 if (!defaultConfigFile.isEmpty()) {
2950 kDebug() <<
"copying default config: " << q->package()->filePath(
"defaultconfig");
2951 KConfigGroup defaultConfig(KSharedConfig::openConfig(defaultConfigFile)->group(
"Configuration"));
2952 defaultConfig.copyTo(mainConfig);
2959 QString AppletPrivate::visibleFailureText(
const QString &reason)
2963 if (reason.isEmpty()) {
2964 text = i18n(
"This object could not be created.");
2967 r.replace(
'\n',
"<br/>");
2968 text = i18n(
"This object could not be created for the following reason:<p><b>%1</b></p>", r);
2974 void AppletPrivate::themeChanged()
2978 q->setBackgroundHints(backgroundHints);
2984 background->getMargins(left, top, right, bottom);
2985 q->setContentsMargins(left, right, top, bottom);
2990 void AppletPrivate::resetConfigurationObject()
2995 mainConfig->deleteGroup();
2999 Corona * corona = qobject_cast<Corona*>(q->scene());
3001 corona->requireConfigSync();
3005 void AppletPrivate::handleDisappeared(AppletHandle *h)
3007 if (h == handle.data()) {
3010 if (scene && h->scene() == scene) {
3011 scene->removeItem(h);
3017 void ContainmentPrivate::checkRemoveAction()
3019 q->enableAction(
"remove", q->immutability() ==
Mutable);
3023 uint AppletPrivate::s_maxAppletId = 0;
3024 int AppletPrivate::s_maxZValue = 0;
3025 int AppletPrivate::s_minZValue = 0;
3027 QSet<QString> AppletPrivate::s_customCategories;
3033 resize(parent->size());
3036 void AppletOverlayWidget::destroy()
3040 connect(anim, SIGNAL(finished()),
this, SLOT(overlayAnimationComplete()));
3041 anim->setTargetWidget(
this);
3044 overlayAnimationComplete();
3048 void AppletOverlayWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
3053 void AppletOverlayWidget::overlayAnimationComplete()
3056 scene()->removeItem(
this);
3061 void AppletOverlayWidget::paint(QPainter *painter,
3068 if (qFuzzyCompare(1, 1+opacity)) {
3073 wash.setAlphaF(opacity);
3075 Applet *applet = qobject_cast<Applet *>(parentWidget());
3078 QPainterPath backgroundShape;
3081 if (parentWidget()->contentsRect().size() != size()) {
3082 resize(parentWidget()->contentsRect().size());
3086 backgroundShape = shape();
3089 painter->setRenderHints(QPainter::Antialiasing);
3090 painter->fillPath(backgroundShape, wash);
3093 #if QT_VERSION >= 0x040700
3097 emit QGraphicsWidget::geometryChanged();
3103 #include "applet.moc"
3104 #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.