00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "applet.h"
00023 #include "applet_p.h"
00024
00025 #include <cmath>
00026 #include <limits>
00027
00028 #include <QAction>
00029 #include <QApplication>
00030 #include <QDesktopWidget>
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 <QTimer>
00044 #include <QUiLoader>
00045
00046 #include <KAction>
00047 #include <KIcon>
00048 #include <KColorScheme>
00049 #include <KConfigDialog>
00050 #include <KDialog>
00051 #include <KIconLoader>
00052 #include <KPluginInfo>
00053 #include <KStandardDirs>
00054 #include <KService>
00055 #include <KServiceTypeTrader>
00056 #include <KShortcut>
00057 #include <KWindowSystem>
00058 #include <KActionCollection>
00059
00060 #include <Solid/PowerManagement>
00061
00062 #include "plasma/configxml.h"
00063 #include "plasma/containment.h"
00064 #include "plasma/containment_p.h"
00065 #include "plasma/corona.h"
00066 #include "plasma/dataenginemanager.h"
00067 #include "plasma/package.h"
00068 #include "plasma/packages_p.h"
00069 #include "plasma/plasma.h"
00070 #include "plasma/scripting/appletscript.h"
00071 #include "plasma/shadowitem_p.h"
00072 #include "plasma/svg.h"
00073 #include "plasma/panelsvg.h"
00074 #include "plasma/theme.h"
00075 #include "plasma/toolbox_p.h"
00076 #include "plasma/view.h"
00077 #include "plasma/widgets/label.h"
00078 #include "plasma/widgets/pushbutton.h"
00079
00080
00081 namespace Plasma
00082 {
00083
00084 Applet::Applet(QGraphicsItem *parent,
00085 const QString& serviceID,
00086 uint appletId)
00087 : QGraphicsWidget(parent),
00088 d(new AppletPrivate(KService::serviceByStorageId(serviceID), appletId, this))
00089 {
00090
00091
00092 d->init();
00093 }
00094
00095 Applet::Applet(QObject* parentObject, const QVariantList& args)
00096 : QGraphicsWidget(0),
00097 d(new AppletPrivate(KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()),
00098 args.count() > 1 ? args[1].toInt() : 0, this))
00099 {
00100
00101
00102
00103 QVariantList &mutableArgs = const_cast<QVariantList&>(args);
00104 if (!mutableArgs.isEmpty()) {
00105 mutableArgs.removeFirst();
00106
00107 if (!mutableArgs.isEmpty()) {
00108 mutableArgs.removeFirst();
00109 }
00110 }
00111
00112 setParent(parentObject);
00113
00114
00115 d->init();
00116
00117
00118
00119 }
00120
00121 Applet::~Applet()
00122 {
00123 if (d->transient) {
00124 d->resetConfigurationObject();
00125 }
00126
00127 delete d;
00128 }
00129
00130 PackageStructure::Ptr Applet::packageStructure()
00131 {
00132 if (!AppletPrivate::packageStructure) {
00133 AppletPrivate::packageStructure = new PlasmoidPackage();
00134 }
00135
00136 return AppletPrivate::packageStructure;
00137 }
00138
00139 void Applet::init()
00140 {
00141 if (d->script && !d->script->init()) {
00142 setFailedToLaunch(true, i18n("Script initialization failed"));
00143 }
00144 }
00145
00146 uint Applet::id() const
00147 {
00148 return d->appletId;
00149 }
00150
00151 void Applet::save(KConfigGroup &g) const
00152 {
00153 KConfigGroup group = g;
00154 if (!group.isValid()) {
00155 group = *d->mainConfigGroup();
00156 }
00157
00158
00159
00160 group.writeEntry("immutability", (int)d->immutability);
00161 group.writeEntry("plugin", pluginName());
00162
00163
00164
00165 group.writeEntry("geometry", geometry());
00166 group.writeEntry("zvalue", zValue());
00167
00168 if (transform() == QTransform()) {
00169 group.deleteEntry("transform");
00170 } else {
00171 QList<qreal> m;
00172 QTransform t = transform();
00173 m << t.m11() << t.m12() << t.m13() << t.m21() << t.m22() << t.m23() << t.m31() << t.m32() << t.m33();
00174 group.writeEntry("transform", m);
00175
00176 }
00177
00178 KConfigGroup appletConfigGroup(&group, "Configuration");
00179
00180 saveState(appletConfigGroup);
00181
00182 if (d->activationAction) {
00183 KConfigGroup shortcutConfig(&group, "Shortcuts");
00184 shortcutConfig.writeEntry("global", d->activationAction->globalShortcut().toString());
00185 }
00186 }
00187
00188 void Applet::restore(KConfigGroup &group)
00189 {
00190 QList<qreal> m = group.readEntry("transform", QList<qreal>());
00191 if (m.count() == 9) {
00192 QTransform t(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
00193 setTransform(t);
00194 }
00195
00196 qreal z = group.readEntry("zvalue", 0);
00197
00198 if (z >= AppletPrivate::s_maxZValue) {
00199 AppletPrivate::s_maxZValue = z;
00200 }
00201
00202 if (z > 0) {
00203 setZValue(z);
00204 }
00205
00206 setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00207
00208 QRectF geom = group.readEntry("geometry", QRectF());
00209 if (geom.isValid()) {
00210 setGeometry(geom);
00211 }
00212
00213 KConfigGroup shortcutConfig(&group, "Shortcuts");
00214 QString shortcutText = shortcutConfig.readEntry("global", QString());
00215 if (!shortcutText.isEmpty()) {
00216 setGlobalShortcut(KShortcut(shortcutText));
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 }
00228
00229 void AppletPrivate::setFocus()
00230 {
00231 kDebug() << "setting focus";
00232 q->setFocus(Qt::ShortcutFocusReason);
00233 }
00234
00235 void Applet::setFailedToLaunch(bool failed, const QString& reason)
00236 {
00237 if (d->failed == failed) {
00238 return;
00239 }
00240
00241 d->failed = failed;
00242 prepareGeometryChange();
00243
00244 qDeleteAll(QGraphicsItem::children());
00245 setLayout(0);
00246
00247 if (failed) {
00248 setBackgroundHints(d->backgroundHints|StandardBackground);
00249
00250 QGraphicsLinearLayout *failureLayout = new QGraphicsLinearLayout();
00251 failureLayout->setContentsMargins(0, 0, 0, 0);
00252 Label *failureWidget = new Plasma::Label(this);
00253 failureWidget->setText(d->visibleFailureText(reason));
00254 QLabel *label = failureWidget->nativeWidget();
00255 label->setWordWrap(true);
00256 failureLayout->addItem(failureWidget);
00257 setLayout(failureLayout);
00258 resize(300,250);
00259 setMinimumSize(failureWidget->size());
00260
00261 d->background->resizePanel(geometry().size());
00262 }
00263 update();
00264 }
00265
00266 void Applet::saveState(KConfigGroup &group) const
00267 {
00268 if (group.config()->name() != config().config()->name()) {
00269
00270
00271 KConfigGroup c = config();
00272 c.copyTo(&group);
00273 }
00274 }
00275
00276 KConfigGroup Applet::config(const QString &group) const
00277 {
00278 KConfigGroup cg = config();
00279 return KConfigGroup(&cg, group);
00280 }
00281
00282 KConfigGroup Applet::config() const
00283 {
00284 if (d->isContainment) {
00285 return *(d->mainConfigGroup());
00286 }
00287
00288 return KConfigGroup(d->mainConfigGroup(), "Configuration");
00289 }
00290
00291 KConfigGroup Applet::globalConfig() const
00292 {
00293 KConfigGroup globalAppletConfig;
00294 const Containment *c = containment();
00295 QString group = isContainment() ? "ContainmentGlobals" : "AppletGlobals";
00296
00297 if (c && c->corona()) {
00298 KSharedConfig::Ptr coronaConfig = c->corona()->config();
00299 globalAppletConfig = KConfigGroup(coronaConfig, group);
00300 } else {
00301 globalAppletConfig = KConfigGroup(KGlobal::config(), group);
00302 }
00303
00304 return KConfigGroup(&globalAppletConfig, d->globalName());
00305 }
00306
00307 void Applet::destroy()
00308 {
00309 if (immutability() != Mutable || d->transient) {
00310 return;
00311 }
00312
00313 d->transient = true;
00314
00315 if (isContainment()) {
00316 d->cleanUpAndDelete();
00317 } else {
00318 connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00319 this, SLOT(appletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00320 Animator::self()->animateItem(this, Animator::DisappearAnimation);
00321 }
00322 }
00323
00324 void AppletPrivate::appletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
00325 {
00326 if (anim != Animator::DisappearAnimation || item != q) {
00327 return;
00328 }
00329
00330 cleanUpAndDelete();
00331 }
00332
00333 void AppletPrivate::selectItemToDestroy()
00334 {
00335
00336 if (q->isContainment() &&
00337 q->view() && q->view()->transform().isScaling() &&
00338 q->scene()->focusItem() != q) {
00339 QGraphicsItem *focus = q->scene()->focusItem();
00340
00341 if (focus) {
00342 Containment *toDestroy = dynamic_cast<Containment*>(focus->topLevelItem());
00343
00344 if (toDestroy) {
00345 toDestroy->destroy();
00346 return;
00347 }
00348 }
00349 }
00350
00351 q->destroy();
00352 }
00353
00354 void AppletPrivate::cleanUpAndDelete()
00355 {
00356
00357 QGraphicsWidget *parent = dynamic_cast<QGraphicsWidget *>(q->parentItem());
00358
00359
00360
00361
00362 if (parent && parent->layout()) {
00363 QGraphicsLayout *l = parent->layout();
00364 for (int i = 0; i < l->count(); ++i) {
00365 if (q == l->itemAt(i)) {
00366 l->removeAt(i);
00367 break;
00368 }
00369 }
00370 }
00371
00372 if (configXml) {
00373 configXml->setDefaults();
00374 }
00375
00376 q->scene()->removeItem(q);
00377 q->deleteLater();
00378 }
00379
00380 ConfigXml* Applet::configScheme() const
00381 {
00382 return d->configXml;
00383 }
00384
00385 DataEngine* Applet::dataEngine(const QString& name) const
00386 {
00387 int index = d->loadedEngines.indexOf(name);
00388 if (index != -1) {
00389 return DataEngineManager::self()->engine(name);
00390 }
00391
00392 DataEngine* engine = DataEngineManager::self()->loadEngine(name);
00393 if (engine->isValid()) {
00394 d->loadedEngines.append(name);
00395 }
00396
00397 return engine;
00398 }
00399
00400 const Package* Applet::package() const
00401 {
00402 return d->package;
00403 }
00404
00405 QGraphicsView *Applet::view() const
00406 {
00407
00408
00409
00410 if (!scene()) {
00411 return 0;
00412 }
00413
00414 foreach (QGraphicsView *view, scene()->views()) {
00415 if (view->sceneRect().intersects(sceneBoundingRect()) ||
00416 view->sceneRect().contains(scenePos())) {
00417 return view;
00418 }
00419 }
00420 return 0;
00421 }
00422
00423 QRectF Applet::mapFromView(const QGraphicsView *view, const QRect &rect) const
00424 {
00425
00426 return mapFromScene(view->mapToScene(rect)).boundingRect().adjusted(0, 0, 1, 1);;
00427 }
00428
00429 QRect Applet::mapToView(const QGraphicsView *view, const QRectF &rect) const
00430 {
00431
00432 return view->mapFromScene(mapToScene(rect)).boundingRect().adjusted(0, 0, -1, -1);;
00433 }
00434
00435 QPoint Applet::popupPosition(const QSize &s) const
00436 {
00437 QGraphicsView *v = view();
00438 Q_ASSERT(v);
00439
00440 QPoint pos = v->mapFromScene(scenePos());
00441 pos = v->mapToGlobal(pos);
00442
00443 Plasma::View *pv = dynamic_cast<Plasma::View *>(v);
00444
00445 Plasma::Location loc = Floating;
00446 if (pv) {
00447 loc = pv->containment()->location();
00448 }
00449
00450 switch (loc) {
00451 case BottomEdge:
00452 pos = QPoint(pos.x(), pos.y() - s.height());
00453 break;
00454 case TopEdge:
00455 pos = QPoint(pos.x(), pos.y() + (int)size().height());
00456 break;
00457 case LeftEdge:
00458 pos = QPoint(pos.x() + (int)size().width(), pos.y());
00459 break;
00460 case RightEdge:
00461 pos = QPoint(pos.x() - s.width(), pos.y());
00462 break;
00463 default:
00464 if (pos.y() - s.height() > 0) {
00465 pos = QPoint(pos.x(), pos.y() - s.height());
00466 } else {
00467 pos = QPoint(pos.x(), pos.y() + (int)size().height());
00468 }
00469 }
00470
00471
00472
00473 QRect screenRect = QApplication::desktop()->screenGeometry(pv ? pv->containment()->screen() : -1);
00474
00475
00476 if (pos.rx() + s.width() > screenRect.right()) {
00477 pos.rx() -= ((pos.rx() + s.width()) - screenRect.right());
00478 }
00479
00480 if (pos.ry() + s.height() > screenRect.bottom()) {
00481 pos.ry() -= ((pos.ry() + s.height()) - screenRect.bottom());
00482 }
00483 pos.rx() = qMax(0, pos.rx());
00484
00485 return pos;
00486 }
00487
00488 void Applet::updateConstraints(Plasma::Constraints constraints)
00489 {
00490 d->scheduleConstraintsUpdate(constraints);
00491 }
00492
00493 void Applet::constraintsEvent(Plasma::Constraints constraints)
00494 {
00495
00496
00497
00498
00499 Q_UNUSED(constraints)
00500
00501 if (d->script) {
00502 d->script->constraintsEvent(constraints);
00503 }
00504 }
00505
00506 QString Applet::name() const
00507 {
00508 if (!d->appletDescription.isValid()) {
00509 return i18n("Unknown Applet");
00510 }
00511
00512 return d->appletDescription.name();
00513 }
00514
00515 QFont Applet::font() const
00516 {
00517 return QApplication::font();
00518 }
00519
00520 QString Applet::icon() const
00521 {
00522 if (!d->appletDescription.isValid()) {
00523 return QString();
00524 }
00525
00526 return d->appletDescription.icon();
00527 }
00528
00529 QString Applet::pluginName() const
00530 {
00531 if (!d->appletDescription.isValid()) {
00532 return QString();
00533 }
00534
00535 return d->appletDescription.pluginName();
00536 }
00537
00538 bool Applet::shouldConserveResources() const
00539 {
00540 return Solid::PowerManagement::appShouldConserveResources();
00541 }
00542
00543 QString Applet::category() const
00544 {
00545 if (!d->appletDescription.isValid()) {
00546 return i18n("Miscellaneous");
00547 }
00548
00549 return d->appletDescription.category();
00550 }
00551
00552 QString Applet::category(const KPluginInfo& applet)
00553 {
00554 return applet.property("X-KDE-PluginInfo-Category").toString();
00555 }
00556
00557 QString Applet::category(const QString& appletName)
00558 {
00559 if (appletName.isEmpty()) {
00560 return QString();
00561 }
00562
00563 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
00564 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
00565
00566 if (offers.isEmpty()) {
00567 return QString();
00568 }
00569
00570 return offers.first()->property("X-KDE-PluginInfo-Category").toString();
00571 }
00572
00573 ImmutabilityType Applet::immutability() const
00574 {
00575
00576 ImmutabilityType coronaImmutability = Mutable;
00577
00578 if (dynamic_cast<Corona*>(scene())) {
00579 coronaImmutability = static_cast<Corona*>(scene())->immutability();
00580 }
00581
00582 if (coronaImmutability == SystemImmutable) {
00583 return SystemImmutable;
00584 } else if (coronaImmutability == UserImmutable && d->immutability != SystemImmutable) {
00585 return UserImmutable;
00586 } else {
00587 return d->immutability;
00588 }
00589 }
00590
00591 void Applet::setImmutability(const ImmutabilityType immutable)
00592 {
00593 if (d->immutability == immutable) {
00594 return;
00595 }
00596
00597 d->immutability = immutable;
00598 updateConstraints(ImmutableConstraint);
00599 }
00600
00601 Applet::BackgroundHints Applet::backgroundHints() const
00602 {
00603 return d->backgroundHints;
00604 }
00605
00606 void Applet::setBackgroundHints(const BackgroundHints hints)
00607 {
00608 d->backgroundHints = hints;
00609
00610
00611 if ((hints & StandardBackground) || (hints & TranslucentBackground)) {
00612 if (!d->background) {
00613 d->background = new Plasma::PanelSvg();
00614 }
00615
00616 if ((hints & TranslucentBackground) && Plasma::Theme::defaultTheme()->currentThemeHasImage("widgets/translucentbackground")) {
00617 d->background->setImagePath("widgets/translucentbackground");
00618 } else {
00619 d->background->setImagePath("widgets/background");
00620 }
00621
00622 d->background->setEnabledBorders(Plasma::PanelSvg::AllBorders);
00623 qreal left, top, right, bottom;
00624 d->background->getMargins(left, top, right, bottom);
00625 setContentsMargins(left, right, top, bottom);
00626 QSizeF fitSize(left + right, top + bottom);
00627 if (minimumSize().expandedTo(fitSize) != minimumSize()) {
00628 setMinimumSize(minimumSize().expandedTo(fitSize));
00629 }
00630 d->background->resizePanel(boundingRect().size());
00631 } else if (d->background) {
00632 qreal left, top, right, bottom;
00633 d->background->getMargins(left, top, right, bottom);
00634
00635
00636 setMinimumSize(qMax(minimumSize().width() - left - right, qreal(1.0)),
00637 qMax(minimumSize().height() - top - bottom, qreal(1.0)));
00638
00639 delete d->background;
00640 d->background = 0;
00641 setContentsMargins(0, 0, 0, 0);
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651 #ifdef DYNAMIC_SHADOWS
00652 if (hints & ShadowedBackground) {
00653 if (d->shadow) {
00654 d->shadow->setVisible(true);
00655 } else {
00656 d->shadow = new ShadowItem(this);
00657 if (scene()) {
00658 scene()->addItem(d->shadow);
00659 d->shadow->show();
00660 }
00661 }
00662 } else {
00663 delete d->shadow;
00664 d->shadow = 0;
00665 }
00666 #endif
00667 }
00668
00669 bool Applet::hasFailedToLaunch() const
00670 {
00671 return d->failed;
00672 }
00673
00674 void Applet::paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
00675 {
00676
00677
00678
00679 }
00680
00681 bool Applet::configurationRequired() const
00682 {
00683 return d->needsConfigOverlay != 0;
00684 }
00685
00686 void Applet::setConfigurationRequired(bool needsConfig, const QString &reason)
00687 {
00688 if ((d->needsConfigOverlay != 0) == needsConfig) {
00689 return;
00690 }
00691
00692 if (d->needsConfigOverlay) {
00693 delete d->needsConfigOverlay;
00694 d->needsConfigOverlay = 0;
00695 return;
00696 }
00697
00698 d->needsConfigOverlay = new AppletOverlayWidget(this);
00699 d->needsConfigOverlay->resize(contentsRect().size());
00700 d->needsConfigOverlay->setPos(contentsRect().topLeft());
00701
00702 int zValue = 100;
00703 foreach (QGraphicsItem *child, QGraphicsItem::children()) {
00704 if (child->zValue() > zValue) {
00705 zValue = child->zValue() + 1;
00706 }
00707 }
00708 d->needsConfigOverlay->setZValue(zValue);
00709
00710 qDeleteAll(d->needsConfigOverlay->QGraphicsItem::children());
00711 QGraphicsGridLayout *configLayout = new QGraphicsGridLayout(d->needsConfigOverlay);
00712 configLayout->setContentsMargins(0, 0, 0, 0);
00713
00714
00715 configLayout->setColumnStretchFactor(0, 10);
00716 configLayout->setColumnStretchFactor(2, 10);
00717 configLayout->setRowStretchFactor(0, 10);
00718 configLayout->setRowStretchFactor(3, 10);
00719
00720 int row = 1;
00721 if (!reason.isEmpty()) {
00722 Label *explanation = new Label(d->needsConfigOverlay);
00723 explanation->setText(reason);
00724 configLayout->addItem(explanation, row, 1);
00725 configLayout->setColumnStretchFactor(1, 10);
00726 ++row;
00727
00728 }
00729
00730 PushButton *configWidget = new PushButton(d->needsConfigOverlay);
00731 configWidget->setText(i18n("Configure..."));
00732 connect(configWidget, SIGNAL(clicked()), this, SLOT(showConfigurationInterface()));
00733 configLayout->addItem(configWidget, row, 1);
00734
00735
00736
00737 d->needsConfigOverlay->show();
00738 }
00739
00740 void Applet::flushPendingConstraintsEvents()
00741 {
00742 if (d->pendingConstraints == NoConstraint) {
00743 return;
00744 }
00745
00746 if (d->constraintsTimerId) {
00747 killTimer(d->constraintsTimerId);
00748 d->constraintsTimerId = 0;
00749 }
00750
00751
00752 Plasma::Constraints c = d->pendingConstraints;
00753 d->pendingConstraints = NoConstraint;
00754
00755 if (c & Plasma::StartupCompletedConstraint) {
00756
00757 bool unlocked = immutability() == Mutable;
00758
00759
00760
00761 QAction* closeApplet = new QAction(i18n("Remove this %1", name()), this);
00762 closeApplet->setIcon(KIcon("edit-delete"));
00763 closeApplet->setEnabled(unlocked);
00764 closeApplet->setVisible(unlocked);
00765 closeApplet->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00766 if (isContainment()) {
00767 closeApplet->setShortcut(QKeySequence("ctrl+shift+r"));
00768 } else {
00769 closeApplet->setShortcut(QKeySequence("ctrl+r"));
00770 }
00771 connect(closeApplet, SIGNAL(triggered(bool)), this, SLOT(selectItemToDestroy()));
00772 d->actions.addAction("remove", closeApplet);
00773 }
00774
00775 if (c & Plasma::ImmutableConstraint) {
00776 bool unlocked = immutability() == Mutable;
00777 QAction *action = d->actions.action("remove");
00778 if (action) {
00779 action->setVisible(unlocked);
00780 action->setEnabled(unlocked);
00781 }
00782 }
00783
00784 if (c & Plasma::SizeConstraint && d->needsConfigOverlay) {
00785 d->needsConfigOverlay->setGeometry(QRectF(QPointF(0, 0), contentsRect().size()));
00786 QGraphicsItem *button = 0;
00787 QList<QGraphicsItem*> children = d->needsConfigOverlay->QGraphicsItem::children();
00788
00789 if (!children.isEmpty()) {
00790 button = children.first();
00791 }
00792
00793 if (button) {
00794 QSizeF s = button->boundingRect().size();
00795 button->setPos(d->needsConfigOverlay->boundingRect().width() / 2 - s.width() / 2,
00796 d->needsConfigOverlay->boundingRect().height() / 2 - s.height() / 2);
00797 }
00798 }
00799
00800 if (c & Plasma::FormFactorConstraint) {
00801 FormFactor f = formFactor();
00802
00803
00804
00805 if (f == Planar) {
00806 setBackgroundHints(d->backgroundHints|ShadowedBackground);
00807 } else if (d->backgroundHints&ShadowedBackground) {
00808 setBackgroundHints(d->backgroundHints^ShadowedBackground);
00809 }
00810
00811 if (!isContainment() && f != Vertical && f != Horizontal) {
00812 setBackgroundHints(d->backgroundHints|StandardBackground);
00813 } else if(d->backgroundHints&StandardBackground) {
00814 setBackgroundHints(d->backgroundHints^StandardBackground);
00815 } else if(d->backgroundHints&TranslucentBackground) {
00816 setBackgroundHints(d->backgroundHints^TranslucentBackground);
00817 }
00818 }
00819
00820
00821 if ((c & Plasma::SizeConstraint || c & Plasma::FormFactorConstraint) &&
00822 aspectRatioMode() == Plasma::Square) {
00823 if (formFactor() == Horizontal) {
00824 setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Expanding));
00825 } else if (formFactor() == Vertical) {
00826 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
00827 }
00828
00829 updateGeometry();
00830 }
00831
00832
00833 if ((c & Plasma::SizeConstraint || c & Plasma::FormFactorConstraint) &&
00834 aspectRatioMode() == Plasma::ConstrainedSquare) {
00835 if (formFactor() == Horizontal) {
00836 setSizePolicy(QSizePolicy(QSizePolicy::Maximum,QSizePolicy::Expanding));
00837 } else if (formFactor() == Vertical) {
00838 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
00839 }
00840
00841 updateGeometry();
00842 }
00843
00844
00845 Containment* containment = qobject_cast<Plasma::Containment*>(this);
00846 if (isContainment() && containment) {
00847 containment->d->containmentConstraintsEvent(c);
00848 }
00849
00850 constraintsEvent(c);
00851
00852 if (layout()) {
00853 layout()->updateGeometry();
00854 }
00855 }
00856
00857 int Applet::type() const
00858 {
00859 return Type;
00860 }
00861
00862 QList<QAction*> Applet::contextualActions()
00863 {
00864
00865 return d->script ? d->script->contextualActions() : QList<QAction*>();
00866 }
00867
00868 QAction* Applet::action(QString name) const
00869 {
00870 return d->actions.action(name);
00871 }
00872
00873 void Applet::addAction(QString name, QAction *action)
00874 {
00875 d->actions.addAction(name, action);
00876 }
00877
00878 void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00879 {
00880 QPainter *p;
00881
00882 QPixmap pixmap(boundingRect().size().toSize());
00883
00884 QGraphicsView* qgv = qobject_cast<QGraphicsView*>(widget ? widget->parent() : 0);
00885 bool ghost = (qgv && (qgv == d->ghostView));
00886
00887 if (ghost) {
00888
00889
00890
00891 kDebug() << "Painting ghosted...";
00892
00893 pixmap.fill(Qt::transparent);
00894
00895 p = new QPainter();
00896 p->begin(&pixmap);
00897 } else {
00898 p = painter;
00899 }
00900
00901 if (d->shadow && d->shadow->shadowedSize() != boundingRect().size()) {
00902
00903 d->shadow->generate();
00904 }
00905
00906 p->save();
00907
00908 if (transform().isRotating()) {
00909 p->setRenderHint(QPainter::SmoothPixmapTransform);
00910 p->setRenderHint(QPainter::Antialiasing);
00911 }
00912
00913 if (d->background &&
00914 formFactor() != Plasma::Vertical &&
00915 formFactor() != Plasma::Horizontal) {
00916
00917 d->background->paintPanel(p, option->rect, QPointF(0,0));
00918 }
00919
00920 if (!d->failed) {
00921 qreal left, top, right, bottom;
00922 getContentsMargins(&left, &top, &right, &bottom);
00923 const QRect contentsRect = QRectF(QPointF(0,0), boundingRect().size())
00924 .adjusted(left, top, -right, -bottom).toAlignedRect();
00925 if (widget && isContainment()) {
00926
00927 View* v = qobject_cast<Plasma::View*>(widget->parent());
00928 if (!v || v->isWallpaperEnabled()) {
00929 Containment::StyleOption coption(*option);
00930 coption.view = v;
00931
00932 paintInterface(p, &coption, contentsRect);
00933 }
00934
00935 p->restore();
00936 return;
00937 }
00938
00939
00940 paintInterface(p, option, contentsRect);
00941 }
00942 p->restore();
00943
00944 if (ghost) {
00945
00946 p->setCompositionMode(QPainter::CompositionMode_DestinationIn);
00947 p->fillRect(pixmap.rect(), QColor(0, 0, 0, (0.3 * 255)));
00948 p->end();
00949
00950 delete p;
00951
00952 painter->drawPixmap(0, 0, pixmap);
00953 }
00954 }
00955
00956 void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option,
00957 const QRect & contentsRect)
00958 {
00959 if (d->script) {
00960 d->script->paintInterface(painter, option, contentsRect);
00961 } else {
00962
00963 }
00964 }
00965
00966 FormFactor Applet::formFactor() const
00967 {
00968 Containment* c = containment();
00969 return c ? c->d->formFactor : Plasma::Planar;
00970 }
00971
00972 Containment* Applet::containment() const
00973 {
00974 if (isContainment()) {
00975 Containment *c = dynamic_cast<Containment*>(const_cast<Applet*>(this));
00976 if (c) {
00977 return c;
00978 }
00979 }
00980
00981 QGraphicsItem *parent = parentItem();
00982 Containment *c = 0;
00983
00984 while (parent) {
00985 Containment *possibleC = dynamic_cast<Containment*>(parent);
00986 if (possibleC && possibleC->isContainment()) {
00987 c = possibleC;
00988 break;
00989 }
00990 parent = parent->parentItem();
00991 }
00992
00993 return c;
00994 }
00995
00996 void Applet::setGlobalShortcut(const KShortcut &shortcut)
00997 {
00998 if (!d->activationAction) {
00999 d->activationAction = new KAction(this);
01000
01001 d->activationAction->setText(name());
01002 d->activationAction->setObjectName(QString("Activate %1 Widget").arg(name()));
01003 connect(d->activationAction, SIGNAL(triggered()), this, SIGNAL(activate()));
01004 connect(this, SIGNAL(activate()), this, SLOT(setFocus()));
01005
01006 QList<QWidget *> widgets = d->actions.associatedWidgets();
01007 foreach (QWidget *w, widgets) {
01008 w->addAction(d->activationAction);
01009 }
01010 }
01011
01012 d->activationAction->setGlobalShortcut(shortcut);
01013 }
01014
01015 KShortcut Applet::globalShortcut() const
01016 {
01017 if (d->activationAction) {
01018 return d->activationAction->globalShortcut();
01019 }
01020
01021 return KShortcut();
01022 }
01023
01024 void Applet::addAssociatedWidget(QWidget *widget)
01025 {
01026 d->actions.addAssociatedWidget(widget);
01027 }
01028
01029 void Applet::removeAssociatedWidget(QWidget *widget)
01030 {
01031 d->actions.removeAssociatedWidget(widget);
01032 }
01033
01034 Location Applet::location() const
01035 {
01036 Containment* c = containment();
01037 return c ? c->d->location : Plasma::Desktop;
01038 }
01039
01040 Plasma::AspectRatioMode Applet::aspectRatioMode() const
01041 {
01042 return d->aspectRatioMode;
01043 }
01044
01045 void Applet::setAspectRatioMode(Plasma::AspectRatioMode mode)
01046 {
01047 d->aspectRatioMode = mode;
01048 }
01049
01050 void Applet::registerAsDragHandle( QGraphicsItem * item )
01051 {
01052 if (!item) {
01053 return;
01054 }
01055
01056 int index = d->registeredAsDragHandle.indexOf(item);
01057
01058 if (index == -1) {
01059 d->registeredAsDragHandle.append(item);
01060 item->installSceneEventFilter(this);
01061 }
01062 }
01063
01064 void Applet::unregisterAsDragHandle(QGraphicsItem *item)
01065 {
01066 if (!item) {
01067 return;
01068 }
01069
01070 int index = d->registeredAsDragHandle.indexOf(item);
01071 if (index != -1) {
01072 d->registeredAsDragHandle.removeAt(index);
01073 item->removeSceneEventFilter(this);
01074 }
01075 }
01076
01077 bool Applet::isRegisteredAsDragHandle( QGraphicsItem * item )
01078 {
01079 return (d->registeredAsDragHandle.indexOf(item) != -1);
01080 }
01081
01082 bool Applet::hasConfigurationInterface() const
01083 {
01084 return d->hasConfigurationInterface;
01085 }
01086
01087 void Applet::setHasConfigurationInterface(bool hasInterface)
01088 {
01089 if (d->hasConfigurationInterface == hasInterface) {
01090 return;
01091 }
01092 d->hasConfigurationInterface = hasInterface;
01093
01094
01095 QAction *configAction = d->actions.action("configure");
01096 if (hasInterface) {
01097 if (! configAction) {
01098 configAction = new QAction(i18n("%1 Settings", name()), this);
01099 configAction->setIcon(KIcon("configure"));
01100 configAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
01101 if (isContainment()) {
01102
01103 configAction->setShortcut(QKeySequence("ctrl+shift+s"));
01104 } else {
01105 configAction->setShortcut(QKeySequence("ctrl+s"));
01106 }
01107
01108 connect(configAction, SIGNAL(triggered(bool)),
01109 this, SLOT(showConfigurationInterface()));
01110 d->actions.addAction("configure", configAction);
01111 }
01112 } else {
01113 d->actions.removeAction(configAction);
01114 }
01115 }
01116
01117 bool Applet::eventFilter( QObject *o, QEvent * e )
01118 {
01119 return QObject::eventFilter(o, e);
01120 }
01121
01122 bool Applet::sceneEventFilter( QGraphicsItem * watched, QEvent * event )
01123 {
01124 switch (event->type()) {
01125 case QEvent::GraphicsSceneMouseMove: {
01126
01127 if ((!containment() || containment()->immutability() == Mutable) && d->registeredAsDragHandle.contains( watched )) {
01128 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
01129 return true;
01130 }
01131 break;
01132 }
01133
01134 default:
01135 break;
01136 }
01137
01138 return QGraphicsItem::sceneEventFilter(watched, event);
01139 }
01140
01141 void Applet::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
01142 {
01143 if (immutability() == Mutable && formFactor() == Plasma::Planar) {
01144 QGraphicsItem *parent = parentItem();
01145 Plasma::Applet *applet = qgraphicsitem_cast<Plasma::Applet*>(parent);
01146
01147 if (applet && applet->isContainment()) {
01148
01149 QPointF curPos = event->pos();
01150 QPointF lastPos = event->lastPos();
01151 QPointF delta = curPos-lastPos;
01152
01153 moveBy(delta.x(),delta.y());
01154 } else if (parent) {
01155
01156
01157 QPointF curPos = parent->transform().map(event->pos());
01158 QPointF lastPos = parent->transform().map(event->lastPos());
01159 QPointF delta = curPos-lastPos;
01160
01161 parent->setPos(parent->pos() + delta);
01162 }
01163 }
01164 }
01165
01166 void Applet::mousePressEvent(QGraphicsSceneMouseEvent *event)
01167 {
01168 setFocus(Qt::MouseFocusReason);
01169 QGraphicsWidget::mousePressEvent(event);
01170 }
01171
01172 void Applet::focusInEvent(QFocusEvent * event)
01173 {
01174 if (!isContainment() && containment()) {
01175
01176 containment()->d->focusApplet(this);
01177 }
01178
01179 QGraphicsWidget::focusInEvent(event);
01180 }
01181
01182 void Applet::resizeEvent(QGraphicsSceneResizeEvent *event)
01183 {
01184 QGraphicsWidget::resizeEvent(event);
01185
01186 if (d->background) {
01187 d->background->resizePanel(boundingRect().size());
01188 }
01189
01190 updateConstraints(Plasma::SizeConstraint);
01191 emit geometryChanged();
01192 }
01193
01194 void Applet::showConfigurationInterface()
01195 {
01196 if (!hasConfigurationInterface()) {
01197 return;
01198 }
01199
01200 const QString dialogId = QString("%1settings%2").arg(id()).arg(name());
01201 KConfigDialog * dlg = KConfigDialog::exists(dialogId);
01202
01203 if (dlg) {
01204 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
01205 dlg->show();
01206 KWindowSystem::activateWindow(dlg->winId());
01207 return;
01208 }
01209
01210 const QString windowTitle = i18nc("@title:window", "%1 Settings", name());
01211 if (d->package && d->configXml) {
01212 QString uiFile = d->package->filePath("mainconfigui");
01213 if (uiFile.isEmpty()) {
01214 return;
01215 }
01216
01217 KConfigDialog *dialog = new KConfigDialog(0, dialogId, d->configXml);
01218 dialog->setWindowTitle(windowTitle);
01219 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01220
01221 QUiLoader loader;
01222 QFile f(uiFile);
01223 if (!f.open(QIODevice::ReadOnly)) {
01224 delete dialog;
01225
01226 if (d->script) {
01227 d->script->showConfigurationInterface();
01228 }
01229 return;
01230 }
01231
01232 QWidget *w = loader.load(&f);
01233 f.close();
01234
01235 dialog->addPage(w, i18n("Settings"), icon(), i18n("%1 Settings", name()));
01236 dialog->show();
01237 } else if (d->script) {
01238 d->script->showConfigurationInterface();
01239 } else {
01240 KConfigSkeleton *nullManager = new KConfigSkeleton(0);
01241 KConfigDialog *dialog = new KConfigDialog(0, dialogId, nullManager);
01242 dialog->setFaceType(KPageDialog::Auto);
01243 dialog->setWindowTitle(windowTitle);
01244 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01245 createConfigurationInterface(dialog);
01246
01247 connect(dialog, SIGNAL(finished()), nullManager, SLOT(deleteLater()));
01248
01249 dialog->showButton( KDialog::Apply, false );
01250 dialog->show();
01251 }
01252
01253 emit releaseVisualFocus();
01254 }
01255
01256 void Applet::createConfigurationInterface(KConfigDialog *parent)
01257 {
01258 Q_UNUSED(parent)
01259
01260
01261 }
01262
01263 KPluginInfo::List Applet::listAppletInfo(const QString &category,
01264 const QString &parentApp)
01265 {
01266 QString constraint;
01267
01268 if (parentApp.isEmpty()) {
01269 constraint.append("not exist [X-KDE-ParentApp]");
01270 } else {
01271 constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
01272 }
01273
01274 if (!category.isEmpty()) {
01275 if (!constraint.isEmpty()) {
01276 constraint.append(" and ");
01277 }
01278
01279 constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
01280 if (category == "Miscellaneous") {
01281 constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
01282 }
01283 }
01284
01285 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01286
01287 return KPluginInfo::fromServices(offers);
01288 }
01289
01290 KPluginInfo::List Applet::listAppletInfoForMimetype(const QString &mimetype)
01291 {
01292 QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
01293
01294 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01295 return KPluginInfo::fromServices(offers);
01296 }
01297
01298 QStringList Applet::listCategories(const QString &parentApp, bool visibleOnly)
01299 {
01300 QString constraint = "exist [X-KDE-PluginInfo-Category]";
01301
01302 if (parentApp.isEmpty()) {
01303 constraint.append(" and not exist [X-KDE-ParentApp]");
01304 } else {
01305 constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
01306 }
01307
01308 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01309 QStringList categories;
01310 foreach (const KService::Ptr &applet, offers) {
01311 QString appletCategory = applet->property("X-KDE-PluginInfo-Category").toString();
01312 if (visibleOnly && applet->noDisplay()) {
01313
01314 continue;
01315 }
01316
01317
01318 if (appletCategory.isEmpty()) {
01319 if (!categories.contains(i18n("Miscellaneous"))) {
01320 categories << i18n("Miscellaneous");
01321 }
01322 } else if (!categories.contains(appletCategory)) {
01323 categories << appletCategory;
01324 }
01325 }
01326
01327 categories.sort();
01328 return categories;
01329 }
01330
01331 Applet* Applet::load(const QString& appletName, uint appletId, const QVariantList& args)
01332 {
01333 if (appletName.isEmpty()) {
01334 return 0;
01335 }
01336
01337 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
01338 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01339
01340 bool isContainment = false;
01341 if (offers.isEmpty()) {
01342
01343
01344 offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
01345 isContainment = true;
01346 if (offers.isEmpty()) {
01347 kDebug() << "offers is empty for " << appletName;
01348 return 0;
01349 }
01350 }
01351
01352
01353
01354 KService::Ptr offer = offers.first();
01355
01356 if (appletId == 0) {
01357 appletId = ++AppletPrivate::s_maxAppletId;
01358 }
01359
01360 if (!offer->property("X-Plasma-API").toString().isEmpty()) {
01361 kDebug() << "we have a script using the" << offer->property("X-Plasma-API").toString() << "API";
01362 if (isContainment) {
01363 return new Containment(0, offer->storageId(), appletId);
01364 }
01365 return new Applet(0, offer->storageId(), appletId);
01366 }
01367
01368 KPluginLoader plugin(*offer);
01369
01370 if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
01371 return 0;
01372 }
01373
01374 QVariantList allArgs;
01375 allArgs << offer->storageId() << appletId << args;
01376 QString error;
01377 Applet* applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
01378
01379 if (!applet) {
01380 kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error;
01381 }
01382
01383 return applet;
01384 }
01385
01386 Applet* Applet::load(const KPluginInfo& info, uint appletId, const QVariantList& args)
01387 {
01388 if (!info.isValid()) {
01389 return 0;
01390 }
01391
01392 return load(info.pluginName(), appletId, args);
01393 }
01394
01395 QVariant Applet::itemChange(GraphicsItemChange change, const QVariant &value)
01396 {
01397
01398 switch (change) {
01399 case ItemPositionChange:
01400 if (d->shadow) {
01401 d->shadow->adjustPosition();
01402 }
01403 break;
01404 case ItemSceneHasChanged: {
01405 QGraphicsScene *newScene = qvariant_cast<QGraphicsScene*>(value);
01406 if (newScene) {
01407 d->checkImmutability();
01408 }
01409
01410 if (d->shadow) {
01411 if (d->shadow->scene()) {
01412 d->shadow->scene()->removeItem(d->shadow);
01413 }
01414
01415 if (newScene) {
01416 newScene->addItem(d->shadow);
01417 d->shadow->generate();
01418 d->shadow->adjustPosition();
01419 d->shadow->show();
01420 }
01421 }
01422 }
01423 break;
01424 case ItemVisibleChange:
01425 if (d->shadow) {
01426 d->shadow->setVisible(isVisible());
01427 }
01428 break;
01429 case ItemPositionHasChanged:
01430 emit geometryChanged();
01431 break;
01432 default:
01433 break;
01434 };
01435
01436 return QGraphicsWidget::itemChange(change, value);
01437 }
01438
01439 QPainterPath Applet::shape() const
01440 {
01441 if (d->script) {
01442 return d->script->shape();
01443 }
01444
01445 return QGraphicsWidget::shape();
01446 }
01447
01448 QSizeF Applet::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
01449 {
01450 QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
01451
01452
01453 if (formFactor() == Horizontal && which == Qt::MinimumSize) {
01454 hint.setHeight(0);
01455 } else if (formFactor() == Vertical && which == Qt::MinimumSize) {
01456 hint.setWidth(0);
01457 }
01458
01459
01460 if (d->aspectRatioMode == Plasma::Square) {
01461 if (formFactor() == Horizontal) {
01462 hint.setWidth(size().height());
01463 } else if (formFactor() == Vertical) {
01464 hint.setHeight(size().width());
01465 }
01466 } else if (d->aspectRatioMode == Plasma::ConstrainedSquare) {
01467
01468 if (formFactor() == Horizontal && (which == Qt::MaximumSize || size().height() <= KIconLoader::SizeLarge)) {
01469 hint.setWidth(size().height());
01470
01471 } else if (formFactor() == Vertical && (which == Qt::MaximumSize || size().width() <= KIconLoader::SizeLarge)) {
01472 hint.setHeight(size().width());
01473 }
01474 }
01475
01476 return hint;
01477 }
01478
01479 void Applet::timerEvent(QTimerEvent *event)
01480 {
01481 if (event->timerId() == d->constraintsTimerId) {
01482 killTimer(d->constraintsTimerId);
01483 d->constraintsTimerId = 0;
01484 flushPendingConstraintsEvents();
01485 }
01486 }
01487
01488 QRect Applet::screenRect() const
01489 {
01490 QPointF bottomRight = pos();
01491 bottomRight.setX(bottomRight.x() + size().width());
01492 bottomRight.setY(bottomRight.y() + size().height());
01493
01494 Containment *c;
01495 c = containment();
01496
01497 if (c) {
01498 QGraphicsView *v;
01499 v = c->view();
01500
01501 if (v) {
01502 QPoint tL = v->mapToGlobal(v->mapFromScene(pos()));
01503 QPoint bR = v->mapToGlobal(v->mapFromScene(bottomRight));
01504
01505 kDebug() << "screenRect = " << QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y());
01506 return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
01507 }
01508 }
01509
01510
01511
01512 return QRect(QPoint(0, 0), QSize(0, 0));
01513 }
01514
01515 void Applet::raise()
01516 {
01517 setZValue(++AppletPrivate::s_maxZValue);
01518 }
01519
01520 void Applet::lower()
01521 {
01522 setZValue(--AppletPrivate::s_minZValue);
01523 }
01524
01525 void Applet::setIsContainment(bool isContainment)
01526 {
01527 if (d->isContainment == isContainment) {
01528 return;
01529 }
01530
01531 d->isContainment = isContainment;
01532
01533 Containment *c = qobject_cast<Containment*>(this);
01534 if (c) {
01535 if (isContainment) {
01536
01537 c->d->createToolBox();
01538 } else {
01539 delete c->d->toolBox;
01540 c->d->toolBox = 0;
01541 }
01542 }
01543 }
01544
01545 bool Applet::isContainment() const
01546 {
01547 return d->isContainment;
01548 }
01549
01550
01551
01552
01553 AppletPrivate::AppletPrivate(KService::Ptr service, int uniqueID, Applet *applet)
01554 : appletId(uniqueID),
01555 q(applet),
01556 backgroundHints(Applet::StandardBackground),
01557 appletDescription(service),
01558 package(0),
01559 needsConfigOverlay(0),
01560 background(0),
01561 script(0),
01562 configXml(0),
01563 shadow(0),
01564 mainConfig(0),
01565 pendingConstraints(NoConstraint),
01566 aspectRatioMode(Plasma::KeepAspectRatio),
01567 ghostView(0),
01568 immutability(Mutable),
01569 actions(applet),
01570 activationAction(0),
01571 constraintsTimerId(0),
01572 hasConfigurationInterface(false),
01573 failed(false),
01574 isContainment(false),
01575 transient(false)
01576 {
01577 if (appletId == 0) {
01578 appletId = ++s_maxAppletId;
01579 } else if (appletId > s_maxAppletId) {
01580 s_maxAppletId = appletId;
01581 }
01582 }
01583
01584 AppletPrivate::~AppletPrivate()
01585 {
01586 foreach ( const QString& engine, loadedEngines ) {
01587 DataEngineManager::self()->unloadEngine( engine );
01588 }
01589 delete background;
01590 delete package;
01591 delete configXml;
01592 delete shadow;
01593 delete mainConfig;
01594 }
01595
01596 void AppletPrivate::init()
01597 {
01598
01599
01600 q->setCacheMode(Applet::DeviceCoordinateCache);
01601 q->setAcceptsHoverEvents(true);
01602 q->setFlag(QGraphicsItem::ItemIsFocusable, true);
01603
01604
01605 q->setLayoutDirection(qApp->layoutDirection());
01606
01607 if (!appletDescription.isValid()) {
01608 kDebug() << "Check your constructor! You probably want to be passing in a Service::Ptr or a QVariantList with a valid storageid as arg[0].";
01609 return;
01610 }
01611
01612 QString api = appletDescription.property("X-Plasma-API").toString();
01613
01614
01615 if (!api.isEmpty()) {
01616
01617 QString path = KStandardDirs::locate("data",
01618 "plasma/plasmoids/" + appletDescription.pluginName() + "/");
01619
01620 if (path.isEmpty()) {
01621 q->setFailedToLaunch(true, i18n("Could not locate the %1 package required for the %2 widget.",
01622 appletDescription.pluginName(), appletDescription.name()));
01623 } else {
01624
01625
01626 PackageStructure::Ptr structure = Plasma::packageStructure(api, Plasma::AppletComponent);
01627 structure->setPath(path);
01628 package = new Package(path, structure);
01629
01630 if (package->isValid()) {
01631
01632
01633
01634
01635 script = Plasma::loadScriptEngine(api, q);
01636 if (!script) {
01637 delete package;
01638 package = 0;
01639 q->setFailedToLaunch(true, i18n("Could not create a %1 ScriptEngine for the %2 widget.",
01640 api, appletDescription.name()));
01641 }
01642 } else {
01643 q->setFailedToLaunch(true, i18n("Could not open the %1 package required for the %2 widget.",
01644 appletDescription.pluginName(), appletDescription.name()));
01645 delete package;
01646 package = 0;
01647 }
01648
01649 if (package) {
01650 setupScriptSupport();
01651 }
01652 }
01653 }
01654
01655 q->setBackgroundHints(Applet::DefaultBackground);
01656
01657 QObject::connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), q, SLOT(themeChanged()));
01658 }
01659
01660
01661
01662 void AppletPrivate::setupScriptSupport()
01663 {
01664 Q_ASSERT(package);
01665 QString xmlPath = package->filePath("mainconfigxml");
01666 if (!xmlPath.isEmpty()) {
01667 QFile file(xmlPath);
01668
01669 KConfigGroup config = q->config();
01670 configXml = new ConfigXml(&config, &file);
01671 }
01672
01673 if (!package->filePath("mainconfigui").isEmpty()) {
01674 q->setHasConfigurationInterface(true);
01675 }
01676 }
01677
01678 QString AppletPrivate::globalName() const
01679 {
01680 if (!appletDescription.isValid()) {
01681 return QString();
01682 }
01683
01684 return appletDescription.service()->library();
01685 }
01686
01687 QString AppletPrivate::instanceName()
01688 {
01689 if (!appletDescription.isValid()) {
01690 return QString();
01691 }
01692
01693 return appletDescription.service()->library() + QString::number(appletId);
01694 }
01695
01696 void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
01697 {
01698 if (!constraintsTimerId) {
01699 constraintsTimerId = q->startTimer(0);
01700 }
01701 pendingConstraints |= c;
01702 }
01703
01704 KConfigGroup* AppletPrivate::mainConfigGroup()
01705 {
01706 if (mainConfig) {
01707 return mainConfig;
01708 }
01709
01710 if (isContainment) {
01711 const Containment *asContainment = qobject_cast<Containment*>(const_cast<Applet*>(q));
01712 Q_ASSERT(asContainment);
01713
01714 KConfigGroup containmentConfig;
01715
01716 if (asContainment->corona()) {
01717 containmentConfig = KConfigGroup(asContainment->corona()->config(), "Containments");
01718 } else {
01719 containmentConfig = KConfigGroup(KGlobal::config(), "Containments");
01720 }
01721
01722 mainConfig = new KConfigGroup(&containmentConfig, QString::number(appletId));
01723 } else {
01724 KConfigGroup appletConfig;
01725 if (q->containment()) {
01726 appletConfig = q->containment()->config();
01727 appletConfig = KConfigGroup(&appletConfig, "Applets");
01728 } else {
01729 kWarning() << "requesting config for" << q->name() << "without a containment!";
01730 appletConfig = KConfigGroup(KGlobal::config(), "Applets");
01731 }
01732
01733 mainConfig = new KConfigGroup(&appletConfig, QString::number(appletId));
01734 }
01735
01736 return mainConfig;
01737 }
01738
01739 QString AppletPrivate::visibleFailureText(const QString& reason)
01740 {
01741 QString text;
01742
01743 if (reason.isEmpty()) {
01744 text = i18n("This object could not be created.");
01745 } else {
01746 text = i18n("This object could not be created for the following reason:<p><b>%1</b></p>", reason);
01747 }
01748
01749 return text;
01750 }
01751
01752 void AppletPrivate::checkImmutability()
01753 {
01754 const bool systemImmutable = q->globalConfig().isImmutable() || q->config().isImmutable() ||
01755 ((!isContainment && q->containment()) &&
01756 q->containment()->immutability() == SystemImmutable) ||
01757 (dynamic_cast<Corona*>(q->scene()) && static_cast<Corona*>(q->scene())->immutability() == SystemImmutable);
01758
01759 if (systemImmutable) {
01760 q->updateConstraints(ImmutableConstraint);
01761 }
01762 }
01763
01764 void AppletPrivate::themeChanged()
01765 {
01766 if (background) {
01767
01768 q->setBackgroundHints(backgroundHints);
01769
01770 qreal left;
01771 qreal right;
01772 qreal top;
01773 qreal bottom;
01774 background->getMargins(left, top, right, bottom);
01775 q->setContentsMargins(left, right, top, bottom);
01776 }
01777 q->update();
01778 }
01779
01780 void AppletPrivate::resetConfigurationObject()
01781 {
01782 mainConfigGroup()->deleteGroup();
01783 delete mainConfig;
01784 mainConfig = 0;
01785 }
01786
01787 uint AppletPrivate::s_maxAppletId = 0;
01788 uint AppletPrivate::s_maxZValue = 0;
01789 uint AppletPrivate::s_minZValue = 0;
01790 PackageStructure::Ptr AppletPrivate::packageStructure(0);
01791
01792 AppletOverlayWidget::AppletOverlayWidget(QGraphicsWidget *parent)
01793 : QGraphicsWidget(parent)
01794 {
01795 resize(parent->size());
01796 }
01797
01798 void AppletOverlayWidget::paint(QPainter *painter,
01799 const QStyleOptionGraphicsItem *option,
01800 QWidget *widget)
01801 {
01802 Q_UNUSED(option)
01803 Q_UNUSED(widget)
01804 painter->save();
01805 painter->setRenderHint(QPainter::Antialiasing);
01806 QColor wash = Plasma::Theme::defaultTheme()->color(Theme::BackgroundColor);
01807 wash.setAlphaF(.6);
01808 painter->fillPath(parentItem()->shape(), wash);
01809 painter->restore();
01810 }
01811
01812 }
01813
01814 #include "applet.moc"