00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "containment.h"
00022 #include "private/containment_p.h"
00023
00024 #include <QApplication>
00025 #include <QClipboard>
00026 #include <QFile>
00027 #include <QGraphicsSceneContextMenuEvent>
00028 #include <QGraphicsView>
00029 #include <QMimeData>
00030 #include <QPainter>
00031 #include <QStyleOptionGraphicsItem>
00032 #include <QGraphicsLayout>
00033 #include <QGraphicsLinearLayout>
00034
00035 #include <kaction.h>
00036 #include <kauthorized.h>
00037 #include <kicon.h>
00038 #include <kmenu.h>
00039 #include <kmessagebox.h>
00040 #include <kmimetype.h>
00041 #include <krun.h>
00042 #include <kservicetypetrader.h>
00043 #include <kstandarddirs.h>
00044 #include <ktemporaryfile.h>
00045 #include <kwindowsystem.h>
00046
00047 #include "animator.h"
00048 #include "context.h"
00049 #include "corona.h"
00050 #include "extenderitem.h"
00051 #include "svg.h"
00052 #include "wallpaper.h"
00053
00054 #include "private/applet_p.h"
00055 #include "private/applethandle_p.h"
00056 #include "private/desktoptoolbox_p.h"
00057 #include "private/extenderitemmimedata_p.h"
00058 #include "private/paneltoolbox_p.h"
00059
00060 namespace Plasma
00061 {
00062
00063 bool ContainmentPrivate::s_positioning = false;
00064 static const char defaultWallpaper[] = "image";
00065 static const char defaultWallpaperMode[] = "SingleImage";
00066
00067 Containment::StyleOption::StyleOption()
00068 : QStyleOptionGraphicsItem(),
00069 view(0)
00070 {
00071 version = Version;
00072 type = Type;
00073 }
00074
00075 Containment::StyleOption::StyleOption(const Containment::StyleOption & other)
00076 : QStyleOptionGraphicsItem(other),
00077 view(other.view)
00078 {
00079 version = Version;
00080 type = Type;
00081 }
00082
00083 Containment::StyleOption::StyleOption(const QStyleOptionGraphicsItem &other)
00084 : QStyleOptionGraphicsItem(other),
00085 view(0)
00086 {
00087 version = Version;
00088 type = Type;
00089 }
00090
00091 Containment::Containment(QGraphicsItem *parent,
00092 const QString &serviceId,
00093 uint containmentId)
00094 : Applet(parent, serviceId, containmentId),
00095 d(new ContainmentPrivate(this))
00096 {
00097
00098
00099 setPos(0, 0);
00100 setBackgroundHints(NoBackground);
00101 setContainmentType(CustomContainment);
00102 setHasConfigurationInterface(false);
00103 }
00104
00105 Containment::Containment(QObject *parent, const QVariantList &args)
00106 : Applet(parent, args),
00107 d(new ContainmentPrivate(this))
00108 {
00109
00110
00111 setPos(0, 0);
00112 setBackgroundHints(NoBackground);
00113 setHasConfigurationInterface(false);
00114 }
00115
00116 Containment::~Containment()
00117 {
00118 delete d;
00119 }
00120
00121 void Containment::init()
00122 {
00123 if (!isContainment()) {
00124 return;
00125 }
00126
00127 setCacheMode(NoCache);
00128 setFlag(QGraphicsItem::ItemIsMovable, false);
00129 setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
00130 setAcceptDrops(true);
00131 setAcceptsHoverEvents(true);
00132
00133
00134 connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00135 this, SLOT(containmentAppletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00136
00137 if (d->type == NoContainmentType) {
00138 setContainmentType(DesktopContainment);
00139 }
00140
00141
00142 ContainmentPrivate::addDefaultActions(d->actions());
00143 bool unlocked = immutability() == Mutable;
00144
00145
00146
00147 QAction *closeApplet = action("remove");
00148 if (closeApplet) {
00149 closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
00150 }
00151
00152 QAction *configAction = action("configure");
00153 if (configAction) {
00154 configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", name()));
00155 }
00156
00157 QAction *appletBrowserAction = action("add widgets");
00158 if (appletBrowserAction) {
00159 appletBrowserAction->setVisible(unlocked);
00160 appletBrowserAction->setEnabled(unlocked);
00161 connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
00162 }
00163
00164 QAction *act = action("next applet");
00165 if (act) {
00166 connect(act, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
00167 }
00168
00169 act = action("previous applet");
00170 if (act) {
00171 connect(act, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
00172 }
00173
00174 if (immutability() != SystemImmutable && corona()) {
00175 QAction *lockDesktopAction = corona()->action("lock widgets");
00176
00177 if (lockDesktopAction) {
00178 d->actions()->addAction("lock widgets", lockDesktopAction);
00179 }
00180 }
00181
00182 if (d->type == PanelContainment ||
00183 d->type == CustomPanelContainment) {
00184 d->actions()->removeAction(action("zoom in"));
00185 } else {
00186 QAction *zoomAction = action("zoom in");
00187 connect(zoomAction, SIGNAL(triggered()), this, SLOT(zoomIn()));
00188
00189 if (corona()) {
00190 QAction *action = corona()->action("zoom out");
00191 if (action) {
00192 d->actions()->addAction("zoom out", action);
00193 }
00194 action = corona()->action("add sibling containment");
00195 if (action) {
00196 d->actions()->addAction("add sibling containment", action);
00197 }
00198
00199 action = corona()->action("configure shortcuts");
00200 if (action) {
00201 d->actions()->addAction("configure shortcuts", action);
00202 }
00203 }
00204
00205 if (d->type == DesktopContainment && d->toolBox) {
00206 d->toolBox->addTool(this->action("add widgets"));
00207 d->toolBox->addTool(this->action("zoom in"));
00208
00209
00210
00211
00212 QAction *configureContainment = this->action("configure");
00213 if (configureContainment) {
00214 d->toolBox->addTool(configureContainment);
00215 }
00216 }
00217
00218
00219
00220 if (d->drawWallpaper) {
00221 setDrawWallpaper(true);
00222 }
00223 }
00224
00225 }
00226
00227 void ContainmentPrivate::addDefaultActions(KActionCollection *actions)
00228 {
00229 actions->setConfigGroup("Shortcuts-Containment");
00230
00231
00232 KAction *appAction = qobject_cast<KAction*>(actions->action("remove"));
00233 appAction->setShortcut(KShortcut("alt+d, alt+r"));
00234 appAction->setText(i18n("Remove this Activity"));
00235 appAction = qobject_cast<KAction*>(actions->action("configure"));
00236 if (appAction) {
00237 appAction->setShortcut(KShortcut("alt+d, alt+s"));
00238 appAction->setText(i18n("Activity Settings"));
00239 }
00240
00241
00242 KAction *appletBrowserAction = actions->addAction("add widgets");
00243 appletBrowserAction->setAutoRepeat(false);
00244 appletBrowserAction->setText(i18n("Add Widgets..."));
00245 appletBrowserAction->setIcon(KIcon("list-add"));
00246 appletBrowserAction->setShortcut(KShortcut("alt+d, a"));
00247
00248 KAction *action = actions->addAction("next applet");
00249 action->setText(i18n("Next Widget"));
00250
00251 action->setShortcut(KShortcut("alt+d, n"));
00252
00253 action = actions->addAction("previous applet");
00254 action->setText(i18n("Previous Widget"));
00255
00256 action->setShortcut(KShortcut("alt+d, p"));
00257
00258 KAction *zoomAction = actions->addAction("zoom in");
00259 zoomAction->setAutoRepeat(false);
00260 zoomAction->setText(i18n("Zoom In"));
00261 zoomAction->setIcon(KIcon("zoom-in"));
00262
00263 zoomAction->setShortcuts(KShortcut("alt+d, +; alt+d, ="));
00264
00265 }
00266
00267
00268 bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
00269 {
00270 QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
00271 QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
00272
00273 if (!qFuzzyCompare(p1.x(), p2.x())) {
00274 if (QApplication::layoutDirection() == Qt::RightToLeft) {
00275 return p1.x() > p2.x();
00276 }
00277
00278 return p1.x() < p2.x();
00279 }
00280
00281 return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
00282 }
00283
00284 void Containment::restore(KConfigGroup &group)
00285 {
00286
00287
00288
00289
00290
00291 if (!isContainment()) {
00292 Applet::restore(group);
00293 return;
00294 }
00295
00296 QRectF geo = group.readEntry("geometry", geometry());
00297
00298
00299
00300 if (geo.size() != geo.size().boundedTo(maximumSize())) {
00301 setMaximumSize(maximumSize().expandedTo(geo.size()));
00302 }
00303 if (geo.size() != geo.size().expandedTo(minimumSize())) {
00304 setMinimumSize(minimumSize().boundedTo(geo.size()));
00305 }
00306
00307
00308 setGeometry(geo);
00309
00310 if (containmentType() != PanelContainment && containmentType() != CustomPanelContainment && geo.right() < 0) {
00311 corona()->addOffscreenWidget(this);
00312 }
00313
00314 setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
00315 setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
00316
00317 setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop));
00318 setActivity(group.readEntry("activity", QString()));
00319
00320 flushPendingConstraintsEvents();
00321 restoreContents(group);
00322 setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00323
00324 setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
00325 group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
00326
00327 if (d->toolBox) {
00328 d->toolBox->load(group);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338 }
00339
00340 void Containment::save(KConfigGroup &g) const
00341 {
00342 if (Applet::d->transient) {
00343 return;
00344 }
00345
00346 KConfigGroup group = g;
00347 if (!group.isValid()) {
00348 group = config();
00349 }
00350
00351
00352 Applet::save(group);
00353 group.writeEntry("screen", d->screen);
00354 group.writeEntry("desktop", d->desktop);
00355 group.writeEntry("formfactor", (int)d->formFactor);
00356 group.writeEntry("location", (int)d->location);
00357 group.writeEntry("activity", d->context()->currentActivity());
00358
00359 if (d->toolBox) {
00360 d->toolBox->save(group);
00361 }
00362
00363 if (d->wallpaper) {
00364 group.writeEntry("wallpaperplugin", d->wallpaper->pluginName());
00365 group.writeEntry("wallpaperpluginmode", d->wallpaper->renderingMode().name());
00366
00367 if (d->wallpaper->isInitialized()) {
00368 KConfigGroup wallpaperConfig(&group, "Wallpaper");
00369 wallpaperConfig = KConfigGroup(&wallpaperConfig, d->wallpaper->pluginName());
00370 d->wallpaper->save(wallpaperConfig);
00371 }
00372 }
00373
00374 saveContents(group);
00375 }
00376
00377 void Containment::saveContents(KConfigGroup &group) const
00378 {
00379 KConfigGroup applets(&group, "Applets");
00380 foreach (const Applet *applet, d->applets) {
00381 KConfigGroup appletConfig(&applets, QString::number(applet->id()));
00382 applet->save(appletConfig);
00383 }
00384 }
00385
00386 void Containment::restoreContents(KConfigGroup &group)
00387 {
00388 KConfigGroup applets(&group, "Applets");
00389
00390
00391
00392 QList<KConfigGroup> appletConfigs;
00393 foreach (const QString &appletGroup, applets.groupList()) {
00394
00395 KConfigGroup appletConfig(&applets, appletGroup);
00396 appletConfigs.append(appletConfig);
00397 }
00398 qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
00399
00400 QMutableListIterator<KConfigGroup> it(appletConfigs);
00401 while (it.hasNext()) {
00402 KConfigGroup &appletConfig = it.next();
00403 int appId = appletConfig.name().toUInt();
00404 QString plugin = appletConfig.readEntry("plugin", QString());
00405
00406 if (plugin.isEmpty()) {
00407 continue;
00408 }
00409
00410 Applet *applet = d->addApplet(plugin, QVariantList(),
00411 appletConfig.readEntry("geometry", QRectF()),
00412 appId, true);
00413 applet->restore(appletConfig);
00414 }
00415 }
00416
00417 Containment::Type Containment::containmentType() const
00418 {
00419 return d->type;
00420 }
00421
00422 void Containment::setContainmentType(Containment::Type type)
00423 {
00424 if (d->type == type) {
00425 return;
00426 }
00427
00428 delete d->toolBox;
00429 d->toolBox = 0;
00430 d->type = type;
00431
00432 if (!isContainment()) {
00433 return;
00434 }
00435
00436 if (type == DesktopContainment || type == PanelContainment) {
00437 d->createToolBox();
00438 }
00439
00440 d->checkRemoveAction();
00441 }
00442
00443 Corona *Containment::corona() const
00444 {
00445 return dynamic_cast<Corona*>(scene());
00446 }
00447
00448 void Containment::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00449 {
00450 event->ignore();
00451 if (d->wallpaper && d->wallpaper->isInitialized()) {
00452 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00453 if (item == this) {
00454 d->wallpaper->mouseMoveEvent(event);
00455 }
00456 }
00457
00458 if (!event->isAccepted()) {
00459 event->accept();
00460 Applet::mouseMoveEvent(event);
00461 }
00462 }
00463
00464 void Containment::mousePressEvent(QGraphicsSceneMouseEvent *event)
00465 {
00466 event->ignore();
00467 if (d->wallpaper && d->wallpaper->isInitialized()) {
00468 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00469 if (item == this) {
00470 d->wallpaper->mousePressEvent(event);
00471 }
00472 }
00473
00474 if (event->isAccepted()) {
00475 setFocus(Qt::MouseFocusReason);
00476 } else if (event->button() == Qt::MidButton) {
00477
00478 event->accept();
00479 } else {
00480 event->accept();
00481 Applet::mousePressEvent(event);
00482 }
00483 }
00484
00485 void Containment::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00486 {
00487 event->ignore();
00488 if (d->wallpaper && d->wallpaper->isInitialized()) {
00489 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00490 if (item == this) {
00491 d->wallpaper->mouseReleaseEvent(event);
00492 }
00493 }
00494
00495 if (event->isAccepted() || !isContainment()) {
00496
00497 } else if (event->button() == Qt::MidButton) {
00498
00499 d->dropData(event);
00500 event->accept();
00501 } else {
00502 event->accept();
00503 Applet::mouseReleaseEvent(event);
00504 }
00505 }
00506
00507 void Containment::showDropZone(const QPoint pos)
00508 {
00509 Q_UNUSED(pos)
00510
00511 }
00512
00513 void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
00514 {
00515 d->showContextMenu(mapToScene(containmentPos), screenPos, false);
00516 }
00517
00518 void Containment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
00519 {
00520
00521 if (!isContainment() || !scene() || !KAuthorized::authorizeKAction("desktop_contextmenu")) {
00522 Applet::contextMenuEvent(event);
00523 return;
00524 }
00525
00526 if (!d->showContextMenu(event->scenePos(), event->screenPos(), true)) {
00527 Applet::contextMenuEvent(event);
00528 } else {
00529 event->accept();
00530 }
00531 }
00532
00533 void ContainmentPrivate::containmentActions(KMenu &desktopMenu)
00534 {
00535 if (static_cast<Corona*>(q->scene())->immutability() != Mutable &&
00536 !KAuthorized::authorizeKAction("unlock_desktop")) {
00537
00538 return;
00539 }
00540
00541
00542 QList<QAction*> actions = q->contextualActions();
00543
00544
00545 QAction *separatorAction = 0;
00546
00547
00548
00549 foreach (QAction *action, actions) {
00550 if (action) {
00551 desktopMenu.addAction(action);
00552 if (action->isSeparator()) {
00553 separatorAction = action;
00554 }
00555 }
00556 }
00557
00558 desktopMenu.addSeparator();
00559
00560 if (type == Containment::DesktopContainment) {
00561 desktopMenu.addAction(q->action("configure"));
00562 }
00563 }
00564
00565 void ContainmentPrivate::appletActions(KMenu &desktopMenu, Applet *applet, bool includeApplet)
00566 {
00567 QList<QAction*> actions;
00568
00569 if (includeApplet) {
00570 actions = applet->contextualActions();
00571 if (!actions.isEmpty()) {
00572 foreach (QAction *action, actions) {
00573 if (action) {
00574 desktopMenu.addAction(action);
00575 }
00576 }
00577 }
00578 }
00579
00580 if (applet->hasConfigurationInterface()) {
00581 QAction *configureApplet = applet->d->actions->action("configure");
00582 if (configureApplet) {
00583 desktopMenu.addAction(configureApplet);
00584 }
00585 }
00586
00587
00588 if (static_cast<Corona*>(q->scene())->immutability() == Mutable) {
00589 if (!desktopMenu.isEmpty()) {
00590 desktopMenu.addSeparator();
00591 }
00592
00593 QAction *closeApplet = applet->d->actions->action("remove");
00594 if (closeApplet) {
00595 desktopMenu.addAction(closeApplet);
00596 }
00597 }
00598
00599 KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
00600 containmentActions(*containmentMenu);
00601 if (!containmentMenu->isEmpty()) {
00602 int enabled = 0;
00603
00604 foreach(QAction *action, containmentMenu->actions()) {
00605 if(action->isEnabled() && !action->isSeparator()) {
00606 enabled++;
00607 }
00608 }
00609
00610 if (enabled > 0) {
00611 desktopMenu.addSeparator();
00612 }
00613
00614
00615 if(enabled < 2) {
00616 foreach(QAction *action, containmentMenu->actions()) {
00617 desktopMenu.addAction(action);
00618 }
00619 } else {
00620 desktopMenu.addMenu(containmentMenu);
00621 }
00622 }
00623 }
00624
00625 bool ContainmentPrivate::showContextMenu(const QPointF &point, const QPoint &screenPos, bool includeApplet)
00626 {
00627 Applet *applet = 0;
00628
00629 QGraphicsItem *item = q->scene()->itemAt(point);
00630 if (item == q) {
00631 item = 0;
00632 }
00633
00634 while (item) {
00635 applet = qgraphicsitem_cast<Applet*>(item);
00636 if (applet && !applet->isContainment()) {
00637 break;
00638 }
00639
00640
00641 applet = 0;
00642 item = item->parentItem();
00643 }
00644
00645 KMenu desktopMenu;
00646
00647 if (applet) {
00648 appletActions(desktopMenu, applet, includeApplet);
00649 } else {
00650 containmentActions(desktopMenu);
00651 }
00652
00653 if (!desktopMenu.isEmpty()) {
00654
00655 desktopMenu.exec(screenPos);
00656 return true;
00657 }
00658
00659 return false;
00660 }
00661
00662 void Containment::setFormFactor(FormFactor formFactor)
00663 {
00664 if (d->formFactor == formFactor) {
00665 return;
00666 }
00667
00668
00669 d->formFactor = formFactor;
00670
00671 if (isContainment() &&
00672 (d->type == PanelContainment || d->type == CustomPanelContainment)) {
00673
00674 d->positionPanel(true);
00675 }
00676
00677 if (d->toolBox) {
00678 if (d->formFactor == Vertical) {
00679 d->toolBox->setCorner(ToolBox::Bottom);
00680
00681 } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
00682 d->toolBox->setCorner(ToolBox::Left);
00683 } else {
00684 d->toolBox->setCorner(ToolBox::Right);
00685 }
00686 }
00687
00688 updateConstraints(Plasma::FormFactorConstraint);
00689
00690 KConfigGroup c = config();
00691 c.writeEntry("formfactor", (int)formFactor);
00692 emit configNeedsSaving();
00693 }
00694
00695 void Containment::setLocation(Location location)
00696 {
00697 if (d->location == location) {
00698 return;
00699 }
00700
00701 bool emitGeomChange = false;
00702
00703 if ((location == TopEdge || location == BottomEdge) &&
00704 (d->location == TopEdge || d->location == BottomEdge)) {
00705 emitGeomChange = true;
00706 }
00707
00708 if ((location == RightEdge || location == LeftEdge) &&
00709 (d->location == RightEdge || d->location == LeftEdge)) {
00710 emitGeomChange = true;
00711 }
00712
00713 d->location = location;
00714
00715 foreach (Applet *applet, d->applets) {
00716 applet->updateConstraints(Plasma::LocationConstraint);
00717 }
00718
00719 if (emitGeomChange) {
00720
00721
00722 emit geometryChanged();
00723 }
00724
00725 updateConstraints(Plasma::LocationConstraint);
00726
00727 KConfigGroup c = config();
00728 c.writeEntry("location", (int)location);
00729 emit configNeedsSaving();
00730 }
00731
00732 void Containment::addSiblingContainment()
00733 {
00734 emit addSiblingContainment(this);
00735 }
00736
00737 void Containment::clearApplets()
00738 {
00739 foreach (Applet *applet, d->applets) {
00740 applet->d->cleanUpAndDelete();
00741 }
00742
00743 d->applets.clear();
00744 }
00745
00746 Applet *Containment::addApplet(const QString &name, const QVariantList &args,
00747 const QRectF &appletGeometry)
00748 {
00749 return d->addApplet(name, args, appletGeometry);
00750 }
00751
00752 void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
00753 {
00754 if (!isContainment() || (!delayInit && immutability() != Mutable)) {
00755 return;
00756 }
00757
00758 if (!applet) {
00759 kDebug() << "adding null applet!?!";
00760 return;
00761 }
00762
00763 if (d->applets.contains(applet)) {
00764 kDebug() << "already have this applet!";
00765 }
00766
00767 Containment *currentContainment = applet->containment();
00768
00769 if (d->type == PanelContainment) {
00770
00771 setBackgroundHints(NoBackground);
00772 }
00773
00774 if (currentContainment && currentContainment != this) {
00775 emit currentContainment->appletRemoved(applet);
00776 if (currentContainment->d->focusedApplet == applet) {
00777 currentContainment->d->focusedApplet = 0;
00778 }
00779
00780 disconnect(applet, 0, currentContainment, 0);
00781 applet->removeSceneEventFilter(currentContainment);
00782 KConfigGroup oldConfig = applet->config();
00783 currentContainment->d->applets.removeAll(applet);
00784 if (currentContainment->d->handles.contains(applet)) {
00785 currentContainment->d->handles.remove(applet);
00786 }
00787 applet->setParentItem(this);
00788
00789
00790
00791 KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
00792 oldConfig.reparent(&c);
00793 applet->d->resetConfigurationObject();
00794
00795 disconnect(applet, SIGNAL(activate()), currentContainment, SIGNAL(activate()));
00796 } else {
00797 applet->setParentItem(this);
00798 }
00799
00800 d->applets << applet;
00801
00802 connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
00803 connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
00804 connect(applet, SIGNAL(appletDestroyed(Plasma::Applet*)), this, SLOT(appletDestroyed(Plasma::Applet*)));
00805 connect(applet, SIGNAL(activate()), this, SIGNAL(activate()));
00806
00807 if (pos != QPointF(-1, -1)) {
00808 applet->setPos(pos);
00809 }
00810
00811 if (delayInit || currentContainment) {
00812 if (d->type == DesktopContainment) {
00813 applet->installSceneEventFilter(this);
00814
00815 }
00816 } else {
00817 applet->init();
00818 Animator::self()->animateItem(applet, Animator::AppearAnimation);
00819 }
00820
00821 applet->updateConstraints(Plasma::AllConstraints);
00822
00823 if (!delayInit) {
00824 applet->flushPendingConstraintsEvents();
00825 }
00826
00827 emit appletAdded(applet, pos);
00828
00829 if (!currentContainment) {
00830 applet->updateConstraints(Plasma::StartupCompletedConstraint);
00831 if (!delayInit) {
00832 applet->flushPendingConstraintsEvents();
00833 }
00834 }
00835
00836 if (!delayInit) {
00837 applet->d->scheduleModificationNotification();
00838 }
00839 }
00840
00841 Applet::List Containment::applets() const
00842 {
00843 return d->applets;
00844 }
00845
00846 void Containment::setScreen(int newScreen, int newDesktop)
00847 {
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858 Q_ASSERT(corona());
00859 int numScreens = corona()->numScreens();
00860 if (newScreen < -1) {
00861 newScreen = -1;
00862 }
00863
00864
00865 if (newDesktop < -1 || newDesktop > KWindowSystem::numberOfDesktops() - 1) {
00866 newDesktop = -1;
00867 }
00868
00869
00870
00871 Containment *swapScreensWith(0);
00872 if (d->type == DesktopContainment || d->type >= CustomContainment) {
00873
00874 if (d->screen < 0 && newScreen > -1) {
00875 connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(positionToolBox()));
00876 } else if (newScreen < 0) {
00877 disconnect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(positionToolBox()));
00878 }
00879
00880 if (newScreen > -1 && corona()) {
00881
00882 Containment *currently = corona()->containmentForScreen(newScreen, newDesktop);
00883 if (currently && currently != this) {
00884 kDebug() << "currently is on screen" << currently->screen()
00885 << "desktop" << currently->desktop()
00886 << "and is" << currently->activity()
00887 << (QObject*)currently << "i'm" << (QObject*)this;
00888
00889 currently->setScreen(-1, newDesktop);
00890 swapScreensWith = currently;
00891 }
00892 }
00893 }
00894
00895 if (newScreen < numScreens && newScreen > -1) {
00896 if (d->type == DesktopContainment ||
00897 d->type >= CustomContainment) {
00898 resize(corona()->screenGeometry(newScreen).size());
00899 }
00900 }
00901
00902 int oldDesktop = d->desktop;
00903 d->desktop = newDesktop;
00904
00905 int oldScreen = d->screen;
00906 d->screen = newScreen;
00907
00908 updateConstraints(Plasma::ScreenConstraint);
00909
00910 if (oldScreen != newScreen || oldDesktop != newDesktop) {
00911 if (oldScreen != newScreen) {
00912 emit screenChanged(oldScreen, newScreen, this);
00913 }
00914
00915 KConfigGroup c = config();
00916 c.writeEntry("screen", d->screen);
00917 c.writeEntry("desktop", d->desktop);
00918 emit configNeedsSaving();
00919 }
00920
00921 if (swapScreensWith) {
00922
00923 swapScreensWith->setScreen(oldScreen, oldDesktop);
00924 }
00925
00926 d->checkRemoveAction();
00927
00928 if (newScreen >= 0) {
00929 emit activate();
00930 }
00931 }
00932
00933 int Containment::screen() const
00934 {
00935 return d->screen;
00936 }
00937
00938 int Containment::desktop() const
00939 {
00940 return d->desktop;
00941 }
00942
00943 KPluginInfo::List Containment::listContainments(const QString &category,
00944 const QString &parentApp)
00945 {
00946 return listContainmentsOfType(QString(), category, parentApp);
00947 }
00948
00949
00950 KPluginInfo::List Containment::listContainmentsOfType(const QString &type,
00951 const QString &category,
00952 const QString &parentApp)
00953 {
00954 QString constraint;
00955
00956 if (parentApp.isEmpty()) {
00957 constraint.append("not exist [X-KDE-ParentApp]");
00958 } else {
00959 constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
00960 }
00961
00962 if (!type.isEmpty()) {
00963 if (!constraint.isEmpty()) {
00964 constraint.append(" and ");
00965 }
00966
00967 constraint.append("'").append(type).append("' ~in [X-Plasma-ContainmentCategories]");
00968 }
00969
00970 if (!category.isEmpty()) {
00971 if (!constraint.isEmpty()) {
00972 constraint.append(" and ");
00973 }
00974
00975 constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
00976 if (category == "Miscellaneous") {
00977 constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
00978 }
00979 }
00980
00981 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00982
00983 return KPluginInfo::fromServices(offers);
00984 }
00985
00986 KPluginInfo::List Containment::listContainmentsForMimetype(const QString &mimetype)
00987 {
00988 QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
00989
00990 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00991 return KPluginInfo::fromServices(offers);
00992 }
00993
00994 QStringList Containment::listContainmentTypes()
00995 {
00996 KPluginInfo::List containmentInfos = listContainments();
00997 QSet<QString> types;
00998
00999 foreach (const KPluginInfo &containmentInfo, containmentInfos) {
01000 QStringList theseTypes = containmentInfo.service()->property("X-Plasma-ContainmentCategories").toStringList();
01001 foreach (const QString &type, theseTypes) {
01002 types.insert(type);
01003 }
01004 }
01005
01006 return types.toList();
01007 }
01008
01009 void Containment::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
01010 {
01011
01012 event->setAccepted(immutability() == Mutable &&
01013 (event->mimeData()->hasFormat(static_cast<Corona*>(scene())->appletMimeType()) ||
01014 KUrl::List::canDecode(event->mimeData()) ||
01015 event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())));
01016
01017 if (!event->isAccepted()) {
01018
01019 QStringList formats = event->mimeData()->formats();
01020
01021 foreach (const QString &format, formats) {
01022 KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(format);
01023 if (!appletList.isEmpty()) {
01024 event->setAccepted(true);
01025 break;
01026 }
01027 }
01028 }
01029
01030 if (event->isAccepted() && view()) {
01031 showDropZone(view()->mapFromScene(event->scenePos()));
01032 }
01033 }
01034
01035 void Containment::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
01036 {
01037 QGraphicsItem *item = scene()->itemAt(event->scenePos());
01038 event->setAccepted(item == this || !item);
01039 Plasma::Containment *c = containment();
01040 if (c && c->immutability() == Plasma::Mutable &&
01041 (event->mimeData()->hasFormat(static_cast<Plasma::Corona*>(scene())->appletMimeType()) ||
01042 KUrl::List::canDecode(event->mimeData())) && view()) {
01043 showDropZone(view()->mapFromScene(event->scenePos()));
01044 }
01045 }
01046
01047 void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
01048 {
01049 if (isContainment()) {
01050 d->dropData(event);
01051 } else {
01052 Applet::dropEvent(event);
01053 }
01054 }
01055
01056 void ContainmentPrivate::dropData(QGraphicsSceneEvent *event)
01057 {
01058 if (q->immutability() != Mutable) {
01059 return;
01060 }
01061
01062 QGraphicsSceneDragDropEvent *dropEvent = dynamic_cast<QGraphicsSceneDragDropEvent*>(event);
01063 QGraphicsSceneMouseEvent *mouseEvent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
01064
01065 QPointF pos;
01066 QPointF scenePos;
01067 QPoint screenPos;
01068 const QMimeData *mimeData = 0;
01069
01070 if (dropEvent) {
01071 pos = dropEvent->pos();
01072 scenePos = dropEvent->scenePos();
01073 screenPos = dropEvent->screenPos();
01074 mimeData = dropEvent->mimeData();
01075 } else if (mouseEvent) {
01076 pos = mouseEvent->pos();
01077 scenePos = mouseEvent->scenePos();
01078 screenPos = mouseEvent->screenPos();
01079 QClipboard *clipboard = QApplication::clipboard();
01080 mimeData = clipboard->mimeData(QClipboard::Selection);
01081
01082 } else {
01083 kDebug() << "unexpected event";
01084 }
01085
01086 if (!mimeData) {
01087
01088 kDebug() << "no mime data";
01089 return;
01090 }
01091
01092
01093
01094 QString appletMimetype(q->corona() ? q->corona()->appletMimeType() : QString());
01095
01096 if (!appletMimetype.isEmpty() && mimeData->hasFormat(appletMimetype)) {
01097 QString data = mimeData->data(appletMimetype);
01098 QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
01099
01100 foreach (const QString &appletName, appletNames) {
01101
01102 QRectF geom(q->mapFromScene(scenePos), QSize(0, 0));
01103 q->addApplet(appletName, QVariantList(), geom);
01104 }
01105 if (dropEvent) {
01106 dropEvent->acceptProposedAction();
01107 }
01108 } else if (mimeData->hasFormat(ExtenderItemMimeData::mimeType())) {
01109 kDebug() << "mimetype plasma/extenderitem is dropped, creating internal:extender";
01110
01111 const ExtenderItemMimeData *extenderData = qobject_cast<const ExtenderItemMimeData*>(mimeData);
01112 if (extenderData) {
01113 ExtenderItem *item = extenderData->extenderItem();
01114 QRectF geometry(pos, item->size());
01115 kDebug() << "desired geometry: " << geometry;
01116 Applet *applet = q->addApplet("internal:extender", QVariantList(), geometry);
01117 item->setExtender(applet->extender());
01118 }
01119 } else if (KUrl::List::canDecode(mimeData)) {
01120
01121
01122 KUrl::List urls = KUrl::List::fromMimeData(mimeData);
01123 foreach (const KUrl &url, urls) {
01124 KMimeType::Ptr mime = KMimeType::findByUrl(url);
01125 QString mimeName = mime->name();
01126 QRectF geom(pos, QSize());
01127 QVariantList args;
01128 args << url.url();
01129
01130 KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(mimeName);
01131
01132 if (!appletList.isEmpty()) {
01133
01135 QMenu choices;
01136 QHash<QAction *, QString> actionsToPlugins;
01137 foreach (const KPluginInfo &info, appletList) {
01138 QAction *action;
01139 if (!info.icon().isEmpty()) {
01140 action = choices.addAction(KIcon(info.icon()), info.name());
01141 } else {
01142 action = choices.addAction(info.name());
01143 }
01144
01145 actionsToPlugins.insert(action, info.pluginName());
01146 }
01147
01148 actionsToPlugins.insert(choices.addAction(i18n("Icon")), "icon");
01149 QAction *choice = choices.exec(screenPos);
01150 if (choice) {
01151 q->addApplet(actionsToPlugins[choice], args, geom);
01152 }
01153 } else if (url.protocol() != "data") {
01154
01155
01156 q->addApplet("icon", args, geom);
01157 }
01158 }
01159
01160 if (dropEvent) {
01161 dropEvent->acceptProposedAction();
01162 }
01163 } else {
01164 QStringList formats = mimeData->formats();
01165 QHash<QString, KPluginInfo> seenPlugins;
01166 QHash<QString, QString> pluginFormats;
01167
01168 foreach (const QString &format, formats) {
01169 KPluginInfo::List plugins = Applet::listAppletInfoForMimetype(format);
01170
01171 foreach (const KPluginInfo &plugin, plugins) {
01172 if (seenPlugins.contains(plugin.pluginName())) {
01173 continue;
01174 }
01175
01176 seenPlugins.insert(plugin.pluginName(), plugin);
01177 pluginFormats.insert(plugin.pluginName(), format);
01178 }
01179 }
01180
01181 QString selectedPlugin;
01182
01183 if (seenPlugins.isEmpty()) {
01184
01185 } else if (seenPlugins.count() == 1) {
01186 selectedPlugin = seenPlugins.constBegin().key();
01187 } else {
01188 QMenu choices;
01189 QHash<QAction *, QString> actionsToPlugins;
01190 foreach (const KPluginInfo &info, seenPlugins) {
01191 QAction *action;
01192 if (!info.icon().isEmpty()) {
01193 action = choices.addAction(KIcon(info.icon()), info.name());
01194 } else {
01195 action = choices.addAction(info.name());
01196 }
01197
01198 actionsToPlugins.insert(action, info.pluginName());
01199 }
01200
01201 QAction *choice = choices.exec(screenPos);
01202 if (choice) {
01203 selectedPlugin = actionsToPlugins[choice];
01204 }
01205 }
01206
01207 if (!selectedPlugin.isEmpty()) {
01208 KTemporaryFile tempFile;
01209 if (tempFile.open()) {
01210
01211 tempFile.setAutoRemove(false);
01212
01213 {
01214 QDataStream stream(&tempFile);
01215 QByteArray data = mimeData->data(pluginFormats[selectedPlugin]);
01216 stream.writeRawData(data, data.size());
01217 }
01218
01219 QRectF geom(pos, QSize());
01220 QVariantList args;
01221 args << tempFile.fileName();
01222 kDebug() << args;
01223 tempFile.close();
01224
01225 q->addApplet(selectedPlugin, args, geom);
01226 }
01227 }
01228 }
01229 }
01230
01231 const QGraphicsItem *Containment::toolBoxItem() const
01232 {
01233 return d->toolBox;
01234 }
01235
01236 void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
01237 {
01238 Applet::resizeEvent(event);
01239
01240 if (!ContainmentPrivate::s_positioning) {
01241 switch (d->type) {
01242 case Containment::PanelContainment:
01243 case Containment::CustomPanelContainment:
01244 d->positionPanel();
01245 break;
01246 default:
01247 d->positionContainments();
01248 break;
01249 }
01250 }
01251
01252 if (d->wallpaper) {
01253 d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
01254 }
01255 }
01256
01257 void Containment::keyPressEvent(QKeyEvent *event)
01258 {
01259
01260
01261 if (event->key() == Qt::Key_Tab) {
01262 if (!d->applets.isEmpty()) {
01263 kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
01264 d->applets.first()->setFocus(Qt::TabFocusReason);
01265 }
01266 }
01267 }
01268
01269 void Containment::wheelEvent(QGraphicsSceneWheelEvent *event)
01270 {
01271 if (d->wallpaper && d->wallpaper->isInitialized()) {
01272 QGraphicsItem *item = scene()->itemAt(event->scenePos());
01273 if (item == this) {
01274 event->ignore();
01275 d->wallpaper->wheelEvent(event);
01276
01277 if (event->isAccepted()) {
01278 return;
01279 }
01280
01281 event->accept();
01282 }
01283 }
01284
01285 if (d->type == DesktopContainment) {
01286 QGraphicsItem *item = scene()->itemAt(event->scenePos());
01287 if (item == this) {
01288 int numDesktops = KWindowSystem::numberOfDesktops();
01289 int currentDesktop = KWindowSystem::currentDesktop();
01290
01291 if (event->delta() < 0) {
01292 KWindowSystem::setCurrentDesktop(currentDesktop % numDesktops + 1);
01293 } else {
01294 KWindowSystem::setCurrentDesktop((numDesktops + currentDesktop - 2) % numDesktops + 1);
01295 }
01296
01297 event->accept();
01298 return;
01299 }
01300 }
01301
01302 event->ignore();
01303 Applet::wheelEvent(event);
01304 }
01305
01306 bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
01307 {
01308 Applet *applet = qgraphicsitem_cast<Applet*>(watched);
01309
01310
01311 Q_ASSERT(applet != 0);
01312 if (!d->applets.contains(applet)) {
01313 return false;
01314 }
01315
01316
01317 switch (event->type()) {
01318 case QEvent::GraphicsSceneHoverEnter:
01319
01320 if (immutability() == Mutable && applet->immutability() == Mutable) {
01321 QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
01322 if (d->handles.contains(applet)) {
01323 AppletHandle *handle = d->handles.value(applet);
01324 if (handle) {
01325 handle->setHoverPos(he->pos());
01326 }
01327 } else {
01328
01329 AppletHandle *handle = new AppletHandle(this, applet, he->pos());
01330 d->handles[applet] = handle;
01331 connect(handle, SIGNAL(disappearDone(AppletHandle*)),
01332 this, SLOT(handleDisappeared(AppletHandle*)));
01333 connect(applet, SIGNAL(geometryChanged()),
01334 handle, SLOT(appletResized()));
01335 }
01336 }
01337 break;
01338 case QEvent::GraphicsSceneHoverMove:
01339 if (immutability() == Mutable && applet->immutability() == Mutable) {
01340 QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
01341 if (d->handles.contains(applet)) {
01342 AppletHandle *handle = d->handles.value(applet);
01343 if (handle) {
01344 handle->setHoverPos(he->pos());
01345 }
01346 }
01347 }
01348 break;
01349 default:
01350 break;
01351 }
01352
01353 return false;
01354 }
01355
01356 QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
01357 {
01358
01359
01360 if (isContainment() && !ContainmentPrivate::s_positioning &&
01361 (change == QGraphicsItem::ItemSceneHasChanged || change == QGraphicsItem::ItemPositionHasChanged)) {
01362 switch (d->type) {
01363 case PanelContainment:
01364 case CustomPanelContainment:
01365 d->positionPanel();
01366 break;
01367 default:
01368 d->positionContainments();
01369 break;
01370 }
01371 }
01372
01373 return Applet::itemChange(change, value);
01374 }
01375
01376 void Containment::enableAction(const QString &name, bool enable)
01377 {
01378 QAction *action = this->action(name);
01379 if (action) {
01380 action->setEnabled(enable);
01381 action->setVisible(enable);
01382 }
01383 }
01384
01385 void Containment::addToolBoxAction(QAction *action)
01386 {
01387 if (!d->toolBox && (d->type == CustomPanelContainment || d->type >= CustomContainment)) {
01388 d->createToolBox();
01389 }
01390
01391 if (d->toolBox) {
01392 d->toolBox->addTool(action);
01393 }
01394 }
01395
01396 void Containment::removeToolBoxAction(QAction *action)
01397 {
01398 if (d->toolBox) {
01399 d->toolBox->removeTool(action);
01400 }
01401 }
01402
01403 void Containment::setToolBoxOpen(bool open)
01404 {
01405 if (open) {
01406 openToolBox();
01407 } else {
01408 closeToolBox();
01409 }
01410 }
01411
01412 void Containment::openToolBox()
01413 {
01414 if (d->toolBox && !d->toolBox->showing()) {
01415 d->toolBox->showToolBox();
01416 emit toolBoxVisibilityChanged(true);
01417 }
01418 }
01419
01420 void Containment::closeToolBox()
01421 {
01422 if (d->toolBox && d->toolBox->showing()) {
01423 d->toolBox->hideToolBox();
01424 emit toolBoxVisibilityChanged(false);
01425 }
01426 }
01427
01428 void Containment::addAssociatedWidget(QWidget *widget)
01429 {
01430 Applet::addAssociatedWidget(widget);
01431 if (d->focusedApplet) {
01432 d->focusedApplet->addAssociatedWidget(widget);
01433 }
01434
01435 foreach (const Applet *applet, d->applets) {
01436 if (applet->d->activationAction) {
01437 widget->addAction(applet->d->activationAction);
01438 }
01439 }
01440 }
01441
01442 void Containment::removeAssociatedWidget(QWidget *widget)
01443 {
01444 Applet::removeAssociatedWidget(widget);
01445 if (d->focusedApplet) {
01446 d->focusedApplet->removeAssociatedWidget(widget);
01447 }
01448
01449 foreach (const Applet *applet, d->applets) {
01450 if (applet->d->activationAction) {
01451 widget->removeAction(applet->d->activationAction);
01452 }
01453 }
01454 }
01455
01456 void Containment::setDrawWallpaper(bool drawWallpaper)
01457 {
01458 d->drawWallpaper = drawWallpaper;
01459 if (drawWallpaper) {
01460 KConfigGroup cfg = config();
01461 QString wallpaper = cfg.readEntry("wallpaperplugin", defaultWallpaper);
01462 QString mode = cfg.readEntry("wallpaperpluginmode", defaultWallpaperMode);
01463 setWallpaper(wallpaper, mode);
01464 } else {
01465 delete d->wallpaper;
01466 d->wallpaper = 0;
01467 }
01468 }
01469
01470 bool Containment::drawWallpaper()
01471 {
01472 return d->drawWallpaper;
01473 }
01474
01475 void Containment::setWallpaper(const QString &pluginName, const QString &mode)
01476 {
01477 KConfigGroup cfg = config();
01478 bool newPlugin = true;
01479 bool newMode = true;
01480
01481 if (d->drawWallpaper) {
01482 if (d->wallpaper) {
01483
01484 if (d->wallpaper->pluginName() != pluginName) {
01485 delete d->wallpaper;
01486 d->wallpaper = 0;
01487 } else {
01488
01489
01490 newMode = d->wallpaper->renderingMode().name() != mode;
01491 newPlugin = false;
01492 }
01493 }
01494
01495 if (!pluginName.isEmpty() && !d->wallpaper) {
01496 d->wallpaper = Plasma::Wallpaper::load(pluginName);
01497 }
01498
01499 if (d->wallpaper) {
01500 d->wallpaper->setParent(this);
01501 d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
01502 d->wallpaper->setRenderingMode(mode);
01503
01504 if (newPlugin) {
01505 connect(d->wallpaper, SIGNAL(update(const QRectF&)),
01506 this, SLOT(updateRect(const QRectF&)));
01507 cfg.writeEntry("wallpaperplugin", pluginName);
01508 }
01509
01510 if (d->wallpaper->isInitialized()) {
01511 KConfigGroup wallpaperConfig = KConfigGroup(&cfg, "Wallpaper");
01512 wallpaperConfig = KConfigGroup(&wallpaperConfig, pluginName);
01513 d->wallpaper->restore(wallpaperConfig);
01514 }
01515
01516 if (newMode) {
01517 cfg.writeEntry("wallpaperpluginmode", mode);
01518 }
01519 }
01520
01521 update();
01522 }
01523
01524 if (!d->wallpaper) {
01525 cfg.deleteEntry("wallpaperplugin");
01526 cfg.deleteEntry("wallpaperpluginmode");
01527 }
01528
01529 if (newPlugin || newMode) {
01530 if (newPlugin && d->wallpaper) {
01531 connect(d->wallpaper, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
01532 connect(d->wallpaper, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
01533 }
01534
01535 emit configNeedsSaving();
01536 }
01537 }
01538
01539 Plasma::Wallpaper *Containment::wallpaper() const
01540 {
01541 return d->wallpaper;
01542 }
01543
01544 void Containment::setActivity(const QString &activity)
01545 {
01546 Context *context = d->context();
01547 if (context->currentActivity() != activity) {
01548 context->setCurrentActivity(activity);
01549
01550 foreach (Applet *a, d->applets) {
01551 a->updateConstraints(ContextConstraint);
01552 }
01553
01554 KConfigGroup c = config();
01555 c.writeEntry("activity", activity);
01556 emit configNeedsSaving();
01557 }
01558 }
01559
01560 QString Containment::activity() const
01561 {
01562 return d->context()->currentActivity();
01563 }
01564
01565 Context *ContainmentPrivate::context()
01566 {
01567 if (!con) {
01568 con = new Context(q);
01569 q->connect(con, SIGNAL(changed(Plasma::Context*)),
01570 q, SIGNAL(contextChanged(Plasma::Context*)));
01571 }
01572
01573 return con;
01574 }
01575
01576 KActionCollection* ContainmentPrivate::actions()
01577 {
01578 return static_cast<Applet*>(q)->d->actions;
01579 }
01580
01581 void ContainmentPrivate::focusApplet(Plasma::Applet *applet)
01582 {
01583 if (focusedApplet == applet) {
01584 return;
01585 }
01586
01587 QList<QWidget *> widgets = actions()->associatedWidgets();
01588 if (focusedApplet) {
01589 foreach (QWidget *w, widgets) {
01590 focusedApplet->removeAssociatedWidget(w);
01591 }
01592 }
01593
01594 if (applet && applets.contains(applet)) {
01595
01596 focusedApplet = applet;
01597 foreach (QWidget *w, widgets) {
01598 focusedApplet->addAssociatedWidget(w);
01599 }
01600
01601 if (!focusedApplet->hasFocus()) {
01602 focusedApplet->setFocus(Qt::ShortcutFocusReason);
01603 }
01604 } else {
01605 focusedApplet = 0;
01606 }
01607 }
01608
01609 void Containment::focusNextApplet()
01610 {
01611 if (d->applets.isEmpty()) {
01612 return;
01613 }
01614 int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
01615 if (index >= d->applets.size()) {
01616 index = 0;
01617 }
01618 kDebug() << "index" << index;
01619 d->focusApplet(d->applets.at(index));
01620 }
01621
01622 void Containment::focusPreviousApplet()
01623 {
01624 if (d->applets.isEmpty()) {
01625 return;
01626 }
01627 int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
01628 if (index < 0) {
01629 index = d->applets.size() - 1;
01630 }
01631 kDebug() << "index" << index;
01632 d->focusApplet(d->applets.at(index));
01633 }
01634
01635 void Containment::destroy()
01636 {
01637 destroy(true);
01638 }
01639
01640 void Containment::showConfigurationInterface()
01641 {
01642 Applet::showConfigurationInterface();
01643 }
01644
01645 void ContainmentPrivate::requestConfiguration()
01646 {
01647 emit q->configureRequested(q);
01648 }
01649
01650 void Containment::destroy(bool confirm)
01651 {
01652 if (immutability() != Mutable || Applet::d->transient) {
01653 return;
01654 }
01655
01656 if (isContainment()) {
01657
01658
01659
01660 Q_ASSERT(corona());
01661 if (d->type != PanelContainment && d->type != CustomPanelContainment &&
01662 (d->screen != -1 || d->screen >= corona()->numScreens())) {
01663 kDebug() << (QObject*)this << "containment has a screen number?" << d->screen;
01664 return;
01665 }
01666
01667
01668 if (!confirm ||
01669 KMessageBox::warningContinueCancel(
01670 view(),
01671 i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
01672 i18nc("@title:window %1 is the name of the containment", "Remove %1", name()), KStandardGuiItem::remove()) == KMessageBox::Continue) {
01673
01674 Applet::destroy();
01675 }
01676 } else {
01677 Applet::destroy();
01678 }
01679 }
01680
01681 void ContainmentPrivate::zoomIn()
01682 {
01683 emit q->zoomRequested(q, Plasma::ZoomIn);
01684 positionToolBox();
01685 }
01686
01687 void ContainmentPrivate::zoomOut()
01688 {
01689 emit q->zoomRequested(q, Plasma::ZoomOut);
01690 positionToolBox();
01691 }
01692
01693 ToolBox *ContainmentPrivate::createToolBox()
01694 {
01695 if (!toolBox) {
01696 switch (type) {
01697 case Containment::PanelContainment:
01698 case Containment::CustomPanelContainment:
01699 toolBox = new PanelToolBox(q);
01700 toolBox->setSize(KIconLoader::SizeSmallMedium);
01701 toolBox->setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
01702 if (q->immutability() != Mutable) {
01703 toolBox->hide();
01704 }
01705 break;
01706 default:
01707 toolBox = new DesktopToolBox(q);
01708 toolBox->setSize(KIconLoader::SizeSmallMedium);
01709 toolBox->setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
01710 break;
01711 }
01712
01713 if (toolBox) {
01714 QObject::connect(toolBox, SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
01715 QObject::connect(toolBox, SIGNAL(toggled()), q, SLOT(updateToolBoxVisibility()));
01716 toolBox->load();
01717 positionToolBox();
01718 }
01719 }
01720
01721 return toolBox;
01722 }
01723
01724 void ContainmentPrivate::positionToolBox()
01725 {
01726 if (toolBox) {
01727 toolBox->reposition();
01728 }
01729 }
01730
01731 void ContainmentPrivate::updateToolBoxVisibility()
01732 {
01733 emit q->toolBoxVisibilityChanged(toolBox->showing());
01734 }
01735
01736 void ContainmentPrivate::triggerShowAddWidgets()
01737 {
01738 emit q->showAddWidgetsInterface(QPointF());
01739 }
01740
01741 void ContainmentPrivate::handleDisappeared(AppletHandle *handle)
01742 {
01743 if (handles.contains(handle->applet())) {
01744 handles.remove(handle->applet());
01745 handle->detachApplet();
01746 if (q->scene()) {
01747 q->scene()->removeItem(handle);
01748 }
01749 handle->deleteLater();
01750 }
01751 }
01752
01753 void ContainmentPrivate::checkRemoveAction()
01754 {
01755 q->enableAction("remove", (q->immutability() == Mutable &&
01756 (screen == -1 ||
01757 type == Plasma::Containment::PanelContainment ||
01758 type == Plasma::Containment::CustomPanelContainment)));
01759 }
01760
01761 void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
01762 {
01763 if (!q->isContainment()) {
01764 return;
01765 }
01766
01767
01768 if (constraints & Plasma::ImmutableConstraint) {
01769
01770 checkRemoveAction();
01771 bool unlocked = q->immutability() == Mutable;
01772 q->setAcceptDrops(unlocked);
01773 q->enableAction("add widgets", unlocked);
01774
01775
01776 foreach (Applet *a, applets) {
01777 a->updateConstraints(ImmutableConstraint);
01778 }
01779
01780 if (toolBox) {
01781 if (type == Containment::PanelContainment || type == Containment::CustomPanelContainment) {
01782 toolBox->setVisible(unlocked);
01783 } else {
01784 toolBox->setIsMovable(unlocked);
01785 }
01786 }
01787
01788
01789 if (!unlocked) {
01790 QMap<Applet*, AppletHandle*> h = handles;
01791 handles.clear();
01792
01793 foreach (AppletHandle *handle, h) {
01794 handle->disconnect(q);
01795
01796 if (q->scene()) {
01797 q->scene()->removeItem(handle);
01798 }
01799
01800 handle->deleteLater();
01801 }
01802 }
01803 }
01804
01805 if (constraints & Plasma::FormFactorConstraint) {
01806 foreach (Applet *applet, applets) {
01807 applet->updateConstraints(Plasma::FormFactorConstraint);
01808 }
01809 }
01810
01811 if (toolBox && (constraints & Plasma::SizeConstraint ||
01812 constraints & Plasma::FormFactorConstraint ||
01813 constraints & Plasma::ScreenConstraint ||
01814 constraints & Plasma::StartupCompletedConstraint)) {
01815
01816 positionToolBox();
01817 }
01818
01819 if (toolBox &&
01820 constraints & Plasma::StartupCompletedConstraint &&
01821 type < Containment::CustomContainment) {
01822 toolBox->addTool(q->action("remove"));
01823 checkRemoveAction();
01824 }
01825 }
01826
01827 Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
01828 const QRectF &appletGeometry, uint id, bool delayInit)
01829 {
01830 if (!q->isContainment()) {
01831 return 0;
01832 }
01833
01834 if (!delayInit && q->immutability() != Mutable) {
01835 kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
01836 return 0;
01837 }
01838
01839 QGraphicsView *v = q->view();
01840 if (v) {
01841 v->setCursor(Qt::BusyCursor);
01842 }
01843
01844 Applet *applet = Applet::load(name, id, args);
01845 if (v) {
01846 v->unsetCursor();
01847 }
01848
01849 if (!applet) {
01850 kDebug() << "Applet" << name << "could not be loaded.";
01851 applet = new Applet(0, QString(), id);
01852 applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
01853 }
01854
01855
01856
01857 q->addApplet(applet, appletGeometry.topLeft(), delayInit);
01858 return applet;
01859 }
01860
01861 bool ContainmentPrivate::regionIsEmpty(const QRectF ®ion, Applet *ignoredApplet) const
01862 {
01863 foreach (Applet *applet, applets) {
01864 if (applet != ignoredApplet && applet->geometry().intersects(region)) {
01865 return false;
01866 }
01867 }
01868 return true;
01869 }
01870
01871 void ContainmentPrivate::appletDestroyed(Plasma::Applet *applet)
01872 {
01873 applets.removeAll(applet);
01874 if (focusedApplet == applet) {
01875 focusedApplet = 0;
01876 }
01877
01878 if (handles.contains(applet)) {
01879 AppletHandle *handle = handles.value(applet);
01880 handles.remove(applet);
01881 if (q->scene()) {
01882 q->scene()->removeItem(handle);
01883 }
01884 handle->deleteLater();
01885 }
01886
01887 emit q->appletRemoved(applet);
01888 emit q->configNeedsSaving();
01889 }
01890
01891 void ContainmentPrivate::containmentAppletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
01892 {
01893 if (anim == Animator::AppearAnimation &&
01894 item->parentItem() == q) {
01895 Applet *applet = qgraphicsitem_cast<Applet*>(item);
01896
01897 if (applet) {
01898 if (type == Containment::DesktopContainment) {
01899 applet->installSceneEventFilter(q);
01900 }
01901
01902 KConfigGroup *cg = applet->d->mainConfigGroup();
01903 applet->save(*cg);
01904 emit q->configNeedsSaving();
01905
01906 }
01907 }
01908 }
01909
01910 bool containmentSortByPosition(const Containment *c1, const Containment *c2)
01911 {
01912 return c1->id() < c2->id();
01913 }
01914
01915 void ContainmentPrivate::positionContainments()
01916 {
01917 Corona *c = q->corona();
01918 if (!c || ContainmentPrivate::s_positioning) {
01919 return;
01920 }
01921
01922 ContainmentPrivate::s_positioning = true;
01923
01924
01925
01926 QList<Containment*> containments = c->containments();
01927 QMutableListIterator<Containment*> it(containments);
01928
01929 while (it.hasNext()) {
01930 Containment *containment = it.next();
01931 if (containment->d->type == Containment::PanelContainment ||
01932 containment->d->type == Containment::CustomPanelContainment ||
01933 q->corona()->offscreenWidgets().contains(containment)) {
01934
01935
01936 it.remove();
01937 continue;
01938 }
01939 }
01940
01941 if (containments.isEmpty()) {
01942 ContainmentPrivate::s_positioning = false;
01943 return;
01944 }
01945
01946 qSort(containments.begin(), containments.end(), containmentSortByPosition);
01947 it.toFront();
01948
01949 int column = 0;
01950 int x = 0;
01951 int y = 0;
01952 int rowHeight = 0;
01953
01954
01955
01956 while (it.hasNext()) {
01957 Containment *containment = it.next();
01958 containment->setPos(x, y);
01959
01960
01961 int height = containment->size().height();
01962 if (height > rowHeight) {
01963 rowHeight = height;
01964 }
01965
01966 ++column;
01967
01968 if (column == CONTAINMENT_COLUMNS) {
01969 column = 0;
01970 x = 0;
01971 y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
01972 rowHeight = 0;
01973 } else {
01974 x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
01975 }
01976
01977
01978 }
01979
01980
01981 ContainmentPrivate::s_positioning = false;
01982 }
01983
01984 void ContainmentPrivate::positionPanel(bool force)
01985 {
01986 if (!q->scene()) {
01987 kDebug() << "no scene yet";
01988 return;
01989 }
01990
01991
01992
01993
01994
01995 const QPointF p = q->pos();
01996
01997 if (!force &&
01998 p.y() + q->size().height() < -INTER_CONTAINMENT_MARGIN &&
01999 q->scene()->collidingItems(q).isEmpty()) {
02000
02001 return;
02002 }
02003
02004
02005 bool horiz = formFactor == Plasma::Horizontal;
02006 qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
02007 qreal lastHeight = 0;
02008
02009
02010
02011
02012 foreach (const Containment *other, q->corona()->containments()) {
02013 if (other == q ||
02014 (other->d->type != Containment::PanelContainment &&
02015 other->d->type != Containment::CustomPanelContainment) ||
02016 horiz != (other->formFactor() == Plasma::Horizontal)) {
02017
02018 continue;
02019 }
02020
02021 if (horiz) {
02022 qreal y = other->pos().y();
02023 if (y < bottom) {
02024 lastHeight = other->size().height();
02025 bottom = y;
02026 }
02027 } else {
02028 qreal width = other->size().width();
02029 qreal x = other->pos().x() + width;
02030 if (x > bottom) {
02031 lastHeight = width;
02032 bottom = x + lastHeight;
02033 }
02034 }
02035 }
02036
02037 kDebug() << "positioning" << (horiz ? "" : "non-") << "horizontal panel; forced?" << force;
02038
02039
02040 QPointF newPos;
02041 if (horiz) {
02042 bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
02043
02044 kDebug() << "moved to" << QPointF(0, bottom - q->size().height());
02045 newPos = QPointF(0, bottom - q->size().height());
02046 } else {
02047 bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
02048
02049 kDebug() << "moved to" << QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
02050 newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
02051 }
02052
02053 if (p != newPos) {
02054 ContainmentPrivate::s_positioning = true;
02055 q->setPos(newPos);
02056 ContainmentPrivate::s_positioning = false;
02057 }
02058 }
02059
02060 }
02061
02062 #include "containment.moc"
02063