• Skip to content
  • Skip to link menu
KDE 4.2 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 <QFile>
00024 #include <QWheelEvent>
00025 #include <QCoreApplication>
00026 
00027 #include <KAuthorized>
00028 #include <KMenu>
00029 #include <KRun>
00030 #include <KToggleAction>
00031 #include <KWindowSystem>
00032 
00033 #include <Plasma/Applet>
00034 #include <Plasma/Corona>
00035 #include <Plasma/Containment>
00036 #include <Plasma/Svg>
00037 #include <Plasma/Wallpaper>
00038 #include <Plasma/Theme>
00039 
00040 #include <kephal/screens.h>
00041 
00042 #include "dashboardview.h"
00043 #include "plasmaapp.h"
00044 #include "plasma-shell-desktop.h"
00045 
00046 #ifdef Q_WS_WIN
00047 #include "windows.h"
00048 #include "windef.h"
00049 #include "wingdi.h"
00050 #include "winuser.h"
00051 #endif
00052 
00053 DesktopView::DesktopView(Plasma::Containment *containment, int id, QWidget *parent)
00054     : Plasma::View(containment, id, parent),
00055       m_dashboard(0),
00056       m_dashboardFollowsDesktop(true)
00057 {
00058     setFocusPolicy(Qt::NoFocus);
00059 #ifdef Q_WS_WIN
00060     setWindowFlags(Qt::FramelessWindowHint);
00061     SetWindowPos(winId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
00062     HWND hwndDesktop = ::FindWindowW(L"Progman", NULL);
00063     SetParent(winId(), hwndDesktop);
00064 #else
00065     setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
00066 #endif
00067 
00068     if (AppSettings::perVirtualDesktopViews()) {
00069         kDebug() << "setting to desktop" << containment->desktop() + 1;
00070         KWindowSystem::setOnDesktop(winId(), containment->desktop() + 1);
00071     } else {
00072         KWindowSystem::setOnAllDesktops(winId(), true);
00073     }
00074 
00075     KWindowSystem::setType(winId(), NET::Desktop);
00076     lower();
00077 
00078     if (containment) {
00079         containment->enableAction("zoom in", false);
00080         containment->enableAction("add sibling containment", false);
00081     }
00082     //FIXME should we have next/prev or up/down/left/right or what?
00083     QAction *action = new QAction(i18n("Next Activity"), this);
00084     action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00085     action->setShortcut(QKeySequence("ctrl+shift+n"));
00086     connect(action, SIGNAL(triggered()), this, SLOT(nextContainment()));
00087     addAction(action);
00088     action = new QAction(i18n("Previous Activity"), this);
00089     action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00090     action->setShortcut(QKeySequence("ctrl+shift+p"));
00091     connect(action, SIGNAL(triggered()), this, SLOT(previousContainment()));
00092     addAction(action);
00093 
00094     const int w = 25;
00095     QPixmap tile(w * 2, w * 2);
00096     tile.fill(palette().base().color());
00097     QPainter pt(&tile);
00098     QColor color = palette().mid().color();
00099     color.setAlphaF(.6);
00100     pt.fillRect(0, 0, w, w, color);
00101     pt.fillRect(w, w, w, w, color);
00102     pt.end();
00103     QBrush b(tile);
00104     setBackgroundBrush(tile);
00105 
00106     adjustSize();
00107 
00108     Kephal::Screens *screens = Kephal::Screens::self();
00109     connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
00110             this, SLOT(screenResized(Kephal::Screen *)));
00111     connect(screens, SIGNAL(screenMoved(Kephal::Screen *, QPoint, QPoint)),
00112             this, SLOT(screenMoved(Kephal::Screen *)));
00113 }
00114 
00115 DesktopView::~DesktopView()
00116 {
00117     delete m_dashboard;
00118 }
00119 
00120 void DesktopView::toggleDashboard()
00121 {
00122     if (!m_dashboard) {
00123         if (!containment()) {
00124             return;
00125         }
00126 
00127         m_dashboardFollowsDesktop = true;
00128         KConfigGroup cg = config();
00129         Plasma::Containment *dc = containment();
00130         int containmentId = cg.readEntry("DashboardContainment", 0);
00131         if (containmentId > 0) {
00132             foreach (Plasma::Containment *c, containment()->corona()->containments()) {
00133                 if ((int)c->id() == containmentId) {
00134                     dc = c;
00135                     m_dashboardFollowsDesktop = false;
00136                     break;
00137                 }
00138             }
00139         }
00140         m_dashboard = new DashboardView(dc, 0);
00141         m_dashboard->addActions(actions());
00142     }
00143 
00144     m_dashboard->toggleVisibility();
00145     kDebug() << "toggling dashboard for screen" << screen() << m_dashboard->isVisible();
00146 }
00147 
00148 void DesktopView::screenResized(Kephal::Screen *s)
00149 {
00150     if (s->id() == screen()) {
00151         kDebug() << screen();
00152         adjustSize();
00153     }
00154 }
00155 
00156 void DesktopView::screenMoved(Kephal::Screen *s)
00157 {
00158     if (s->id() == screen()) {
00159         kDebug() << screen();
00160         adjustSize();
00161     }
00162 }
00163 
00164 void DesktopView::adjustSize()
00165 {
00166     // adapt to screen resolution changes
00167     QRect geom = Kephal::ScreenUtils::screenGeometry(screen());
00168     kDebug() << "screen" << screen() << "geom" << geom;
00169     setGeometry(geom);
00170     containment()->resize(geom.size());
00171     kDebug() << "Containment's geom after resize" << containment()->geometry(); 
00172 
00173     if (m_dashboard) {
00174         m_dashboard->setGeometry(geom);
00175     }
00176 
00177     kDebug() << "Done" << screen() << geometry();
00178 }
00179 
00180 bool DesktopView::isDashboardVisible() const
00181 {
00182     return m_dashboard && m_dashboard->isVisible();
00183 }
00184 
00185 void DesktopView::setContainment(Plasma::Containment *containment)
00186 {
00187     Plasma::Containment *oldContainment = this->containment();
00188     if (containment == oldContainment) {
00189         return;
00190     }
00191 
00192     Plasma::ZoomLevel zoomLevel = PlasmaApp::self()->desktopZoomLevel();
00193     if (zoomLevel == Plasma::DesktopZoom && containment) {
00194         //make sure actions are up-to-date
00195         //this is icky but necessary to have the toolbox show the right actions for the zoom level
00196         containment->enableAction("zoom in", false);
00197         containment->enableAction("add sibling containment", false);
00198     }
00199 
00200     if (m_dashboard && m_dashboardFollowsDesktop) {
00201         m_dashboard->setContainment(containment);
00202     }
00203 
00204     if (oldContainment && zoomLevel == Plasma::DesktopZoom) {
00205         //make sure actions are up-to-date
00206         oldContainment->enableAction("zoom in", false);
00207         oldContainment->enableAction("add sibling containment", false);
00208     }
00209 
00210     View::setContainment(containment);
00211 }
00212 
00213 void DesktopView::zoomIn(Plasma::ZoomLevel zoomLevel)
00214 {
00215     if (zoomLevel == Plasma::DesktopZoom) {
00216         setDragMode(NoDrag);
00217         qreal factor = Plasma::scalingFactor(zoomLevel) / matrix().m11();
00218         scale(factor, factor);
00219         if (containment()) {
00220             //disconnect from other containments
00221             Plasma::Corona *corona = containment()->corona();
00222             if (corona) {
00223                 QList<Plasma::Containment*> containments = corona->containments();
00224                 foreach (Plasma::Containment *c, containments) {
00225                     if (c == containment() || c->containmentType() == Plasma::Containment::PanelContainment) {
00226                         continue;
00227                     }
00228                     disconnect(c, 0, this, 0);
00229                 }
00230             }
00231             setSceneRect(containment()->geometry());
00232         }
00233     } else if (zoomLevel == Plasma::GroupZoom) {
00234         qreal factor = Plasma::scalingFactor(zoomLevel);
00235         factor = factor / matrix().m11();
00236         scale(factor, factor);
00237         setSceneRect(QRectF(0, 0, scene()->sceneRect().right(), scene()->sceneRect().bottom() + TOOLBOX_MARGIN));
00238     } else {
00239         setDragMode(NoDrag);
00240     }
00241 }
00242 
00243 void DesktopView::zoomOut(Plasma::ZoomLevel zoomLevel)
00244 {
00245     setDragMode(ScrollHandDrag);
00246     qreal factor = Plasma::scalingFactor(zoomLevel);
00247     qreal s = factor / matrix().m11();
00248     scale(s, s);
00249     setSceneRect(QRectF(0, 0, scene()->sceneRect().right(), scene()->sceneRect().bottom() + TOOLBOX_MARGIN));
00250 
00251     if (containment()) {
00252         ensureVisible(containment()->sceneBoundingRect());
00253     }
00254 }
00255 
00256 void DesktopView::wheelEvent(QWheelEvent* event)
00257 {
00258     QGraphicsItem * item = scene() ? scene()->itemAt(sceneRect().topLeft() + event->pos()) : 0;
00259 
00260     if ((!item || item == (QGraphicsItem*)containment()) && event->modifiers() & Qt::ControlModifier) {
00261         if (event->modifiers() & Qt::ControlModifier) {
00262             if (event->delta() < 0) {
00263                 PlasmaApp::self()->zoom(containment(), Plasma::ZoomOut);
00264             } else {
00265                 PlasmaApp::self()->zoom(containment(), Plasma::ZoomIn);
00266             }
00267         }
00268 
00269         event->accept();
00270         return;
00271     }
00272 
00273     QGraphicsView::wheelEvent(event);
00274 }
00275 
00276 // This function is reimplemented from QGraphicsView to work around the problem
00277 // that QPainter::fillRect(QRectF/QRect, QBrush), which QGraphicsView uses, is
00278 // potentially slow when the anti-aliasing hint is set and as implemented won't
00279 // hit accelerated code at all when it isn't set.  This implementation avoids
00280 // the problem by using integer coordinates and by using drawTiledPixmap() in
00281 // the case of a texture brush, and fillRect(QRect, QColor) in the case of a
00282 // solid pattern.  As an additional optimization it draws the background with
00283 // CompositionMode_Source.
00284 void DesktopView::drawBackground(QPainter *painter, const QRectF &rect)
00285 {
00286     const QPainter::CompositionMode savedMode = painter->compositionMode();
00287     const QBrush brush = backgroundBrush();
00288 
00289     switch (brush.style())
00290     {
00291     case Qt::TexturePattern:
00292     {
00293         // Note: this assumes that the brush origin is (0, 0), and that
00294         //       the brush has an identity transformation matrix.
00295         const QPixmap texture = brush.texture();
00296         QRect r = rect.toAlignedRect();
00297         r.setLeft(r.left() - (r.left() % texture.width()));
00298         r.setTop(r.top() - (r.top() % texture.height()));
00299         painter->setCompositionMode(QPainter::CompositionMode_Source);
00300         painter->drawTiledPixmap(r, texture);
00301         painter->setCompositionMode(savedMode);
00302         return;
00303     }
00304 
00305     case Qt::SolidPattern:
00306         painter->setCompositionMode(QPainter::CompositionMode_Source);
00307         painter->fillRect(rect.toAlignedRect(), brush.color());
00308         painter->setCompositionMode(savedMode);
00309         return;
00310 
00311     default:
00312         QGraphicsView::drawBackground(painter, rect);
00313     }
00314 }
00315 
00316 void DesktopView::screenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment* containment)
00317 {
00318     kDebug() << "was:" << wasScreen << "is:" << isScreen << "my screen:" << screen() << "containment:" << (QObject*)containment << "myself:" << (QObject*)this;
00319     if (containment->containmentType() == Plasma::Containment::PanelContainment) {
00320         // we don't care about panel containments changing screens on us
00321         return;
00322     }
00323 
00324     if (wasScreen == screen() && this->containment() == containment) {
00325             setContainment(0);
00326     }
00327 
00328     if (isScreen == screen()) {
00329         setContainment(containment);
00330     }
00331 }
00332 
00333 void DesktopView::nextContainment()
00334 {
00335     QList<Plasma::Containment*> containments = containment()->corona()->containments();
00336     int start = containments.indexOf(containment());
00337     int i = (start + 1) % containments.size();
00338     //FIXME this is a *horrible* way of choosing a "next" containment.
00339     while (i != start) {
00340         if (containments.at(i)->containmentType() != Plasma::Containment::PanelContainment &&
00341             containments.at(i)->screen() == -1) {
00342             break;
00343         }
00344         i = (i + 1) % containments.size();
00345     }
00346 
00347     Plasma::Containment *c = containments.at(i);
00348     setContainment(c);
00349 }
00350 
00351 void DesktopView::previousContainment()
00352 {
00353     QList<Plasma::Containment*> containments = containment()->corona()->containments();
00354     int start = containments.indexOf(containment());
00355     //fun fact: in c++, (-1 % foo) == -1
00356     int i = start - 1;
00357     if (i < 0) {
00358         i += containments.size();
00359     }
00360     //FIXME this is a *horrible* way of choosing a "previous" containment.
00361     while (i != start) {
00362         if (containments.at(i)->containmentType() != Plasma::Containment::PanelContainment &&
00363             containments.at(i)->screen() == -1) {
00364             break;
00365         }
00366         if (--i < 0) {
00367             i += containments.size();
00368         }
00369     }
00370 
00371     Plasma::Containment *c = containments.at(i);
00372     setContainment(c);
00373 }
00374 
00375 #include "desktopview.moc"
00376 

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
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
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