• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Plasma

desktopview.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2007 Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License version 2 as
00007  *   published by the Free Software Foundation
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "desktopview.h"
00021 
00022 #include <QAction>
00023 #include <QDesktopWidget>
00024 #include <QFile>
00025 #include <QWheelEvent>
00026 #include <QCoreApplication>
00027 
00028 #include <KAuthorized>
00029 #include <KMenu>
00030 #include <KRun>
00031 #include <KToggleAction>
00032 #include <KWindowSystem>
00033 
00034 #include "plasma/applet.h"
00035 #include "plasma/corona.h"
00036 #include "plasma/containment.h"
00037 #include "plasma/svg.h"
00038 
00039 #include "dashboardview.h"
00040 #include "plasmaapp.h"
00041 
00042 DesktopView::DesktopView(Plasma::Containment *containment, int id, QWidget *parent)
00043     : Plasma::View(containment, id, parent),
00044       m_zoomLevel(Plasma::DesktopZoom),
00045       m_dashboard(0),
00046       m_dashboardFollowsDesktop(true)
00047 {
00048     setFocusPolicy(Qt::NoFocus);
00049 
00050     if (containment) {
00051         connectContainment(containment);
00052         containment->enableAction("zoom in", false);
00053         containment->enableAction("add sibling containment", false);
00054     }
00055     //FIXME should we have next/prev or up/down/left/right or what?
00056     QAction *action = new QAction(i18n("Next Activity"), this);
00057     action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00058     action->setShortcut(QKeySequence("ctrl+shift+n"));
00059     connect(action, SIGNAL(triggered()), this, SLOT(nextContainment()));
00060     addAction(action);
00061     action = new QAction(i18n("Previous Activity"), this);
00062     action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00063     action->setShortcut(QKeySequence("ctrl+shift+p"));
00064     connect(action, SIGNAL(triggered()), this, SLOT(previousContainment()));
00065     addAction(action);
00066 
00067     const int w = 25;
00068     QPixmap tile(w * 2, w * 2);
00069     tile.fill(palette().base().color());
00070     QPainter pt(&tile);
00071     QColor color = palette().mid().color();
00072     color.setAlphaF(.6);
00073     pt.fillRect(0, 0, w, w, color);
00074     pt.fillRect(w, w, w, w, color);
00075     pt.end();
00076     QBrush b(tile);
00077     setBackgroundBrush(tile);
00078 }
00079 
00080 DesktopView::~DesktopView()
00081 {
00082     delete m_dashboard;
00083 }
00084 
00085 void DesktopView::connectContainment(Plasma::Containment *containment)
00086 {
00087     if (containment) {
00088         connect(containment, SIGNAL(zoomRequested(Plasma::Containment*,Plasma::ZoomDirection)),
00089                 this, SLOT(zoom(Plasma::Containment*,Plasma::ZoomDirection)));
00090         connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showAppletBrowser()));
00091         connect(containment, SIGNAL(addSiblingContainment(Plasma::Containment *)), this, SLOT(addContainment(Plasma::Containment *)));
00092         connect(containment, SIGNAL(focusRequested(Plasma::Containment *)), this, SLOT(setContainment(Plasma::Containment *)));
00093     }
00094 }
00095 
00096 void DesktopView::toggleDashboard()
00097 {
00098     if (!m_dashboard) {
00099         if (!containment()) {
00100             return;
00101         }
00102 
00103         m_dashboardFollowsDesktop = true;
00104         KConfigGroup cg = config();
00105         Plasma::Containment *dc = containment();
00106         int containmentId = cg.readEntry("DashboardContainment", 0);
00107         if (containmentId > 0) {
00108             foreach (Plasma::Containment *c, containment()->corona()->containments()) {
00109                 if (c->id() == containmentId) {
00110                     dc = c;
00111                     m_dashboardFollowsDesktop = false;
00112                     break;
00113                 }
00114             }
00115         }
00116         m_dashboard = new DashboardView(dc, 0);
00117         m_dashboard->addActions(actions());
00118     }
00119 
00120     m_dashboard->toggleVisibility();
00121     kDebug() << "toggling dashboard for screen" << screen() << m_dashboard->isVisible();
00122 }
00123 
00124 void DesktopView::adjustSize()
00125 {
00126     // adapt to screen resolution changes
00127     QDesktopWidget *desktop = QApplication::desktop();
00128     QRect geom = desktop->screenGeometry(screen());
00129     setGeometry(geom);
00130     containment()->resize(geom.size());
00131 
00132     if (m_dashboard) {
00133         m_dashboard->setGeometry(geom);
00134     }
00135 }
00136 
00137 void DesktopView::setIsDesktop(bool isDesktop)
00138 {
00139     if (isDesktop) {
00140         setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
00141 
00142         KWindowSystem::setOnAllDesktops(winId(), true);
00143         KWindowSystem::setType(winId(), NET::Desktop);
00144         lower();
00145 
00146         adjustSize();
00147     } else {
00148         setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
00149 
00150         KWindowSystem::setOnAllDesktops(winId(), false);
00151         KWindowSystem::setType(winId(), NET::Normal); 
00152     }
00153 }
00154 
00155 bool DesktopView::isDesktop() const
00156 {
00157     return KWindowInfo(winId(), NET::WMWindowType).windowType(NET::Desktop);
00158 }
00159 
00160 void DesktopView::setContainment(Plasma::Containment *containment)
00161 {
00162     Plasma::Containment *oldContainment = this->containment();
00163     if (containment == oldContainment) {
00164         return;
00165     }
00166 
00167     if (m_zoomLevel == Plasma::DesktopZoom) {
00168         //make sure actions are up-to-date
00169         //this is icky but necessary to have the toolbox show the right actions for the zoom level
00170         containment->enableAction("zoom in", false);
00171         containment->enableAction("add sibling containment", false);
00172     }
00173 
00174     if (m_dashboard && m_dashboardFollowsDesktop) {
00175         m_dashboard->setContainment(containment);
00176     }
00177 
00178     if (m_zoomLevel == Plasma::DesktopZoom) {
00179         //switch connections
00180         disconnect(oldContainment, 0, this, 0);
00181         connectContainment(containment);
00182         //make sure actions are up-to-date
00183         oldContainment->enableAction("zoom in", true);
00184         oldContainment->enableAction("add sibling containment", true);
00185     }
00186 
00187     View::setContainment(containment);
00188 }
00189 
00190 void DesktopView::addContainment(Plasma::Containment *fromContainment)
00191 {
00192     if (fromContainment) {
00193         Plasma::Corona *corona = fromContainment->corona();
00194         if (corona) {
00195             //make it the same type of containment
00196             Plasma::Containment *c = corona->addContainment(fromContainment->pluginName());
00197             if (m_zoomLevel != Plasma::DesktopZoom) {
00198                 connectContainment(c);
00199             }
00200             //note: this will set a sane size too, assuming we have a screen
00201             setContainment(c);
00202             kDebug() << "containment added at" << c->geometry();
00203         }
00204     }
00205 }
00206 
00207 void DesktopView::zoom(Plasma::Containment *containment, Plasma::ZoomDirection direction)
00208 {
00209     if (direction == Plasma::ZoomIn) {
00210         zoomIn(containment);
00211     } else if (direction == Plasma::ZoomOut) {
00212         zoomOut(containment);
00213     }
00214 }
00215 
00216 void DesktopView::zoomIn(Plasma::Containment *toContainment)
00217 {
00218     if (toContainment && containment() != toContainment) {
00219         setContainment(toContainment);
00220     }
00221 
00222     if (m_zoomLevel == Plasma::GroupZoom) {
00223         setDragMode(NoDrag);
00224         m_zoomLevel = Plasma::DesktopZoom;
00225         qreal factor = Plasma::scalingFactor(m_zoomLevel) / matrix().m11();
00226         scale(factor, factor);
00227         if (containment()) {
00228             //disconnect from other containments
00229             Plasma::Corona *corona = containment()->corona();
00230             if (corona) {
00231                 QList<Plasma::Containment*> containments = corona->containments();
00232                 foreach (Plasma::Containment *c, containments) {
00233                     if (c == containment() || c->containmentType() == Plasma::Containment::PanelContainment) {
00234                         continue;
00235                     }
00236                     disconnect(c, 0, this, 0);
00237                 }
00238             }
00239             setSceneRect(containment()->geometry());
00240             containment()->closeToolBox();
00241             containment()->enableAction("zoom in", false);
00242             containment()->enableAction("add sibling containment", false);
00243         }
00244     } else if (m_zoomLevel == Plasma::OverviewZoom) {
00245         m_zoomLevel = Plasma::GroupZoom;
00246         qreal factor = Plasma::scalingFactor(m_zoomLevel);
00247         factor = factor / matrix().m11();
00248         scale(factor, factor);
00249         setSceneRect(QRectF(0, 0, scene()->sceneRect().right(), scene()->sceneRect().bottom()));
00250 
00251         if (containment()) {
00252             //make sure everyone can zoom out again
00253             Plasma::Corona *corona = containment()->corona();
00254             if (corona) {
00255                 QList<Plasma::Containment*> containments = corona->containments();
00256                 foreach (Plasma::Containment *c, containments) {
00257                     if (c->containmentType() == Plasma::Containment::PanelContainment) {
00258                         continue;
00259                     }
00260                     c->enableAction("zoom out", true);
00261                 }
00262             }
00263 
00264             ensureVisible(containment()->sceneBoundingRect());
00265         }
00266     } else {
00267         setDragMode(NoDrag);
00268         if (containment()) {
00269             containment()->closeToolBox();
00270             containment()->enableAction("zoom in", false);
00271             containment()->enableAction("add sibling containment", false);
00272         }
00273     }
00274 }
00275 
00276 void DesktopView::zoomOut(Plasma::Containment *fromContainment)
00277 {
00278     if (m_zoomLevel == Plasma::DesktopZoom) {
00279         fromContainment->enableAction("zoom in", true);
00280         fromContainment->enableAction("add sibling containment", true);
00281         m_zoomLevel = Plasma::GroupZoom;
00282         //connect to other containments
00283         //FIXME if some other view is zoomed out, a little madness will ensue
00284         Plasma::Corona *corona = containment()->corona();
00285         if (corona) {
00286             QList<Plasma::Containment*> containments = corona->containments();
00287             foreach (Plasma::Containment *c, containments) {
00288                 if (c == fromContainment ||
00289                     c->containmentType() == Plasma::Containment::PanelContainment) {
00290                     continue;
00291                 }
00292                 connectContainment(c);
00293             }
00294         }
00295     } else if (m_zoomLevel == Plasma::GroupZoom) {
00296         //make sure nobody can zoom out
00297         Plasma::Corona *corona = fromContainment->corona();
00298         if (corona) {
00299             QList<Plasma::Containment*> containments = corona->containments();
00300             foreach (Plasma::Containment *c, containments) {
00301                 if (c->containmentType() == Plasma::Containment::PanelContainment) {
00302                     continue;
00303                 }
00304                 c->enableAction("zoom out", false);
00305             }
00306         }
00307         m_zoomLevel = Plasma::OverviewZoom;
00308     } else {
00309         fromContainment->enableAction("zoom out", false);
00310         return;
00311     }
00312 
00313     setDragMode(ScrollHandDrag);
00314     qreal factor = Plasma::scalingFactor(m_zoomLevel);
00315     qreal s = factor / matrix().m11();
00316     scale(s, s);
00317     setSceneRect(QRectF(0, 0, scene()->sceneRect().right(), scene()->sceneRect().bottom()));
00318 
00319     ensureVisible(fromContainment->sceneBoundingRect());
00320 }
00321 
00322 void DesktopView::showAppletBrowser()
00323 {
00324     if (m_dashboard && m_dashboard->isVisible()) {
00325         return;
00326     }
00327 
00328     PlasmaApp::self()->showAppletBrowser(containment());
00329 }
00330 
00331 void DesktopView::wheelEvent(QWheelEvent* event)
00332 {
00333     if (scene() && scene()->itemAt(event->pos())) {
00334         QGraphicsView::wheelEvent(event);
00335         return;
00336     }
00337 
00338     if (event->modifiers() & Qt::ControlModifier) {
00339         if (event->delta() < 0) {
00340             zoomOut(containment());
00341         } else {
00342             zoomIn(containment());
00343         }
00344     }
00345 }
00346 
00347 // This function is reimplemented from QGraphicsView to work around the problem
00348 // that QPainter::fillRect(QRectF/QRect, QBrush), which QGraphicsView uses, is
00349 // potentially slow when the anti-aliasing hint is set and as implemented won't
00350 // hit accelerated code at all when it isn't set.  This implementation avoids
00351 // the problem by using integer coordinates and by using drawTiledPixmap() in
00352 // the case of a texture brush, and fillRect(QRect, QColor) in the case of a
00353 // solid pattern.  As an additional optimization it draws the background with
00354 // CompositionMode_Source.
00355 void DesktopView::drawBackground(QPainter *painter, const QRectF &rect)
00356 {
00357     const QPainter::CompositionMode savedMode = painter->compositionMode();
00358     const QBrush brush = backgroundBrush();
00359 
00360     switch (brush.style())
00361     {
00362     case Qt::TexturePattern:
00363     {
00364         // Note: this assumes that the brush origin is (0, 0), and that
00365         //       the brush has an identity transformation matrix.
00366         const QPixmap texture = brush.texture();
00367         QRect r = rect.toAlignedRect();
00368         r.setLeft(r.left() - (r.left() % texture.width()));
00369         r.setTop(r.top() - (r.top() % texture.height()));
00370         painter->setCompositionMode(QPainter::CompositionMode_Source);
00371         painter->drawTiledPixmap(r, texture);
00372         painter->setCompositionMode(savedMode);
00373         return;
00374     }
00375 
00376     case Qt::SolidPattern:
00377         painter->setCompositionMode(QPainter::CompositionMode_Source);
00378         painter->fillRect(rect.toAlignedRect(), brush.color());
00379         painter->setCompositionMode(savedMode);
00380         return;
00381 
00382     default:
00383         QGraphicsView::drawBackground(painter, rect);
00384     }
00385 }
00386 
00387 void DesktopView::screenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment* containment)
00388 {
00389     kDebug() << "was, is, containment:" << wasScreen << isScreen << (QObject*)containment;
00390     if (containment->containmentType() == Plasma::Containment::PanelContainment) {
00391         // we don't care about panel containments changing screens on us
00392         return;
00393     }
00394 
00395     if (wasScreen == screen()) {
00396         if (this->containment() == containment) {
00397             setContainment(0);
00398         }
00399     }
00400 
00401     if (isScreen == screen()) {
00402         setContainment(containment);
00403     }
00404 }
00405 
00406 void DesktopView::nextContainment()
00407 {
00408     QList<Plasma::Containment*> containments = containment()->corona()->containments();
00409     int start = containments.indexOf(containment());
00410     int i = (start + 1) % containments.size();
00411     //FIXME this is a *horrible* way of choosing a "next" containment.
00412     while (i != start) {
00413         if (containments.at(i)->containmentType() != Plasma::Containment::PanelContainment &&
00414             containments.at(i)->screen() == -1) {
00415             break;
00416         }
00417         i = (i + 1) % containments.size();
00418     }
00419 
00420     Plasma::Containment *c = containments.at(i);
00421     setContainment(c);
00422 }
00423 
00424 void DesktopView::previousContainment()
00425 {
00426     QList<Plasma::Containment*> containments = containment()->corona()->containments();
00427     int start = containments.indexOf(containment());
00428     //fun fact: in c++, (-1 % foo) == -1
00429     int i = start - 1;
00430     if (i < 0) {
00431         i += containments.size();
00432     }
00433     //FIXME this is a *horrible* way of choosing a "previous" containment.
00434     while (i != start) {
00435         if (containments.at(i)->containmentType() != Plasma::Containment::PanelContainment &&
00436             containments.at(i)->screen() == -1) {
00437             break;
00438         }
00439         if (--i < 0) {
00440             i += containments.size();
00441         }
00442     }
00443 
00444     Plasma::Containment *c = containments.at(i);
00445     setContainment(c);
00446 }
00447 
00448 #include "desktopview.moc"
00449 

Plasma

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

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal