00001 #ifndef APPLET_CPP
00002 #define APPLET_CPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "applet.h"
00025 #include "private/applet_p.h"
00026
00027 #include <cmath>
00028 #include <limits>
00029
00030 #include <QApplication>
00031 #include <QEvent>
00032 #include <QFile>
00033 #include <QGraphicsGridLayout>
00034 #include <QGraphicsSceneMouseEvent>
00035 #include <QGraphicsView>
00036 #include <QLabel>
00037 #include <QList>
00038 #include <QGraphicsLinearLayout>
00039 #include <QPainter>
00040 #include <QSize>
00041 #include <QStyleOptionGraphicsItem>
00042 #include <QTextDocument>
00043 #include <QUiLoader>
00044 #include <QVBoxLayout>
00045 #include <QWidget>
00046
00047 #include <kaction.h>
00048 #include <kactioncollection.h>
00049 #include <kauthorized.h>
00050 #include <kcolorscheme.h>
00051 #include <kconfigdialog.h>
00052 #include <kdialog.h>
00053 #include <kicon.h>
00054 #include <kiconloader.h>
00055 #include <kkeysequencewidget.h>
00056 #include <kplugininfo.h>
00057 #include <kstandarddirs.h>
00058 #include <kservice.h>
00059 #include <kservicetypetrader.h>
00060 #include <kshortcut.h>
00061 #include <kwindowsystem.h>
00062 #include <kpushbutton.h>
00063
00064 #include <solid/powermanagement.h>
00065
00066 #include "configloader.h"
00067 #include "containment.h"
00068 #include "corona.h"
00069 #include "dataenginemanager.h"
00070 #include "extender.h"
00071 #include "extenderitem.h"
00072 #include "package.h"
00073 #include "plasma.h"
00074 #include "scripting/appletscript.h"
00075 #include "svg.h"
00076 #include "framesvg.h"
00077 #include "private/framesvg_p.h"
00078 #include "popupapplet.h"
00079 #include "theme.h"
00080 #include "view.h"
00081 #include "widgets/iconwidget.h"
00082 #include "widgets/label.h"
00083 #include "widgets/pushbutton.h"
00084 #include "widgets/busywidget.h"
00085 #include "tooltipmanager.h"
00086 #include "wallpaper.h"
00087 #include "paintutils.h"
00088
00089 #include "private/containment_p.h"
00090 #include "private/extenderapplet_p.h"
00091 #include "private/packages_p.h"
00092 #include "private/popupapplet_p.h"
00093 #include "private/toolbox_p.h"
00094
00095
00096 namespace Plasma
00097 {
00098
00099 Applet::Applet(QGraphicsItem *parent, const QString &serviceID, uint appletId)
00100 : QGraphicsWidget(parent),
00101 d(new AppletPrivate(KService::serviceByStorageId(serviceID), appletId, this))
00102 {
00103
00104
00105 d->init();
00106 }
00107
00108 Applet::Applet(QGraphicsItem *parent,
00109 const QString &serviceID,
00110 uint appletId,
00111 const QVariantList &args)
00112 : QGraphicsWidget(parent),
00113 d(new AppletPrivate(KService::serviceByStorageId(serviceID), appletId, this))
00114 {
00115
00116
00117
00118 QVariantList &mutableArgs = const_cast<QVariantList &>(args);
00119 if (!mutableArgs.isEmpty()) {
00120 mutableArgs.removeFirst();
00121
00122 if (!mutableArgs.isEmpty()) {
00123 mutableArgs.removeFirst();
00124 }
00125 }
00126
00127 d->args = mutableArgs;
00128
00129 d->init();
00130 }
00131
00132 Applet::Applet(QObject *parentObject, const QVariantList &args)
00133 : QGraphicsWidget(0),
00134 d(new AppletPrivate(
00135 KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()),
00136 args.count() > 1 ? args[1].toInt() : 0, this))
00137 {
00138
00139
00140
00141 QVariantList &mutableArgs = const_cast<QVariantList &>(args);
00142 if (!mutableArgs.isEmpty()) {
00143 mutableArgs.removeFirst();
00144
00145 if (!mutableArgs.isEmpty()) {
00146 mutableArgs.removeFirst();
00147 }
00148 }
00149
00150 d->args = mutableArgs;
00151
00152 setParent(parentObject);
00153
00154
00155
00156 d->init();
00157
00158
00159
00160 }
00161
00162 Applet::~Applet()
00163 {
00164
00165 emit appletDestroyed(this);
00166
00167 if (!d->transient && d->extender) {
00168
00169
00170
00171
00172
00173 d->extender->saveState();
00174
00175 foreach (ExtenderItem *item, d->extender->attachedItems()) {
00176 if (item->autoExpireDelay()) {
00177
00178
00179 item->destroy();
00180 }
00181 }
00182 }
00183
00184
00185 delete KConfigDialog::exists(d->configDialogId());
00186 delete d;
00187 }
00188
00189 PackageStructure::Ptr Applet::packageStructure()
00190 {
00191 if (!AppletPrivate::packageStructure) {
00192 AppletPrivate::packageStructure = new PlasmoidPackage();
00193 }
00194
00195 return AppletPrivate::packageStructure;
00196 }
00197
00198 void Applet::init()
00199 {
00200 if (d->script) {
00201 if (d->package) {
00202 d->setupScriptSupport();
00203 }
00204
00205 if (!d->script->init()) {
00206 setFailedToLaunch(true, i18n("Script initialization failed"));
00207 delete d->script;
00208 d->script = 0;
00209 delete d->package;
00210 d->package = 0;
00211 }
00212 }
00213 }
00214
00215 uint Applet::id() const
00216 {
00217 return d->appletId;
00218 }
00219
00220 void Applet::save(KConfigGroup &g) const
00221 {
00222 if (d->transient) {
00223 return;
00224 }
00225
00226 KConfigGroup group = g;
00227 if (!group.isValid()) {
00228 group = *d->mainConfigGroup();
00229 }
00230
00231
00232
00233
00234 group.writeEntry("immutability", (int)d->immutability);
00235 group.writeEntry("plugin", pluginName());
00236
00237 group.writeEntry("geometry", geometry());
00238 group.writeEntry("zvalue", zValue());
00239
00240 if (!d->started) {
00241 return;
00242 }
00243
00244
00245
00246
00247
00248 if (transform() == QTransform()) {
00249 group.deleteEntry("transform");
00250 } else {
00251 QList<qreal> m;
00252 QTransform t = transform();
00253 m << t.m11() << t.m12() << t.m13() << t.m21() << t.m22() << t.m23() << t.m31() << t.m32() << t.m33();
00254 group.writeEntry("transform", m);
00255
00256 }
00257
00258 KConfigGroup appletConfigGroup(&group, "Configuration");
00259 saveState(appletConfigGroup);
00260
00261 if (d->configLoader) {
00262
00263
00264 disconnect(d->configLoader, SIGNAL(configChanged()), this, SLOT(configChanged()));
00265 d->configLoader->writeConfig();
00266 connect(d->configLoader, SIGNAL(configChanged()), this, SLOT(configChanged()));
00267 }
00268 }
00269
00270 void Applet::restore(KConfigGroup &group)
00271 {
00272 QList<qreal> m = group.readEntry("transform", QList<qreal>());
00273 if (m.count() == 9) {
00274 QTransform t(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
00275 setTransform(t);
00276 }
00277
00278 qreal z = group.readEntry("zvalue", 0);
00279
00280 if (z >= AppletPrivate::s_maxZValue) {
00281 AppletPrivate::s_maxZValue = z;
00282 }
00283
00284 if (z > 0) {
00285 setZValue(z);
00286 }
00287
00288 setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00289
00290 QRectF geom = group.readEntry("geometry", QRectF());
00291 if (geom.isValid()) {
00292 setGeometry(geom);
00293 }
00294
00295 KConfigGroup shortcutConfig(&group, "Shortcuts");
00296 QString shortcutText = shortcutConfig.readEntryUntranslated("global", QString());
00297 if (!shortcutText.isEmpty()) {
00298 setGlobalShortcut(KShortcut(shortcutText));
00299
00300
00301
00302
00303
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 }
00315
00316 void AppletPrivate::setFocus()
00317 {
00318
00319 q->setFocus(Qt::ShortcutFocusReason);
00320 }
00321
00322 void Applet::setFailedToLaunch(bool failed, const QString &reason)
00323 {
00324 if (d->failed == failed) {
00325 if (failed && !reason.isEmpty()) {
00326 foreach (QGraphicsItem *item, QGraphicsItem::children()) {
00327 Label *l = dynamic_cast<Label *>(item);
00328 if (l) {
00329 l->setText(d->visibleFailureText(reason));
00330 }
00331 }
00332 }
00333 return;
00334 }
00335
00336 d->failed = failed;
00337 prepareGeometryChange();
00338
00339 qDeleteAll(QGraphicsItem::children());
00340 setLayout(0);
00341
00342 if (failed) {
00343 setBackgroundHints(d->backgroundHints|StandardBackground);
00344
00345 QGraphicsLinearLayout *failureLayout = new QGraphicsLinearLayout(this);
00346 failureLayout->setContentsMargins(0, 0, 0, 0);
00347
00348 IconWidget *failureIcon = new IconWidget(this);
00349 failureIcon->setIcon(KIcon("dialog-error"));
00350 failureLayout->addItem(failureIcon);
00351
00352 Label *failureWidget = new Plasma::Label(this);
00353 failureWidget->setText(d->visibleFailureText(reason));
00354 QLabel *label = failureWidget->nativeWidget();
00355 label->setWordWrap(true);
00356 failureLayout->addItem(failureWidget);
00357
00358 Plasma::ToolTipManager::self()->registerWidget(failureIcon);
00359 Plasma::ToolTipContent data(i18n("Unable to load the widget"), reason,
00360 KIcon("dialog-error"));
00361 Plasma::ToolTipManager::self()->setContent(failureIcon, data);
00362
00363 setLayout(failureLayout);
00364 resize(300, 250);
00365 setMinimumSize(failureLayout->minimumSize());
00366 d->background->resizeFrame(geometry().size());
00367 }
00368
00369 update();
00370 }
00371
00372 void Applet::saveState(KConfigGroup &group) const
00373 {
00374 if (group.config()->name() != config().config()->name()) {
00375
00376
00377 KConfigGroup c = config();
00378 c.copyTo(&group);
00379 }
00380 }
00381
00382 KConfigGroup Applet::config(const QString &group) const
00383 {
00384 if (d->transient) {
00385 return KConfigGroup(KGlobal::config(), "PlasmaTransientsConfig");
00386 }
00387
00388 KConfigGroup cg = config();
00389 return KConfigGroup(&cg, group);
00390 }
00391
00392 KConfigGroup Applet::config() const
00393 {
00394 if (d->transient) {
00395 return KConfigGroup(KGlobal::config(), "PlasmaTransientsConfig");
00396 }
00397
00398 if (d->isContainment) {
00399 return *(d->mainConfigGroup());
00400 }
00401
00402 return KConfigGroup(d->mainConfigGroup(), "Configuration");
00403 }
00404
00405 KConfigGroup Applet::globalConfig() const
00406 {
00407 KConfigGroup globalAppletConfig;
00408 QString group = isContainment() ? "ContainmentGlobals" : "AppletGlobals";
00409
00410 Corona *corona = qobject_cast<Corona*>(scene());
00411 if (corona) {
00412 KSharedConfig::Ptr coronaConfig = corona->config();
00413 globalAppletConfig = KConfigGroup(coronaConfig, group);
00414 } else {
00415 globalAppletConfig = KConfigGroup(KGlobal::config(), group);
00416 }
00417
00418 return KConfigGroup(&globalAppletConfig, d->globalName());
00419 }
00420
00421 void Applet::destroy()
00422 {
00423 if (immutability() != Mutable || d->transient || !d->started) {
00424 return;
00425 }
00426
00427 d->transient = true;
00428
00429 if (isContainment()) {
00430 d->cleanUpAndDelete();
00431 } else {
00432 connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00433 this, SLOT(appletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00434 Animator::self()->animateItem(this, Animator::DisappearAnimation);
00435 }
00436 }
00437
00438 bool Applet::destroyed() const
00439 {
00440 return d->transient;
00441 }
00442
00443 void AppletPrivate::appletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
00444 {
00445 if (anim != Animator::DisappearAnimation || item != q) {
00446 return;
00447 }
00448
00449 cleanUpAndDelete();
00450 }
00451
00452 void AppletPrivate::selectItemToDestroy()
00453 {
00454
00455 if (isContainment) {
00456 QGraphicsView *view = q->view();
00457 if (view && view->transform().isScaling() &&
00458 q->scene()->focusItem() != q) {
00459 QGraphicsItem *focus = q->scene()->focusItem();
00460
00461 if (focus) {
00462 Containment *toDestroy = dynamic_cast<Containment*>(focus->topLevelItem());
00463
00464 if (toDestroy) {
00465 toDestroy->destroy();
00466 return;
00467 }
00468 }
00469 }
00470 }
00471
00472 q->destroy();
00473 }
00474
00475 void AppletPrivate::updateRect(const QRectF &rect)
00476 {
00477 q->update(rect);
00478 }
00479
00480 void AppletPrivate::cleanUpAndDelete()
00481 {
00482
00483 QGraphicsWidget *parent = dynamic_cast<QGraphicsWidget *>(q->parentItem());
00484
00485
00486
00487
00488
00489 if (parent && parent->layout()) {
00490 QGraphicsLayout *l = parent->layout();
00491 for (int i = 0; i < l->count(); ++i) {
00492 if (q == l->itemAt(i)) {
00493 l->removeAt(i);
00494 break;
00495 }
00496 }
00497 }
00498
00499 if (configLoader) {
00500 configLoader->setDefaults();
00501 }
00502
00503 resetConfigurationObject();
00504
00505 q->scene()->removeItem(q);
00506 q->deleteLater();
00507 }
00508
00509 void AppletPrivate::createMessageOverlay(bool usePopup)
00510 {
00511 if (messageOverlay) {
00512 qDeleteAll(messageOverlay->children());
00513 messageOverlay->setLayout(0);
00514 }
00515
00516 PopupApplet *popup = qobject_cast<Plasma::PopupApplet*>(q);
00517
00518 if (!messageOverlay) {
00519 if (usePopup && popup && popup->widget()) {
00520 messageOverlayProxy = new QGraphicsProxyWidget(q);
00521 messageOverlayProxy->setWidget(popup->widget());
00522 messageOverlay = new AppletOverlayWidget(messageOverlayProxy);
00523 } else if (usePopup && popup && popup->graphicsWidget() &&
00524 popup->graphicsWidget() != extender) {
00525 messageOverlay = new AppletOverlayWidget(popup->graphicsWidget());
00526 } else {
00527 messageOverlay = new AppletOverlayWidget(q);
00528 }
00529 }
00530
00531 if (usePopup && popup && popup->widget()) {
00532
00533 messageOverlay->setGeometry(popup->widget()->contentsRect());
00534 } else if (usePopup && popup && popup->graphicsWidget() &&
00535 popup->graphicsWidget() != extender) {
00536
00537 messageOverlay->setGeometry(popup->graphicsWidget()->boundingRect());
00538 } else {
00539
00540 messageOverlay->setGeometry(q->contentsRect());
00541
00542
00543 int zValue = 100;
00544 foreach (QGraphicsItem *child, q->QGraphicsItem::children()) {
00545 if (child->zValue() > zValue) {
00546 zValue = child->zValue() + 1;
00547 }
00548 }
00549 messageOverlay->setZValue(zValue);
00550 }
00551 }
00552
00553 void AppletPrivate::destroyMessageOverlay()
00554 {
00555
00556 if (!messageOverlay) {
00557 return;
00558 }
00559
00560 messageOverlay->destroy();
00561 messageOverlay = 0;
00562
00563 if (messageOverlayProxy) {
00564 messageOverlayProxy->setWidget(0);
00565 delete messageOverlayProxy;
00566 messageOverlayProxy = 0;
00567 }
00568
00569 MessageButton buttonCode = ButtonNo;
00570
00571 PushButton *button = qobject_cast<PushButton *>(q->sender());
00572 if (button) {
00573 if (button->text() == i18n("Ok")) {
00574 buttonCode = ButtonOk;
00575 }
00576 if (button->text() == i18n("Yes")) {
00577 buttonCode = ButtonYes;
00578 }
00579 if (button->text() == i18n("No")) {
00580 buttonCode = ButtonNo;
00581 }
00582 if (button->text() == i18n("Cancel")) {
00583 buttonCode = ButtonCancel;
00584 }
00585
00586 emit q->messageButtonPressed(buttonCode);
00587 }
00588 }
00589
00590 ConfigLoader *Applet::configScheme() const
00591 {
00592 return d->configLoader;
00593 }
00594
00595 DataEngine *Applet::dataEngine(const QString &name) const
00596 {
00597 return d->dataEngine(name);
00598 }
00599
00600 const Package *Applet::package() const
00601 {
00602 return d->package;
00603 }
00604
00605 QGraphicsView *Applet::view() const
00606 {
00607
00608
00609
00610 if (!scene()) {
00611 return 0;
00612 }
00613
00614 QGraphicsView *found = 0;
00615 QGraphicsView *possibleFind = 0;
00616
00617 foreach (QGraphicsView *view, scene()->views()) {
00618
00619
00620 if (view->sceneRect().intersects(sceneBoundingRect()) ||
00621 view->sceneRect().contains(scenePos())) {
00622
00623 if (view->isActiveWindow()) {
00624 found = view;
00625 } else {
00626 possibleFind = view;
00627 }
00628 }
00629 }
00630
00631 return found ? found : possibleFind;
00632 }
00633
00634 QRectF Applet::mapFromView(const QGraphicsView *view, const QRect &rect) const
00635 {
00636
00637 return mapFromScene(view->mapToScene(rect)).boundingRect().adjusted(0, 0, 1, 1);
00638 }
00639
00640 QRect Applet::mapToView(const QGraphicsView *view, const QRectF &rect) const
00641 {
00642
00643 return view->mapFromScene(mapToScene(rect)).boundingRect().adjusted(0, 0, -1, -1);
00644 }
00645
00646 QPoint Applet::popupPosition(const QSize &s) const
00647 {
00648 Corona * corona = qobject_cast<Corona*>(scene());
00649 Q_ASSERT(corona);
00650 return corona->popupPosition(this, s);
00651 }
00652
00653 void Applet::updateConstraints(Plasma::Constraints constraints)
00654 {
00655 d->scheduleConstraintsUpdate(constraints);
00656 }
00657
00658 void Applet::constraintsEvent(Plasma::Constraints constraints)
00659 {
00660
00661
00662
00663
00664 Q_UNUSED(constraints)
00665
00666
00667 if (d->script) {
00668 d->script->constraintsEvent(constraints);
00669 }
00670 }
00671
00672 void Applet::initExtenderItem(ExtenderItem *item)
00673 {
00674 if (d->script) {
00675 emit extenderItemRestored(item);
00676 } else {
00677 kWarning() << "Missing implementation of initExtenderItem in the applet "
00678 << item->config().readEntry("SourceAppletPluginName", "")
00679 << "!\n Any applet that uses extenders should implement initExtenderItem to "
00680 << "instantiate a widget. Destroying the item...";
00681 item->destroy();
00682 }
00683 }
00684
00685 Extender *Applet::extender() const
00686 {
00687 if (!d->extender) {
00688 new Extender(const_cast<Applet*>(this));
00689 }
00690
00691 return d->extender;
00692 }
00693
00694 void Applet::setBusy(bool busy)
00695 {
00696 if (busy) {
00697 if (!d->busyWidget) {
00698 d->createMessageOverlay(false);
00699 d->messageOverlay->opacity = 0;
00700
00701 QGraphicsLinearLayout *mainLayout = new QGraphicsLinearLayout(d->messageOverlay);
00702 d->busyWidget = new Plasma::BusyWidget(d->messageOverlay);
00703 d->busyWidget->setAcceptHoverEvents(false);
00704 d->busyWidget->setAcceptedMouseButtons(Qt::NoButton);
00705 d->messageOverlay->setAcceptHoverEvents(false);
00706
00707 mainLayout->addStretch();
00708 mainLayout->addItem(d->busyWidget);
00709 mainLayout->addStretch();
00710 }
00711 } else if (d->busyWidget) {
00712
00713 d->busyWidget = 0;
00714 d->destroyMessageOverlay();
00715 }
00716 }
00717
00718 bool Applet::isBusy() const
00719 {
00720 return d->busyWidget && d->busyWidget->isVisible();
00721 }
00722
00723 QString Applet::name() const
00724 {
00725 if (d->isContainment) {
00726 if (!d->appletDescription.isValid()) {
00727 return i18n("Unknown Activity");
00728 }
00729
00730 const Containment *c = qobject_cast<const Containment*>(this);
00731 if (c && !c->activity().isNull()) {
00732 return i18n("%1 Activity", c->activity());
00733 }
00734 } else if (!d->appletDescription.isValid()) {
00735 return i18n("Unknown Widget");
00736 }
00737
00738 return d->appletDescription.name();
00739 }
00740
00741 QFont Applet::font() const
00742 {
00743 return QApplication::font();
00744 }
00745
00746 QString Applet::icon() const
00747 {
00748 if (!d->appletDescription.isValid()) {
00749 return QString();
00750 }
00751
00752 return d->appletDescription.icon();
00753 }
00754
00755 QString Applet::pluginName() const
00756 {
00757 if (!d->appletDescription.isValid()) {
00758 return QString();
00759 }
00760
00761 return d->appletDescription.pluginName();
00762 }
00763
00764 bool Applet::shouldConserveResources() const
00765 {
00766 return Solid::PowerManagement::appShouldConserveResources();
00767 }
00768
00769 QString Applet::category() const
00770 {
00771 if (!d->appletDescription.isValid()) {
00772 return i18nc("misc category", "Miscellaneous");
00773 }
00774
00775 return d->appletDescription.category();
00776 }
00777
00778 QString Applet::category(const KPluginInfo &applet)
00779 {
00780 return applet.property("X-KDE-PluginInfo-Category").toString();
00781 }
00782
00783 QString Applet::category(const QString &appletName)
00784 {
00785 if (appletName.isEmpty()) {
00786 return QString();
00787 }
00788
00789 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
00790 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
00791
00792 if (offers.isEmpty()) {
00793 offers = KServiceTypeTrader::self()->query("Plasma/PopupApplet", constraint);
00794 }
00795
00796 if (offers.isEmpty()) {
00797 return QString();
00798 }
00799
00800 return offers.first()->property("X-KDE-PluginInfo-Category").toString();
00801 }
00802
00803 ImmutabilityType Applet::immutability() const
00804 {
00805
00806 ImmutabilityType coronaImmutability = Mutable;
00807
00808 if (qobject_cast<Corona*>(scene())) {
00809 coronaImmutability = static_cast<Corona*>(scene())->immutability();
00810 }
00811
00812 if (coronaImmutability == SystemImmutable) {
00813 return SystemImmutable;
00814 } else if (coronaImmutability == UserImmutable && d->immutability != SystemImmutable) {
00815 return UserImmutable;
00816 } else {
00817 return d->immutability;
00818 }
00819 }
00820
00821 void Applet::setImmutability(const ImmutabilityType immutable)
00822 {
00823 if (d->immutability == immutable) {
00824 return;
00825 }
00826
00827 d->immutability = immutable;
00828 updateConstraints(ImmutableConstraint);
00829 }
00830
00831 Applet::BackgroundHints Applet::backgroundHints() const
00832 {
00833 return d->backgroundHints;
00834 }
00835
00836 void Applet::setBackgroundHints(const BackgroundHints hints)
00837 {
00838 if (d->backgroundHints == hints) {
00839 return;
00840 }
00841
00842 d->backgroundHints = hints;
00843 d->preferredBackgroundHints = hints;
00844
00845
00846 if ((hints & StandardBackground) || (hints & TranslucentBackground)) {
00847 if (!d->background) {
00848 d->background = new Plasma::FrameSvg(this);
00849 }
00850
00851 if ((hints & TranslucentBackground) &&
00852 Plasma::Theme::defaultTheme()->currentThemeHasImage("widgets/translucentbackground")) {
00853 d->background->setImagePath("widgets/translucentbackground");
00854 } else {
00855 d->background->setImagePath("widgets/background");
00856 }
00857
00858 d->background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
00859 qreal left, top, right, bottom;
00860 d->background->getMargins(left, top, right, bottom);
00861 setContentsMargins(left, right, top, bottom);
00862 QSizeF fitSize(left + right, top + bottom);
00863 if (minimumSize().expandedTo(fitSize) != minimumSize()) {
00864 setMinimumSize(minimumSize().expandedTo(fitSize));
00865 }
00866 d->background->resizeFrame(boundingRect().size());
00867
00868
00869
00870 if (d->background->hasElement("overlay")) {
00871 QSize overlaySize = d->background->elementSize("overlay");
00872
00873
00874 qsrand(id());
00875 d->background->d->overlayPos.rx() = - (overlaySize.width() /2) + (overlaySize.width() /4) * (qrand() % (4 + 1));
00876 d->background->d->overlayPos.ry() = (- (overlaySize.height() /2) + (overlaySize.height() /4) * (qrand() % (4 + 1)))/2;
00877 }
00878
00879 } else if (d->background) {
00880 qreal left, top, right, bottom;
00881 d->background->getMargins(left, top, right, bottom);
00882
00883
00884 setMinimumSize(qMax(minimumSize().width() - left - right, qreal(1.0)),
00885 qMax(minimumSize().height() - top - bottom, qreal(1.0)));
00886
00887 delete d->background;
00888 d->background = 0;
00889 setContentsMargins(0, 0, 0, 0);
00890 }
00891
00892 update();
00893 }
00894
00895 bool Applet::hasFailedToLaunch() const
00896 {
00897 return d->failed;
00898 }
00899
00900 void Applet::paintWindowFrame(QPainter *painter,
00901 const QStyleOptionGraphicsItem *option, QWidget *widget)
00902 {
00903 Q_UNUSED(painter)
00904 Q_UNUSED(option)
00905 Q_UNUSED(widget)
00906
00907
00908
00909 }
00910
00911 bool Applet::configurationRequired() const
00912 {
00913 return d->needsConfig;
00914 }
00915
00916 void Applet::setConfigurationRequired(bool needsConfig, const QString &reason)
00917 {
00918 if (d->needsConfig == needsConfig) {
00919 return;
00920 }
00921
00922 d->needsConfig = needsConfig;
00923
00924 if (!needsConfig) {
00925 d->destroyMessageOverlay();
00926 return;
00927 }
00928
00929 d->createMessageOverlay(true);
00930 d->messageOverlay->opacity = 0.4;
00931
00932 QGraphicsGridLayout *configLayout = new QGraphicsGridLayout(d->messageOverlay);
00933 configLayout->setContentsMargins(0, 0, 0, 0);
00934
00935
00936 configLayout->setColumnStretchFactor(0, 5);
00937 configLayout->setColumnStretchFactor(2, 5);
00938 configLayout->setRowStretchFactor(0, 5);
00939 configLayout->setRowStretchFactor(3, 5);
00940
00941 int row = 1;
00942 if (!reason.isEmpty()) {
00943 Label *explanation = new Label(d->messageOverlay);
00944 explanation->setText(reason);
00945 configLayout->addItem(explanation, row, 1);
00946 configLayout->setColumnStretchFactor(1, 5);
00947 ++row;
00948 configLayout->setAlignment(explanation, Qt::AlignBottom | Qt::AlignCenter);
00949 }
00950
00951 PushButton *configWidget = new PushButton(d->messageOverlay);
00952 configWidget->setText(i18n("Configure..."));
00953 connect(configWidget, SIGNAL(clicked()), this, SLOT(showConfigurationInterface()));
00954 configLayout->addItem(configWidget, row, 1);
00955
00956
00957
00958
00959 d->messageOverlay->show();
00960 }
00961
00962 void Applet::showMessage(const QIcon &icon, const QString &message, const MessageButtons buttons)
00963 {
00964 if (message.isEmpty()) {
00965 d->destroyMessageOverlay();
00966 return;
00967 }
00968
00969 d->createMessageOverlay();
00970 d->messageOverlay->opacity = 0.8;
00971 QGraphicsLinearLayout *mainLayout = new QGraphicsLinearLayout(d->messageOverlay);
00972 mainLayout->setOrientation(Qt::Vertical);
00973 mainLayout->addStretch();
00974
00975 QGraphicsLinearLayout *messageLayout = new QGraphicsLinearLayout();
00976 messageLayout->setOrientation(Qt::Horizontal);
00977
00978 QGraphicsLinearLayout *buttonLayout = new QGraphicsLinearLayout();
00979 buttonLayout->setOrientation(Qt::Horizontal);
00980
00981 mainLayout->addItem(messageLayout);
00982 mainLayout->addItem(buttonLayout);
00983 mainLayout->addStretch();
00984
00985 IconWidget *messageIcon = new IconWidget(this);
00986 Label *messageText = new Label(this);
00987 messageText->nativeWidget()->setWordWrap(true);
00988
00989 messageLayout->addStretch();
00990 messageLayout->addItem(messageIcon);
00991 messageLayout->addItem(messageText);
00992 messageLayout->addStretch();
00993
00994 messageIcon->setIcon(icon);
00995 messageText->setText(message);
00996
00997
00998 buttonLayout->addStretch();
00999
01000 if (buttons & ButtonOk) {
01001 PushButton *ok = new PushButton(this);
01002 ok->setText(i18n("Ok"));
01003 buttonLayout->addItem(ok);
01004 connect(ok, SIGNAL(clicked()), this, SLOT(destroyMessageOverlay()));
01005 }
01006 if (buttons & ButtonYes) {
01007 PushButton *yes = new PushButton(this);
01008 yes->setText(i18n("Yes"));
01009 buttonLayout->addItem(yes);
01010 connect(yes, SIGNAL(clicked()), this, SLOT(destroyMessageOverlay()));
01011 }
01012 if (buttons & ButtonNo) {
01013 PushButton *no = new PushButton(this);
01014 no->setText(i18n("No"));
01015 buttonLayout->addItem(no);
01016 connect(no, SIGNAL(clicked()), this, SLOT(destroyMessageOverlay()));
01017 }
01018 if (buttons & ButtonCancel) {
01019 PushButton *cancel = new PushButton(this);
01020 cancel->setText(i18n("Cancel"));
01021 buttonLayout->addItem(cancel);
01022 connect(cancel, SIGNAL(clicked()), this, SLOT(destroyMessageOverlay()));
01023 }
01024
01025 buttonLayout->addStretch();
01026
01027 d->messageOverlay->show();
01028
01029 }
01030
01031 QVariantList Applet::startupArguments() const
01032 {
01033 return d->args;
01034 }
01035
01036 void Applet::flushPendingConstraintsEvents()
01037 {
01038 if (d->pendingConstraints == NoConstraint) {
01039 return;
01040 }
01041
01042 if (d->constraintsTimerId) {
01043 killTimer(d->constraintsTimerId);
01044 d->constraintsTimerId = 0;
01045 }
01046
01047
01048 Plasma::Constraints c = d->pendingConstraints;
01049 d->pendingConstraints = NoConstraint;
01050
01051 if (c & Plasma::StartupCompletedConstraint) {
01052
01053 bool unlocked = immutability() == Mutable;
01054
01055
01056
01057 QAction *closeApplet = d->actions->action("remove");
01058 if (closeApplet) {
01059 closeApplet->setEnabled(unlocked);
01060 closeApplet->setVisible(unlocked);
01061 connect(closeApplet, SIGNAL(triggered(bool)), this, SLOT(selectItemToDestroy()));
01062 }
01063
01064 QAction *configAction = d->actions->action("configure");
01065 if (configAction) {
01066
01067 if (d->isContainment) {
01068 connect(configAction, SIGNAL(triggered()), this, SLOT(requestConfiguration()));
01069 } else {
01070 connect(configAction, SIGNAL(triggered(bool)), this, SLOT(showConfigurationInterface()));
01071 }
01072 bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
01073 canConfig = canConfig && (d->hasConfigurationInterface || d->isContainment);
01074 configAction->setVisible(canConfig);
01075 configAction->setEnabled(canConfig);
01076 }
01077
01078 d->updateShortcuts();
01079 Corona * corona = qobject_cast<Corona*>(scene());
01080 if (corona) {
01081 connect(corona, SIGNAL(shortcutsChanged()), this, SLOT(updateShortcuts()));
01082 }
01083 }
01084
01085 if (c & Plasma::ImmutableConstraint) {
01086 bool unlocked = immutability() == Mutable;
01087 QAction *action = d->actions->action("remove");
01088 if (action) {
01089 action->setVisible(unlocked);
01090 action->setEnabled(unlocked);
01091 }
01092
01093 bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
01094 canConfig = canConfig && (d->hasConfigurationInterface || d->isContainment);
01095 action = d->actions->action("configure");
01096 if (action) {
01097 action->setVisible(canConfig);
01098 action->setEnabled(canConfig);
01099 }
01100 }
01101
01102 if (c & Plasma::SizeConstraint) {
01103 if (d->messageOverlay) {
01104 d->messageOverlay->setGeometry(QRectF(QPointF(0, 0), geometry().size()));
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 }
01119
01120 if (d->started && layout()) {
01121 layout()->updateGeometry();
01122 }
01123 }
01124
01125 if (c & Plasma::FormFactorConstraint) {
01126 FormFactor f = formFactor();
01127 if (!d->isContainment && f != Vertical && f != Horizontal) {
01128 setBackgroundHints(d->preferredBackgroundHints);
01129 } else {
01130 BackgroundHints hints = d->preferredBackgroundHints;
01131 setBackgroundHints(NoBackground);
01132 d->preferredBackgroundHints = hints;
01133 }
01134
01135 if (d->failed) {
01136 if (f == Vertical || f == Horizontal) {
01137 setMinimumSize(0, 0);
01138 QGraphicsLayoutItem *item = layout()->itemAt(1);
01139 layout()->removeAt(1);
01140 delete item;
01141 }
01142 }
01143 }
01144 if (c & Plasma::SizeConstraint || c & Plasma::FormFactorConstraint) {
01145 if (aspectRatioMode() == Plasma::Square || aspectRatioMode() == Plasma::ConstrainedSquare) {
01146
01147 if (formFactor() == Horizontal) {
01148 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
01149 } else if (formFactor() == Vertical) {
01150 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
01151 }
01152 }
01153 updateGeometry();
01154 }
01155
01156
01157 Containment* containment = qobject_cast<Plasma::Containment*>(this);
01158 if (d->isContainment && containment) {
01159 containment->d->containmentConstraintsEvent(c);
01160 }
01161
01162 PopupApplet* popup = qobject_cast<Plasma::PopupApplet*>(this);
01163 if (popup) {
01164 popup->d->popupConstraintsEvent(c);
01165 }
01166
01167
01168 constraintsEvent(c);
01169
01170 if (c & StartupCompletedConstraint) {
01171
01172 if (d->modificationsTimerId > 0) {
01173 killTimer(d->modificationsTimerId);
01174 }
01175
01176 d->modificationsTimerId = 0;
01177 }
01178 }
01179
01180 int Applet::type() const
01181 {
01182 return Type;
01183 }
01184
01185 QList<QAction*> Applet::contextualActions()
01186 {
01187
01188 return d->script ? d->script->contextualActions() : QList<QAction*>();
01189 }
01190
01191 QAction *Applet::action(QString name) const
01192 {
01193 return d->actions->action(name);
01194 }
01195
01196 void Applet::addAction(QString name, QAction *action)
01197 {
01198 d->actions->addAction(name, action);
01199 }
01200
01201 void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
01202 {
01203 if (!d->started) {
01204
01205 return;
01206 }
01207
01208 if (transform().isRotating()) {
01209 painter->setRenderHint(QPainter::SmoothPixmapTransform);
01210 painter->setRenderHint(QPainter::Antialiasing);
01211 }
01212
01213 if (d->background &&
01214 formFactor() != Plasma::Vertical &&
01215 formFactor() != Plasma::Horizontal) {
01216
01217 d->background->paintFrame(painter);
01218 }
01219
01220 if (d->failed) {
01221
01222 return;
01223 }
01224
01225 qreal left, top, right, bottom;
01226 getContentsMargins(&left, &top, &right, &bottom);
01227 QRect contentsRect = QRectF(QPointF(0, 0),
01228 boundingRect().size()).adjusted(left, top, -right, -bottom).toRect();
01229
01230 if (widget && d->isContainment) {
01231
01232 View* v = qobject_cast<Plasma::View*>(widget->parent());
01233 Containment* c = qobject_cast<Plasma::Containment*>(this);
01234
01235
01236 if (v && c && c->d->toolBox) {
01237 if (c->d->toolBox->viewTransform().isScaling() && !v->transform().isScaling()) {
01238 c->d->positionToolBox();
01239 }
01240 if (v) {
01241 c->d->toolBox->setViewTransform(v->transform());
01242 }
01243 }
01244
01245 if (!v || v->isWallpaperEnabled()) {
01246
01247
01248 if (c && c->drawWallpaper() && c->wallpaper()) {
01249 Wallpaper *w = c->wallpaper();
01250 if (!w->isInitialized()) {
01251
01252 KConfigGroup wallpaperConfig = c->config();
01253 wallpaperConfig = KConfigGroup(&wallpaperConfig, "Wallpaper");
01254 wallpaperConfig = KConfigGroup(&wallpaperConfig, w->pluginName());
01255 w->restore(wallpaperConfig);
01256 }
01257
01258 painter->save();
01259 c->wallpaper()->paint(painter, option->exposedRect);
01260 painter->restore();
01261 }
01262
01263
01264
01265 Containment::StyleOption coption(*option);
01266 coption.view = v;
01267 paintInterface(painter, &coption, contentsRect);
01268 }
01269 } else {
01270
01271
01272 paintInterface(painter, option, contentsRect);
01273 }
01274 }
01275
01276 void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
01277 {
01278 if (d->script) {
01279 d->script->paintInterface(painter, option, contentsRect);
01280 } else {
01281
01282 }
01283 }
01284
01285 FormFactor Applet::formFactor() const
01286 {
01287 Containment *c = containment();
01288 return c ? c->d->formFactor : Plasma::Planar;
01289 }
01290
01291 Containment *Applet::containment() const
01292 {
01293 if (d->isContainment) {
01294 Containment *c = qobject_cast<Containment*>(const_cast<Applet*>(this));
01295 if (c) {
01296 return c;
01297 }
01298 }
01299
01300 QGraphicsItem *parent = parentItem();
01301 Containment *c = 0;
01302
01303 while (parent) {
01304 Containment *possibleC = dynamic_cast<Containment*>(parent);
01305 if (possibleC && possibleC->Applet::d->isContainment) {
01306 c = possibleC;
01307 break;
01308 }
01309 parent = parent->parentItem();
01310 }
01311
01312 return c;
01313 }
01314
01315 void Applet::setGlobalShortcut(const KShortcut &shortcut)
01316 {
01317 if (!d->activationAction) {
01318 d->activationAction = new KAction(this);
01319 d->activationAction->setText(i18n("Activate %1 Widget", name()));
01320 d->activationAction->setObjectName(QString("activate widget %1").arg(id()));
01321 connect(d->activationAction, SIGNAL(triggered()), this, SIGNAL(activate()));
01322
01323 QList<QWidget *> widgets = d->actions->associatedWidgets();
01324 foreach (QWidget *w, widgets) {
01325 w->addAction(d->activationAction);
01326 }
01327 }
01328
01329
01330 d->activationAction->setGlobalShortcut(
01331 shortcut,
01332 KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut),
01333 KAction::NoAutoloading);
01334
01335 KConfigGroup shortcutConfig(d->mainConfigGroup(), "Shortcuts");
01336 shortcutConfig.writeEntry("global", d->activationAction->globalShortcut().toString());
01337 d->scheduleModificationNotification();
01338
01339 }
01340
01341 KShortcut Applet::globalShortcut() const
01342 {
01343 if (d->activationAction) {
01344 return d->activationAction->globalShortcut();
01345 }
01346
01347 return KShortcut();
01348 }
01349
01350 bool Applet::isPopupShowing() const
01351 {
01352 return false;
01353 }
01354
01355 void Applet::addAssociatedWidget(QWidget *widget)
01356 {
01357 d->actions->addAssociatedWidget(widget);
01358 }
01359
01360 void Applet::removeAssociatedWidget(QWidget *widget)
01361 {
01362 d->actions->removeAssociatedWidget(widget);
01363 }
01364
01365 Location Applet::location() const
01366 {
01367 Containment *c = containment();
01368 return c ? c->d->location : Plasma::Desktop;
01369 }
01370
01371 Context *Applet::context() const
01372 {
01373 Containment *c = containment();
01374 Q_ASSERT(c);
01375 return c->d->context();
01376 }
01377
01378 Plasma::AspectRatioMode Applet::aspectRatioMode() const
01379 {
01380 return d->aspectRatioMode;
01381 }
01382
01383 void Applet::setAspectRatioMode(Plasma::AspectRatioMode mode)
01384 {
01385 d->aspectRatioMode = mode;
01386 }
01387
01388 void Applet::registerAsDragHandle(QGraphicsItem *item)
01389 {
01390 if (!item || d->registeredAsDragHandle.contains(item)) {
01391 return;
01392 }
01393
01394 d->registeredAsDragHandle.insert(item);
01395 item->installSceneEventFilter(this);
01396 }
01397
01398 void Applet::unregisterAsDragHandle(QGraphicsItem *item)
01399 {
01400 if (!item) {
01401 return;
01402 }
01403
01404 if (d->registeredAsDragHandle.remove(item)) {
01405 item->removeSceneEventFilter(this);
01406 }
01407 }
01408
01409 bool Applet::isRegisteredAsDragHandle(QGraphicsItem *item)
01410 {
01411 return d->registeredAsDragHandle.contains(item);
01412 }
01413
01414 bool Applet::hasConfigurationInterface() const
01415 {
01416 return d->hasConfigurationInterface;
01417 }
01418
01419
01420
01421 void Applet::setHasConfigurationInterface(bool hasInterface)
01422 {
01423 if (d->hasConfigurationInterface == hasInterface) {
01424 return;
01425 }
01426
01427 d->hasConfigurationInterface = hasInterface;
01428
01429
01430 if (!hasInterface && (d->isContainment || qobject_cast<Plasma::Containment*>(this))) {
01431 return;
01432 }
01433
01434
01435 KAction *configAction = qobject_cast<KAction*>(d->actions->action("configure"));
01436 if (configAction) {
01437 bool canConfig = false;
01438 if (hasInterface) {
01439 bool unlocked = immutability() == Mutable;
01440 canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
01441 }
01442 configAction->setVisible(canConfig);
01443 configAction->setEnabled(canConfig);
01444 }
01445 }
01446
01447 KActionCollection* AppletPrivate::defaultActions(QObject *parent)
01448 {
01449 KActionCollection *actions = new KActionCollection(parent);
01450 actions->setConfigGroup("Shortcuts-Applet");
01451
01452 KAction *configAction = actions->addAction("configure");
01453 configAction->setAutoRepeat(false);
01454 configAction->setText(i18n("Widget Settings"));
01455 configAction->setIcon(KIcon("configure"));
01456 configAction->setShortcut(KShortcut("alt+d, s"));
01457
01458 KAction *closeApplet = actions->addAction("remove");
01459 closeApplet->setAutoRepeat(false);
01460 closeApplet->setText("Remove this Widget");
01461 closeApplet->setIcon(KIcon("edit-delete"));
01462 closeApplet->setShortcut(KShortcut("alt+d, r"));
01463
01464 return actions;
01465 }
01466
01467 bool Applet::eventFilter(QObject *o, QEvent *e)
01468 {
01469 return QObject::eventFilter(o, e);
01470 }
01471
01472 bool Applet::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
01473 {
01474 switch (event->type()) {
01475 case QEvent::GraphicsSceneMouseMove:
01476 {
01477
01478
01479 if (d->registeredAsDragHandle.contains(watched)) {
01480 Containment *c = containment();
01481 if (!c || c->immutability() == Mutable) {
01482 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
01483 return true;
01484 }
01485 }
01486 break;
01487 }
01488
01489 default:
01490 break;
01491 }
01492
01493 return QGraphicsItem::sceneEventFilter(watched, event);
01494 }
01495
01496 void Applet::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
01497 {
01498 if (immutability() == Mutable && formFactor() == Plasma::Planar) {
01499 QGraphicsItem *parent = parentItem();
01500 Plasma::Applet *applet = qgraphicsitem_cast<Plasma::Applet*>(parent);
01501
01502 if (applet && applet->isContainment()) {
01503
01504 QPointF curPos = event->pos();
01505 QPointF lastPos = event->lastPos();
01506 QPointF delta = curPos - lastPos;
01507
01508 moveBy(delta.x(), delta.y());
01509 } else if (parent) {
01510
01511
01512
01513 QPointF curPos = parent->transform().map(event->pos());
01514 QPointF lastPos = parent->transform().map(event->lastPos());
01515 QPointF delta = curPos - lastPos;
01516
01517 parent->setPos(parent->pos() + delta);
01518 }
01519 }
01520 }
01521
01522 void Applet::focusInEvent(QFocusEvent *event)
01523 {
01524 if (!isContainment() && containment()) {
01525
01526 containment()->d->focusApplet(this);
01527 }
01528
01529 QGraphicsWidget::focusInEvent(event);
01530 }
01531
01532 void Applet::resizeEvent(QGraphicsSceneResizeEvent *event)
01533 {
01534 QGraphicsWidget::resizeEvent(event);
01535
01536 if (d->background) {
01537 d->background->resizeFrame(boundingRect().size());
01538 }
01539
01540 updateConstraints(Plasma::SizeConstraint);
01541
01542 d->scheduleModificationNotification();
01543 emit geometryChanged();
01544 }
01545
01546 void Applet::showConfigurationInterface()
01547 {
01548 if (!hasConfigurationInterface()) {
01549 return;
01550 }
01551
01552 if (immutability() != Mutable && !KAuthorized::authorize("PlasmaAllowConfigureWhenLocked")) {
01553
01554 return;
01555 }
01556
01557 KConfigDialog *dlg = KConfigDialog::exists(d->configDialogId());
01558
01559 if (dlg) {
01560 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
01561 dlg->show();
01562 KWindowSystem::activateWindow(dlg->winId());
01563 return;
01564 }
01565
01566 if (d->package && d->configLoader) {
01567 KConfigDialog *dialog = new KConfigDialog(0, d->configDialogId(), d->configLoader);
01568
01569 QString uiFile = d->package->filePath("mainconfigui");
01570 if (!uiFile.isEmpty()) {
01571 dialog->setWindowTitle(d->configWindowTitle());
01572 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01573
01574 QUiLoader loader;
01575 QFile f(uiFile);
01576 if (!f.open(QIODevice::ReadOnly)) {
01577 delete dialog;
01578
01579 if (d->script) {
01580 d->script->showConfigurationInterface();
01581 }
01582 return;
01583 }
01584
01585 QWidget *w = loader.load(&f);
01586 f.close();
01587
01588 dialog->addPage(w, i18n("Settings"), icon(), i18n("%1 Settings", name()));
01589 }
01590
01591 d->addGlobalShortcutsPage(dialog);
01592 dialog->show();
01593 } else if (d->script) {
01594 d->script->showConfigurationInterface();
01595 } else {
01596 KConfigDialog *dialog = d->generateGenericConfigDialog();
01597 createConfigurationInterface(dialog);
01598 d->addGlobalShortcutsPage(dialog);
01599 dialog->show();
01600 }
01601
01602 emit releaseVisualFocus();
01603 }
01604
01605 QString AppletPrivate::configDialogId() const
01606 {
01607 return QString("%1settings%2").arg(appletId).arg(q->name());
01608 }
01609
01610 QString AppletPrivate::configWindowTitle() const
01611 {
01612 return i18nc("@title:window", "%1 Settings", q->name());
01613 }
01614
01615 QSet<QString> AppletPrivate::knownCategories()
01616 {
01617
01618
01619 QSet<QString> categories = s_customCategories;
01620 categories << QString(I18N_NOOP("Accessibility")).toLower()
01621 << QString(I18N_NOOP("Application Launchers")).toLower()
01622 << QString(I18N_NOOP("Astronomy")).toLower()
01623 << QString(I18N_NOOP("Date and Time")).toLower()
01624 << QString(I18N_NOOP("Development Tools")).toLower()
01625 << QString(I18N_NOOP("Education")).toLower()
01626 << QString(I18N_NOOP("Environment and Weather")).toLower()
01627 << QString(I18N_NOOP("Examples")).toLower()
01628 << QString(I18N_NOOP("File System")).toLower()
01629 << QString(I18N_NOOP("Fun and Games")).toLower()
01630 << QString(I18N_NOOP("Graphics")).toLower()
01631 << QString(I18N_NOOP("Language")).toLower()
01632 << QString(I18N_NOOP("Mapping")).toLower()
01633 << QString(I18N_NOOP("Miscellaneous")).toLower()
01634 << QString(I18N_NOOP("Multimedia")).toLower()
01635 << QString(I18N_NOOP("Online Services")).toLower()
01636 << QString(I18N_NOOP("System Information")).toLower()
01637 << QString(I18N_NOOP("Utilities")).toLower()
01638 << QString(I18N_NOOP("Windows and Tasks")).toLower();
01639 return categories;
01640 }
01641
01642 KConfigDialog *AppletPrivate::generateGenericConfigDialog()
01643 {
01644 KConfigSkeleton *nullManager = new KConfigSkeleton(0);
01645 KConfigDialog *dialog = new KConfigDialog(0, configDialogId(), nullManager);
01646 dialog->setFaceType(KPageDialog::Auto);
01647 dialog->setWindowTitle(configWindowTitle());
01648 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01649 QObject::connect(dialog, SIGNAL(finished()), nullManager, SLOT(deleteLater()));
01650 return dialog;
01651 }
01652
01653 void AppletPrivate::addGlobalShortcutsPage(KConfigDialog *dialog)
01654 {
01655 if (isContainment) {
01656 return;
01657 }
01658
01659 QWidget *page = new QWidget;
01660 QVBoxLayout *layout = new QVBoxLayout(page);
01661
01662 if (!shortcutEditor) {
01663 shortcutEditor = new KKeySequenceWidget(page);
01664 QObject::connect(shortcutEditor, SIGNAL(destroyed(QObject*)), q, SLOT(clearShortcutEditorPtr()));
01665 }
01666
01667 shortcutEditor->setKeySequence(q->globalShortcut().primary());
01668 layout->addWidget(shortcutEditor);
01669 layout->addStretch();
01670 dialog->addPage(page, i18n("Keyboard Shortcut"), "preferences-desktop-keyboard");
01671
01672
01673 dialog->showButton(KDialog::Apply, false);
01674 QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()));
01675 QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()));
01676 }
01677
01678 void AppletPrivate::clearShortcutEditorPtr()
01679 {
01680 shortcutEditor = 0;
01681 }
01682
01683 void AppletPrivate::configDialogFinished()
01684 {
01685 if (shortcutEditor) {
01686 QKeySequence sequence = shortcutEditor->keySequence();
01687 if (sequence != q->globalShortcut().primary()) {
01688 q->setGlobalShortcut(KShortcut(sequence));
01689 emit q->configNeedsSaving();
01690 }
01691 }
01692
01693 if (!configLoader) {
01694
01695 q->configChanged();
01696 }
01697 }
01698
01699 void AppletPrivate::updateShortcuts()
01700 {
01701 if (isContainment) {
01702
01703
01704 QList<QString> names;
01705 QList<QAction*> qactions;
01706 names << "zoom out" << "add sibling containment" << "configure shortcuts" << "lock widgets";
01707 foreach (const QString &name, names) {
01708 QAction *a = actions->action(name);
01709 actions->takeAction(a);
01710 qactions << a;
01711 }
01712
01713 actions->readSettings();
01714
01715 for (int i=0; i<names.size(); ++i) {
01716 QAction *a = qactions.at(i);
01717 if (a) {
01718 actions->addAction(names.at(i), a);
01719 }
01720 }
01721 } else {
01722 actions->readSettings();
01723 }
01724 }
01725
01726 void Applet::configChanged()
01727 {
01728 if (d->script) {
01729 d->script->configChanged();
01730 }
01731 }
01732
01733 void Applet::createConfigurationInterface(KConfigDialog *parent)
01734 {
01735 Q_UNUSED(parent)
01736
01737
01738 }
01739
01740 bool Applet::hasAuthorization(const QString &constraint) const
01741 {
01742 KConfigGroup constraintGroup(KGlobal::config(), "Constraints");
01743 return constraintGroup.readEntry(constraint, true);
01744 }
01745
01746 KPluginInfo::List Applet::listAppletInfo(const QString &category,
01747 const QString &parentApp)
01748 {
01749 QString constraint;
01750
01751 if (parentApp.isEmpty()) {
01752 constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
01753 } else {
01754 constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
01755 }
01756
01757
01758 if (category.isEmpty()) {
01759 KConfigGroup group(KGlobal::config(), "General");
01760 QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
01761 foreach (const QString &category, excluded) {
01762 constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'");
01763 }
01764 } else {
01765 constraint.append(" and ");
01766
01767 constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
01768 if (category == "Miscellaneous") {
01769 constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
01770 }
01771 }
01772
01773 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01774 offers << KServiceTypeTrader::self()->query("Plasma/PopupApplet", constraint);
01775
01776
01777 KConfigGroup constraintGroup(KGlobal::config(), "Constraints");
01778 foreach (const QString &key, constraintGroup.keyList()) {
01779
01780 if (constraintGroup.readEntry(key, true)) {
01781 continue;
01782 }
01783
01784 QMutableListIterator<KService::Ptr> it(offers);
01785 while (it.hasNext()) {
01786 KService::Ptr p = it.next();
01787 QString prop = QString("X-Plasma-Requires-").append(key);
01788 QVariant req = p->property(prop, QVariant::String);
01789
01790 QString reqValue;
01791 if (req.isValid()) {
01792 reqValue = req.toString();
01793 } else {
01794
01795
01796
01797 }
01798
01799 if (!(reqValue == "Optional" || reqValue == "Unused")) {
01800
01801 it.remove();
01802 }
01803 }
01804 }
01805
01806
01807
01808 return KPluginInfo::fromServices(offers);
01809 }
01810
01811 KPluginInfo::List Applet::listAppletInfoForMimetype(const QString &mimetype)
01812 {
01813 QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
01814
01815 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01816 offers << KServiceTypeTrader::self()->query("Plasma/PopupApplet", constraint);
01817 return KPluginInfo::fromServices(offers);
01818 }
01819
01820 QStringList Applet::listCategories(const QString &parentApp, bool visibleOnly)
01821 {
01822 QString constraint = "exist [X-KDE-PluginInfo-Category]";
01823
01824 if (parentApp.isEmpty()) {
01825 constraint.append("and (not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
01826 } else {
01827 constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
01828 }
01829
01830 KConfigGroup group(KGlobal::config(), "General");
01831 QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
01832 foreach (const QString &category, excluded) {
01833 constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'");
01834 }
01835
01836 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01837 offers << KServiceTypeTrader::self()->query("Plasma/PopupApplet", constraint);
01838 QStringList categories;
01839 QSet<QString> known = AppletPrivate::knownCategories();
01840 foreach (const KService::Ptr &applet, offers) {
01841 QString appletCategory = applet->property("X-KDE-PluginInfo-Category").toString();
01842 if (visibleOnly && applet->noDisplay()) {
01843
01844 continue;
01845 }
01846
01847
01848 if (!appletCategory.isEmpty() && !known.contains(appletCategory.toLower())) {
01849 kDebug() << "Unknown category: " << applet->name() << "says it is in the"
01850 << appletCategory << "category which is unknown to us";
01851 appletCategory.clear();
01852 }
01853
01854 if (appletCategory.isEmpty()) {
01855 if (!categories.contains(i18nc("misc category", "Miscellaneous"))) {
01856 categories << i18nc("misc category", "Miscellaneous");
01857 }
01858 } else if (!categories.contains(appletCategory)) {
01859 categories << appletCategory;
01860 }
01861 }
01862
01863 categories.sort();
01864 return categories;
01865 }
01866
01867 void Applet::setCustomCategories(const QStringList &categories)
01868 {
01869 AppletPrivate::s_customCategories = QSet<QString>::fromList(categories);
01870 }
01871
01872 QStringList Applet::customCategories()
01873 {
01874 return AppletPrivate::s_customCategories.toList();
01875 }
01876
01877 Applet::Applet(const QString &packagePath, uint appletId, const QVariantList &args)
01878 : QGraphicsWidget(0),
01879 d(new AppletPrivate(KService::Ptr(new KService(packagePath + "/metadata.desktop")), appletId, this))
01880 {
01881 Q_UNUSED(args)
01882 d->init(packagePath);
01883 }
01884
01885 Applet *Applet::loadPlasmoid(const QString &path, uint appletId, const QVariantList &args)
01886 {
01887 if (QFile::exists(path + "/metadata.desktop")) {
01888 return new Applet(path, appletId, args);
01889 }
01890
01891 return 0;
01892 }
01893
01894 Applet *Applet::load(const QString &appletName, uint appletId, const QVariantList &args)
01895 {
01896 if (appletName.isEmpty()) {
01897 return 0;
01898 }
01899
01900 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
01901 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01902
01903 bool isContainment = false;
01904 if (offers.isEmpty()) {
01905
01906
01907 offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
01908 if (offers.count() > 0) {
01909 isContainment = true;
01910 }
01911 }
01912
01913 bool isPopupApplet = false;
01914 if (offers.isEmpty()) {
01915 offers = KServiceTypeTrader::self()->query("Plasma/PopupApplet", constraint);
01916 if (offers.count() > 0) {
01917 isPopupApplet = true;
01918 }
01919 }
01920
01921
01922
01923
01924
01925 if (offers.isEmpty()) {
01926 kDebug() << "offers is empty for " << appletName;
01927 return 0;
01928 }
01929
01930 KService::Ptr offer = offers.first();
01931
01932 if (appletId == 0) {
01933 appletId = ++AppletPrivate::s_maxAppletId;
01934 }
01935
01936 QVariantList allArgs;
01937 allArgs << offer->storageId() << appletId << args;
01938
01939 if (!offer->property("X-Plasma-API").toString().isEmpty()) {
01940 kDebug() << "we have a script using the"
01941 << offer->property("X-Plasma-API").toString() << "API";
01942 if (isContainment) {
01943 return new Containment(0, allArgs);
01944 } else if (isPopupApplet) {
01945 return new PopupApplet(0, allArgs);
01946 } else {
01947 return new Applet(0, allArgs);
01948 }
01949 }
01950
01951 KPluginLoader plugin(*offer);
01952
01953 if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion()) &&
01954 (appletName != "internal:extender")) {
01955 return 0;
01956 }
01957
01958
01959 QString error;
01960 Applet *applet;
01961
01962 if (appletName == "internal:extender") {
01963 applet = new ExtenderApplet(0, allArgs);
01964 } else {
01965 applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
01966 }
01967
01968 if (!applet) {
01969 kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error;
01970 }
01971
01972 return applet;
01973 }
01974
01975 Applet *Applet::load(const KPluginInfo &info, uint appletId, const QVariantList &args)
01976 {
01977 if (!info.isValid()) {
01978 return 0;
01979 }
01980
01981 return load(info.pluginName(), appletId, args);
01982 }
01983
01984 QVariant Applet::itemChange(GraphicsItemChange change, const QVariant &value)
01985 {
01986 QVariant ret = QGraphicsWidget::itemChange(change, value);
01987
01988
01989 switch (change) {
01990 case ItemSceneHasChanged:
01991 {
01992 QGraphicsScene *newScene = qvariant_cast<QGraphicsScene*>(value);
01993 if (newScene) {
01994 d->checkImmutability();
01995 }
01996 }
01997 break;
01998 case ItemParentChange:
01999 if (d->mainConfig && !d->isContainment &&
02000 !containment() &&
02001 dynamic_cast<Containment*>(value.value<QGraphicsItem *>())) {
02002
02003
02004
02005 kWarning() << "Configuration object was requested prior to init(), which is too early. "
02006 "Please fix this item:" << parentItem() << value.value<QGraphicsItem *>()
02007 << name();
02008 KConfigGroup *old = d->mainConfig;
02009 KConfigGroup appletConfig = dynamic_cast<Containment*>(value.value<QGraphicsItem *>())->config();
02010 appletConfig = KConfigGroup(&appletConfig, "Applets");
02011 d->mainConfig = new KConfigGroup(&appletConfig, QString::number(d->appletId));
02012 old->copyTo(d->mainConfig);
02013 old->deleteGroup();
02014 delete old;
02015 } else if (!d->isContainment) {
02016 Plasma::PopupApplet *pa = qobject_cast<Plasma::PopupApplet *>(this);
02017 if (!pa) {
02018 break;
02019 }
02020
02021 if (containment()) {
02022 disconnect(containment(), SIGNAL(geometryChanged()), pa, SLOT(updateDialogPosition()));
02023 }
02024 Plasma::Containment *cont = dynamic_cast<Containment*>(value.value<QGraphicsItem *>());
02025 if (cont) {
02026 connect(cont, SIGNAL(geometryChanged()), pa, SLOT(updateDialogPosition()));
02027 }
02028 }
02029 case ItemPositionChange:
02030 return (immutability() == Mutable || isContainment() || formFactor() == Horizontal || formFactor() == Vertical) ? value : pos();
02031 break;
02032 case ItemTransformChange:
02033 return immutability() == Mutable ? value : transform();
02034 break;
02035 case ItemPositionHasChanged:
02036 emit geometryChanged();
02037
02038 case ItemTransformHasChanged:
02039 d->scheduleModificationNotification();
02040 break;
02041 default:
02042 break;
02043 };
02044
02045 return ret;
02046 }
02047
02048 QPainterPath Applet::shape() const
02049 {
02050 if (d->script) {
02051 return d->script->shape();
02052 }
02053
02054 return QGraphicsWidget::shape();
02055 }
02056
02057 QSizeF Applet::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
02058 {
02059 QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
02060
02061
02062 if (formFactor() == Horizontal && which == Qt::MinimumSize) {
02063 hint.setHeight(0);
02064 } else if (formFactor() == Vertical && which == Qt::MinimumSize) {
02065 hint.setWidth(0);
02066 }
02067
02068
02069 if (d->aspectRatioMode == Plasma::Square) {
02070 if (formFactor() == Horizontal) {
02071 hint.setWidth(size().height());
02072 } else if (formFactor() == Vertical) {
02073 hint.setHeight(size().width());
02074 }
02075 } else if (d->aspectRatioMode == Plasma::ConstrainedSquare) {
02076
02077 if (formFactor() == Horizontal &&
02078 (which == Qt::MaximumSize || size().height() <= KIconLoader::SizeLarge)) {
02079 hint.setWidth(size().height());
02080
02081 } else if (formFactor() == Vertical &&
02082 (which == Qt::MaximumSize || size().width() <= KIconLoader::SizeLarge)) {
02083 hint.setHeight(size().width());
02084 }
02085 }
02086
02087 return hint;
02088 }
02089
02090 void Applet::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
02091 {
02092 Q_UNUSED(event)
02093 }
02094
02095 void Applet::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
02096 {
02097 Q_UNUSED(event)
02098 }
02099
02100 void Applet::timerEvent(QTimerEvent *event)
02101 {
02102 if (d->transient) {
02103 killTimer(d->constraintsTimerId);
02104 killTimer(d->modificationsTimerId);
02105 return;
02106 }
02107
02108 if (event->timerId() == d->constraintsTimerId) {
02109 killTimer(d->constraintsTimerId);
02110 d->constraintsTimerId = 0;
02111
02112
02113
02114 if(!(d->pendingConstraints & Plasma::StartupCompletedConstraint)) {
02115 flushPendingConstraintsEvents();
02116 }
02117 } else if (event->timerId() == d->modificationsTimerId) {
02118 killTimer(d->modificationsTimerId);
02119 d->modificationsTimerId = 0;
02120
02121 KConfigGroup cg;
02122 save(cg);
02123 emit configNeedsSaving();
02124 }
02125 }
02126
02127 QRect Applet::screenRect() const
02128 {
02129 QGraphicsView *v = view();
02130
02131 if (v) {
02132 QPointF bottomRight = pos();
02133 bottomRight.rx() += size().width();
02134 bottomRight.ry() += size().height();
02135
02136 QPoint tL = v->mapToGlobal(v->mapFromScene(pos()));
02137 QPoint bR = v->mapToGlobal(v->mapFromScene(bottomRight));
02138 return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
02139 }
02140
02141
02142
02143 return QRect(QPoint(0, 0), QSize(0, 0));
02144 }
02145
02146 void Applet::raise()
02147 {
02148 setZValue(++AppletPrivate::s_maxZValue);
02149 }
02150
02151 void Applet::lower()
02152 {
02153 setZValue(--AppletPrivate::s_minZValue);
02154 }
02155
02156 void AppletPrivate::setIsContainment(bool nowIsContainment, bool forceUpdate)
02157 {
02158 if (isContainment == nowIsContainment && !forceUpdate) {
02159 return;
02160 }
02161
02162 isContainment = nowIsContainment;
02163
02164
02165
02166
02167 delete mainConfig;
02168 mainConfig = 0;
02169 }
02170
02171 bool Applet::isContainment() const
02172 {
02173 return d->isContainment;
02174 }
02175
02176
02177
02178 AppletPrivate::AppletPrivate(KService::Ptr service, int uniqueID, Applet *applet)
02179 : appletId(uniqueID),
02180 q(applet),
02181 backgroundHints(Applet::NoBackground),
02182 preferredBackgroundHints(Applet::StandardBackground),
02183 aspectRatioMode(Plasma::KeepAspectRatio),
02184 immutability(Mutable),
02185 appletDescription(service),
02186 extender(0),
02187 background(0),
02188 mainConfig(0),
02189 pendingConstraints(NoConstraint),
02190 messageOverlay(0),
02191 messageOverlayProxy(0),
02192 busyWidget(0),
02193 script(0),
02194 package(0),
02195 configLoader(0),
02196 actions(AppletPrivate::defaultActions(applet)),
02197 activationAction(0),
02198 shortcutEditor(0),
02199 constraintsTimerId(0),
02200 modificationsTimerId(-1),
02201 hasConfigurationInterface(false),
02202 failed(false),
02203 isContainment(false),
02204 transient(false),
02205 needsConfig(false),
02206 started(false)
02207 {
02208 if (appletId == 0) {
02209 appletId = ++s_maxAppletId;
02210 } else if (appletId > s_maxAppletId) {
02211 s_maxAppletId = appletId;
02212 }
02213 }
02214
02215 AppletPrivate::~AppletPrivate()
02216 {
02217 modificationsTimerId = -1;
02218
02219 if (activationAction && activationAction->isGlobalShortcutEnabled()) {
02220
02221 activationAction->forgetGlobalShortcut();
02222 }
02223
02224 if (extender) {
02225 delete extender;
02226 extender = 0;
02227 }
02228
02229 delete script;
02230 script = 0;
02231 delete package;
02232 package = 0;
02233 delete configLoader;
02234 configLoader = 0;
02235 delete mainConfig;
02236 mainConfig = 0;
02237 }
02238
02239 void AppletPrivate::init(const QString &packagePath)
02240 {
02241
02242
02243 q->setCacheMode(Applet::DeviceCoordinateCache);
02244 q->setAcceptsHoverEvents(true);
02245 q->setFlag(QGraphicsItem::ItemIsFocusable, true);
02246 q->setFocusPolicy(Qt::ClickFocus);
02247
02248
02249 q->setLayoutDirection(qApp->layoutDirection());
02250
02251 if (!appletDescription.isValid()) {
02252 kDebug() << "Check your constructor! "
02253 << "You probably want to be passing in a Service::Ptr "
02254 << "or a QVariantList with a valid storageid as arg[0].";
02255 return;
02256 }
02257
02258 QString api = appletDescription.property("X-Plasma-API").toString();
02259
02260
02261 if (!api.isEmpty()) {
02262
02263 QString path = packagePath;
02264 if (path.isEmpty()) {
02265 path = KStandardDirs::locate("data", "plasma/plasmoids/" + appletDescription.pluginName() + '/');
02266 } else if (!path.endsWith('/')) {
02267 path.append('/');
02268 }
02269
02270 if (path.isEmpty()) {
02271 q->setFailedToLaunch(
02272 true,
02273 i18nc("Package file, name of the widget",
02274 "Could not locate the %1 package required for the %2 widget.",
02275 appletDescription.pluginName(), appletDescription.name()));
02276 } else {
02277
02278
02279 PackageStructure::Ptr structure = Plasma::packageStructure(api, Plasma::AppletComponent);
02280 structure->setPath(path);
02281 package = new Package(path, structure);
02282
02283 if (package->isValid()) {
02284
02285
02286
02287
02288 script = Plasma::loadScriptEngine(api, q);
02289 if (!script) {
02290 delete package;
02291 package = 0;
02292 q->setFailedToLaunch(true,
02293 i18nc("API or programming language the widget was written in, name of the widget",
02294 "Could not create a %1 ScriptEngine for the %2 widget.",
02295 api, appletDescription.name()));
02296 }
02297 } else {
02298 q->setFailedToLaunch(true, i18nc("Package file, name of the widget",
02299 "Could not open the %1 package required for the %2 widget.",
02300 appletDescription.pluginName(), appletDescription.name()));
02301 delete package;
02302 package = 0;
02303 }
02304 }
02305 }
02306
02307
02308 QSize size = appletDescription.property("X-Plasma-DefaultSize").toSize();
02309 if (size.isEmpty()) {
02310 size = QSize(200, 200);
02311 }
02312
02313 q->resize(size);
02314
02315 q->setBackgroundHints(Applet::DefaultBackground);
02316 q->setHasConfigurationInterface(true);
02317
02318 QAction *closeApplet = actions->action("remove");
02319 closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", q->name()));
02320 QAction *configAction = actions->action("configure");
02321 configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", q->name()));
02322
02323 QObject::connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), q, SLOT(themeChanged()));
02324 QObject::connect(q, SIGNAL(activate()), q, SLOT(setFocus()));
02325 }
02326
02327
02328
02329 void AppletPrivate::setupScriptSupport()
02330 {
02331 Q_ASSERT(package);
02332 kDebug() << "setting up script support, package is in" << package->path()
02333 << "which is a" << package->structure()->type() << "package"
02334 << ", main script is" << package->filePath("mainscript");
02335
02336 QString translationsPath = package->filePath("translations");
02337 if (!translationsPath.isEmpty()) {
02338
02339
02340 KGlobal::dirs()->addResourceDir("locale", translationsPath);
02341 KGlobal::locale()->insertCatalog(package->metadata().pluginName());
02342 }
02343
02344 QString xmlPath = package->filePath("mainconfigxml");
02345 if (!xmlPath.isEmpty()) {
02346 QFile file(xmlPath);
02347 KConfigGroup config = q->config();
02348 configLoader = new ConfigLoader(&config, &file);
02349 QObject::connect(configLoader, SIGNAL(configChanged()), q, SLOT(configChanged()));
02350 }
02351
02352 if (!package->filePath("mainconfigui").isEmpty()) {
02353 q->setHasConfigurationInterface(true);
02354 }
02355 }
02356
02357 QString AppletPrivate::globalName() const
02358 {
02359 if (!appletDescription.isValid()) {
02360 return QString();
02361 }
02362
02363 return appletDescription.service()->library();
02364 }
02365
02366 QString AppletPrivate::instanceName()
02367 {
02368 if (!appletDescription.isValid()) {
02369 return QString();
02370 }
02371
02372 return appletDescription.service()->library() + QString::number(appletId);
02373 }
02374
02375 void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
02376 {
02377
02378
02379 if (started && !constraintsTimerId && !(c & Plasma::StartupCompletedConstraint)) {
02380 constraintsTimerId = q->startTimer(0);
02381 }
02382
02383 if (c & Plasma::StartupCompletedConstraint) {
02384 started = true;
02385 }
02386
02387 pendingConstraints |= c;
02388 }
02389
02390 void AppletPrivate::scheduleModificationNotification()
02391 {
02392
02393 if (modificationsTimerId != -1) {
02394
02395 if (modificationsTimerId) {
02396 q->killTimer(modificationsTimerId);
02397 }
02398
02399 modificationsTimerId = q->startTimer(1000);
02400 }
02401 }
02402
02403 KConfigGroup *AppletPrivate::mainConfigGroup()
02404 {
02405 if (mainConfig) {
02406 return mainConfig;
02407 }
02408
02409 if (isContainment) {
02410 Corona *corona = qobject_cast<Corona*>(q->scene());
02411 KConfigGroup containmentConfig;
02412
02413
02414 if (corona) {
02415 containmentConfig = KConfigGroup(corona->config(), "Containments");
02416 } else {
02417 containmentConfig = KConfigGroup(KGlobal::config(), "Containments");
02418 }
02419
02420 mainConfig = new KConfigGroup(&containmentConfig, QString::number(appletId));
02421 } else {
02422 KConfigGroup appletConfig;
02423 if (q->containment()) {
02424 appletConfig = q->containment()->config();
02425 appletConfig = KConfigGroup(&appletConfig, "Applets");
02426 } else {
02427 kWarning() << "requesting config for" << q->name() << "without a containment!";
02428 appletConfig = KConfigGroup(KGlobal::config(), "Applets");
02429 }
02430
02431 mainConfig = new KConfigGroup(&appletConfig, QString::number(appletId));
02432 }
02433
02434 return mainConfig;
02435 }
02436
02437 QString AppletPrivate::visibleFailureText(const QString &reason)
02438 {
02439 QString text;
02440
02441 if (reason.isEmpty()) {
02442 text = i18n("This object could not be created.");
02443 } else {
02444 text = i18n("This object could not be created for the following reason:<p><b>%1</b></p>", reason);
02445 }
02446
02447 return text;
02448 }
02449
02450 void AppletPrivate::checkImmutability()
02451 {
02452 const bool systemImmutable = q->globalConfig().isImmutable() || q->config().isImmutable() ||
02453 ((!isContainment && q->containment()) &&
02454 q->containment()->immutability() == SystemImmutable) ||
02455 (qobject_cast<Corona*>(q->scene()) && static_cast<Corona*>(q->scene())->immutability() == SystemImmutable);
02456
02457 if (systemImmutable) {
02458 q->updateConstraints(ImmutableConstraint);
02459 }
02460 }
02461
02462 void AppletPrivate::themeChanged()
02463 {
02464 if (background) {
02465
02466 q->setBackgroundHints(backgroundHints);
02467
02468 qreal left;
02469 qreal right;
02470 qreal top;
02471 qreal bottom;
02472 background->getMargins(left, top, right, bottom);
02473 q->setContentsMargins(left, right, top, bottom);
02474 }
02475 q->update();
02476 }
02477
02478 void AppletPrivate::resetConfigurationObject()
02479 {
02480
02481 mainConfigGroup();
02482
02483 mainConfig->deleteGroup();
02484 delete mainConfig;
02485 mainConfig = 0;
02486
02487 Corona * corona = qobject_cast<Corona*>(q->scene());
02488 if (corona) {
02489 corona->requireConfigSync();
02490 }
02491 }
02492
02493 uint AppletPrivate::s_maxAppletId = 0;
02494 int AppletPrivate::s_maxZValue = 0;
02495 int AppletPrivate::s_minZValue = 0;
02496 PackageStructure::Ptr AppletPrivate::packageStructure(0);
02497 QSet<QString> AppletPrivate::s_customCategories;
02498
02499 AppletOverlayWidget::AppletOverlayWidget(QGraphicsWidget *parent)
02500 : QGraphicsWidget(parent),
02501 opacity(0.4)
02502 {
02503 resize(parent->size());
02504 Animator::self()->animateItem(this, Animator::AppearAnimation);
02505 }
02506
02507 void AppletOverlayWidget::destroy()
02508 {
02509 connect(Animator::self(),
02510 SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
02511 this,
02512 SLOT(overlayAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
02513 Animator::self()->animateItem(this, Animator::DisappearAnimation);
02514 }
02515
02516 void AppletOverlayWidget::overlayAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation)
02517 {
02518 if (item == this) {
02519 deleteLater();
02520 }
02521 }
02522
02523 void AppletOverlayWidget::paint(QPainter *painter,
02524 const QStyleOptionGraphicsItem *option,
02525 QWidget *widget)
02526 {
02527 Q_UNUSED(option)
02528 Q_UNUSED(widget)
02529
02530 if (qFuzzyCompare(1, 1+opacity)) {
02531 return;
02532 }
02533
02534 QColor wash = Plasma::Theme::defaultTheme()->color(Theme::BackgroundColor);
02535 wash.setAlphaF(opacity);
02536
02537 Applet *applet = qobject_cast<Applet *>(parentWidget());
02538
02539
02540 QPainterPath backgroundShape;
02541 if (!applet || applet->backgroundHints() & Applet::StandardBackground) {
02542
02543 if (parentWidget()->contentsRect().size() != size()) {
02544 resize(parentWidget()->contentsRect().size());
02545 }
02546 backgroundShape = PaintUtils::roundedRectangle(contentsRect(), 5);
02547 } else {
02548 backgroundShape = shape();
02549 }
02550
02551 painter->save();
02552 painter->setRenderHints(QPainter::Antialiasing);
02553 painter->fillPath(backgroundShape, wash);
02554 painter->restore();
02555 }
02556
02557 }
02558
02559 #include "applet.moc"
02560 #include "private/applet_p.moc"
02561 #endif // APPLET_CPP