Plasma
view.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2007 Aaron Seigo <aseigo@kde.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Library General Public License as 00006 * published by the Free Software Foundation; either version 2, or 00007 * (at your option) any later version. 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 "view.h" 00021 00022 #include <QTimer> 00023 00024 #include <kdebug.h> 00025 #include <kglobal.h> 00026 #include <kwindowsystem.h> 00027 #include <kactioncollection.h> 00028 00029 #include "corona.h" 00030 #include "containment.h" 00031 #include "wallpaper.h" 00032 00033 using namespace Plasma; 00034 00035 namespace Plasma 00036 { 00037 00038 class ViewPrivate 00039 { 00040 public: 00041 ViewPrivate(View *view, int uniqueId) 00042 : q(view), 00043 containment(0), 00044 viewId(0), 00045 lastScreen(-1), 00046 lastDesktop(-2), 00047 drawWallpaper(true), 00048 trackChanges(true), 00049 init(false) 00050 { 00051 if (uniqueId > 0 && !viewIds.contains(uniqueId)) { 00052 s_maxViewId = uniqueId; 00053 viewId = uniqueId; 00054 } 00055 00056 if (viewId == 0) { 00057 // we didn't get a sane value assigned to us, so lets 00058 // grab the next available id 00059 viewId = ++s_maxViewId; 00060 } 00061 viewIds.insert(viewId); 00062 } 00063 00064 ~ViewPrivate() 00065 { 00066 } 00067 00068 void privateInit() 00069 { 00070 q->setContainment(containment); 00071 init = true; 00072 } 00073 00074 void updateSceneRect() 00075 { 00076 if (!containment || !trackChanges) { 00077 return; 00078 } 00079 00080 kDebug() << "!!!!!!!!!!!!!!!!! setting the scene rect to" 00081 << containment->sceneBoundingRect() 00082 << "associated screen is" << containment->screen(); 00083 00084 emit q->sceneRectAboutToChange(); 00085 if (q->transform().isIdentity()) { //we're not zoomed out 00086 q->setSceneRect(containment->sceneBoundingRect()); 00087 } else { 00088 //kDebug() << "trying to show the containment nicely"; 00089 q->ensureVisible(containment->sceneBoundingRect()); 00090 //q->centerOn(containment); 00091 } 00092 emit q->sceneRectChanged(); 00093 } 00094 00095 void containmentDestroyed() 00096 { 00097 containment = 0; 00098 emit q->lostContainment(); 00099 } 00100 00101 void containmentScreenChanged(int wasScreen, int newScreen, Plasma::Containment *containment) 00102 { 00103 Q_UNUSED(wasScreen) 00104 lastScreen = newScreen; 00105 lastDesktop = containment->desktop(); 00106 } 00107 00108 void initGraphicsView() 00109 { 00110 q->setFrameShape(QFrame::NoFrame); 00111 q->setAttribute(Qt::WA_TranslucentBackground); 00112 q->setAutoFillBackground(true); 00113 q->setDragMode(QGraphicsView::NoDrag); 00114 q->setInteractive(true); 00115 q->setAcceptDrops(true); 00116 q->setAlignment(Qt::AlignLeft | Qt::AlignTop); 00117 q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00118 q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00119 } 00120 00121 static int s_maxViewId; 00122 //ugly but the only reliable way to do collision detection of ids 00123 static QSet<int> viewIds; 00124 00125 Plasma::View *q; 00126 Plasma::Containment *containment; 00127 int viewId; 00128 int lastScreen; 00129 int lastDesktop; 00130 bool drawWallpaper : 1; 00131 bool trackChanges : 1; 00132 bool init : 1; 00133 }; 00134 00135 int ViewPrivate::s_maxViewId(0); 00136 QSet<int> ViewPrivate::viewIds; 00137 00138 View::View(Containment *containment, QWidget *parent) 00139 : QGraphicsView(parent), 00140 d(new ViewPrivate(this, 0)) 00141 { 00142 d->initGraphicsView(); 00143 00144 if (containment) { 00145 setScene(containment->scene()); 00146 d->containment = containment; 00147 QTimer::singleShot(0, this, SLOT(privateInit())); 00148 } 00149 } 00150 00151 View::View(Containment *containment, int viewId, QWidget *parent) 00152 : QGraphicsView(parent), 00153 d(new ViewPrivate(this, viewId)) 00154 { 00155 d->initGraphicsView(); 00156 00157 if (containment) { 00158 setScene(containment->scene()); 00159 d->containment = containment; 00160 QTimer::singleShot(0, this, SLOT(privateInit())); 00161 } 00162 } 00163 00164 View::~View() 00165 { 00166 delete d; 00167 // FIXME FIX a focus crash but i wasn't able to reproduce in a simple test case for Qt guys 00168 // NB: this is also done in Corona 00169 clearFocus(); 00170 } 00171 00172 void View::setScreen(int screen, int desktop) 00173 { 00174 if (screen < 0) { 00175 return; 00176 } 00177 00178 // handle desktop views 00179 // -1 == All desktops 00180 if (desktop < -1 || desktop > KWindowSystem::numberOfDesktops() - 1) { 00181 desktop = -1; 00182 } 00183 00184 d->lastScreen = screen; 00185 d->lastDesktop = desktop; 00186 00187 // handle views that are working with panel containment types 00188 if (d->containment && 00189 (d->containment->type() == Containment::PanelContainment || 00190 d->containment->type() == Containment::CustomPanelContainment)) { 00191 d->containment->setScreen(screen, desktop); 00192 return; 00193 } 00194 00195 Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene()); 00196 if (corona) { 00197 Containment *containment = corona->containmentForScreen(screen, desktop); 00198 00199 if (containment) { 00200 d->containment = 0; //so that we don't end up on the old containment's screen 00201 setContainment(containment); 00202 } 00203 } 00204 } 00205 00206 int View::screen() const 00207 { 00208 return d->lastScreen; 00209 } 00210 00211 int View::desktop() const 00212 { 00213 if (d->containment) { 00214 return d->containment->desktop(); 00215 } 00216 00217 return d->lastDesktop; 00218 } 00219 00220 int View::effectiveDesktop() const 00221 { 00222 int desk = desktop(); 00223 return desk > -1 ? desk : KWindowSystem::currentDesktop(); 00224 } 00225 00226 void View::setContainment(Plasma::Containment *containment) 00227 { 00228 if (d->init && containment == d->containment) { 00229 return; 00230 } 00231 00232 if (d->containment) { 00233 disconnect(d->containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed())); 00234 disconnect(d->containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect())); 00235 disconnect(d->containment, SIGNAL(screenChanged(int, int, Plasma::Containment *)), this, SLOT(containmentScreenChanged(int, int, Plasma::Containment *))); 00236 d->containment->removeAssociatedWidget(this); 00237 } 00238 00239 if (!containment) { 00240 d->containment = 0; 00241 return; 00242 } 00243 00244 Containment *oldContainment = d->containment; 00245 00246 int screen = d->lastScreen; 00247 int desktop = d->lastDesktop; 00248 if (oldContainment && oldContainment != containment) { 00249 screen = oldContainment->screen(); 00250 desktop = oldContainment->desktop(); 00251 } 00252 00253 if (scene() != containment->scene()) { 00254 setScene(containment->scene()); 00255 } 00256 00257 d->containment = containment; 00258 00259 //add keyboard-shortcut actions 00260 d->containment->addAssociatedWidget(this); 00261 00262 int otherScreen = containment->screen(); 00263 int otherDesktop = containment->desktop(); 00264 00265 if (screen > -1) { 00266 d->lastScreen = screen; 00267 d->lastDesktop = desktop; 00268 //kDebug() << "set screen from setContainment due to old containment"; 00269 if (oldContainment && oldContainment != containment) { 00270 oldContainment->setScreen(-1, -1); 00271 } 00272 00273 if (screen != containment->screen() || desktop != containment->desktop()) { 00274 containment->setScreen(screen, desktop); 00275 } 00276 } else { 00277 d->lastScreen = otherScreen; 00278 d->lastDesktop = otherDesktop; 00279 } 00280 00281 if (oldContainment && oldContainment != containment && otherScreen > -1 && 00282 (!containment || otherScreen != containment->screen() || otherDesktop != containment->desktop())) { 00283 // assign the old containment the old screen/desktop 00284 //kDebug() << "set screen from setContainment" << screen << otherScreen << desktop << otherDesktop; 00285 oldContainment->setScreen(otherScreen, otherDesktop); 00286 } 00287 00288 00289 /* 00290 if (oldContainment) { 00291 kDebug() << "old" << (QObject*)oldContainment << screen << oldContainment->screen() 00292 << "new" << (QObject*)containment << otherScreen << containment->screen(); 00293 } 00294 */ 00295 00296 d->updateSceneRect(); 00297 connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed())); 00298 connect(containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect())); 00299 connect(containment, SIGNAL(screenChanged(int, int, Plasma::Containment *)), this, SLOT(containmentScreenChanged(int, int, Plasma::Containment *))); 00300 } 00301 00302 Containment *View::containment() const 00303 { 00304 return d->containment; 00305 } 00306 00307 Containment *View::swapContainment(const QString &name, const QVariantList &args) 00308 { 00309 return swapContainment(d->containment, name, args); 00310 } 00311 00312 Containment *View::swapContainment(Plasma::Containment *existing, const QString &name, const QVariantList &args) 00313 { 00314 if (!existing) { 00315 return 0; 00316 } 00317 00318 Containment *old = existing; 00319 Plasma::Corona *corona = old->corona(); 00320 Plasma::Containment *c = corona->addContainmentDelayed(name, args); 00321 if (c) { 00322 c->init(); 00323 00324 KConfigGroup oldConfig = old->config(); 00325 KConfigGroup newConfig = c->config(); 00326 00327 // ensure that the old containments configuration is up to date 00328 old->save(oldConfig); 00329 00330 // Copy configuration to new containment 00331 oldConfig.copyTo(&newConfig); 00332 00333 if (old == d->containment) { 00334 // set our containment to the new one, if the the old containment was us 00335 setContainment(c); 00336 } 00337 00338 // load the configuration of the old containment into the new one 00339 c->restore(newConfig); 00340 c->updateConstraints(Plasma::StartupCompletedConstraint); 00341 c->flushPendingConstraintsEvents(); 00342 emit corona->containmentAdded(c); 00343 foreach (Applet *applet, c->applets()) { 00344 applet->init(); 00345 // We have to flush the applet constraints manually 00346 applet->flushPendingConstraintsEvents(); 00347 } 00348 00349 // destroy the old one 00350 old->destroy(false); 00351 00352 // and now save the config 00353 c->save(newConfig); 00354 corona->requestConfigSync(); 00355 00356 return c; 00357 } 00358 00359 return old; 00360 } 00361 00362 KConfigGroup View::config() const 00363 { 00364 KConfigGroup views(KGlobal::config(), "PlasmaViews"); 00365 return KConfigGroup(&views, QString::number(d->viewId)); 00366 } 00367 00368 void View::configNeedsSaving() const 00369 { 00370 Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene()); 00371 if (corona) { 00372 corona->requestConfigSync(); 00373 } else { 00374 KGlobal::config()->sync(); 00375 } 00376 } 00377 00378 00379 int View::id() const 00380 { 00381 return d->viewId; 00382 } 00383 00384 void View::setWallpaperEnabled(bool draw) 00385 { 00386 d->drawWallpaper = draw; 00387 } 00388 00389 bool View::isWallpaperEnabled() const 00390 { 00391 return d->drawWallpaper; 00392 } 00393 00394 void View::setTrackContainmentChanges(bool trackChanges) 00395 { 00396 d->trackChanges = trackChanges; 00397 } 00398 00399 bool View::trackContainmentChanges() 00400 { 00401 return d->trackChanges; 00402 } 00403 00404 View * View::topLevelViewAt(const QPoint & pos) 00405 { 00406 QWidget *w = QApplication::topLevelAt(pos); 00407 if (w) { 00408 Plasma::View *v = qobject_cast<Plasma::View *>(w); 00409 return v; 00410 } else { 00411 return 0; 00412 } 00413 } 00414 00415 } // namespace Plasma 00416 00417 #include "view.moc" 00418
KDE 4.7 API Reference