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"