-moved "add activity" action here
[kdebase.git] / workspace / plasma / shells / desktop / plasmaapp.cpp
blob7371e65f63f73697146998b559ddaf86d55a93dc
1 /*
2 * Copyright 2006 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "plasmaapp.h"
22 #ifdef Q_WS_WIN
23 #ifdef _WIN32_WINNT
24 #undef _WIN32_WINNT
25 #endif
26 #define _WIN32_WINNT 0x0500
27 #include <windows.h>
28 #endif
30 #include <unistd.h>
32 #ifndef _SC_PHYS_PAGES
33 #ifdef Q_OS_FREEBSD
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
36 #endif
38 #ifdef Q_OS_NETBSD
39 #include <sys/param.h>
40 #include <sys/sysctl.h>
41 #endif
42 #endif
44 #include <QApplication>
45 #include <QDesktopWidget>
46 #include <QPixmapCache>
47 #include <QTimer>
48 #include <QtDBus/QtDBus>
50 #include <KAction>
51 #include <KCrash>
52 #include <KDebug>
53 #include <KCmdLineArgs>
54 #include <KWindowSystem>
56 #include <ksmserver_interface.h>
58 #include <Plasma/Containment>
59 #include <Plasma/Theme>
60 #include <Plasma/Dialog>
62 #include "appletbrowser.h"
63 #include "appadaptor.h"
64 #include "backgrounddialog.h"
65 #include "desktopcorona.h"
66 #include "desktopview.h"
67 #include "panelview.h"
68 #include "plasma-shell-desktop.h"
69 #include "toolbutton.h"
71 #include <kephal/screens.h>
73 #ifdef Q_WS_X11
74 #include <X11/Xlib.h>
75 #include <X11/extensions/Xrender.h>
76 #endif
78 PlasmaApp* PlasmaApp::self()
80 if (!kapp) {
81 return new PlasmaApp();
84 return qobject_cast<PlasmaApp*>(kapp);
87 PlasmaApp::PlasmaApp()
88 : KUniqueApplication(),
90 m_corona(0),
91 m_appletBrowser(0),
92 m_zoomLevel(Plasma::DesktopZoom),
93 m_panelHidden(0)
95 KGlobal::locale()->insertCatalog("libplasma");
96 KGlobal::locale()->insertCatalog("plasma-shells-common");
97 KCrash::setFlags(KCrash::AutoRestart);
99 new PlasmaAppAdaptor(this);
100 QDBusConnection::sessionBus().registerObject("/App", this);
101 notifyStartup(false);
103 // Enlarge application pixmap cache
104 // Calculate the size required to hold background pixmaps for all screens.
105 // Add 10% so that other (smaller) pixmaps can also be cached.
106 int cacheSize = 0;
107 for (int i = 0; i < Kephal::ScreenUtils::numScreens(); i++) {
108 QSize size = Kephal::ScreenUtils::screenSize(i);
109 cacheSize += 4 * size.width() * size.height() / 1024;
111 cacheSize += cacheSize / 10;
113 // Calculate the size of physical system memory; _SC_PHYS_PAGES *
114 // _SC_PAGESIZE is documented to be able to overflow 32-bit integers,
115 // so apply a 10-bit shift. FreeBSD 6-STABLE doesn't have _SC_PHYS_PAGES
116 // (it is documented in FreeBSD 7-STABLE as "Solaris and Linux extension")
117 // so use sysctl in those cases.
118 #if defined(_SC_PHYS_PAGES)
119 int memorySize = sysconf(_SC_PHYS_PAGES);
120 memorySize *= sysconf(_SC_PAGESIZE) / 1024;
121 #else
122 #ifdef Q_OS_FREEBSD
123 int sysctlbuf[2];
124 size_t size = sizeof(sysctlbuf);
125 int memorySize;
126 // This could actually use hw.physmem instead, but I can't find
127 // reliable documentation on how to read the value (which may
128 // not fit in a 32 bit integer).
129 if (!sysctlbyname("vm.stats.vm.v_page_size", sysctlbuf, &size, NULL, 0)) {
130 memorySize = sysctlbuf[0] / 1024;
131 size = sizeof(sysctlbuf);
132 if (!sysctlbyname("vm.stats.vm.v_page_count", sysctlbuf, &size, NULL, 0)) {
133 memorySize *= sysctlbuf[0];
136 #endif
137 #ifdef Q_OS_NETBSD
138 size_t memorySize;
139 size_t len;
140 static int mib[] = { CTL_HW, HW_PHYSMEM };
142 len = sizeof(memorySize);
143 sysctl(mib, 2, &memorySize, &len, NULL, 0);
144 memorySize /= 1024;
145 #endif
146 #ifdef Q_WS_WIN
147 size_t memorySize;
149 MEMORYSTATUSEX statex;
150 statex.dwLength = sizeof (statex);
151 GlobalMemoryStatusEx (&statex);
153 memorySize = (statex.ullTotalPhys/1024) + (statex.ullTotalPageFile/1024);
154 #endif
155 // If you have no suitable sysconf() interface and are not FreeBSD,
156 // then you are out of luck and get a compile error.
157 #endif
159 // Increase the pixmap cache size to 1% of system memory if it isn't already
160 // larger so as to maximize cache usage. 1% of 1GB ~= 10MB.
161 if (cacheSize < memorySize / 100) {
162 cacheSize = memorySize / 100;
165 kDebug() << "Setting the pixmap cache size to" << cacheSize << "kilobytes";
166 QPixmapCache::setCacheLimit(cacheSize);
168 KAction *showAction = new KAction(this);
169 showAction->setText(i18n("Show Dashboard"));
170 showAction->setObjectName("Show Dashboard"); // NO I18N
171 showAction->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F12));
172 connect(showAction, SIGNAL(triggered()), this, SLOT(toggleDashboard()));
174 connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
175 QTimer::singleShot(0, this, SLOT(setupDesktop()));
178 PlasmaApp::~PlasmaApp()
180 delete m_appletBrowser;
183 void PlasmaApp::setupDesktop()
185 #ifdef Q_WS_X11
186 Atom atoms[5];
187 const char * const atomNames[] = {"XdndAware", "XdndEnter", "XdndFinished", "XdndPosition", "XdndStatus"};
188 XInternAtoms(QX11Info::display(), const_cast<char **>(atomNames), 5, False, atoms);
189 m_XdndAwareAtom = atoms[0];
190 m_XdndEnterAtom = atoms[1];
191 m_XdndFinishedAtom = atoms[2];
192 m_XdndPositionAtom = atoms[3];
193 m_XdndStatusAtom = atoms[4];
194 const int xdndversion = 5;
195 m_XdndVersionAtom = (Atom)xdndversion;
196 #endif
198 // intialize the default theme and set the font
199 Plasma::Theme *theme = Plasma::Theme::defaultTheme();
200 theme->setFont(AppSettings::desktopFont());
201 connect(theme, SIGNAL(themeChanged()), this, SLOT(compositingChanged()));
203 // this line initializes the corona.
204 corona();
206 Kephal::Screens *screens = Kephal::Screens::self();
207 connect(screens, SIGNAL(screenRemoved(int)), SLOT(screenRemoved(int)));
209 // and now, let everyone know we're ready!
210 notifyStartup(true);
213 void PlasmaApp::cleanup()
215 if (m_corona) {
216 m_corona->saveLayout();
219 // save the mapping of Views to Containments at the moment
220 // of application exit so we can restore that when we start again.
221 KConfigGroup viewIds(KGlobal::config(), "ViewIds");
222 viewIds.deleteGroup();
224 foreach (PanelView *v, m_panels) {
225 if (v->containment()) {
226 viewIds.writeEntry(QString::number(v->containment()->id()), v->id());
230 foreach (DesktopView *v, m_desktops) {
231 if (v->containment()) {
232 viewIds.writeEntry(QString::number(v->containment()->id()), v->id());
236 QList<DesktopView*> desktops = m_desktops;
237 m_desktops.clear();
238 qDeleteAll(desktops);
240 QList<PanelView*> panels = m_panels;
241 m_panels.clear();
242 qDeleteAll(panels);
244 delete m_corona;
246 //TODO: This manual sync() should not be necessary. Remove it when
247 // KConfig was fixed
248 KGlobal::config()->sync();
251 void PlasmaApp::syncConfig()
253 KGlobal::config()->sync();
256 void PlasmaApp::toggleDashboardIfWindows()
258 const int desktop = KWindowSystem::currentDesktop();
260 foreach (WId id, KWindowSystem::stackingOrder()) {
261 const KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMState |
262 NET::XAWMState | NET::WMWindowType |
263 NET::WMVisibleName);
264 NET::WindowType type = info.windowType(NET::Normal | NET::Dialog);
265 if ((type == NET::Normal || type == NET::Dialog) &&
266 info.isOnDesktop(desktop) && !(info.state() & NET::Hidden) /*!info.isMinimized()*/) {
267 kDebug() << info.visibleName() << info.state() << info.windowType(NET::Normal | NET::Dialog);
268 toggleDashboard();
269 return;
274 void PlasmaApp::toggleDashboard()
276 int currentScreen = 0;
277 if (Kephal::ScreenUtils::numScreens() > 1) {
278 currentScreen = Kephal::ScreenUtils::screenId(QCursor::pos());
281 int currentDesktop = -1;
282 if (AppSettings::perVirtualDesktopViews()) {
283 currentDesktop = KWindowSystem::currentDesktop();
286 DesktopView *view = viewForScreen(currentScreen, currentDesktop);
287 if (!view) {
288 kWarning() << "we don't have a DesktopView for the current screen!" << currentScreen << currentDesktop;
289 return;
292 view->toggleDashboard();
295 void PlasmaApp::panelHidden(bool hidden)
297 if (hidden) {
298 ++m_panelHidden;
299 //kDebug() << "panel hidden" << m_panelHidden;
300 } else {
301 --m_panelHidden;
302 if (m_panelHidden < 0) {
303 kDebug() << "panelHidden(false) called too many times!";
304 m_panelHidden = 0;
306 //kDebug() << "panel unhidden" << m_panelHidden;
310 Plasma::ZoomLevel PlasmaApp::desktopZoomLevel() const
312 return m_zoomLevel;
315 QList<PanelView*> PlasmaApp::panelViews() const
317 return m_panels;
320 void PlasmaApp::compositingChanged()
322 #ifdef Q_WS_X11
323 foreach (PanelView *panel, m_panels) {
324 panel->recreateUnhideTrigger();
326 #endif
329 #ifdef Q_WS_X11
330 PanelView *PlasmaApp::findPanelForTrigger(WId trigger) const
332 foreach (PanelView *panel, m_panels) {
333 if (panel->unhideTrigger() == trigger) {
334 return panel;
338 return 0;
341 bool PlasmaApp::x11EventFilter(XEvent *event)
343 if (m_panelHidden &&
344 (event->type == ClientMessage ||
345 (event->xany.send_event != True && (event->type == EnterNotify ||
346 event->type == MotionNotify)))) {
349 if (event->type == ClientMessage) {
350 kDebug() << "client message with" << event->xclient.message_type << m_XdndEnterAtom << event->xcrossing.window;
354 bool dndEnter = false;
355 bool dndPosition = false;
356 if (event->type == ClientMessage) {
357 dndEnter = event->xclient.message_type == m_XdndEnterAtom;
358 if (!dndEnter) {
359 dndPosition = event->xclient.message_type == m_XdndPositionAtom;
360 if (!dndPosition) {
361 //kDebug() << "FAIL!";
362 return KUniqueApplication::x11EventFilter(event);
364 } else {
365 //kDebug() << "on enter" << event->xclient.data.l[0];
369 PanelView *panel = findPanelForTrigger(event->xcrossing.window);
370 //kDebug() << "panel?" << panel << ((dndEnter || dndPosition) ? "Drag and drop op" : "Mouse move op");
371 if (panel) {
372 if (dndEnter || dndPosition) {
373 QPoint p;
375 const unsigned long *l = (const unsigned long *)event->xclient.data.l;
376 if (dndPosition) {
377 p = QPoint((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff);
380 XClientMessageEvent response;
381 response.type = ClientMessage;
382 response.window = l[0];
383 response.format = 32;
384 response.data.l[0] = panel->winId(); //event->xcrossing.window;
386 if (panel->hintOrUnhide(p, true)) {
387 response.message_type = m_XdndFinishedAtom;
388 response.data.l[1] = 0; // flags
389 response.data.l[2] = XNone;
390 } else {
391 response.message_type = m_XdndStatusAtom;
392 response.data.l[1] = 0; // flags
393 response.data.l[2] = 0; // x, y
394 response.data.l[3] = 0; // w, h
395 response.data.l[4] = 0; // action
398 XSendEvent(QX11Info::display(), l[0], False, NoEventMask, (XEvent*)&response);
399 } else if (event->type == EnterNotify) {
400 panel->hintOrUnhide(QPoint(-1, -1));
401 //kDebug() << "entry";
402 //FIXME: this if it was possible to avoid the polling
403 /*} else if (event->type == LeaveNotify) {
404 panel->unhintHide();
406 } else if (event->type == MotionNotify) {
407 XMotionEvent *motion = (XMotionEvent*)event;
408 //kDebug() << "motion" << motion->x << motion->y << panel->location();
409 panel->hintOrUnhide(QPoint(motion->x_root, motion->y_root));
412 return true;
416 return KUniqueApplication::x11EventFilter(event);
418 #endif
420 void PlasmaApp::screenRemoved(int id)
422 kDebug() << id;
423 QMutableListIterator<DesktopView *> it(m_desktops);
424 while (it.hasNext()) {
425 DesktopView *view = it.next();
426 if (view->screen() == id) {
427 // the screen was removed, so we'll destroy the
428 // corresponding view
429 kDebug() << "removing the view for screen" << id;
430 view->setContainment(0);
431 it.remove();
432 delete view;
436 QMutableListIterator<PanelView*> pIt(m_panels);
437 while (pIt.hasNext()) {
438 PanelView *panel = pIt.next();
439 if (panel->screen() == id) {
440 kDebug() << "removing a panel for screen" << id;
441 panel->setContainment(0);
442 pIt.remove();
443 delete panel;
448 DesktopView* PlasmaApp::viewForScreen(int screen, int desktop) const
450 foreach (DesktopView *view, m_desktops) {
451 //kDebug() << "comparing" << view->screen() << screen;
452 if (view->screen() == screen && (desktop < 0 || view->desktop() == desktop)) {
453 return view;
457 return 0;
460 Plasma::Corona* PlasmaApp::corona()
462 if (!m_corona) {
463 QTime t;
464 t.start();
465 DesktopCorona *c = new DesktopCorona(this);
466 connect(c, SIGNAL(containmentAdded(Plasma::Containment*)),
467 this, SLOT(containmentAdded(Plasma::Containment*)));
468 connect(c, SIGNAL(configSynced()), this, SLOT(syncConfig()));
469 connect(c, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)),
470 this, SLOT(updateActions(Plasma::ImmutabilityType)));
472 foreach (DesktopView *view, m_desktops) {
473 connect(c, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)),
474 view, SLOT(screenOwnerChanged(int,int,Plasma::Containment*)));
477 //actions!
478 KAction *activityAction = new KAction(i18n("Add Activity"), this);
479 activityAction->setIcon(KIcon("list-add"));
480 activityAction->setVisible(false);
481 activityAction->setEnabled(false);
482 connect(activityAction, SIGNAL(triggered()), this, SLOT(addContainment()));
483 activityAction->setShortcut(QKeySequence("alt+d,alt+a"));
484 activityAction->setShortcutContext(Qt::ApplicationShortcut);
485 c->addAction("add sibling containment", activityAction);
487 m_corona = c;
488 c->setItemIndexMethod(QGraphicsScene::NoIndex);
489 c->initializeLayout();
490 c->checkScreens();
491 kDebug() << " ------------------------------------------>" << t.elapsed();
494 return m_corona;
497 void PlasmaApp::showAppletBrowser()
499 Plasma::Containment *containment = dynamic_cast<Plasma::Containment *>(sender());
501 if (!containment) {
502 return;
505 foreach (DesktopView *view, m_desktops) {
506 if (view->containment() == containment && view->isDashboardVisible()) {
507 // the dashboard will pick this one up!
508 return;
512 showAppletBrowser(containment);
515 void PlasmaApp::showAppletBrowser(Plasma::Containment *containment)
517 if (!containment) {
518 return;
521 if (!m_appletBrowser) {
522 m_appletBrowser = new Plasma::AppletBrowser();
523 m_appletBrowser->setContainment(containment);
524 m_appletBrowser->setApplication();
525 m_appletBrowser->setAttribute(Qt::WA_DeleteOnClose);
526 m_appletBrowser->setWindowTitle(i18n("Add Widgets"));
527 m_appletBrowser->setWindowIcon(KIcon("plasmagik"));
528 connect(m_appletBrowser, SIGNAL(destroyed()), this, SLOT(appletBrowserDestroyed()));
529 } else {
530 m_appletBrowser->setContainment(containment);
533 KWindowSystem::setOnDesktop(m_appletBrowser->winId(), KWindowSystem::currentDesktop());
534 m_appletBrowser->show();
535 KWindowSystem::activateWindow(m_appletBrowser->winId());
538 void PlasmaApp::appletBrowserDestroyed()
540 m_appletBrowser = 0;
543 bool PlasmaApp::hasComposite()
545 // return true;
546 #ifdef Q_WS_X11
547 return KWindowSystem::compositingActive();
548 #else
549 return false;
550 #endif
553 void PlasmaApp::notifyStartup(bool completed)
555 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
557 const QString startupID("workspace desktop");
558 if (completed) {
559 ksmserver.resumeStartup(startupID);
560 } else {
561 ksmserver.suspendStartup(startupID);
565 bool PlasmaApp::isPanelContainment(Plasma::Containment *containment)
567 Plasma::Containment::Type t = containment->containmentType();
569 return t == Plasma::Containment::PanelContainment ||
570 t == Plasma::Containment::CustomPanelContainment;
574 void PlasmaApp::createView(Plasma::Containment *containment)
576 kDebug() << "Containment name:" << containment->name()
577 << "| type" << containment->containmentType()
578 << "| screen:" << containment->screen()
579 << "| desktop:" << containment->desktop()
580 << "| geometry:" << containment->geometry()
581 << "| zValue:" << containment->zValue();
583 // find the mapping of View to Containment, if any,
584 // so we can restore things on start.
585 KConfigGroup viewIds(KGlobal::config(), "ViewIds");
586 int id = viewIds.readEntry(QString::number(containment->id()), 0);
588 WId viewWindow = 0;
590 if (isPanelContainment(containment)) {
591 if (containment->screen() < Kephal::ScreenUtils::numScreens()) {
592 PanelView *panelView = new PanelView(containment, id);
593 viewWindow = panelView->winId();
594 connect(panelView, SIGNAL(destroyed(QObject*)), this, SLOT(panelRemoved(QObject*)));
595 m_panels << panelView;
596 panelView->show();
598 } else if (containment->screen() > -1 &&
599 containment->screen() < Kephal::ScreenUtils::numScreens()) {
600 DesktopView *view = viewForScreen(containment->screen(), containment->desktop());
601 if (view) {
602 kDebug() << "had a view for" << containment->screen() << containment->desktop();
603 // we already have a view for this screen
604 return;
607 kDebug() << "creating a new view for" << containment->screen() << containment->desktop()
608 << "and we have" << Kephal::ScreenUtils::numScreens() << "screens";
610 // we have a new screen. neat.
611 view = new DesktopView(containment, id, 0);
612 viewWindow = view->winId();
613 if (m_corona) {
614 connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)),
615 view, SLOT(screenOwnerChanged(int,int,Plasma::Containment*)));
618 m_desktops.append(view);
619 view->show();
622 #ifdef Q_WS_X11
623 //FIXME: if argb visuals enabled Qt will always set WM_CLASS as "qt-subapplication" no matter what
624 //the application name is we set the proper XClassHint here, hopefully won't be necessary anymore when
625 //qapplication will manage apps with argvisuals in a better way
626 if (viewWindow) {
627 XClassHint classHint;
628 classHint.res_name = const_cast<char*>("Plasma");
629 classHint.res_class = const_cast<char*>("Plasma");
630 XSetClassHint(QX11Info::display(), viewWindow, &classHint);
632 #endif
635 void PlasmaApp::containmentAdded(Plasma::Containment *containment)
637 if (isPanelContainment(containment)) {
638 foreach (PanelView * panel, m_panels) {
639 if (panel->containment() == containment) {
640 kDebug() << "not creating second PanelView with existing Containment!!";
641 return;
646 createView(containment);
647 disconnect(containment, 0, this, 0);
648 connect(containment, SIGNAL(zoomRequested(Plasma::Containment*,Plasma::ZoomDirection)),
649 this, SLOT(zoom(Plasma::Containment*,Plasma::ZoomDirection)));
650 connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showAppletBrowser()));
651 connect(containment, SIGNAL(configureRequested(Plasma::Containment*)),
652 this, SLOT(configureContainment(Plasma::Containment*)));
654 if (containment->containmentType() == Plasma::Containment::DesktopContainment
655 && m_zoomLevel == Plasma::DesktopZoom) {
656 foreach (QAction *action, m_corona->actions()) {
657 containment->addToolBoxAction(action);
662 void PlasmaApp::configureContainment(Plasma::Containment *containment)
664 const QString id = "plasma_containment_settings_" + QString::number(containment->id());
665 BackgroundDialog *configDialog = qobject_cast<BackgroundDialog*>(KConfigDialog::exists(id));
666 kDebug() << configDialog;
668 if (configDialog) {
669 configDialog->reloadConfig();
670 } else {
671 const QSize resolution = QApplication::desktop()->screenGeometry(containment->screen()).size();
672 Plasma::View *view = viewForScreen(containment->screen(), containment->desktop());
674 if (!view) {
675 view = viewForScreen(desktop()->screenNumber(QCursor::pos()), containment->desktop());
677 if (!view) {
678 if (m_desktops.count() < 1) {
679 return;
682 view = m_desktops.at(0);
687 KConfigSkeleton *nullManager = new KConfigSkeleton(0);
688 configDialog = new BackgroundDialog(resolution, containment, view, 0, id, nullManager);
689 configDialog->setAttribute(Qt::WA_DeleteOnClose);
691 connect(configDialog, SIGNAL(destroyed(QObject*)), nullManager, SLOT(deleteLater()));
694 configDialog->show();
695 KWindowSystem::setOnDesktop(configDialog->winId(), KWindowSystem::currentDesktop());
696 KWindowSystem::activateWindow(configDialog->winId());
699 void PlasmaApp::addContainment()
701 //try to find the "active" containment to get a plugin name
702 int currentScreen = Kephal::ScreenUtils::screenId(QCursor::pos());
703 int currentDesktop = -1;
704 if (AppSettings::perVirtualDesktopViews()) {
705 currentDesktop = KWindowSystem::currentDesktop();
707 Plasma::Containment *fromContainment=m_corona->containmentForScreen(currentScreen, currentDesktop);
709 QString plugin = fromContainment ? fromContainment->pluginName() : QString();
710 Plasma::Containment *c = m_corona->addContainment(plugin);
712 if (c && fromContainment) {
713 foreach (DesktopView *view, m_desktops) {
714 if (view->containment() == fromContainment){
715 view->setContainment(c);
716 return;
720 // if we reach here, the containment isn't going to be taken over by the view,
721 // so we're going to resize it ourselves!
722 c->resize(fromContainment->size());
726 void PlasmaApp::zoom(Plasma::Containment *containment, Plasma::ZoomDirection direction)
728 if (direction == Plasma::ZoomIn) {
729 zoomIn(containment);
730 foreach (DesktopView *view, m_desktops) {
731 view->zoomIn(m_zoomLevel);
734 if (m_zoomLevel == Plasma::DesktopZoom) {
735 int currentDesktop = -1;
736 if (AppSettings::perVirtualDesktopViews()) {
737 currentDesktop = KWindowSystem::currentDesktop();
740 DesktopView *view = viewForScreen(desktop()->screenNumber(QCursor::pos()), currentDesktop);
742 if (view && view->containment() != containment) {
743 // zooming in all the way, so lets swap containments about if need be
744 view->setContainment(containment);
747 } else if (direction == Plasma::ZoomOut) {
748 zoomOut(containment);
749 foreach (DesktopView *view, m_desktops) {
750 view->zoomOut(m_zoomLevel);
755 void PlasmaApp::zoomIn(Plasma::Containment *containment)
757 bool isMutable = m_corona->immutability() == Plasma::Mutable;
758 bool zoomIn = true;
759 bool zoomOut = true;
760 bool addSibling = isMutable;
761 bool remove = false;
763 if (m_zoomLevel == Plasma::GroupZoom) {
764 setControllerVisible(false);
765 m_zoomLevel = Plasma::DesktopZoom;
766 containment->closeToolBox();
767 addSibling = false;
768 zoomIn = false;
769 } else if (m_zoomLevel == Plasma::OverviewZoom) {
770 m_zoomLevel = Plasma::GroupZoom;
771 remove = isMutable && true;
774 //make sure everybody can zoom out again
775 foreach (Plasma::Containment *c, m_corona->containments()) {
776 if (isPanelContainment(c)) {
777 continue;
780 if (m_zoomLevel == Plasma::DesktopZoom) {
781 foreach (QAction *action, m_corona->actions()) {
782 c->addToolBoxAction(action);
786 c->enableAction("zoom in", zoomIn);
787 c->enableAction("zoom out", zoomOut);
788 c->enableAction("remove", remove && (c->screen() == -1));
789 c->enableAction("add widgets", isMutable);
791 m_corona->enableAction("add sibling containment", addSibling);
794 void PlasmaApp::zoomOut(Plasma::Containment *)
796 bool isMutable = m_corona->immutability() == Plasma::Mutable;
797 bool zoomIn = true;
798 bool zoomOut = true;
799 bool addSibling = isMutable && true; //FIXME wtf?
800 bool addWidgets = isMutable && true;
802 if (m_zoomLevel == Plasma::DesktopZoom) {
803 setControllerVisible(true);
804 m_zoomLevel = Plasma::GroupZoom;
805 } else if (m_zoomLevel == Plasma::GroupZoom) {
806 m_zoomLevel = Plasma::OverviewZoom;
807 zoomOut = false;
808 addWidgets = false;
811 //make sure everybody can zoom out again
812 foreach (Plasma::Containment *c, m_corona->containments()) {
813 if (isPanelContainment(c)) {
814 continue;
817 if (m_zoomLevel == Plasma::GroupZoom) {
818 foreach (QAction *action, m_corona->actions()) {
819 c->removeToolBoxAction(action);
823 c->enableAction("zoom in", zoomIn);
824 c->enableAction("zoom out", zoomOut);
825 c->enableAction("remove", isMutable && c->screen() == -1);
826 c->enableAction("add widgets", addWidgets);
828 m_corona->enableAction("add sibling containment", addSibling);
831 void PlasmaApp::setControllerVisible(bool show)
833 if (show && !m_controllerDialog) {
834 m_controllerDialog = new Plasma::Dialog;
835 QVBoxLayout *layout = new QVBoxLayout(m_controllerDialog);
837 foreach (QAction *action, m_corona->actions()) {
838 ToolButton *actionButton = new ToolButton(m_controllerDialog);
839 actionButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
840 actionButton->setDefaultAction(action);
841 layout->addWidget(actionButton);
844 m_controllerDialog->show();
845 } else if (!show) {
846 delete m_controllerDialog;
847 m_controllerDialog = 0;
851 void PlasmaApp::panelRemoved(QObject* panel)
853 m_panels.removeAll((PanelView*)panel);
856 void PlasmaApp::updateActions(Plasma::ImmutabilityType immutability)
858 bool enable = immutability == Plasma::Mutable && m_zoomLevel != Plasma::DesktopZoom;
859 kDebug() << enable;
860 m_corona->enableAction("add sibling containment", enable);
864 #include "plasmaapp.moc"