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

Plasma

desktop.cpp

Go to the documentation of this file.
00001 /*
00002 *   Copyright 2007 by Aaron Seigo <aseigo@kde.org>
00003 *   Copyright 2008 by Alexis Ménard <darktears31@gmail.com>
00004 *
00005 *
00006 *   This program is free software; you can redistribute it and/or modify
00007 *   it under the terms of the GNU Library General Public License version 2,
00008 *   or (at your option) any later version.
00009 *
00010 *   This program is distributed in the hope that it will be useful,
00011 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 *   GNU General Public License for more details
00014 *
00015 *   You should have received a copy of the GNU Library General Public
00016 *   License along with this program; if not, write to the
00017 *   Free Software Foundation, Inc.,
00018 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019 */
00020 
00021 #include "desktop.h"
00022 
00023 #include <QAction>
00024 #include <QApplication>
00025 #include <QDesktopWidget>
00026 #include <QFile>
00027 #include <QFileInfo>
00028 #include <QGraphicsScene>
00029 #include <QGraphicsView>
00030 #include <QPainter>
00031 #include <QTimeLine>
00032 
00033 #include <KAuthorized>
00034 #include <KComboBox>
00035 #include <KDebug>
00036 #include <KFileDialog>
00037 #include <KImageFilePreview>
00038 #include <KRun>
00039 #include <KStandardDirs>
00040 #include <KWindowSystem>
00041 
00042 #include "plasma/corona.h"
00043 #include "plasma/appletbrowser.h"
00044 #include "plasma/animator.h"
00045 #include "plasma/theme.h"
00046 #include "kworkspace/kworkspace.h"
00047 #include "knewstuff2/engine.h"
00048 
00049 #include "krunner_interface.h"
00050 #include "screensaver_interface.h"
00051 #include "ksmserver_interface.h"
00052 
00053 #include "backgrounddialog.h"
00054 
00055 using namespace Plasma;
00056 
00057 DefaultDesktop::DefaultDesktop(QObject *parent, const QVariantList &args)
00058     : Containment(parent, args),
00059       m_lockDesktopAction(0),
00060       m_appletBrowserAction(0),
00061       m_addPanelAction(0),
00062       m_runCommandAction(0),
00063       m_lockScreenAction(0),
00064       m_logoutAction(0),
00065       m_configDialog(0),
00066       m_wallpaperPath(0),
00067       m_wallpaperPosition(0),
00068       m_renderer(resolution(), 1.0),
00069       m_rendererToken(-1)
00070 {
00071     qRegisterMetaType<QImage>("QImage");
00072     qRegisterMetaType<QPersistentModelIndex>("QPersistentModelIndex");
00073     connect(&m_renderer, SIGNAL(done(int, QImage)),
00074             this, SLOT(updateBackground(int, QImage)));
00075     connect(&m_slideshowTimer, SIGNAL(timeout()),
00076             this, SLOT(nextSlide()));
00077     //kDebug() << "!!! loading desktop";
00078 }
00079 
00080 DefaultDesktop::~DefaultDesktop()
00081 {
00082     delete m_configDialog;
00083 }
00084 
00085 void DefaultDesktop::nextSlide(bool skipUpdates)
00086 {
00087     if (++m_currentSlide >= m_slideFiles.size()) {
00088         m_currentSlide = 0;
00089     }
00090 
00091     if (m_slideFiles.size() > 0) {
00092         // do not change to the same background if we have a choice
00093         // if there is only one background, it may be changed by someone else
00094         if (m_slideFiles.size() > 1 && m_wallpaperPath == m_slideFiles[m_currentSlide]) {
00095             // try next one, they can't be the same (at least the same path)
00096             if (++m_currentSlide >= m_slideFiles.size()) {
00097                 m_currentSlide = 0;
00098             }
00099         }
00100 
00101         m_wallpaperPath = m_slideFiles[m_currentSlide];
00102         if (!skipUpdates) {
00103             updateBackground();
00104         }
00105     }
00106 }
00107 
00108 QSize DefaultDesktop::resolution() const
00109 {
00110     return QApplication::desktop()->screenGeometry(screen()).size();
00111 }
00112 
00113 void DefaultDesktop::constraintsEvent(Plasma::Constraints constraints)
00114 {
00115     if (constraints & Plasma::StartupCompletedConstraint) {
00116         qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
00117         reloadConfig();
00118     }
00119 
00120     if (constraints & Plasma::SizeConstraint) {
00121         m_renderer.setSize(size().toSize()); 
00122 
00123         if (m_rendererToken != -1) {
00124             // if the renderer token is still -1, then we haven't actually started up yet
00125             // and there is no point in touching the renderer at this point
00126             updateBackground();
00127         }
00128     }
00129 
00130     if (constraints & Plasma::ImmutableConstraint && m_appletBrowserAction) {
00131         // we need to update the menu items that have already been created
00132         bool locked = immutability() != Mutable;
00133         m_addPanelAction->setVisible(!locked);
00134     }
00135 }
00136 
00137 void DefaultDesktop::configure()
00138 {
00139     KConfigGroup cg = config();
00140     KConfigGroup gcg = globalConfig();
00141     if (m_configDialog == 0) {
00142         const QSize resolution = 
00143             QApplication::desktop()->screenGeometry(screen()).size();
00144         m_configDialog = new BackgroundDialog(resolution, cg, gcg, 0);
00145         connect(m_configDialog, SIGNAL(okClicked()), 
00146                 this, SLOT(applyConfig()));
00147         connect(m_configDialog, SIGNAL(applyClicked()), 
00148                 this, SLOT(applyConfig()));
00149     }
00150     else {
00151         m_configDialog->reloadConfig(cg, gcg);
00152     }
00153 
00154     m_configDialog->show();
00155     KWindowSystem::setOnDesktop(m_configDialog->winId(), KWindowSystem::currentDesktop());
00156     KWindowSystem::activateWindow(m_configDialog->winId());
00157 }
00158 
00159 void DefaultDesktop::applyConfig()
00160 {
00161     Q_ASSERT(m_configDialog);
00162     m_configDialog->saveConfig(config(), globalConfig());
00163     emit configNeedsSaving();
00164 
00165     reloadConfig();
00166 }
00167 
00168 void DefaultDesktop::reloadConfig()
00169 {
00170     KConfigGroup cg = config();
00171 
00172     // store the state of the existing wallpaper config so we can determine later
00173     // if we need to trigger updates
00174     QString oldWallpaperPath(m_wallpaperPath);
00175     QColor old_wallpaperColor = m_wallpaperColor;
00176     int old_wallPaperPosition = m_wallpaperPosition;
00177 
00178     // If no wallpaper is set, a default will be set in updateBackground()
00179     // which is called as soon as constraints are updated.
00180     m_wallpaperPath = cg.readEntry("wallpaper", QString());
00181     m_backgroundMode = cg.readEntry("backgroundmode", int(BackgroundDialog::kStaticBackground));
00182 
00183     if (m_backgroundMode != BackgroundDialog::kNoBackground &&
00184         (m_wallpaperPath.isEmpty() || !KStandardDirs::exists(m_wallpaperPath)))  {
00185         m_wallpaperPath = Plasma::Theme::defaultTheme()->wallpaperPath(size().toSize());
00186         cg.writeEntry("wallpaper", m_wallpaperPath);
00187     }
00188 
00189     if (!m_wallpaperPath.isEmpty()) {
00190         kDebug() << "Using configured wallpaper" << m_wallpaperPath;
00191     }
00192 
00193     // used in both modes, so read it no matter which mode we are in
00194     m_wallpaperPosition = cg.readEntry("wallpaperposition", int(Background::ScaleCrop));
00195     m_wallpaperColor = cg.readEntry("wallpapercolor", QColor(Qt::black));
00196 
00197     if (m_backgroundMode == BackgroundDialog::kStaticBackground ||
00198         m_backgroundMode == BackgroundDialog::kNoBackground) {
00199         m_slideshowTimer.stop();
00200         // Only set the wallpaper if constraints have been loaded
00201         // and background image has changed
00202         if (oldWallpaperPath != m_wallpaperPath ||
00203             m_wallpaperPosition != old_wallPaperPosition ||
00204             m_wallpaperColor != old_wallpaperColor) {
00205             updateBackground();
00206         }
00207     } else {
00208         QStringList dirs = cg.readEntry("slidepaths", QStringList());
00209         QStringList filters;
00210         filters << "*.png" << "*.jpeg" << "*.jpg" << "*.svg" << "*.svgz";
00211 
00212         m_slideFiles.clear();
00213 
00214         for (int i = 0; i < dirs.size(); ++i) {
00215             QString path = dirs[i];
00216             // TODO load packages, too
00217             QDir dir(path);
00218             dir.setNameFilters(filters);
00219             dir.setFilter(QDir::Files | QDir::Hidden);
00220 
00221             QFileInfoList files = dir.entryInfoList();
00222             foreach (const QFileInfo &wp, files) {
00223                 int position = m_slideFiles.size() == 0 ? 0 : qrand() % m_slideFiles.size();
00224                 m_slideFiles.insert(position, wp.filePath());
00225             }
00226 
00227             // now make it look in sub-dirs
00228             dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
00229             QFileInfoList subdirs = dir.entryInfoList();
00230             foreach (const QFileInfo &wp, subdirs) {
00231                 dirs.append(wp.filePath());
00232             }
00233         }
00234 
00235         int delay = cg.readEntry("slideTimer", 60);
00236         m_slideshowTimer.setInterval(delay * 1000);
00237         if (!m_slideshowTimer.isActive()) {
00238             m_slideshowTimer.start();
00239         }
00240         m_currentSlide = -1;
00241         nextSlide(false);
00242     }
00243 }
00244 
00245 void DefaultDesktop::updateBackground()
00246 {
00247     if (m_wallpaperPath.isEmpty() && m_backgroundMode != BackgroundDialog::kNoBackground) {
00248         m_wallpaperPath = Plasma::Theme::defaultTheme()->wallpaperPath(size().toSize());
00249         kDebug() << "Setting wallpaper to default" << m_wallpaperPath;
00250         emit configNeedsSaving();
00251     }
00252 
00253     m_rendererToken = 
00254         m_renderer.render(m_wallpaperPath,
00255                           m_wallpaperColor,
00256                           (Background::ResizeMethod)m_wallpaperPosition,
00257                           Qt::SmoothTransformation);                       
00258     suspendStartup( true ); // during KDE startup, make ksmserver until the wallpaper is ready
00259 }
00260 
00261 void DefaultDesktop::updateBackground(int token, const QImage &img)
00262 {
00263     if (m_rendererToken == token) {
00264         m_bitmapBackground = QPixmap::fromImage(img);
00265         update();
00266         suspendStartup( false );
00267     }
00268 }
00269 
00270 void DefaultDesktop::addPanel()
00271 {
00272     if (corona()) {
00273         // make a panel at the top
00274         Containment* panel = corona()->addContainment("panel");
00275         panel->showConfigurationInterface();
00276 
00277         panel->setScreen(screen());
00278         panel->setLocation(Plasma::TopEdge);
00279 
00280         // trigger an instant layout so we immediately have a proper geometry 
00281         // rather than waiting around for the event loop
00282         panel->updateConstraints(Plasma::StartupCompletedConstraint);
00283         panel->flushPendingConstraintsEvents();
00284     }
00285 }
00286 
00287 void DefaultDesktop::runCommand()
00288 {
00289     if (!KAuthorized::authorizeKAction("run_command")) {
00290         return;
00291     }
00292 
00293     QString interface("org.kde.krunner");
00294     org::kde::krunner::Interface krunner(interface, "/Interface",
00295                                          QDBusConnection::sessionBus());
00296     if (krunner.isValid()) {
00297         krunner.display();
00298     }
00299 }
00300 
00301 void DefaultDesktop::suspendStartup(bool suspend)
00302 {
00303     org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
00304     const QString startupID("desktop wallaper");
00305     if (suspend) {
00306         ksmserver.suspendStartup(startupID);
00307     } else {
00308         ksmserver.resumeStartup(startupID);
00309     }
00310 }
00311 
00312 void DefaultDesktop::lockScreen()
00313 {
00314     if (!KAuthorized::authorizeKAction("lock_screen")) {
00315         return;
00316     }
00317 
00318     QString interface("org.freedesktop.ScreenSaver");
00319     org::freedesktop::ScreenSaver screensaver(interface, "/ScreenSaver",
00320                                               QDBusConnection::sessionBus());
00321     if (screensaver.isValid()) {
00322         screensaver.Lock();
00323     }
00324 }
00325 
00326 QList<QAction*> DefaultDesktop::contextualActions()
00327 {
00328     //TODO: should we offer "Switch User" here?
00329 
00330     if (!m_appletBrowserAction) {
00331         m_appletBrowserAction = action("add widgets");
00332 
00333         m_addPanelAction = new QAction(i18n("Add Panel"), this);
00334         connect(m_addPanelAction, SIGNAL(triggered(bool)), this, SLOT(addPanel()));
00335         m_addPanelAction->setIcon(KIcon("list-add"));
00336 
00337         m_runCommandAction = new QAction(i18n("Run Command..."), this);
00338         connect(m_runCommandAction, SIGNAL(triggered(bool)), this, SLOT(runCommand()));
00339         m_runCommandAction->setIcon(KIcon("system-run"));
00340 
00341         m_setupDesktopAction = new QAction(i18n("Desktop Settings..."), this);
00342         m_setupDesktopAction->setIcon(KIcon("configure"));
00343         connect(m_setupDesktopAction, SIGNAL(triggered()), this, SLOT(configure()));
00344 
00345         m_lockDesktopAction = action("lock widgets");
00346 
00347         m_lockScreenAction = new QAction(i18n("Lock Screen"), this);
00348         m_lockScreenAction->setIcon(KIcon("system-lock-screen"));
00349         connect(m_lockScreenAction, SIGNAL(triggered(bool)), this, SLOT(lockScreen()));
00350 
00351         m_logoutAction = new QAction(i18n("Leave..."), this);
00352         m_logoutAction->setIcon(KIcon("system-shutdown"));
00353         connect(m_logoutAction, SIGNAL(triggered(bool)), this, SLOT(logout()));
00354         constraintsEvent(Plasma::ImmutableConstraint);
00355 
00356         m_separator = new QAction(this);
00357         m_separator->setSeparator(true);
00358 
00359         m_separator2 = new QAction(this);
00360         m_separator2->setSeparator(true);
00361     }
00362 
00363     QList<QAction*> actions;
00364 
00365     if (KAuthorized::authorizeKAction("run_command")) {
00366         actions.append(m_runCommandAction);
00367     }
00368 
00369     actions.append(m_appletBrowserAction);
00370     actions.append(m_addPanelAction);
00371     actions.append(m_setupDesktopAction);
00372     if (screen() == -1) {
00373         actions.append(action("remove"));
00374     }
00375 
00376     actions.append(m_lockDesktopAction);
00377 
00378     actions.append(m_separator);
00379 
00380     if (KAuthorized::authorizeKAction("lock_screen")) {
00381         actions.append(m_lockScreenAction);
00382     }
00383 
00384     if (KAuthorized::authorizeKAction("logout")) {
00385         actions.append(m_logoutAction);
00386     }
00387 
00388     return actions;
00389 }
00390 
00391 void DefaultDesktop::logout()
00392 {
00393     if (!KAuthorized::authorizeKAction("logout")) {
00394         return;
00395     }
00396     KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault,
00397                                 KWorkSpace::ShutdownTypeDefault,
00398                                 KWorkSpace::ShutdownModeDefault);
00399 }
00400 
00401 void DefaultDesktop::paintInterface(QPainter *painter,
00402                                     const QStyleOptionGraphicsItem *option,
00403                                     const QRect& contentsRect)
00404 {
00405     //kDebug() << "paintInterface of background";
00406     if (m_bitmapBackground.isNull()) {
00407         Containment::paintInterface(painter, option, contentsRect);
00408         return;
00409     }
00410 
00411     painter->save();
00412 
00413     if (painter->worldMatrix() == QMatrix()) {
00414         // draw the background untransformed when possible;(saves lots of per-pixel-math)
00415         painter->resetTransform();
00416     }
00417 
00418     // blit the background (saves all the per-pixel-products that blending does)
00419     painter->setCompositionMode(QPainter::CompositionMode_Source);
00420 
00421     // for pixmaps we draw only the exposed part (untransformed since the
00422     // bitmapBackground already has the size of the viewport)
00423     painter->drawPixmap(option->exposedRect, m_bitmapBackground, option->exposedRect);
00424     //kDebug() << "draw pixmap of background to" << option->exposedRect;
00425 
00426     // restore transformation and composition mode
00427     painter->restore();
00428 }
00429 
00430 K_EXPORT_PLASMA_APPLET(desktop, DefaultDesktop)
00431 
00432 #include "desktop.moc"

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