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 //setCacheMode(QGraphicsView::CacheBackground); 00115 q->setInteractive(true); 00116 q->setAcceptDrops(true); 00117 q->setAlignment(Qt::AlignLeft | Qt::AlignTop); 00118 q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00119 q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00120 } 00121 00122 static int s_maxViewId; 00123 //ugly but the only reliable way to do collision detection of ids 00124 static QSet<int> viewIds; 00125 00126 Plasma::View *q; 00127 Plasma::Containment *containment; 00128 int viewId; 00129 int lastScreen; 00130 int lastDesktop; 00131 bool drawWallpaper : 1; 00132 bool trackChanges : 1; 00133 bool init : 1; 00134 }; 00135 00136 int ViewPrivate::s_maxViewId(0); 00137 QSet<int> ViewPrivate::viewIds; 00138 00139 View::View(Containment *containment, QWidget *parent) 00140 : QGraphicsView(parent), 00141 d(new ViewPrivate(this, 0)) 00142 { 00143 d->initGraphicsView(); 00144 00145 if (containment) { 00146 setScene(containment->scene()); 00147 d->containment = containment; 00148 QTimer::singleShot(0, this, SLOT(privateInit())); 00149 } 00150 } 00151 00152 View::View(Containment *containment, int viewId, QWidget *parent) 00153 : QGraphicsView(parent), 00154 d(new ViewPrivate(this, viewId)) 00155 { 00156 d->initGraphicsView(); 00157 00158 if (containment) { 00159 setScene(containment->scene()); 00160 d->containment = containment; 00161 QTimer::singleShot(0, this, SLOT(privateInit())); 00162 } 00163 } 00164 00165 View::~View() 00166 { 00167 delete d; 00168 // FIXME FIX a focus crash but i wasn't able to reproduce in a simple test case for Qt guys 00169 // NB: this is also done in Corona 00170 clearFocus(); 00171 } 00172 00173 void View::setScreen(int screen, int desktop) 00174 { 00175 if (screen < 0) { 00176 return; 00177 } 00178 00179 // handle desktop views 00180 // -1 == All desktops 00181 if (desktop < -1 || desktop > KWindowSystem::numberOfDesktops() - 1) { 00182 desktop = -1; 00183 } 00184 00185 d->lastScreen = screen; 00186 d->lastDesktop = desktop; 00187 00188 // handle views that are working with panel containment types 00189 if (d->containment && 00190 (d->containment->type() == Containment::PanelContainment || 00191 d->containment->type() == Containment::CustomPanelContainment)) { 00192 d->containment->setScreen(screen, desktop); 00193 return; 00194 } 00195 00196 Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene()); 00197 if (corona) { 00198 Containment *containment = corona->containmentForScreen(screen, desktop); 00199 00200 if (containment) { 00201 d->containment = 0; //so that we don't end up on the old containment's screen 00202 setContainment(containment); 00203 } 00204 } 00205 } 00206 00207 int View::screen() const 00208 { 00209 return d->lastScreen; 00210 } 00211 00212 int View::desktop() const 00213 { 00214 if (d->containment) { 00215 return d->containment->desktop(); 00216 } 00217 00218 return d->lastDesktop; 00219 } 00220 00221 int View::effectiveDesktop() const 00222 { 00223 int desk = desktop(); 00224 return desk > -1 ? desk : KWindowSystem::currentDesktop(); 00225 } 00226 00227 void View::setContainment(Plasma::Containment *containment) 00228 { 00229 if (d->init && containment == d->containment) { 00230 return; 00231 } 00232 00233 if (d->containment) { 00234 disconnect(d->containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed())); 00235 disconnect(d->containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect())); 00236 disconnect(d->containment, SIGNAL(screenChanged(int, int, Plasma::Containment *)), this, SLOT(containmentScreenChanged(int, int, Plasma::Containment *))); 00237 d->containment->removeAssociatedWidget(this); 00238 } 00239 00240 if (!containment) { 00241 d->containment = 0; 00242 return; 00243 } 00244 00245 Containment *oldContainment = d->containment; 00246 00247 int screen = d->lastScreen; 00248 int desktop = d->lastDesktop; 00249 if (oldContainment && oldContainment != containment) { 00250 screen = oldContainment->screen(); 00251 desktop = oldContainment->desktop(); 00252 } 00253 00254 if (scene() != containment->scene()) { 00255 setScene(containment->scene()); 00256 } 00257 00258 d->containment = containment; 00259 00260 //add keyboard-shortcut actions 00261 d->containment->addAssociatedWidget(this); 00262 00263 int otherScreen = containment->screen(); 00264 int otherDesktop = containment->desktop(); 00265 00266 if (screen > -1) { 00267 d->lastScreen = screen; 00268 d->lastDesktop = desktop; 00269 //kDebug() << "set screen from setContainment due to old containment"; 00270 if (oldContainment && oldContainment != containment) { 00271 oldContainment->setScreen(-1, -1); 00272 } 00273 00274 if (screen != containment->screen() || desktop != containment->desktop()) { 00275 containment->setScreen(screen, desktop); 00276 } 00277 } else { 00278 d->lastScreen = otherScreen; 00279 d->lastDesktop = otherDesktop; 00280 } 00281 00282 if (oldContainment && oldContainment != containment && otherScreen > -1 && 00283 (!containment || otherScreen != containment->screen() || otherDesktop != containment->desktop())) { 00284 // assign the old containment the old screen/desktop 00285 //kDebug() << "set screen from setContainment" << screen << otherScreen << desktop << otherDesktop; 00286 oldContainment->setScreen(otherScreen, otherDesktop); 00287 } 00288 00289 00290 /* 00291 if (oldContainment) { 00292 kDebug() << "old" << (QObject*)oldContainment << screen << oldContainment->screen() 00293 << "new" << (QObject*)containment << otherScreen << containment->screen(); 00294 } 00295 */ 00296 00297 d->updateSceneRect(); 00298 connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed())); 00299 connect(containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect())); 00300 connect(containment, SIGNAL(screenChanged(int, int, Plasma::Containment *)), this, SLOT(containmentScreenChanged(int, int, Plasma::Containment *))); 00301 } 00302 00303 Containment *View::containment() const 00304 { 00305 return d->containment; 00306 } 00307 00308 Containment *View::swapContainment(const QString &name, const QVariantList &args) 00309 { 00310 return swapContainment(d->containment, name, args); 00311 } 00312 00313 Containment *View::swapContainment(Plasma::Containment *existing, const QString &name, const QVariantList &args) 00314 { 00315 if (!existing) { 00316 return 0; 00317 } 00318 00319 Containment *old = existing; 00320 Plasma::Corona *corona = old->corona(); 00321 Plasma::Containment *c = corona->addContainmentDelayed(name, args); 00322 if (c) { 00323 c->init(); 00324 00325 KConfigGroup oldConfig = old->config(); 00326 KConfigGroup newConfig = c->config(); 00327 00328 // ensure that the old containments configuration is up to date 00329 old->save(oldConfig); 00330 00331 // Copy configuration to new containment 00332 oldConfig.copyTo(&newConfig); 00333 00334 if (old == d->containment) { 00335 // set our containment to the new one, if the the old containment was us 00336 setContainment(c); 00337 } 00338 00339 // load the configuration of the old containment into the new one 00340 c->restore(newConfig); 00341 c->updateConstraints(Plasma::StartupCompletedConstraint); 00342 c->flushPendingConstraintsEvents(); 00343 emit corona->containmentAdded(c); 00344 foreach (Applet *applet, c->applets()) { 00345 applet->init(); 00346 // We have to flush the applet constraints manually 00347 applet->flushPendingConstraintsEvents(); 00348 } 00349 00350 // destroy the old one 00351 old->destroy(false); 00352 00353 // and now save the config 00354 c->save(newConfig); 00355 corona->requestConfigSync(); 00356 00357 return c; 00358 } 00359 00360 return old; 00361 } 00362 00363 KConfigGroup View::config() const 00364 { 00365 KConfigGroup views(KGlobal::config(), "PlasmaViews"); 00366 return KConfigGroup(&views, QString::number(d->viewId)); 00367 } 00368 00369 void View::configNeedsSaving() const 00370 { 00371 Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene()); 00372 if (corona) { 00373 corona->requestConfigSync(); 00374 } else { 00375 KGlobal::config()->sync(); 00376 } 00377 } 00378 00379 00380 int View::id() const 00381 { 00382 return d->viewId; 00383 } 00384 00385 void View::setWallpaperEnabled(bool draw) 00386 { 00387 d->drawWallpaper = draw; 00388 } 00389 00390 bool View::isWallpaperEnabled() const 00391 { 00392 return d->drawWallpaper; 00393 } 00394 00395 void View::setTrackContainmentChanges(bool trackChanges) 00396 { 00397 d->trackChanges = trackChanges; 00398 } 00399 00400 bool View::trackContainmentChanges() 00401 { 00402 return d->trackChanges; 00403 } 00404 00405 View * View::topLevelViewAt(const QPoint & pos) 00406 { 00407 QWidget *w = QApplication::topLevelAt(pos); 00408 if (w) { 00409 Plasma::View *v = qobject_cast<Plasma::View *>(w); 00410 return v; 00411 } else { 00412 return 0; 00413 } 00414 } 00415 00416 } // namespace Plasma 00417 00418 #include "view.moc" 00419
KDE 4.6 API Reference