• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
containment.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2007 by Aaron Seigo <aseigo@kde.org>
3  * Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
4  * Copyright 2009 Chani Armitage <chani@kde.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #include "containment.h"
23 #include "private/containment_p.h"
24 
25 #include "config-plasma.h"
26 
27 #include <QApplication>
28 #include <QClipboard>
29 #include <QFile>
30 #include <QGraphicsSceneContextMenuEvent>
31 #include <QGraphicsView>
32 #include <QMimeData>
33 #include <QPainter>
34 #include <QStyleOptionGraphicsItem>
35 #include <QGraphicsLayout>
36 #include <QGraphicsLinearLayout>
37 
38 #include <kaction.h>
39 #include <kauthorized.h>
40 #include <kicon.h>
41 #include <kmenu.h>
42 #include <kmessagebox.h>
43 #include <kmimetype.h>
44 #include <kservicetypetrader.h>
45 #include <kstandarddirs.h>
46 #include <ktemporaryfile.h>
47 #include <kwindowsystem.h>
48 
49 #ifndef PLASMA_NO_KIO
50 #include "kio/jobclasses.h" // for KIO::JobFlags
51 #include "kio/job.h"
52 #include "kio/scheduler.h"
53 #endif
54 
55 #include "abstracttoolbox.h"
56 #include "animator.h"
57 #include "context.h"
58 #include "containmentactions.h"
59 #include "containmentactionspluginsconfig.h"
60 #include "corona.h"
61 #include "extender.h"
62 #include "extenderitem.h"
63 #include "svg.h"
64 #include "wallpaper.h"
65 
66 #include "remote/accessappletjob.h"
67 #include "remote/accessmanager.h"
68 
69 #include "private/applet_p.h"
70 #include "private/containmentactionspluginsconfig_p.h"
71 #include "private/extenderitemmimedata_p.h"
72 #include "private/extenderapplet_p.h"
73 #include "private/wallpaper_p.h"
74 
75 #include "plasma/plasma.h"
76 #include "animations/animation.h"
77 
78 namespace Plasma
79 {
80 
81 bool ContainmentPrivate::s_positioningPanels = false;
82 QHash<QString, ContainmentActions*> ContainmentPrivate::globalActionPlugins;
83 static const char defaultWallpaper[] = "image";
84 static const char defaultWallpaperMode[] = "SingleImage";
85 
86 Containment::StyleOption::StyleOption()
87  : QStyleOptionGraphicsItem(),
88  view(0)
89 {
90  version = Version;
91  type = Type;
92 }
93 
94 Containment::StyleOption::StyleOption(const Containment::StyleOption & other)
95  : QStyleOptionGraphicsItem(other),
96  view(other.view)
97 {
98  version = Version;
99  type = Type;
100 }
101 
102 Containment::StyleOption::StyleOption(const QStyleOptionGraphicsItem &other)
103  : QStyleOptionGraphicsItem(other),
104  view(0)
105 {
106  version = Version;
107  type = Type;
108 }
109 
110 Containment::Containment(QGraphicsItem *parent,
111  const QString &serviceId,
112  uint containmentId)
113  : Applet(parent, serviceId, containmentId),
114  d(new ContainmentPrivate(this))
115 {
116  // WARNING: do not access config() OR globalConfig() in this method!
117  // that requires a scene, which is not available at this point
118  setPos(0, 0);
119  setBackgroundHints(NoBackground);
120  setContainmentType(CustomContainment);
121 }
122 
123 Containment::Containment(QObject *parent, const QVariantList &args)
124  : Applet(parent, args),
125  d(new ContainmentPrivate(this))
126 {
127  // WARNING: do not access config() OR globalConfig() in this method!
128  // that requires a scene, which is not available at this point
129  setPos(0, 0);
130  setBackgroundHints(NoBackground);
131 }
132 
133 Containment::Containment(const QString &packagePath, uint appletId, const QVariantList &args)
134  : Plasma::Applet(packagePath, appletId, args),
135  d(new ContainmentPrivate(this))
136 {
137  // WARNING: do not access config() OR globalConfig() in this method!
138  // that requires a scene, which is not available at this point
139  setPos(0, 0);
140  setBackgroundHints(NoBackground);
141 }
142 
143 Containment::~Containment()
144 {
145  // Applet touches our dptr if we are a containment and is the superclass (think of dtors)
146  // so we reset this as we exit the building
147  Applet::d->isContainment = false;
148  delete d;
149 }
150 
151 void Containment::init()
152 {
153  Applet::init();
154  if (!isContainment()) {
155  return;
156  }
157 
158  setCacheMode(NoCache);
159  setFlag(QGraphicsItem::ItemIsMovable, false);
160  setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
161  setAcceptDrops(true);
162  setAcceptsHoverEvents(true);
163 
164  if (d->type == NoContainmentType) {
165  setContainmentType(DesktopContainment);
166  }
167 
168  //connect actions
169  ContainmentPrivate::addDefaultActions(d->actions(), this);
170  bool unlocked = immutability() == Mutable;
171 
172  //fix the text of the actions that need name()
173  //btw, do we really want to use name() when it's a desktopcontainment?
174  QAction *closeApplet = action("remove");
175  if (closeApplet) {
176  closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
177  }
178 
179  QAction *configAction = action("configure");
180  if (configAction) {
181  configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", name()));
182  }
183 
184  QAction *appletBrowserAction = action("add widgets");
185  if (appletBrowserAction) {
186  appletBrowserAction->setVisible(unlocked);
187  appletBrowserAction->setEnabled(unlocked);
188  connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
189  }
190 
191  QAction *act = action("next applet");
192  if (act) {
193  connect(act, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
194  }
195 
196  act = action("previous applet");
197  if (act) {
198  connect(act, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
199  }
200 
201  if (immutability() != SystemImmutable && corona()) {
202  QAction *lockDesktopAction = corona()->action("lock widgets");
203  //keep a pointer so nobody notices it moved to corona
204  if (lockDesktopAction) {
205  d->actions()->addAction("lock widgets", lockDesktopAction);
206  }
207  }
208  if (d->type != PanelContainment && d->type != CustomPanelContainment) {
209  if (corona()) {
210  //FIXME this is just here because of the darn keyboard shortcut :/
211  act = corona()->action("manage activities");
212  if (act) {
213  d->actions()->addAction("manage activities", act);
214  }
215  //a stupid hack to make this one's keyboard shortcut work
216  act = corona()->action("configure shortcuts");
217  if (act) {
218  d->actions()->addAction("configure shortcuts", act);
219  }
220  }
221 
222  if (d->type == DesktopContainment) {
223  addToolBoxAction(action("add widgets"));
224 
225  //TODO: do we need some way to allow this be overridden?
226  // it's always available because shells rely on this
227  // to offer their own custom configuration as well
228  QAction *configureContainment = action("configure");
229  if (configureContainment) {
230  addToolBoxAction(configureContainment);
231  }
232  }
233  }
234 }
235 
236 void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containment *c)
237 {
238  actions->setConfigGroup("Shortcuts-Containment");
239 
240  //adjust applet actions
241  KAction *appAction = qobject_cast<KAction*>(actions->action("remove"));
242  appAction->setShortcut(KShortcut("alt+d, alt+r"));
243  if (c && c->d->isPanelContainment()) {
244  appAction->setText(i18n("Remove this Panel"));
245  } else {
246  appAction->setText(i18n("Remove this Activity"));
247  }
248 
249  appAction = qobject_cast<KAction*>(actions->action("configure"));
250  if (appAction) {
251  appAction->setShortcut(KShortcut("alt+d, alt+s"));
252  appAction->setText(i18n("Activity Settings"));
253  }
254 
255  //add our own actions
256  KAction *appletBrowserAction = actions->addAction("add widgets");
257  appletBrowserAction->setAutoRepeat(false);
258  appletBrowserAction->setText(i18n("Add Widgets..."));
259  appletBrowserAction->setIcon(KIcon("list-add"));
260  appletBrowserAction->setShortcut(KShortcut("alt+d, a"));
261  appletBrowserAction->setData(AbstractToolBox::AddTool);
262 
263  KAction *action = actions->addAction("next applet");
264  action->setText(i18n("Next Widget"));
265  //no icon
266  action->setShortcut(KShortcut("alt+d, n"));
267  action->setData(AbstractToolBox::ControlTool);
268 
269  action = actions->addAction("previous applet");
270  action->setText(i18n("Previous Widget"));
271  //no icon
272  action->setShortcut(KShortcut("alt+d, p"));
273  action->setData(AbstractToolBox::ControlTool);
274 }
275 
276 // helper function for sorting the list of applets
277 bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
278 {
279  QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
280  QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
281 
282  if (!qFuzzyCompare(p1.x(), p2.x())) {
283  if (QApplication::layoutDirection() == Qt::RightToLeft) {
284  return p1.x() > p2.x();
285  }
286 
287  return p1.x() < p2.x();
288  }
289 
290  return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
291 }
292 
293 void Containment::restore(KConfigGroup &group)
294 {
295  /*kDebug() << "!!!!!!!!!!!!initConstraints" << group.name() << d->type;
296  kDebug() << " location:" << group.readEntry("location", (int)d->location);
297  kDebug() << " geom:" << group.readEntry("geometry", geometry());
298  kDebug() << " formfactor:" << group.readEntry("formfactor", (int)d->formFactor);
299  kDebug() << " screen:" << group.readEntry("screen", d->screen);*/
300  if (!isContainment()) {
301  Applet::restore(group);
302  return;
303  }
304 
305  QRectF geo = group.readEntry("geometry", geometry());
306  //override max/min
307  //this ensures panels are set to their saved size even when they have max & min set to prevent
308  //resizing
309  if (geo.size() != geo.size().boundedTo(maximumSize())) {
310  setMaximumSize(maximumSize().expandedTo(geo.size()));
311  }
312 
313  if (geo.size() != geo.size().expandedTo(minimumSize())) {
314  setMinimumSize(minimumSize().boundedTo(geo.size()));
315  }
316 
317 
318  resize(geo.size());
319  //are we an offscreen containment?
320  if (containmentType() != PanelContainment && containmentType() != CustomPanelContainment && geo.right() < 0) {
321  corona()->addOffscreenWidget(this);
322  }
323 
324  setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
325  setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
326  //kDebug() << "setScreen from restore";
327  d->lastScreen = group.readEntry("lastScreen", d->lastScreen);
328  d->lastDesktop = group.readEntry("lastDesktop", d->lastDesktop);
329  d->setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop), false);
330  QString activityId = group.readEntry("activityId", QString());
331  if (!activityId.isEmpty()) {
332  d->context()->setCurrentActivityId(activityId);
333  }
334  setActivity(group.readEntry("activity", QString()));
335 
336  flushPendingConstraintsEvents();
337  restoreContents(group);
338  setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
339 
340  setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
341  group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
342 
343  QMetaObject::invokeMethod(d->toolBox.data(), "restore", Q_ARG(KConfigGroup, group));
344 
345  KConfigGroup cfg;
346  if (containmentType() == PanelContainment || containmentType() == CustomPanelContainment) {
347  //don't let global desktop actions conflict with panels
348  //this also prevents panels from sharing config with each other
349  //but the panels aren't configurable anyways, and I doubt that'll change.
350  d->containmentActionsSource = ContainmentPrivate::Local;
351  cfg = KConfigGroup(&group, "ActionPlugins");
352  } else {
353  QString source = group.readEntry("ActionPluginsSource", QString());
354  if (source == "Global") {
355  cfg = KConfigGroup(corona()->config(), "ActionPlugins");
356  d->containmentActionsSource = ContainmentPrivate::Global;
357  } else if (source == "Activity") {
358  cfg = KConfigGroup(corona()->config(), "Activities");
359  cfg = KConfigGroup(&cfg, activityId);
360  cfg = KConfigGroup(&cfg, "ActionPlugins");
361  d->containmentActionsSource = ContainmentPrivate::Activity;
362  } else if (source == "Local") {
363  cfg = group;
364  d->containmentActionsSource = ContainmentPrivate::Local;
365  } else {
366  //default to global
367  //but, if there is no global config, try copying it from local.
368  cfg = KConfigGroup(corona()->config(), "ActionPlugins");
369  if (!cfg.exists()) {
370  cfg = KConfigGroup(&group, "ActionPlugins");
371  }
372  d->containmentActionsSource = ContainmentPrivate::Global;
373  group.writeEntry("ActionPluginsSource", "Global");
374  }
375  }
376  //kDebug() << cfg.keyList();
377  if (cfg.exists()) {
378  foreach (const QString &key, cfg.keyList()) {
379  //kDebug() << "loading" << key;
380  setContainmentActions(key, cfg.readEntry(key, QString()));
381  }
382  } else { //shell defaults
383  ContainmentActionsPluginsConfig conf = corona()->containmentActionsDefaults(d->type);
384  //steal the data directly, for efficiency
385  QHash<QString,QString> defaults = conf.d->plugins;
386  for (QHash<QString,QString>::const_iterator it = defaults.constBegin(),
387  end = defaults.constEnd(); it != end; ++it) {
388  setContainmentActions(it.key(), it.value());
389  }
390  }
391 
392  /*
393  kDebug() << "Containment" << id() <<
394  "screen" << screen() <<
395  "geometry is" << geometry() <<
396  "wallpaper" << ((d->wallpaper) ? d->wallpaper->pluginName() : QString()) <<
397  "wallpaper mode" << wallpaperMode() <<
398  "config entries" << group.entryMap();
399  */
400 }
401 
402 void Containment::save(KConfigGroup &g) const
403 {
404  if (Applet::d->transient) {
405  return;
406  }
407 
408  KConfigGroup group = g;
409  if (!group.isValid()) {
410  group = config();
411  }
412 
413  // locking is saved in Applet::save
414  Applet::save(group);
415 
416  if (!isContainment()) {
417  return;
418  }
419 
420  group.writeEntry("screen", d->screen);
421  group.writeEntry("lastScreen", d->lastScreen);
422  group.writeEntry("desktop", d->desktop);
423  group.writeEntry("lastDesktop", d->lastDesktop);
424  group.writeEntry("formfactor", (int)d->formFactor);
425  group.writeEntry("location", (int)d->location);
426  group.writeEntry("activity", d->context()->currentActivity());
427  group.writeEntry("activityId", d->context()->currentActivityId());
428 
429 
430  QMetaObject::invokeMethod(d->toolBox.data(), "save", Q_ARG(KConfigGroup, group));
431 
432 
433  if (d->wallpaper) {
434  group.writeEntry("wallpaperplugin", d->wallpaper->pluginName());
435  group.writeEntry("wallpaperpluginmode", d->wallpaper->renderingMode().name());
436 
437  if (d->wallpaper->isInitialized()) {
438  KConfigGroup wallpaperConfig(&group, "Wallpaper");
439  wallpaperConfig = KConfigGroup(&wallpaperConfig, d->wallpaper->pluginName());
440  d->wallpaper->save(wallpaperConfig);
441  }
442  }
443 
444  saveContents(group);
445 }
446 
447 void Containment::saveContents(KConfigGroup &group) const
448 {
449  KConfigGroup applets(&group, "Applets");
450  foreach (const Applet *applet, d->applets) {
451  KConfigGroup appletConfig(&applets, QString::number(applet->id()));
452  applet->save(appletConfig);
453  }
454 }
455 
456 void ContainmentPrivate::initApplets()
457 {
458  foreach (Applet *applet, applets) {
459  applet->restore(*applet->d->mainConfigGroup());
460  applet->init();
461  kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Applet" << applet->name();
462  }
463 
464  q->flushPendingConstraintsEvents();
465 
466  foreach (Applet *applet, applets) {
467  applet->flushPendingConstraintsEvents();
468  }
469 
470  kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Containment's applets initialized" << q->name();
471 }
472 
473 void Containment::restoreContents(KConfigGroup &group)
474 {
475  KConfigGroup applets(&group, "Applets");
476 
477  // Sort the applet configs in order of geometry to ensure that applets
478  // are added from left to right or top to bottom for a panel containment
479  QList<KConfigGroup> appletConfigs;
480  foreach (const QString &appletGroup, applets.groupList()) {
481  //kDebug() << "reading from applet group" << appletGroup;
482  KConfigGroup appletConfig(&applets, appletGroup);
483  appletConfigs.append(appletConfig);
484  }
485  qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
486 
487  QMutableListIterator<KConfigGroup> it(appletConfigs);
488  while (it.hasNext()) {
489  KConfigGroup &appletConfig = it.next();
490  int appId = appletConfig.name().toUInt();
491  QString plugin = appletConfig.readEntry("plugin", QString());
492 
493  if (plugin.isEmpty()) {
494  continue;
495  }
496 
497  d->addApplet(plugin, QVariantList(), appletConfig.readEntry("geometry", QRectF()), appId, true);
498  }
499 }
500 
501 Containment::Type Containment::containmentType() const
502 {
503  return d->type;
504 }
505 
506 void Containment::setContainmentType(Containment::Type type)
507 {
508  if (d->type == type) {
509  return;
510  }
511 
512  delete d->toolBox.data();
513  d->type = type;
514  d->checkContainmentFurniture();
515 }
516 
517 void ContainmentPrivate::checkContainmentFurniture()
518 {
519  if (q->isContainment() &&
520  (type == Containment::DesktopContainment || type == Containment::PanelContainment)) {
521  createToolBox();
522  }
523 }
524 
525 Corona *Containment::corona() const
526 {
527  return qobject_cast<Corona*>(scene());
528 }
529 
530 void Containment::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
531 {
532  event->ignore();
533  if (d->wallpaper && d->wallpaper->isInitialized()) {
534  QGraphicsItem *item = scene()->itemAt(event->scenePos());
535  if (item == this) {
536  d->wallpaper->mouseMoveEvent(event);
537  }
538  }
539 
540  if (!event->isAccepted()) {
541  event->accept();
542  Applet::mouseMoveEvent(event);
543  }
544 }
545 
546 void Containment::mousePressEvent(QGraphicsSceneMouseEvent *event)
547 {
548  //close a toolbox if exists, to emulate qmenu behavior
549  if (d->toolBox) {
550  d->toolBox.data()->setShowing(false);
551  }
552  event->ignore();
553  if (d->appletAt(event->scenePos())) {
554  return; //no unexpected click-throughs
555  }
556 
557  if (d->wallpaper && d->wallpaper->isInitialized() && !event->isAccepted()) {
558  d->wallpaper->mousePressEvent(event);
559  }
560 
561  if (event->isAccepted()) {
562  setFocus(Qt::MouseFocusReason);
563  } else if (event->button() == Qt::RightButton && event->modifiers() == Qt::NoModifier) {
564  // we'll catch this in the context menu even
565  Applet::mousePressEvent(event);
566  } else {
567  QString trigger = ContainmentActions::eventToString(event);
568  if (d->prepareContainmentActions(trigger, event->screenPos())) {
569  d->actionPlugins()->value(trigger)->contextEvent(event);
570  }
571 
572  if (!event->isAccepted()) {
573  Applet::mousePressEvent(event);
574  }
575  }
576 }
577 
578 void Containment::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
579 {
580  event->ignore();
581 
582  if (d->appletAt(event->scenePos())) {
583  return; //no unexpected click-throughs
584  }
585 
586  QString trigger = ContainmentActions::eventToString(event);
587 
588  if (d->wallpaper && d->wallpaper->isInitialized()) {
589  d->wallpaper->mouseReleaseEvent(event);
590  }
591 
592  if (!event->isAccepted() && isContainment()) {
593  if (d->prepareContainmentActions(trigger, event->screenPos())) {
594  d->actionPlugins()->value(trigger)->contextEvent(event);
595  }
596 
597  event->accept();
598  Applet::mouseReleaseEvent(event);
599  }
600 }
601 
602 void Containment::showDropZone(const QPoint pos)
603 {
604  Q_UNUSED(pos)
605  //Base implementation does nothing, don't put code here
606 }
607 
608 void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
609 {
610  //kDebug() << containmentPos << screenPos;
611  QGraphicsSceneContextMenuEvent gvevent;
612  gvevent.setScreenPos(screenPos);
613  gvevent.setScenePos(mapToScene(containmentPos));
614  gvevent.setPos(containmentPos);
615  gvevent.setReason(QGraphicsSceneContextMenuEvent::Mouse);
616  gvevent.setWidget(view());
617  contextMenuEvent(&gvevent);
618 }
619 
620 void Containment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
621 {
622  if (!isContainment() || !KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
623  Applet::contextMenuEvent(event);
624  return;
625  }
626 
627  KMenu desktopMenu;
628  Applet *applet = d->appletAt(event->scenePos());
629  //kDebug() << "context menu event " << (QObject*)applet;
630 
631  if (applet) {
632  d->addAppletActions(desktopMenu, applet, event);
633  } else {
634  d->addContainmentActions(desktopMenu, event);
635  }
636 
637  //kDebug() << "executing at" << screenPos;
638  QMenu *menu = &desktopMenu;
639  //kDebug() << "showing menu, actions" << desktopMenu.actions().size() << desktopMenu.actions().first()->menu();
640  if (desktopMenu.actions().size() == 1 && desktopMenu.actions().first()->menu()) {
641  // we have a menu with a single top level menu; just show that top level menu instad.
642  menu = desktopMenu.actions().first()->menu();
643  }
644 
645  if (!menu->isEmpty()) {
646  QPoint pos = event->screenPos();
647  if (applet && d->isPanelContainment()) {
648  menu->adjustSize();
649  pos = applet->popupPosition(menu->size());
650  if (event->reason() == QGraphicsSceneContextMenuEvent::Mouse) {
651  // if the menu pops up way away from the mouse press, then move it
652  // to the mouse press
653  if (d->formFactor == Vertical) {
654  if (pos.y() + menu->height() < event->screenPos().y()) {
655  pos.setY(event->screenPos().y());
656  }
657  } else if (d->formFactor == Horizontal) {
658  if (pos.x() + menu->width() < event->screenPos().x()) {
659  pos.setX(event->screenPos().x());
660  }
661  }
662  }
663  }
664 
665  menu->exec(pos);
666  event->accept();
667  } else {
668  Applet::contextMenuEvent(event);
669  }
670 }
671 
672 void ContainmentPrivate::addContainmentActions(KMenu &desktopMenu, QEvent *event)
673 {
674  if (static_cast<Corona*>(q->scene())->immutability() != Mutable &&
675  !KAuthorized::authorizeKAction("plasma/containment_actions")) {
676  //kDebug() << "immutability";
677  return;
678  }
679 
680  const QString trigger = ContainmentActions::eventToString(event);
681  prepareContainmentActions(trigger, QPoint(), &desktopMenu);
682 }
683 
684 void ContainmentPrivate::addAppletActions(KMenu &desktopMenu, Applet *applet, QEvent *event)
685 {
686  foreach (QAction *action, applet->contextualActions()) {
687  if (action) {
688  desktopMenu.addAction(action);
689  }
690  }
691 
692  if (!applet->d->failed) {
693  QAction *configureApplet = applet->d->actions->action("configure");
694  if (configureApplet && configureApplet->isEnabled()) {
695  desktopMenu.addAction(configureApplet);
696  }
697 
698  QAction *runAssociatedApplication = applet->d->actions->action("run associated application");
699  if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
700  desktopMenu.addAction(runAssociatedApplication);
701  }
702  }
703 
704  KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
705  addContainmentActions(*containmentMenu, event);
706  if (!containmentMenu->isEmpty()) {
707  int enabled = 0;
708  //count number of real actions
709  QListIterator<QAction *> actionsIt(containmentMenu->actions());
710  while (enabled < 3 && actionsIt.hasNext()) {
711  QAction *action = actionsIt.next();
712  if (action->isVisible() && !action->isSeparator()) {
713  ++enabled;
714  }
715  }
716 
717  if (enabled) {
718  //if there is only one, don't create a submenu
719  if (enabled < 2) {
720  foreach (QAction *action, containmentMenu->actions()) {
721  if (action->isVisible() && !action->isSeparator()) {
722  desktopMenu.addAction(action);
723  }
724  }
725  } else {
726  desktopMenu.addMenu(containmentMenu);
727  }
728  }
729  }
730 
731  if (q->immutability() == Mutable &&
732  !q->property("hideCloseAppletInContextMenu").toBool()) {
733  QAction *closeApplet = applet->d->actions->action("remove");
734  //kDebug() << "checking for removal" << closeApplet;
735  if (closeApplet) {
736  if (!desktopMenu.isEmpty()) {
737  desktopMenu.addSeparator();
738  }
739 
740  //kDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
741  desktopMenu.addAction(closeApplet);
742  }
743  }
744 }
745 
746 Applet* ContainmentPrivate::appletAt(const QPointF &point)
747 {
748  Applet *applet = 0;
749 
750  QGraphicsItem *item = q->scene()->itemAt(point);
751  if (item == q) {
752  item = 0;
753  }
754 
755  while (item) {
756  if (item->isWidget()) {
757  applet = qobject_cast<Applet*>(static_cast<QGraphicsWidget*>(item));
758  if (applet) {
759  if (applet->isContainment()) {
760  applet = 0;
761  }
762  break;
763  }
764  }
765  AppletHandle *handle = dynamic_cast<AppletHandle*>(item);
766  if (handle) {
767  //pretend it was on the applet
768  applet = handle->applet();
769  break;
770  }
771  item = item->parentItem();
772  }
773  return applet;
774 }
775 
776 void Containment::setFormFactor(FormFactor formFactor)
777 {
778  if (d->formFactor == formFactor) {
779  return;
780  }
781 
782  //kDebug() << "switching FF to " << formFactor;
783  d->formFactor = formFactor;
784 
785  if (isContainment() &&
786  (d->type == PanelContainment || d->type == CustomPanelContainment)) {
787  // we are a panel and we have chaged our orientation
788  d->positionPanel(true);
789  }
790 
791  QMetaObject::invokeMethod(d->toolBox.data(), "reposition");
792 
793  updateConstraints(Plasma::FormFactorConstraint);
794 
795  KConfigGroup c = config();
796  c.writeEntry("formfactor", (int)formFactor);
797  emit configNeedsSaving();
798 }
799 
800 void Containment::setLocation(Location location)
801 {
802  if (d->location == location) {
803  return;
804  }
805 
806  bool emitGeomChange = false;
807 
808  if ((location == TopEdge || location == BottomEdge) &&
809  (d->location == TopEdge || d->location == BottomEdge)) {
810  emitGeomChange = true;
811  }
812 
813  if ((location == RightEdge || location == LeftEdge) &&
814  (d->location == RightEdge || d->location == LeftEdge)) {
815  emitGeomChange = true;
816  }
817 
818  d->location = location;
819 
820  foreach (Applet *applet, d->applets) {
821  applet->updateConstraints(Plasma::LocationConstraint);
822  }
823 
824  if (emitGeomChange) {
825  // our geometry on the scene will not actually change,
826  // but for the purposes of views it has
827  emit geometryChanged();
828  }
829 
830  updateConstraints(Plasma::LocationConstraint);
831 
832  KConfigGroup c = config();
833  c.writeEntry("location", (int)location);
834  emit configNeedsSaving();
835 }
836 
837 void Containment::addSiblingContainment()
838 {
839  emit addSiblingContainment(this);
840 }
841 
842 void Containment::clearApplets()
843 {
844  foreach (Applet *applet, d->applets) {
845  applet->d->cleanUpAndDelete();
846  }
847 
848  d->applets.clear();
849 }
850 
851 Applet *Containment::addApplet(const QString &name, const QVariantList &args,
852  const QRectF &appletGeometry)
853 {
854  return d->addApplet(name, args, appletGeometry);
855 }
856 
857 void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
858 {
859  if (!isContainment() || (!delayInit && immutability() != Mutable)) {
860  return;
861  }
862 
863  if (!applet) {
864  kDebug() << "adding null applet!?!";
865  return;
866  }
867 
868  if (d->applets.contains(applet)) {
869  kDebug() << "already have this applet!";
870  }
871 
872  Containment *currentContainment = applet->containment();
873 
874  if (d->type == PanelContainment) {
875  //panels don't want backgrounds, which is important when setting geometry
876  setBackgroundHints(NoBackground);
877  }
878 
879  if (currentContainment && currentContainment != this) {
880  emit currentContainment->appletRemoved(applet);
881  if (currentContainment->d->focusedApplet == applet) {
882  currentContainment->d->focusedApplet = 0;
883  }
884 
885  disconnect(applet, 0, currentContainment, 0);
886  KConfigGroup oldConfig = applet->config();
887  currentContainment->d->applets.removeAll(applet);
888  applet->setParentItem(this);
889  applet->setParent(this);
890 
891  // now move the old config to the new location
892  //FIXME: this doesn't seem to get the actual main config group containing plugin=, etc
893  KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
894  oldConfig.reparent(&c);
895  applet->d->resetConfigurationObject();
896 
897  disconnect(applet, SIGNAL(activate()), currentContainment, SIGNAL(activate()));
898  } else {
899  applet->setParentItem(this);
900  applet->setParent(this);
901  }
902 
903  d->applets << applet;
904 
905  connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
906  connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
907  connect(applet, SIGNAL(appletDestroyed(Plasma::Applet*)), this, SLOT(appletDestroyed(Plasma::Applet*)));
908  connect(applet, SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkStatus(Plasma::ItemStatus)));
909  connect(applet, SIGNAL(activate()), this, SIGNAL(activate()));
910 
911  if (pos != QPointF(-1, -1)) {
912  applet->setPos(pos);
913  }
914 
915  if (!delayInit && !currentContainment) {
916  applet->restore(*applet->d->mainConfigGroup());
917  applet->init();
918  Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::AppearAnimation);
919  if (anim) {
920  connect(anim, SIGNAL(finished()), this, SLOT(appletAppearAnimationComplete()));
921  anim->setTargetWidget(applet);
922  //FIXME: small hack until we have proper js anim support; allows 'zoom' to work in the
923  //'right' direction for appearance
924  anim->setDirection(QAbstractAnimation::Backward);
925  anim->start(QAbstractAnimation::DeleteWhenStopped);
926  } else {
927  d->appletAppeared(applet);
928  }
929  }
930 
931  applet->setFlag(QGraphicsItem::ItemIsMovable, true);
932  applet->updateConstraints(Plasma::AllConstraints);
933  if (!delayInit) {
934  applet->flushPendingConstraintsEvents();
935  }
936  emit appletAdded(applet, pos);
937 
938  if (!currentContainment) {
939  applet->updateConstraints(Plasma::StartupCompletedConstraint);
940  if (!delayInit) {
941  applet->flushPendingConstraintsEvents();
942  }
943  }
944 
945  if (!delayInit) {
946  applet->d->scheduleModificationNotification();
947  }
948 }
949 
950 Applet::List Containment::applets() const
951 {
952  return d->applets;
953 }
954 
955 void Containment::setScreen(int newScreen, int newDesktop)
956 {
957  d->setScreen(newScreen, newDesktop);
958 }
959 
960 void ContainmentPrivate::setScreen(int newScreen, int newDesktop, bool preventInvalidDesktops)
961 {
962  // What we want to do in here is:
963  // * claim the screen as our own
964  // * signal whatever may be watching this containment about the switch
965  // * if we are a full screen containment, then:
966  // * resize to match the screen if we're that kind of containment
967  // * kick other full-screen containments off this screen
968  // * if we had a screen, then give our screen to the containment
969  // we kick out
970  //
971  // a screen of -1 means no associated screen.
972  Corona *corona = q->corona();
973  Q_ASSERT(corona);
974 
975  //if it's an offscreen widget, don't allow to claim a screen, after all it's *off*screen
976  if (corona->offscreenWidgets().contains(q)) {
977  return;
978  }
979 
980  int numScreens = corona->numScreens();
981  if (newScreen < -1) {
982  newScreen = -1;
983  }
984 
985  // -1 == All desktops
986  if (newDesktop < -1 || (preventInvalidDesktops && newDesktop > KWindowSystem::numberOfDesktops() - 1)) {
987  newDesktop = -1;
988  }
989 
990  //kDebug() << activity() << "setting screen to " << newScreen << newDesktop << "and type is" << type;
991 
992  Containment *swapScreensWith(0);
993  const bool isDesktopContainment = type == Containment::DesktopContainment ||
994  type == Containment::CustomContainment;
995  if (isDesktopContainment) {
996  // we want to listen to changes in work area if our screen changes
997  if (toolBox) {
998  if (screen < 0 && newScreen > -1) {
999  QObject::connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), toolBox.data(), SLOT(reposition()), Qt::UniqueConnection);
1000  } else if (newScreen < 0) {
1001  QObject::disconnect(KWindowSystem::self(), SIGNAL(workAreaChanged()), toolBox.data(), SLOT(reposition()));
1002  }
1003  }
1004 
1005  if (newScreen > -1) {
1006  // sanity check to make sure someone else doesn't have this screen already!
1007  Containment *currently = corona->containmentForScreen(newScreen, newDesktop);
1008  if (currently && currently != q) {
1009  kDebug() << "currently is on screen" << currently->screen()
1010  << "desktop" << currently->desktop()
1011  << "and is" << currently->activity()
1012  << (QObject*)currently << "i'm" << (QObject*)q;
1013  currently->setScreen(-1, currently->desktop());
1014  swapScreensWith = currently;
1015  }
1016  }
1017  }
1018 
1019  if (newScreen < numScreens && newScreen > -1 && isDesktopContainment) {
1020  q->resize(corona->screenGeometry(newScreen).size());
1021  }
1022 
1023  int oldDesktop = desktop;
1024  desktop = newDesktop;
1025 
1026  int oldScreen = screen;
1027  screen = newScreen;
1028 
1029  q->updateConstraints(Plasma::ScreenConstraint);
1030 
1031  if (oldScreen != newScreen || oldDesktop != newDesktop) {
1032  /*
1033  kDebug() << "going to signal change for" << q
1034  << ", old screen & desktop:" << oldScreen << oldDesktop
1035  << ", new:" << screen << desktop;
1036  */
1037  KConfigGroup c = q->config();
1038  c.writeEntry("screen", screen);
1039  c.writeEntry("desktop", desktop);
1040  if (newScreen != -1) {
1041  lastScreen = newScreen;
1042  lastDesktop = newDesktop;
1043  c.writeEntry("lastScreen", lastScreen);
1044  c.writeEntry("lastDesktop", lastDesktop);
1045  }
1046  emit q->configNeedsSaving();
1047  emit q->screenChanged(oldScreen, newScreen, q);
1048  }
1049 
1050  if (swapScreensWith) {
1051  //kDebug() << "setScreen due to swap, part 2";
1052  swapScreensWith->setScreen(oldScreen, oldDesktop);
1053  }
1054 
1055  checkRemoveAction();
1056 
1057  if (newScreen >= 0) {
1058  emit q->activate();
1059  }
1060 }
1061 
1062 int Containment::screen() const
1063 {
1064  return d->screen;
1065 }
1066 
1067 int Containment::lastScreen() const
1068 {
1069  return d->lastScreen;
1070 }
1071 
1072 int Containment::desktop() const
1073 {
1074  return d->desktop;
1075 }
1076 
1077 int Containment::lastDesktop() const
1078 {
1079  return d->lastDesktop;
1080 }
1081 
1082 KPluginInfo::List Containment::listContainments(const QString &category,
1083  const QString &parentApp)
1084 {
1085  return listContainmentsOfType(QString(), category, parentApp);
1086 }
1087 
1088 
1089 KPluginInfo::List Containment::listContainmentsOfType(const QString &type,
1090  const QString &category,
1091  const QString &parentApp)
1092 {
1093  QString constraint;
1094 
1095  if (parentApp.isEmpty()) {
1096  constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
1097  } else {
1098  constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
1099  }
1100 
1101  if (!type.isEmpty()) {
1102  if (!constraint.isEmpty()) {
1103  constraint.append(" and ");
1104  }
1105 
1106  constraint.append("'").append(type).append("' ~in [X-Plasma-ContainmentCategories]");
1107  }
1108 
1109  if (!category.isEmpty()) {
1110  if (!constraint.isEmpty()) {
1111  constraint.append(" and ");
1112  }
1113 
1114  constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
1115  if (category == "Miscellaneous") {
1116  constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
1117  }
1118  }
1119 
1120  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
1121  //kDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches";
1122  return KPluginInfo::fromServices(offers);
1123 }
1124 
1125 KPluginInfo::List Containment::listContainmentsForMimetype(const QString &mimetype)
1126 {
1127  const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
1128  //kDebug() << mimetype << constraint;
1129  const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
1130  return KPluginInfo::fromServices(offers);
1131 }
1132 
1133 QStringList Containment::listContainmentTypes()
1134 {
1135  KPluginInfo::List containmentInfos = listContainments();
1136  QSet<QString> types;
1137 
1138  foreach (const KPluginInfo &containmentInfo, containmentInfos) {
1139  QStringList theseTypes = containmentInfo.service()->property("X-Plasma-ContainmentCategories").toStringList();
1140  foreach (const QString &type, theseTypes) {
1141  types.insert(type);
1142  }
1143  }
1144 
1145  return types.toList();
1146 }
1147 
1148 void Containment::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
1149 {
1150  event->setAccepted(immutability() == Mutable &&
1151  (event->mimeData()->hasFormat(static_cast<Corona*>(scene())->appletMimeType()) ||
1152  KUrl::List::canDecode(event->mimeData()) ||
1153  event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())));
1154  //kDebug() << immutability() << Mutable << (immutability() == Mutable) << event->isAccepted();
1155 
1156  if (!event->isAccepted()) {
1157  // check to see if we have an applet that accepts the format.
1158  QStringList formats = event->mimeData()->formats();
1159 
1160  foreach (const QString &format, formats) {
1161  KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(format);
1162  if (!appletList.isEmpty()) {
1163  event->setAccepted(true);
1164  break;
1165  }
1166  }
1167 
1168  if (!event->isAccepted()) {
1169  foreach (const QString &format, formats) {
1170  KPluginInfo::List wallpaperList = Wallpaper::listWallpaperInfoForMimetype(format);
1171  if (!wallpaperList.isEmpty()) {
1172  event->setAccepted(true);
1173  break;
1174  }
1175  }
1176  }
1177  }
1178 
1179  if (event->isAccepted()) {
1180  if (d->dropZoneStarted) {
1181  showDropZone(event->pos().toPoint());
1182  } else {
1183  if (!d->showDropZoneDelayTimer) {
1184  d->showDropZoneDelayTimer = new QTimer(this);
1185  d->showDropZoneDelayTimer->setSingleShot(true);
1186  connect(d->showDropZoneDelayTimer, SIGNAL(timeout()), this, SLOT(showDropZoneDelayed()));
1187  }
1188 
1189  d->dropPoints.insert(0, event->pos());
1190  d->showDropZoneDelayTimer->start(300);
1191  }
1192  }
1193 }
1194 
1195 void Containment::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
1196 {
1197  if (event->pos().y() < 1 || event->pos().y() > size().height() ||
1198  event->pos().x() < 1 || event->pos().x() > size().width()) {
1199  if (d->showDropZoneDelayTimer) {
1200  d->showDropZoneDelayTimer->stop();
1201  }
1202 
1203  showDropZone(QPoint());
1204  d->dropZoneStarted = false;
1205  }
1206 }
1207 
1208 void ContainmentPrivate::showDropZoneDelayed()
1209 {
1210  dropZoneStarted = true;
1211  q->showDropZone(dropPoints.value(0).toPoint());
1212  dropPoints.remove(0);
1213 }
1214 
1215 void Containment::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
1216 {
1217  //event->setAccepted(item == this || item == d->toolBox.data() || !item);
1218  //kDebug() << event->isAccepted() << d->showDropZoneDelayTimer->isActive();
1219  if (!event->isAccepted()) {
1220  if (d->showDropZoneDelayTimer) {
1221  d->showDropZoneDelayTimer->stop();
1222  }
1223  } else if ((!d->showDropZoneDelayTimer || !d->showDropZoneDelayTimer->isActive()) && immutability() == Plasma::Mutable) {
1224  showDropZone(event->pos().toPoint());
1225  }
1226 }
1227 
1228 void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
1229 {
1230  showDropZone(QPoint());
1231  d->dropZoneStarted = false;
1232  if (isContainment()) {
1233  d->dropData(event->scenePos(), event->screenPos(), event);
1234  } else {
1235  Applet::dropEvent(event);
1236  }
1237 }
1238 
1239 void ContainmentPrivate::dropData(QPointF scenePos, QPoint screenPos, QGraphicsSceneDragDropEvent *dropEvent)
1240 {
1241  if (q->immutability() != Mutable) {
1242  return;
1243  }
1244 
1245  QPointF pos = q->mapFromScene(scenePos);
1246  const QMimeData *mimeData = 0;
1247 
1248  if (dropEvent) {
1249  mimeData = dropEvent->mimeData();
1250  } else {
1251  QClipboard *clipboard = QApplication::clipboard();
1252  mimeData = clipboard->mimeData(QClipboard::Selection);
1253  //TODO if that's not supported (ie non-linux) should we try clipboard instead of selection?
1254  }
1255 
1256  if (!mimeData) {
1257  //Selection is either empty or not supported on this OS
1258  kDebug() << "no mime data";
1259  return;
1260  }
1261 
1262  //kDebug() << event->mimeData()->text();
1263 
1264  QString appletMimetype(q->corona() ? q->corona()->appletMimeType() : QString());
1265 
1266  if (!appletMimetype.isEmpty() && mimeData->hasFormat(appletMimetype)) {
1267  QString data = mimeData->data(appletMimetype);
1268  const QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
1269  foreach (const QString &appletName, appletNames) {
1270  //kDebug() << "doing" << appletName;
1271  QRectF geom(pos, QSize(0, 0));
1272  q->addApplet(appletName, QVariantList(), geom);
1273  }
1274  if (dropEvent) {
1275  dropEvent->acceptProposedAction();
1276  }
1277  } else if (mimeData->hasFormat(ExtenderItemMimeData::mimeType())) {
1278  kDebug() << "mimetype plasma/extenderitem is dropped, creating internal:extender";
1279  //Handle dropping extenderitems.
1280  const ExtenderItemMimeData *extenderData = qobject_cast<const ExtenderItemMimeData*>(mimeData);
1281  if (extenderData) {
1282  ExtenderItem *item = extenderData->extenderItem();
1283  QRectF geometry(pos - extenderData->pointerOffset(), item->size());
1284  kDebug() << "desired geometry: " << geometry;
1285  Applet *applet = qobject_cast<ExtenderApplet *>(item->extender() ? item->extender()->applet() : 0);
1286  if (applet) {
1287  qreal left, top, right, bottom;
1288  applet->getContentsMargins(&left, &top, &right, &bottom);
1289  applet->setPos(geometry.topLeft() - QPointF(int(left), int(top)));
1290  applet->show();
1291  } else {
1292  applet = addApplet("internal:extender", QVariantList(), geometry, 0, true);
1293  applet->hide();
1294  applet->init();
1295  appletAppeared(applet);
1296  applet->flushPendingConstraintsEvents();
1297  applet->d->scheduleModificationNotification();
1298  applet->adjustSize();
1299  applet->show();
1300  }
1301  item->setExtender(applet->extender());
1302  }
1303  } else if (KUrl::List::canDecode(mimeData)) {
1304  //TODO: collect the mimetypes of available script engines and offer
1305  // to create widgets out of the matching URLs, if any
1306  const KUrl::List urls = KUrl::List::fromMimeData(mimeData);
1307  foreach (const KUrl &url, urls) {
1308  if (AccessManager::supportedProtocols().contains(url.protocol())) {
1309  AccessAppletJob *job = AccessManager::self()->accessRemoteApplet(url);
1310  if (dropEvent) {
1311  dropPoints[job] = dropEvent->pos();
1312  } else {
1313  dropPoints[job] = scenePos;
1314  }
1315  QObject::connect(AccessManager::self(), SIGNAL(finished(Plasma::AccessAppletJob*)),
1316  q, SLOT(remoteAppletReady(Plasma::AccessAppletJob*)));
1317  }
1318 #ifndef PLASMA_NO_KIO
1319  else {
1320  KMimeType::Ptr mime = KMimeType::findByUrl(url);
1321  QString mimeName = mime->name();
1322  QRectF geom(pos, QSize());
1323  QVariantList args;
1324  args << url.url();
1325  kDebug() << "can decode" << mimeName << args;
1326 
1327  // It may be a directory or a file, let's stat
1328  KIO::JobFlags flags = KIO::HideProgressInfo;
1329  KIO::MimetypeJob *job = KIO::mimetype(url, flags);
1330  if (dropEvent) {
1331  dropPoints[job] = dropEvent->pos();
1332  } else {
1333  dropPoints[job] = scenePos;
1334  }
1335 
1336  QObject::connect(job, SIGNAL(result(KJob*)), q, SLOT(dropJobResult(KJob*)));
1337  QObject::connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
1338  q, SLOT(mimeTypeRetrieved(KIO::Job*,QString)));
1339 
1340  KMenu *choices = new KMenu("Content dropped");
1341  choices->addAction(KIcon("process-working"), i18n("Fetching file type..."));
1342  if (dropEvent) {
1343  choices->popup(dropEvent->screenPos());
1344  } else {
1345  choices->popup(screenPos);
1346  }
1347 
1348  dropMenus[job] = choices;
1349  }
1350 #endif
1351  }
1352 
1353  if (dropEvent) {
1354  dropEvent->acceptProposedAction();
1355  }
1356  } else {
1357  QStringList formats = mimeData->formats();
1358  QHash<QString, KPluginInfo> seenPlugins;
1359  QHash<QString, QString> pluginFormats;
1360 
1361  foreach (const QString &format, formats) {
1362  KPluginInfo::List plugins = Applet::listAppletInfoForMimetype(format);
1363 
1364  foreach (const KPluginInfo &plugin, plugins) {
1365  if (seenPlugins.contains(plugin.pluginName())) {
1366  continue;
1367  }
1368 
1369  seenPlugins.insert(plugin.pluginName(), plugin);
1370  pluginFormats.insert(plugin.pluginName(), format);
1371  }
1372  }
1373  //kDebug() << "Mimetype ..." << formats << seenPlugins.keys() << pluginFormats.values();
1374 
1375  QString selectedPlugin;
1376 
1377  if (seenPlugins.isEmpty()) {
1378  // do nothing
1379  } else if (seenPlugins.count() == 1) {
1380  selectedPlugin = seenPlugins.constBegin().key();
1381  } else {
1382  KMenu choices;
1383  QHash<QAction *, QString> actionsToPlugins;
1384  foreach (const KPluginInfo &info, seenPlugins) {
1385  QAction *action;
1386  if (!info.icon().isEmpty()) {
1387  action = choices.addAction(KIcon(info.icon()), info.name());
1388  } else {
1389  action = choices.addAction(info.name());
1390  }
1391 
1392  actionsToPlugins.insert(action, info.pluginName());
1393  }
1394 
1395  QAction *choice = choices.exec(screenPos);
1396  if (choice) {
1397  selectedPlugin = actionsToPlugins[choice];
1398  }
1399  }
1400 
1401  if (!selectedPlugin.isEmpty()) {
1402  if (!dropEvent) {
1403  // since we may have entered an event loop up above with the menu,
1404  // the clipboard item may no longer be valid, as QClipboard resets
1405  // the object behind the back of the application with a zero timer
1406  // so we fetch it again here
1407  QClipboard *clipboard = QApplication::clipboard();
1408  mimeData = clipboard->mimeData(QClipboard::Selection);
1409  }
1410 
1411  KTemporaryFile tempFile;
1412  if (mimeData && tempFile.open()) {
1413  //TODO: what should we do with files after the applet is done with them??
1414  tempFile.setAutoRemove(false);
1415 
1416  {
1417  QDataStream stream(&tempFile);
1418  QByteArray data = mimeData->data(pluginFormats[selectedPlugin]);
1419  stream.writeRawData(data, data.size());
1420  }
1421 
1422  QRectF geom(pos, QSize());
1423  QVariantList args;
1424  args << tempFile.fileName();
1425  kDebug() << args;
1426  tempFile.close();
1427 
1428  q->addApplet(selectedPlugin, args, geom);
1429  }
1430  }
1431  }
1432 }
1433 
1434 void ContainmentPrivate::clearDataForMimeJob(KIO::Job *job)
1435 {
1436 #ifndef PLASMA_NO_KIO
1437  QObject::disconnect(job, 0, q, 0);
1438  dropPoints.remove(job);
1439  KMenu *choices = dropMenus.take(job);
1440  delete choices;
1441  job->kill();
1442 #endif // PLASMA_NO_KIO
1443 }
1444 
1445 void ContainmentPrivate::remoteAppletReady(Plasma::AccessAppletJob *job)
1446 {
1447  QPointF pos = dropPoints.take(job);
1448  if (job->error()) {
1449  //TODO: nice user visible error handling (knotification probably?)
1450  kDebug() << "remote applet access failed: " << job->errorText();
1451  return;
1452  }
1453 
1454  if (!job->applet()) {
1455  kDebug() << "how did we end up here? if applet is null, the job->error should be nonzero";
1456  return;
1457  }
1458 
1459  q->addApplet(job->applet(), pos);
1460 }
1461 
1462 void ContainmentPrivate::dropJobResult(KJob *job)
1463 {
1464 #ifndef PLASMA_NO_KIO
1465  KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
1466  if (!tjob) {
1467  kDebug() << "job is not a KIO::TransferJob, won't handle the drop...";
1468  clearDataForMimeJob(tjob);
1469  return;
1470  }
1471  if (job->error()) {
1472  kDebug() << "ERROR" << tjob->error() << ' ' << tjob->errorString();
1473  }
1474  // We call mimetypeRetrieved since there might be other mechanisms
1475  // for finding suitable applets. Cleanup happens there as well.
1476  mimeTypeRetrieved(qobject_cast<KIO::Job *>(job), QString());
1477 #endif // PLASMA_NO_KIO
1478 }
1479 
1480 void ContainmentPrivate::mimeTypeRetrieved(KIO::Job *job, const QString &mimetype)
1481 {
1482 #ifndef PLASMA_NO_KIO
1483  kDebug() << "Mimetype Job returns." << mimetype;
1484  KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
1485  if (!tjob) {
1486  kDebug() << "job should be a TransferJob, but isn't";
1487  clearDataForMimeJob(job);
1488  return;
1489  }
1490  KPluginInfo::List appletList = Applet::listAppletInfoForUrl(tjob->url());
1491  if (mimetype.isEmpty() && !appletList.count()) {
1492  clearDataForMimeJob(job);
1493  kDebug() << "No applets found matching the url (" << tjob->url() << ") or the mimetype (" << mimetype << ")";
1494  return;
1495  } else {
1496 
1497  QPointF posi; // will be overwritten with the event's position
1498  if (dropPoints.keys().contains(tjob)) {
1499  posi = dropPoints[tjob];
1500  kDebug() << "Received a suitable dropEvent at" << posi;
1501  } else {
1502  kDebug() << "Bailing out. Cannot find associated dropEvent related to the TransferJob";
1503  clearDataForMimeJob(job);
1504  return;
1505  }
1506 
1507  KMenu *choices = dropMenus.value(tjob);
1508  if (!choices) {
1509  kDebug() << "Bailing out. No QMenu found for this job.";
1510  clearDataForMimeJob(job);
1511  return;
1512  }
1513 
1514  QVariantList args;
1515  args << tjob->url().url() << mimetype;
1516 
1517  kDebug() << "Creating menu for:" << mimetype << posi << args;
1518 
1519  appletList << Applet::listAppletInfoForMimetype(mimetype);
1520  KPluginInfo::List wallpaperList;
1521  if (drawWallpaper) {
1522  if (wallpaper && wallpaper->supportsMimetype(mimetype)) {
1523  wallpaperList << wallpaper->d->wallpaperDescription;
1524  } else {
1525  wallpaperList = Wallpaper::listWallpaperInfoForMimetype(mimetype);
1526  }
1527  }
1528 
1529  if (!appletList.isEmpty() || !wallpaperList.isEmpty()) {
1530  choices->clear();
1531  QHash<QAction *, QString> actionsToApplets;
1532  choices->addTitle(i18n("Widgets"));
1533  foreach (const KPluginInfo &info, appletList) {
1534  kDebug() << info.name();
1535  QAction *action;
1536  if (!info.icon().isEmpty()) {
1537  action = choices->addAction(KIcon(info.icon()), info.name());
1538  } else {
1539  action = choices->addAction(info.name());
1540  }
1541 
1542  actionsToApplets.insert(action, info.pluginName());
1543  kDebug() << info.pluginName();
1544  }
1545  actionsToApplets.insert(choices->addAction(i18n("Icon")), "icon");
1546 
1547  QHash<QAction *, QString> actionsToWallpapers;
1548  if (!wallpaperList.isEmpty()) {
1549  choices->addTitle(i18n("Wallpaper"));
1550 
1551  QMap<QString, KPluginInfo> sorted;
1552  foreach (const KPluginInfo &info, appletList) {
1553  sorted.insert(info.name(), info);
1554  }
1555 
1556  foreach (const KPluginInfo &info, wallpaperList) {
1557  QAction *action;
1558  if (!info.icon().isEmpty()) {
1559  action = choices->addAction(KIcon(info.icon()), info.name());
1560  } else {
1561  action = choices->addAction(info.name());
1562  }
1563 
1564  actionsToWallpapers.insert(action, info.pluginName());
1565  }
1566  }
1567 
1568  QAction *choice = choices->exec();
1569  if (choice) {
1570  // Put the job on hold so it can be recycled to fetch the actual content,
1571  // which is to be expected when something's dropped onto the desktop and
1572  // an applet is to be created with this URL
1573  if (!mimetype.isEmpty() && !tjob->error()) {
1574  tjob->putOnHold();
1575  KIO::Scheduler::publishSlaveOnHold();
1576  }
1577  QString plugin = actionsToApplets.value(choice);
1578  if (plugin.isEmpty()) {
1579  //set wallpapery stuff
1580  plugin = actionsToWallpapers.value(choice);
1581  if (!wallpaper || plugin != wallpaper->pluginName()) {
1582  kDebug() << "Wallpaper dropped:" << tjob->url();
1583  q->setWallpaper(plugin);
1584  }
1585 
1586  if (wallpaper) {
1587  kDebug() << "Wallpaper dropped:" << tjob->url();
1588  wallpaper->setUrls(KUrl::List() << tjob->url());
1589  }
1590  } else {
1591  addApplet(actionsToApplets[choice], args, QRectF(posi, QSize()));
1592  }
1593 
1594  clearDataForMimeJob(job);
1595  return;
1596  }
1597  } else {
1598  // we can at least create an icon as a link to the URL
1599  addApplet("icon", args, QRectF(posi, QSize()));
1600  }
1601  }
1602 
1603  clearDataForMimeJob(job);
1604 #endif // PLASMA_NO_KIO
1605 }
1606 
1607 #ifndef KDE_NO_DEPRECATED
1608 const QGraphicsItem *Containment::toolBoxItem() const
1609 {
1610  return d->toolBox.data();
1611 }
1612 #endif
1613 
1614 void Containment::setToolBox(AbstractToolBox *toolBox)
1615 {
1616  if (d->toolBox.data()) {
1617  d->toolBox.data()->deleteLater();
1618  }
1619  d->toolBox = toolBox;
1620 }
1621 
1622 AbstractToolBox *Containment::toolBox() const
1623 {
1624  return d->toolBox.data();
1625 }
1626 
1627 void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
1628 {
1629  Applet::resizeEvent(event);
1630 
1631  if (isContainment()) {
1632  if (d->isPanelContainment()) {
1633  d->positionPanel();
1634  } else if (corona()) {
1635  QMetaObject::invokeMethod(corona(), "layoutContainments");
1636  }
1637 
1638  if (d->wallpaper) {
1639  d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
1640  }
1641  }
1642 }
1643 
1644 void Containment::keyPressEvent(QKeyEvent *event)
1645 {
1646  //kDebug() << "keyPressEvent with" << event->key()
1647  // << "and hoping and wishing for a" << Qt::Key_Tab;
1648  if (event->key() == Qt::Key_Tab) { // && event->modifiers() == 0) {
1649  if (!d->applets.isEmpty()) {
1650  kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
1651  d->applets.first()->setFocus(Qt::TabFocusReason);
1652  }
1653  }
1654 }
1655 
1656 void Containment::wheelEvent(QGraphicsSceneWheelEvent *event)
1657 {
1658  event->ignore();
1659  if (d->appletAt(event->scenePos())) {
1660  return; //no unexpected click-throughs
1661  }
1662 
1663  if (d->wallpaper && d->wallpaper->isInitialized()) {
1664  QGraphicsItem *item = scene()->itemAt(event->scenePos());
1665  if (item == this) {
1666  event->ignore();
1667  d->wallpaper->wheelEvent(event);
1668 
1669  if (event->isAccepted()) {
1670  return;
1671  }
1672  }
1673  }
1674 
1675  QString trigger = ContainmentActions::eventToString(event);
1676 
1677  if (d->prepareContainmentActions(trigger, event->screenPos())) {
1678  d->actionPlugins()->value(trigger)->contextEvent(event);
1679  event->accept();
1680  } else {
1681  event->ignore();
1682  Applet::wheelEvent(event);
1683  }
1684 }
1685 
1686 bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
1687 {
1688  return Applet::sceneEventFilter(watched, event);
1689 }
1690 
1691 QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
1692 {
1693  //FIXME if the applet is moved to another containment we need to unfocus it
1694 
1695  if (isContainment() &&
1696  (change == QGraphicsItem::ItemSceneHasChanged ||
1697  change == QGraphicsItem::ItemPositionHasChanged)) {
1698  switch (d->type) {
1699  case PanelContainment:
1700  case CustomPanelContainment:
1701  d->positionPanel();
1702  break;
1703  default:
1704  if (corona()) {
1705  QMetaObject::invokeMethod(corona(), "layoutContainments");
1706  }
1707  break;
1708  }
1709  }
1710 
1711  return Applet::itemChange(change, value);
1712 }
1713 
1714 void Containment::enableAction(const QString &name, bool enable)
1715 {
1716  QAction *action = this->action(name);
1717  if (action) {
1718  action->setEnabled(enable);
1719  action->setVisible(enable);
1720  }
1721 }
1722 
1723 void Containment::addToolBoxAction(QAction *action)
1724 {
1725  d->createToolBox();
1726  if (d->toolBox) {
1727  d->toolBox.data()->addTool(action);
1728  }
1729 }
1730 
1731 void Containment::removeToolBoxAction(QAction *action)
1732 {
1733  if (d->toolBox) {
1734  d->toolBox.data()->removeTool(action);
1735  }
1736 }
1737 
1738 void Containment::setToolBoxOpen(bool open)
1739 {
1740  if (open) {
1741  openToolBox();
1742  } else {
1743  closeToolBox();
1744  }
1745 }
1746 
1747 bool Containment::isToolBoxOpen() const
1748 {
1749  return (d->toolBox && d->toolBox.data()->isShowing());
1750 }
1751 
1752 void Containment::openToolBox()
1753 {
1754  if (d->toolBox && !d->toolBox.data()->isShowing()) {
1755  d->toolBox.data()->setShowing(true);
1756  emit toolBoxVisibilityChanged(true);
1757  }
1758 }
1759 
1760 void Containment::closeToolBox()
1761 {
1762  if (d->toolBox && d->toolBox.data()->isShowing()) {
1763  d->toolBox.data()->setShowing(false);
1764  emit toolBoxVisibilityChanged(false);
1765  }
1766 }
1767 
1768 void Containment::addAssociatedWidget(QWidget *widget)
1769 {
1770  Applet::addAssociatedWidget(widget);
1771  if (d->focusedApplet) {
1772  d->focusedApplet->addAssociatedWidget(widget);
1773  }
1774 
1775  foreach (const Applet *applet, d->applets) {
1776  if (applet->d->activationAction) {
1777  widget->addAction(applet->d->activationAction);
1778  }
1779  }
1780 }
1781 
1782 void Containment::removeAssociatedWidget(QWidget *widget)
1783 {
1784  Applet::removeAssociatedWidget(widget);
1785  if (d->focusedApplet) {
1786  d->focusedApplet->removeAssociatedWidget(widget);
1787  }
1788 
1789  foreach (const Applet *applet, d->applets) {
1790  if (applet->d->activationAction) {
1791  widget->removeAction(applet->d->activationAction);
1792  }
1793  }
1794 }
1795 
1796 void Containment::setDrawWallpaper(bool drawWallpaper)
1797 {
1798  d->drawWallpaper = drawWallpaper;
1799  if (drawWallpaper) {
1800  KConfigGroup cfg = config();
1801  const QString wallpaper = cfg.readEntry("wallpaperplugin", defaultWallpaper);
1802  const QString mode = cfg.readEntry("wallpaperpluginmode", defaultWallpaperMode);
1803  setWallpaper(wallpaper, mode);
1804  } else {
1805  delete d->wallpaper;
1806  d->wallpaper = 0;
1807  }
1808 }
1809 
1810 bool Containment::drawWallpaper()
1811 {
1812  return d->drawWallpaper;
1813 }
1814 
1815 void Containment::setWallpaper(const QString &pluginName, const QString &mode)
1816 {
1817  KConfigGroup cfg = config();
1818  bool newPlugin = true;
1819  bool newMode = true;
1820 
1821  if (d->drawWallpaper) {
1822  if (d->wallpaper) {
1823  // we have a wallpaper, so let's decide whether we need to swap it out
1824  if (d->wallpaper->pluginName() != pluginName) {
1825  delete d->wallpaper;
1826  d->wallpaper = 0;
1827  } else {
1828  // it's the same plugin, so let's save its state now so when
1829  // we call restore later on we're safe
1830  newMode = d->wallpaper->renderingMode().name() != mode;
1831  newPlugin = false;
1832  }
1833  }
1834 
1835  if (!pluginName.isEmpty() && !d->wallpaper) {
1836  d->wallpaper = Plasma::Wallpaper::load(pluginName);
1837  }
1838 
1839  if (d->wallpaper) {
1840  d->wallpaper->setParent(this);
1841  d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
1842  d->wallpaper->setRenderingMode(mode);
1843 
1844  if (newPlugin) {
1845  cfg.writeEntry("wallpaperplugin", pluginName);
1846  }
1847 
1848  if (d->wallpaper->isInitialized()) {
1849  KConfigGroup wallpaperConfig = KConfigGroup(&cfg, "Wallpaper");
1850  wallpaperConfig = KConfigGroup(&wallpaperConfig, pluginName);
1851  d->wallpaper->restore(wallpaperConfig);
1852  }
1853 
1854  if (newMode) {
1855  cfg.writeEntry("wallpaperpluginmode", mode);
1856  }
1857  }
1858 
1859  update();
1860  }
1861 
1862  if (!d->wallpaper) {
1863  cfg.deleteEntry("wallpaperplugin");
1864  cfg.deleteEntry("wallpaperpluginmode");
1865  }
1866 
1867  if (newPlugin || newMode) {
1868  if (newPlugin && d->wallpaper) {
1869  connect(d->wallpaper, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
1870  connect(d->wallpaper, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
1871  }
1872 
1873  emit configNeedsSaving();
1874  }
1875 }
1876 
1877 Plasma::Wallpaper *Containment::wallpaper() const
1878 {
1879  return d->wallpaper;
1880 }
1881 
1882 void Containment::setContainmentActions(const QString &trigger, const QString &pluginName)
1883 {
1884  KConfigGroup cfg = containmentActionsConfig();
1885  ContainmentActions *plugin = 0;
1886 
1887  if (d->actionPlugins()->contains(trigger)) {
1888  plugin = d->actionPlugins()->value(trigger);
1889  if (plugin->pluginName() != pluginName) {
1890  d->actionPlugins()->remove(trigger);
1891  delete plugin;
1892  plugin=0;
1893  }
1894  }
1895  if (pluginName.isEmpty()) {
1896  cfg.deleteEntry(trigger);
1897  } else if (plugin) {
1898  //it already existed, just reload config
1899  if (plugin->isInitialized()) {
1900  plugin->setContainment(this); //to be safe
1901  //FIXME make a truly unique config group
1902  KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
1903  plugin->restore(pluginConfig);
1904  }
1905  } else {
1906  switch (d->containmentActionsSource) {
1907  case ContainmentPrivate::Activity:
1908  //FIXME
1909  case ContainmentPrivate::Local:
1910  plugin = ContainmentActions::load(this, pluginName);
1911  break;
1912  default:
1913  plugin = ContainmentActions::load(0, pluginName);
1914  }
1915  if (plugin) {
1916  cfg.writeEntry(trigger, pluginName);
1917  d->actionPlugins()->insert(trigger, plugin);
1918  } else {
1919  //bad plugin... gets removed. is this a feature or a bug?
1920  cfg.deleteEntry(trigger);
1921  }
1922  }
1923 
1924  emit configNeedsSaving();
1925 }
1926 
1927 QStringList Containment::containmentActionsTriggers()
1928 {
1929  return d->actionPlugins()->keys();
1930 }
1931 
1932 QString Containment::containmentActions(const QString &trigger)
1933 {
1934  ContainmentActions *c = d->actionPlugins()->value(trigger);
1935  return c ? c->pluginName() : QString();
1936 }
1937 
1938 void Containment::setActivity(const QString &activity)
1939 {
1940  Context *context = d->context();
1941  if (context->currentActivity() != activity) {
1942  context->setCurrentActivity(activity);
1943  }
1944 }
1945 
1946 void ContainmentPrivate::onContextChanged(Plasma::Context *con)
1947 {
1948  foreach (Applet *a, applets) {
1949  a->updateConstraints(ContextConstraint);
1950  }
1951 
1952  KConfigGroup c = q->config();
1953  QString act = con->currentActivityId();
1954 
1955  //save anything that's been set (boy I hope this avoids overwriting things)
1956  //FIXME of course if the user sets the name to an empty string we have a bug
1957  //but once we get context retrieving the name as soon as the id is set, this issue should go away
1958  if (!act.isEmpty()) {
1959  c.writeEntry("activityId", act);
1960  }
1961  act = con->currentActivity();
1962  if (!act.isEmpty()) {
1963  c.writeEntry("activity", act);
1964  }
1965 
1966  if (toolBox) {
1967  toolBox.data()->update();
1968  }
1969  emit q->configNeedsSaving();
1970  emit q->contextChanged(con);
1971 }
1972 
1973 QString Containment::activity() const
1974 {
1975  return d->context()->currentActivity();
1976 }
1977 
1978 Context *Containment::context() const
1979 {
1980  return d->context();
1981 }
1982 
1983 Context *ContainmentPrivate::context()
1984 {
1985  if (!con) {
1986  con = new Context(q);
1987  q->connect(con, SIGNAL(changed(Plasma::Context*)),
1988  q, SLOT(onContextChanged(Plasma::Context*)));
1989  }
1990 
1991  return con;
1992 }
1993 
1994 KActionCollection* ContainmentPrivate::actions()
1995 {
1996  return static_cast<Applet*>(q)->d->actions;
1997 }
1998 
1999 void ContainmentPrivate::focusApplet(Plasma::Applet *applet)
2000 {
2001  if (focusedApplet == applet) {
2002  return;
2003  }
2004 
2005  QList<QWidget *> widgets = actions()->associatedWidgets();
2006  if (focusedApplet) {
2007  foreach (QWidget *w, widgets) {
2008  focusedApplet->removeAssociatedWidget(w);
2009  }
2010  }
2011 
2012  if (applet && applets.contains(applet)) {
2013  //kDebug() << "switching to" << applet->name();
2014  focusedApplet = applet;
2015  foreach (QWidget *w, widgets) {
2016  focusedApplet->addAssociatedWidget(w);
2017  }
2018 
2019  if (!focusedApplet->hasFocus()) {
2020  focusedApplet->setFocus(Qt::ShortcutFocusReason);
2021  }
2022  } else {
2023  focusedApplet = 0;
2024  }
2025 }
2026 
2027 void Containment::focusNextApplet()
2028 {
2029  if (d->applets.isEmpty()) {
2030  return;
2031  }
2032  int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
2033  if (index >= d->applets.size()) {
2034  index = 0;
2035  }
2036  kDebug() << "index" << index;
2037  d->focusApplet(d->applets.at(index));
2038 }
2039 
2040 void Containment::focusPreviousApplet()
2041 {
2042  if (d->applets.isEmpty()) {
2043  return;
2044  }
2045  int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
2046  if (index < 0) {
2047  index = d->applets.size() - 1;
2048  }
2049  kDebug() << "index" << index;
2050  d->focusApplet(d->applets.at(index));
2051 }
2052 
2053 void Containment::destroy()
2054 {
2055  destroy(true);
2056 }
2057 
2058 void Containment::showConfigurationInterface()
2059 {
2060  Applet::showConfigurationInterface();
2061 }
2062 
2063 void Containment::configChanged()
2064 {
2065  Applet::configChanged();
2066 }
2067 
2068 void ContainmentPrivate::configChanged()
2069 {
2070  if (drawWallpaper) {
2071  KConfigGroup group = q->config();
2072  q->setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
2073  group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
2074  }
2075 }
2076 
2077 void ContainmentPrivate::requestConfiguration()
2078 {
2079  emit q->configureRequested(q);
2080 }
2081 
2082 void ContainmentPrivate::checkStatus(Plasma::ItemStatus appletStatus)
2083 {
2084  //kDebug() << "================== "<< appletStatus << q->status();
2085  if (appletStatus == q->status()) {
2086  emit q->newStatus(appletStatus);
2087  return;
2088  }
2089 
2090  if (appletStatus < q->status()) {
2091  // check to see if any other applet has a higher status, and stick with that
2092  // if we do
2093  foreach (Applet *applet, applets) {
2094  if (applet->status() > appletStatus) {
2095  appletStatus = applet->status();
2096  }
2097  }
2098  }
2099 
2100  q->setStatus(appletStatus);
2101 }
2102 
2103 void Containment::destroy(bool confirm)
2104 {
2105  if (immutability() != Mutable || Applet::d->transient) {
2106  return;
2107  }
2108 
2109  if (isContainment() && confirm) {
2110  //FIXME: should not be blocking
2111  const QString title = i18nc("@title:window %1 is the name of the containment", "Remove %1", name());
2112  KGuiItem remove = KStandardGuiItem::remove();
2113  remove.setText(title);
2114  if (KMessageBox::warningContinueCancel(view(),
2115  i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
2116  title, remove) != KMessageBox::Continue) {
2117  return;
2118  }
2119  }
2120 
2121  Applet::destroy();
2122 }
2123 
2124 void ContainmentPrivate::createToolBox()
2125 {
2126  if (!toolBox && KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
2127  toolBox = Plasma::AbstractToolBox::load(q->corona()->preferredToolBoxPlugin(type), QVariantList(), q);
2128 
2129  if (toolBox) {
2130  QObject::connect(toolBox.data(), SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
2131  QObject::connect(toolBox.data(), SIGNAL(toggled()), q, SLOT(updateToolBoxVisibility()));
2132 
2133  positionToolBox();
2134  }
2135  }
2136 }
2137 
2138 void ContainmentPrivate::positionToolBox()
2139 {
2140  QMetaObject::invokeMethod(toolBox.data(), "reposition");
2141 }
2142 
2143 void ContainmentPrivate::updateToolBoxVisibility()
2144 {
2145  emit q->toolBoxVisibilityChanged(toolBox.data()->isShowing());
2146 }
2147 
2148 void ContainmentPrivate::triggerShowAddWidgets()
2149 {
2150  emit q->showAddWidgetsInterface(QPointF());
2151 }
2152 
2153 void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
2154 {
2155  if (!q->isContainment()) {
2156  return;
2157  }
2158 
2159  //kDebug() << "got containmentConstraintsEvent" << constraints << (QObject*)toolBox;
2160  if (constraints & Plasma::ImmutableConstraint) {
2161  //update actions
2162  checkRemoveAction();
2163  const bool unlocked = q->immutability() == Mutable;
2164  q->setAcceptDrops(unlocked);
2165  q->enableAction("add widgets", unlocked);
2166 
2167  // tell the applets too
2168  foreach (Applet *a, applets) {
2169  a->setImmutability(q->immutability());
2170  a->updateConstraints(ImmutableConstraint);
2171  }
2172  }
2173 
2174  // pass on the constraints that are relevant here
2175  Constraints appletConstraints = NoConstraint;
2176  if (constraints & FormFactorConstraint) {
2177  appletConstraints |= FormFactorConstraint;
2178  }
2179 
2180  if (constraints & ScreenConstraint) {
2181  appletConstraints |= ScreenConstraint;
2182  }
2183 
2184  if (appletConstraints != NoConstraint) {
2185  foreach (Applet *applet, applets) {
2186  applet->updateConstraints(appletConstraints);
2187  }
2188  }
2189 
2190  if (toolBox && (constraints & Plasma::SizeConstraint ||
2191  constraints & Plasma::FormFactorConstraint ||
2192  constraints & Plasma::ScreenConstraint ||
2193  constraints & Plasma::StartupCompletedConstraint)) {
2194  //kDebug() << "Positioning toolbox";
2195  positionToolBox();
2196  }
2197 
2198  if (constraints & Plasma::StartupCompletedConstraint && type < Containment::CustomContainment) {
2199  q->addToolBoxAction(q->action("remove"));
2200  checkRemoveAction();
2201  }
2202 }
2203 
2204 Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
2205  const QRectF &appletGeometry, uint id, bool delayInit)
2206 {
2207  if (!q->isContainment()) {
2208  return 0;
2209  }
2210 
2211  if (!delayInit && q->immutability() != Mutable) {
2212  kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
2213  return 0;
2214  }
2215 
2216  QGraphicsView *v = q->view();
2217  if (v) {
2218  v->setCursor(Qt::BusyCursor);
2219  }
2220 
2221  Applet *applet = Applet::load(name, id, args);
2222  if (v) {
2223  v->unsetCursor();
2224  }
2225 
2226  if (!applet) {
2227  kDebug() << "Applet" << name << "could not be loaded.";
2228  applet = new Applet(0, QString(), id);
2229  applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
2230  }
2231 
2232  //kDebug() << applet->name() << "sizehint:" << applet->sizeHint() << "geometry:" << applet->geometry();
2233 
2234  q->addApplet(applet, appletGeometry.topLeft(), delayInit);
2235  return applet;
2236 }
2237 
2238 bool ContainmentPrivate::regionIsEmpty(const QRectF &region, Applet *ignoredApplet) const
2239 {
2240  foreach (Applet *applet, applets) {
2241  if (applet != ignoredApplet && applet->geometry().intersects(region)) {
2242  return false;
2243  }
2244  }
2245  return true;
2246 }
2247 
2248 void ContainmentPrivate::appletDestroyed(Plasma::Applet *applet)
2249 {
2250  applets.removeAll(applet);
2251  if (focusedApplet == applet) {
2252  focusedApplet = 0;
2253  }
2254 
2255  emit q->appletRemoved(applet);
2256  emit q->configNeedsSaving();
2257 }
2258 
2259 void ContainmentPrivate::appletAppearAnimationComplete()
2260 {
2261  Animation *anim = qobject_cast<Animation *>(q->sender());
2262  if (anim) {
2263  Applet *applet = qobject_cast<Applet*>(anim->targetWidget());
2264  if (applet) {
2265  appletAppeared(applet);
2266  }
2267  }
2268 }
2269 
2270 void ContainmentPrivate::appletAppeared(Applet *applet)
2271 {
2272  //kDebug() << type << Containment::DesktopContainment;
2273  KConfigGroup *cg = applet->d->mainConfigGroup();
2274  applet->save(*cg);
2275  emit q->configNeedsSaving();
2276 }
2277 
2278 void ContainmentPrivate::positionPanel(bool force)
2279 {
2280  if (!q->scene()) {
2281  kDebug() << "no scene yet";
2282  return;
2283  }
2284 
2285  // already positioning the panel - avoid infinite loops
2286  if (ContainmentPrivate::s_positioningPanels) {
2287  return;
2288  }
2289 
2290  // we position panels in negative coordinates, and stack all horizontal
2291  // and all vertical panels with each other.
2292 
2293 
2294  const QPointF p = q->pos();
2295 
2296  if (!force &&
2297  p.y() + q->size().height() < -INTER_CONTAINMENT_MARGIN &&
2298  q->scene()->collidingItems(q).isEmpty()) {
2299  // already positioned and not running into any other panels
2300  return;
2301  }
2302 
2303 
2304  QPointF newPos = preferredPanelPos(q->corona());
2305  if (p != newPos) {
2306  ContainmentPrivate::s_positioningPanels = true;
2307  q->setPos(newPos);
2308  ContainmentPrivate::s_positioningPanels = false;
2309  }
2310 }
2311 
2312 bool ContainmentPrivate::isPanelContainment() const
2313 {
2314  return type == Containment::PanelContainment || type == Containment::CustomPanelContainment;
2315 }
2316 
2317 QPointF ContainmentPrivate::preferredPos(Corona *corona) const
2318 {
2319  Q_ASSERT(corona);
2320 
2321  if (isPanelContainment()) {
2322  //kDebug() << "is a panel, so put it at" << preferredPanelPos(corona);
2323  return preferredPanelPos(corona);
2324  }
2325 
2326  QPointF pos(0, 0);
2327  QTransform t;
2328  while (QGraphicsItem *i = corona->itemAt(pos, t)) {
2329  pos.setX(i->scenePos().x() + i->boundingRect().width() + 10);
2330  }
2331 
2332  //kDebug() << "not a panel, put it at" << pos;
2333  return pos;
2334 }
2335 
2336 QPointF ContainmentPrivate::preferredPanelPos(Corona *corona) const
2337 {
2338  Q_ASSERT(corona);
2339 
2340  //TODO: research how non-Horizontal, non-Vertical (e.g. Planar) panels behave here
2341  bool horiz = formFactor == Plasma::Horizontal;
2342  qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
2343  qreal lastHeight = 0;
2344 
2345  // this should be ok for small numbers of panels, but if we ever end
2346  // up managing hundreds of them, this simplistic alogrithm will
2347  // likely be too slow.
2348  foreach (const Containment *other, corona->containments()) {
2349  if (other == q ||
2350  !other->d->isPanelContainment() ||
2351  horiz != (other->formFactor() == Plasma::Horizontal)) {
2352  // only line up with panels of the same orientation
2353  continue;
2354  }
2355 
2356  if (horiz) {
2357  qreal y = other->pos().y();
2358  if (y < bottom) {
2359  lastHeight = other->size().height();
2360  bottom = y;
2361  }
2362  } else {
2363  qreal width = other->size().width();
2364  qreal x = other->pos().x() + width;
2365  if (x > bottom) {
2366  lastHeight = width;
2367  bottom = x + lastHeight;
2368  }
2369  }
2370  }
2371 
2372  // give a space equal to the height again of the last item so there is
2373  // room to grow.
2374  QPointF newPos;
2375  if (horiz) {
2376  bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
2377  //TODO: fix x position for non-flush-left panels
2378  kDebug() << "moved to" << QPointF(0, bottom - q->size().height());
2379  newPos = QPointF(0, bottom - q->size().height());
2380  } else {
2381  bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
2382  //TODO: fix y position for non-flush-top panels
2383  kDebug() << "moved to" << QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
2384  newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
2385  }
2386 
2387  return newPos;
2388 }
2389 
2390 
2391 bool ContainmentPrivate::prepareContainmentActions(const QString &trigger, const QPoint &screenPos, KMenu *menu)
2392 {
2393  ContainmentActions *plugin = actionPlugins()->value(trigger);
2394  if (!plugin) {
2395  return false;
2396  }
2397  plugin->setContainment(q);
2398 
2399  if (!plugin->isInitialized()) {
2400  KConfigGroup cfg = q->containmentActionsConfig();
2401  KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
2402  plugin->restore(pluginConfig);
2403  }
2404 
2405  if (plugin->configurationRequired()) {
2406  KMenu *localMenu = menu ? menu : new KMenu();
2407 
2408  localMenu->addTitle(i18n("This plugin needs to be configured"));
2409  localMenu->addAction(q->action("configure"));
2410 
2411  if (!menu) {
2412  localMenu->exec(screenPos);
2413  delete localMenu;
2414  }
2415 
2416  return false;
2417  } else if (menu) {
2418  QList<QAction*> actions = plugin->contextualActions();
2419  if (actions.isEmpty()) {
2420  //it probably didn't bother implementing the function. give the user a chance to set
2421  //a better plugin. note that if the user sets no-plugin this won't happen...
2422  if (!isPanelContainment() && q->action("configure")) {
2423  menu->addAction(q->action("configure"));
2424  }
2425  } else {
2426  menu->addActions(actions);
2427  }
2428  }
2429 
2430  return true;
2431 }
2432 
2433 KConfigGroup Containment::containmentActionsConfig()
2434 {
2435  KConfigGroup cfg;
2436  switch (d->containmentActionsSource) {
2437  case ContainmentPrivate::Local:
2438  cfg = config();
2439  cfg = KConfigGroup(&cfg, "ActionPlugins");
2440  break;
2441  case ContainmentPrivate::Activity:
2442  cfg = KConfigGroup(corona()->config(), "Activities");
2443  cfg = KConfigGroup(&cfg, d->context()->currentActivityId());
2444  cfg = KConfigGroup(&cfg, "ActionPlugins");
2445  break;
2446  default:
2447  cfg = KConfigGroup(corona()->config(), "ActionPlugins");
2448  }
2449  return cfg;
2450 }
2451 
2452 QHash<QString, ContainmentActions*> * ContainmentPrivate::actionPlugins()
2453 {
2454  switch (containmentActionsSource) {
2455  case Activity:
2456  //FIXME
2457  case Local:
2458  return &localActionPlugins;
2459  default:
2460  return &globalActionPlugins;
2461  }
2462 }
2463 
2464 } // Plasma namespace
2465 
2466 #include "containment.moc"
2467 
Plasma::Containment::showDropZone
virtual void showDropZone(const QPoint pos)
Shows a visual clue for drag and drop The default implementation does nothing, reimplement in contain...
Definition: containment.cpp:602
Plasma::Applet::destroy
virtual void destroy()
Destroys the applet; it will be removed nicely and deleted.
Definition: applet.cpp:479
Plasma::SizeConstraint
the size of the applet was changed
Definition: plasma.h:49
Plasma::Vertical
The applet is constrained horizontally, but can expand vertically.
Definition: plasma.h:77
Plasma::Containment::restoreContents
virtual void restoreContents(KConfigGroup &group)
Called when the contents of the containment should be loaded.
Definition: containment.cpp:473
Plasma::Applet::activate
void activate()
Emitted when activation is requested due to, for example, a global keyboard shortcut.
Plasma::Containment::NoContainmentType
Definition: containment.h:100
Plasma::Containment::listContainments
static KPluginInfo::List listContainments(const QString &category=QString(), const QString &parentApp=QString())
Returns a list of all known containments.
Definition: containment.cpp:1082
Plasma::StartupCompletedConstraint
application startup has completed
Definition: plasma.h:51
Plasma::Applet::showConfigurationInterface
virtual void showConfigurationInterface()
Lets the user interact with the plasmoid options.
Definition: applet.cpp:1898
Plasma::Containment::mouseReleaseEvent
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Definition: containment.cpp:578
Plasma::Corona::screenGeometry
virtual QRect screenGeometry(int id) const
Returns the geometry of a given screen.
Definition: corona.cpp:441
Plasma::Applet::flushPendingConstraintsEvents
void flushPendingConstraintsEvents()
Sends all pending contraints updates to the applet.
Definition: applet.cpp:1204
Plasma::Corona::numScreens
virtual int numScreens() const
Returns the number of screens available to plasma.
Definition: corona.cpp:436
Plasma::ImmutabilityType
ImmutabilityType
Defines the immutability of items like applets, corona and containments they can be free to modify...
Definition: plasma.h:197
Plasma::Corona::offscreenWidgets
QList< QGraphicsWidget * > offscreenWidgets() const
Definition: corona.cpp:422
Plasma::ContainmentActions
The base ContainmentActions class.
Definition: containmentactions.h:55
context.h
animation.h
Plasma::Containment::destroy
void destroy()
Destroys this containment and all its applets (after a confirmation dialog); it will be removed nicel...
Definition: containment.cpp:2053
Plasma::Containment::configureRequested
void configureRequested(Plasma::Containment *containment)
Emitted when the user wants to configure/change containment.
Plasma::Containment::toolBoxItem
const QGraphicsItem * toolBoxItem() const
Definition: containment.cpp:1608
Plasma::Containment::StyleOption::Type
Definition: containment.h:85
Plasma::Containment::activity
QString activity() const
Definition: containment.cpp:1973
extender.h
abstracttoolbox.h
Plasma::Containment::setDrawWallpaper
void setDrawWallpaper(bool drawWallpaper)
Sets whether wallpaper is painted or not.
Definition: containment.cpp:1796
Plasma::AccessAppletJob::applet
Applet * applet() const
Definition: accessappletjob.cpp:185
Plasma::Containment::context
Context * context() const
Definition: containment.cpp:1978
Plasma::Containment::setFormFactor
void setFormFactor(Plasma::FormFactor formFactor)
Sets the form factor for this Containment.
Definition: containment.cpp:776
Plasma::Applet::restore
virtual void restore(KConfigGroup &group)
Restores state information about this applet saved previously in save(KConfigGroup&).
Definition: applet.cpp:310
Plasma::SystemImmutable
the item is locked down by the system, the user can't unlock it
Definition: plasma.h:201
Plasma::Containment::mousePressEvent
void mousePressEvent(QGraphicsSceneMouseEvent *event)
Definition: containment.cpp:546
Plasma::Applet::location
virtual Location location() const
Returns the location of the scene which is displaying applet.
Definition: applet.cpp:1618
Plasma::Applet::newStatus
void newStatus(Plasma::ItemStatus status)
Emitted when the applet status changes.
Plasma::Applet::formFactor
virtual FormFactor formFactor() const
Returns the current form factor the applet is being displayed in.
Definition: applet.cpp:1479
Plasma::Containment::enableAction
void enableAction(const QString &name, bool enable)
convenience function - enables or disables an action by name
Definition: containment.cpp:1714
Plasma::Containment::containmentType
Type containmentType() const
Returns the type of containment.
Definition: containment.cpp:501
QWidget
Plasma::Containment::dropEvent
void dropEvent(QGraphicsSceneDragDropEvent *event)
Definition: containment.cpp:1228
Plasma::Containment::PanelContainment
A desktop panel.
Definition: containment.h:102
Plasma::Applet::geometryChanged
void geometryChanged()
Emitted whenever the applet makes a geometry change, so that views can coordinate themselves with the...
Plasma::Containment::listContainmentTypes
static QStringList listContainmentTypes()
Definition: containment.cpp:1133
Plasma::Corona::containmentActionsDefaults
ContainmentActionsPluginsConfig containmentActionsDefaults(Containment::Type containmentType)
Definition: corona.cpp:777
Plasma::Containment::containmentActionsTriggers
QStringList containmentActionsTriggers()
Definition: containment.cpp:1927
Plasma::AbstractToolBox::AddTool
Definition: abstracttoolbox.h:48
Plasma::defaultWallpaperMode
static const char defaultWallpaperMode[]
Definition: containment.cpp:84
Plasma::Context
Definition: context.h:33
Plasma::Containment::applets
Applet::List applets() const
Definition: containment.cpp:950
Plasma::ImmutableConstraint
the immutability (locked) nature of the applet changed
Definition: plasma.h:50
Plasma::Containment::ContainmentPrivate
friend class ContainmentPrivate
Definition: containment.h:664
Plasma::Context::currentActivityId
QString currentActivityId() const
Definition: context.cpp:81
Plasma::Containment::isToolBoxOpen
bool isToolBoxOpen() const
Definition: containment.cpp:1747
containment.h
Plasma::Animation
Abstract representation of a single animation.
Definition: animation.h:46
QObject
Plasma::Applet::NoBackground
Not drawing a background under the applet, the applet has its own implementation. ...
Definition: applet.h:104
Plasma::Applet::itemChange
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Reimplemented from QGraphicsItem.
Definition: applet.cpp:2436
Plasma::version
unsigned int version()
The runtime version of libplasma.
Definition: version.cpp:26
Plasma::ContainmentActions::load
static ContainmentActions * load(Containment *parent, const QString &name, const QVariantList &args=QVariantList())
Attempts to load a containmentactions.
Definition: containmentactions.cpp:81
Plasma::Horizontal
The applet is constrained vertically, but can expand horizontally.
Definition: plasma.h:75
Plasma::Containment::StyleOption
Definition: containment.h:77
Plasma::Mutable
The item can be modified in any way.
Definition: plasma.h:198
Plasma::Containment::corona
Corona * corona() const
Returns the Corona (if any) that this Containment is hosted by.
Definition: containment.cpp:525
wallpaper.h
Plasma::Containment::CustomContainment
A containment that is neither a desktop nor a panel but something application specific.
Definition: containment.h:103
Plasma::Applet::configChanged
virtual void configChanged()
Called when applet configuration values have changed.
Definition: applet.cpp:2198
Plasma::Applet::immutability
ImmutabilityType immutability() const
Plasma::Containment::removeToolBoxAction
void removeToolBoxAction(QAction *action)
Remove an action from the toolbox.
Definition: containment.cpp:1731
Plasma::AbstractToolBox::load
static AbstractToolBox * load(const QString &name, const QVariantList &args=QVariantList(), Plasma::Containment *containment=0)
Create a new AbstractToolBox, loading the proper plugin.
Definition: abstracttoolbox.cpp:59
Plasma::defaultWallpaper
static const char defaultWallpaper[]
Definition: containment.cpp:83
Plasma::Applet
The base Applet class.
Definition: applet.h:77
Plasma::Containment::save
void save(KConfigGroup &group) const
Definition: containment.cpp:402
Plasma::appletConfigLessThan
bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
Definition: containment.cpp:277
Plasma::Containment::dragEnterEvent
void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
Definition: containment.cpp:1148
Plasma::Applet::sceneEventFilter
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
Definition: applet.cpp:1779
Plasma::Containment::setScreen
void setScreen(int screen, int desktop=-1)
Sets the physical screen this Containment is associated with.
Definition: containment.cpp:955
Plasma::Containment::appletRemoved
void appletRemoved(Plasma::Applet *applet)
This signal is emitted when an applet is destroyed.
Plasma::Applet::id
uint id
Definition: applet.h:91
accessmanager.h
Plasma::ContextConstraint
the context (e.g.
Definition: plasma.h:52
Plasma::Location
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
Definition: plasma.h:108
Plasma::Containment::keyPressEvent
void keyPressEvent(QKeyEvent *event)
Definition: containment.cpp:1644
Plasma::Containment::showContextMenu
void showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
Shows the context menu for the containment directly, bypassing Applets altogether.
Definition: containment.cpp:608
Plasma::Containment::setActivity
void setActivity(const QString &activity)
Sets the current activity by name.
Definition: containment.cpp:1938
Plasma::Containment::sceneEventFilter
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
Definition: containment.cpp:1686
Plasma::Containment::addSiblingContainment
void addSiblingContainment()
Tells the corona to create a new desktop containment.
Definition: containment.cpp:837
Plasma::Containment::StyleOption::Version
Definition: containment.h:88
Plasma::Applet::listAppletInfoForMimetype
static KPluginInfo::List listAppletInfoForMimetype(const QString &mimetype)
Returns a list of all known applets associated with a certain mimetype.
Definition: applet.cpp:2317
Plasma::Context::setCurrentActivity
void setCurrentActivity(const QString &name)
Definition: context.cpp:55
Plasma::Containment::screen
int screen() const
Definition: containment.cpp:1062
Plasma::Containment::lastScreen
int lastScreen() const
Definition: containment.cpp:1067
Plasma::Containment::dragLeaveEvent
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
Definition: containment.cpp:1195
Plasma::AccessManager::supportedProtocols
static QStringList supportedProtocols()
Definition: accessmanager.cpp:97
Plasma::Corona::action
QAction * action(QString name) const
Returns the QAction with the given name from our collection.
Definition: corona.cpp:716
Plasma::AllConstraints
Definition: plasma.h:54
Plasma::AccessManager::self
static AccessManager * self()
Singleton pattern accessor.
Definition: accessmanager.cpp:54
Plasma::Applet::setImmutability
void setImmutability(const ImmutabilityType immutable)
Sets the immutability type for this applet (not immutable, user immutable or system immutable) ...
Definition: applet.cpp:919
Plasma::AccessAppletJob
This class is used for asynchronously accessing an applet published on a remote system.
Definition: accessappletjob.h:42
Plasma::FormFactor
FormFactor
The FormFactor enumeration describes how a Plasma::Applet should arrange itself.
Definition: plasma.h:64
Plasma::Containment::restore
void restore(KConfigGroup &group)
Definition: containment.cpp:293
Plasma::Containment::contextMenuEvent
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
Definition: containment.cpp:620
Plasma::Applet::containment
Containment * containment() const
Definition: applet.cpp:1518
Plasma::Applet::removeAssociatedWidget
virtual void removeAssociatedWidget(QWidget *widget)
un-associate actions from this widget, including ones added after this call.
Definition: applet.cpp:1613
Plasma::Containment::listContainmentsOfType
static KPluginInfo::List listContainmentsOfType(const QString &type, const QString &category=QString(), const QString &parentApp=QString())
Returns a list of all known Containments that match the parameters.
Definition: containment.cpp:1089
Plasma::NoCache
Definition: theme.cpp:68
Plasma::Containment::containmentActions
QString containmentActions(const QString &trigger)
Definition: containment.cpp:1932
Plasma::Containment::setLocation
void setLocation(Plasma::Location location)
Informs the Corona as to what position it is in.
Definition: containment.cpp:800
Plasma::Containment::saveContents
virtual void saveContents(KConfigGroup &group) const
Called when the contents of the containment should be saved.
Definition: containment.cpp:447
Plasma::ContainmentActions::isInitialized
bool isInitialized() const
Definition: containmentactions.cpp:166
Plasma::Containment::init
void init()
Reimplemented from Applet.
Definition: containment.cpp:151
Plasma::ContainmentActions::eventToString
static QString eventToString(QEvent *event)
Turns a mouse or wheel event into a string suitable for a ContainmentActions.
Definition: containmentactions.cpp:225
Plasma::TopEdge
Along the top of the screen.
Definition: plasma.h:114
Plasma::FormFactorConstraint
The FormFactor for an object.
Definition: plasma.h:46
Plasma::Containment::focusPreviousApplet
void focusPreviousApplet()
switch keyboard focus to the previous one of our applets
Definition: containment.cpp:2040
Plasma::AbstractToolBox
Definition: abstracttoolbox.h:40
Plasma::AccessManager::accessRemoteApplet
AccessAppletJob * accessRemoteApplet(const KUrl &location) const
Access a native plasmoid hosted on another machine.
Definition: accessmanager.cpp:71
Plasma::Applet::listAppletInfoForUrl
static KPluginInfo::List listAppletInfoForUrl(const QUrl &url)
Returns a list of all known applets associated with a certain URL.
Definition: applet.cpp:2327
containmentactions.h
Plasma::Containment::clearApplets
void clearApplets()
Removes all applets from this Containment.
Definition: containment.cpp:842
Plasma::Containment::desktop
int desktop() const
Definition: containment.cpp:1072
Plasma::Containment::resizeEvent
void resizeEvent(QGraphicsSceneResizeEvent *event)
Definition: containment.cpp:1627
Plasma::Containment::Containment
Containment(QGraphicsItem *parent=0, const QString &serviceId=QString(), uint containmentId=0)
Definition: containment.cpp:110
Plasma::Containment::itemChange
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Definition: containment.cpp:1691
plasma.h
Plasma::Applet::resizeEvent
void resizeEvent(QGraphicsSceneResizeEvent *event)
Reimplemented from QGraphicsItem.
Definition: applet.cpp:1879
Plasma::Containment::listContainmentsForMimetype
static KPluginInfo::List listContainmentsForMimetype(const QString &mimetype)
Returns a list of all known applets associated with a certain mimetype.
Definition: containment.cpp:1125
Plasma::Applet::config
KConfigGroup config() const
Returns the KConfigGroup to access the applets configuration.
Definition: applet.cpp:450
Plasma::Containment::CustomPanelContainment
A customized desktop panel.
Definition: containment.h:105
Plasma::BottomEdge
Along the bottom of the screen.
Definition: plasma.h:115
Plasma::Containment::configChanged
void configChanged()
Called when applet configuration values have changed.
Definition: containment.cpp:2063
Plasma::Applet::view
QGraphicsView * view() const
Returns the view this widget is visible on, or 0 if none can be found.
Definition: applet.cpp:696
Plasma::ScreenConstraint
Which screen an object is on.
Definition: plasma.h:48
Plasma::ContainmentActions::pluginName
QString pluginName
Definition: containmentactions.h:59
Plasma::Applet::name
QString name
Definition: applet.h:81
Plasma::Containment::appletAdded
void appletAdded(Plasma::Applet *applet, const QPointF &pos)
This signal is emitted when a new applet is created by the containment.
Plasma::ContainmentActions::restore
void restore(const KConfigGroup &config)
This method should be called once the plugin is loaded or settings are changed.
Definition: containmentactions.cpp:171
Plasma::Containment::setContainmentType
void setContainmentType(Containment::Type type)
Sets the type of this containment.
Definition: containment.cpp:506
Plasma::Applet::List
QList< Applet * > List
Definition: applet.h:97
Plasma::type
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
Definition: easingcurve.cpp:63
Plasma::LocationConstraint
The Location of an object.
Definition: plasma.h:47
Plasma::Containment::toolBox
AbstractToolBox * toolBox() const
Definition: containment.cpp:1622
Plasma::Containment::setWallpaper
void setWallpaper(const QString &pluginName, const QString &mode=QString())
Sets wallpaper plugin.
Definition: containment.cpp:1815
Plasma::Applet::popupPosition
QPoint popupPosition(const QSize &s) const
Reccomended position for a popup window like a menu or a tooltip given its size.
Definition: applet.cpp:737
Plasma::Applet::setBackgroundHints
void setBackgroundHints(const BackgroundHints hints)
Sets the BackgroundHints for this applet.
Definition: applet.cpp:938
Plasma::Containment::setToolBoxOpen
void setToolBoxOpen(bool open)
Sets the open or closed state of the Containment's toolbox.
Definition: containment.cpp:1738
Plasma::Wallpaper::listWallpaperInfoForMimetype
static KPluginInfo::List listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor=QString())
Returns a list of all known wallpapers that can accept the given mimetype.
Definition: wallpaper.cpp:162
Plasma::Containment::drawWallpaper
bool drawWallpaper()
Return whether wallpaper is painted or not.
Definition: containment.cpp:1810
Plasma::Applet::updateConstraints
void updateConstraints(Plasma::Constraints constraints=Plasma::AllConstraints)
Called when any of the geometry constraints have been updated.
Definition: applet.cpp:750
Plasma::Applet::name
QString name() const
Returns the user-visible name for the applet, as specified in the .desktop file.
Plasma::Animator::create
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
Definition: animator.cpp:61
Plasma::Containment::toolBoxVisibilityChanged
void toolBoxVisibilityChanged(bool)
Emitted when the toolbox is hidden or shown.
corona.h
Plasma::ContainmentActions::setContainment
void setContainment(Containment *newContainment)
newContainment the containment the plugin should be associated with.
Definition: containmentactions.cpp:389
Plasma::AbstractToolBox::ControlTool
Definition: abstracttoolbox.h:50
Plasma::Applet::save
virtual void save(KConfigGroup &group) const
Saves state information about this applet that will be accessed when next instantiated in the restore...
Definition: applet.cpp:260
QGraphicsView
Plasma::Containment::showConfigurationInterface
void showConfigurationInterface()
Definition: containment.cpp:2058
Plasma::Containment::setContainmentActions
void setContainmentActions(const QString &trigger, const QString &pluginName)
Sets a containmentactions plugin.
Definition: containment.cpp:1882
Plasma::Corona::containmentForScreen
Containment * containmentForScreen(int screen, int desktop=-1) const
Returns the Containment, if any, for a given physical screen and desktop.
Definition: corona.cpp:296
Plasma::Applet::type
int type() const
Reimplemented from QGraphicsItem.
Definition: applet.cpp:1379
Plasma::Containment::addApplet
Applet * addApplet(const QString &name, const QVariantList &args=QVariantList(), const QRectF &geometry=QRectF(-1,-1,-1,-1))
Adds an applet to this Containment.
Definition: containment.cpp:851
Plasma::Applet::addAssociatedWidget
virtual void addAssociatedWidget(QWidget *widget)
associate actions with this widget, including ones added after this call.
Definition: applet.cpp:1608
Plasma::Containment::openToolBox
void openToolBox()
Open the Containment's toolbox.
Definition: containment.cpp:1752
containmentactionspluginsconfig.h
Plasma::Containment::dragMoveEvent
void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
Definition: containment.cpp:1215
Plasma::Containment::wheelEvent
void wheelEvent(QGraphicsSceneWheelEvent *event)
Definition: containment.cpp:1656
Plasma::Containment::containmentActionsConfig
KConfigGroup containmentActionsConfig()
Definition: containment.cpp:2433
Plasma::Containment::addAssociatedWidget
void addAssociatedWidget(QWidget *widget)
associate actions with this widget, including ones added after this call.
Definition: containment.cpp:1768
Plasma::Containment::DesktopContainment
A desktop containment.
Definition: containment.h:101
Plasma::Applet::appletDestroyed
void appletDestroyed(Plasma::Applet *applet)
Emitted when the applet is deleted.
Plasma::Containment
The base class for plugins that provide backgrounds and applet grouping containers.
Definition: containment.h:72
Plasma::ItemStatus
ItemStatus
Status of an applet.
Definition: plasma.h:256
Plasma::RightEdge
Along the right side of the screen.
Definition: plasma.h:117
Plasma::Applet::configNeedsSaving
void configNeedsSaving()
Emitted when an applet has changed values in its configuration and wishes for them to be saved at the...
Plasma::Containment::setToolBox
void setToolBox(AbstractToolBox *toolBox)
Sets a custom ToolBox if there was an old one it will be deleted and the new one won't have any actio...
Definition: containment.cpp:1614
Plasma::Containment::StyleOption::StyleOption
StyleOption()
Definition: containment.cpp:86
animator.h
Plasma::Corona::addOffscreenWidget
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
Definition: corona.cpp:377
Plasma::Animator::AppearAnimation
Definition: animator.h:56
Plasma::Applet::action
Q_INVOKABLE QAction * action(QString name) const
Returns the QAction with the given name from our collection.
Definition: applet.cpp:1390
Plasma::Containment::focusNextApplet
void focusNextApplet()
switch keyboard focus to the next of our applets
Definition: containment.cpp:2027
Plasma::Context::currentActivity
QString currentActivity() const
Definition: context.cpp:66
Plasma::Applet::isContainment
bool isContainment() const
Definition: applet.cpp:2647
Plasma::Containment::Type
Type
Definition: containment.h:99
accessappletjob.h
Plasma::Applet::init
virtual void init()
This method is called once the applet is loaded and added to a Corona.
Definition: applet.cpp:243
Plasma::Containment::removeAssociatedWidget
void removeAssociatedWidget(QWidget *widget)
un-associate actions from this widget, including ones added after this call.
Definition: containment.cpp:1782
Plasma::Containment::addToolBoxAction
void addToolBoxAction(QAction *action)
Add an action to the toolbox.
Definition: containment.cpp:1723
Plasma::Containment::closeToolBox
void closeToolBox()
Closes Containment's toolbox.
Definition: containment.cpp:1760
Plasma::Containment::mouseMoveEvent
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Definition: containment.cpp:530
QStyleOptionGraphicsItem
Plasma::LeftEdge
Along the left side of the screen.
Definition: plasma.h:116
Plasma::ContainmentActionsPluginsConfig
A class that holds a map of triggers to plugin names.
Definition: containmentactionspluginsconfig.h:41
Plasma::Applet::mouseMoveEvent
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Definition: applet.cpp:1862
KJob
Plasma::Applet::releaseVisualFocus
void releaseVisualFocus()
This signal indicates that an application launch, window creation or window focus event was triggered...
Plasma::NoConstraint
No constraint; never passed in to Applet::constraintsEvent on its own.
Definition: plasma.h:45
extenderitem.h
Plasma::Applet::geometry
QRectF geometry
Definition: applet.h:89
svg.h
Plasma::Containment::lastDesktop
int lastDesktop() const
Definition: containment.cpp:1077
Plasma::Applet::pluginName
QString pluginName() const
Returns the plugin name for the applet.
Plasma::Wallpaper
The base Wallpaper class.
Definition: wallpaper.h:56
Plasma::Containment::~Containment
~Containment()
Definition: containment.cpp:143
Plasma::Wallpaper::load
static Wallpaper * load(const QString &name, const QVariantList &args=QVariantList())
Attempts to load a wallpaper.
Definition: wallpaper.cpp:180
Plasma::Animation::setTargetWidget
void setTargetWidget(QGraphicsWidget *widget)
Set the widget on which the animation is to be performed.
Definition: animation.cpp:62
Plasma::Corona
A QGraphicsScene for Plasma::Applets.
Definition: corona.h:48
QGraphicsWidget
Plasma::Containment::wallpaper
Plasma::Wallpaper * wallpaper() const
Return wallpaper plugin.
Definition: containment.cpp:1877
Plasma::Applet::load
static Applet * load(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
Attempts to load an applet.
Definition: applet.cpp:2422
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:33 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal