2008-11-04 00:08:39 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2007 Aaron Seigo <aseigo@kde.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Library General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "view.h"
|
|
|
|
|
2009-01-28 13:34:45 +01:00
|
|
|
#include <QTimer>
|
|
|
|
|
2010-11-10 16:25:56 +01:00
|
|
|
#include <kdebug.h>
|
2008-11-04 03:55:37 +01:00
|
|
|
#include <kglobal.h>
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kwindowsystem.h>
|
|
|
|
#include <kactioncollection.h>
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
#include "corona.h"
|
|
|
|
#include "containment.h"
|
|
|
|
#include "wallpaper.h"
|
|
|
|
|
|
|
|
using namespace Plasma;
|
|
|
|
|
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
|
|
|
class ViewPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ViewPrivate(View *view, int uniqueId)
|
|
|
|
: q(view),
|
|
|
|
containment(0),
|
2008-12-17 01:40:42 +01:00
|
|
|
viewId(0),
|
|
|
|
lastScreen(-1),
|
2009-01-28 13:34:45 +01:00
|
|
|
lastDesktop(-2),
|
|
|
|
drawWallpaper(true),
|
|
|
|
trackChanges(true),
|
|
|
|
init(false)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2009-12-16 23:45:28 +01:00
|
|
|
if (uniqueId > 0 && !viewIds.contains(uniqueId)) {
|
2008-11-04 00:08:39 +01:00
|
|
|
s_maxViewId = uniqueId;
|
|
|
|
viewId = uniqueId;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (viewId == 0) {
|
|
|
|
// we didn't get a sane value assigned to us, so lets
|
|
|
|
// grab the next available id
|
|
|
|
viewId = ++s_maxViewId;
|
|
|
|
}
|
2009-12-16 23:45:28 +01:00
|
|
|
viewIds.insert(viewId);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
~ViewPrivate()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-01-28 13:34:45 +01:00
|
|
|
void privateInit()
|
|
|
|
{
|
|
|
|
q->setContainment(containment);
|
|
|
|
init = true;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void updateSceneRect()
|
|
|
|
{
|
|
|
|
if (!containment || !trackChanges) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "!!!!!!!!!!!!!!!!! setting the scene rect to"
|
|
|
|
<< containment->sceneBoundingRect()
|
|
|
|
<< "associated screen is" << containment->screen();
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
emit q->sceneRectAboutToChange();
|
|
|
|
if (q->transform().isIdentity()) { //we're not zoomed out
|
|
|
|
q->setSceneRect(containment->sceneBoundingRect());
|
|
|
|
} else {
|
|
|
|
//kDebug() << "trying to show the containment nicely";
|
|
|
|
q->ensureVisible(containment->sceneBoundingRect());
|
|
|
|
//q->centerOn(containment);
|
|
|
|
}
|
|
|
|
emit q->sceneRectChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void containmentDestroyed()
|
|
|
|
{
|
|
|
|
containment = 0;
|
2009-09-23 22:37:17 +02:00
|
|
|
emit q->lostContainment();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-02-24 21:28:29 +01:00
|
|
|
void containmentScreenChanged(int wasScreen, int newScreen, Plasma::Containment *containment)
|
|
|
|
{
|
2009-03-19 23:49:34 +01:00
|
|
|
Q_UNUSED(wasScreen)
|
2009-02-24 21:28:29 +01:00
|
|
|
lastScreen = newScreen;
|
2009-03-19 23:49:34 +01:00
|
|
|
lastDesktop = containment->desktop();
|
2009-02-24 21:28:29 +01:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void initGraphicsView()
|
|
|
|
{
|
|
|
|
q->setFrameShape(QFrame::NoFrame);
|
2009-02-16 20:24:05 +01:00
|
|
|
q->setAttribute(Qt::WA_TranslucentBackground);
|
2008-11-04 00:08:39 +01:00
|
|
|
q->setAutoFillBackground(true);
|
|
|
|
q->setDragMode(QGraphicsView::NoDrag);
|
|
|
|
q->setInteractive(true);
|
|
|
|
q->setAcceptDrops(true);
|
|
|
|
q->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
|
|
|
q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
}
|
|
|
|
|
2009-01-28 13:34:45 +01:00
|
|
|
static int s_maxViewId;
|
2009-12-16 23:45:28 +01:00
|
|
|
//ugly but the only reliable way to do collision detection of ids
|
|
|
|
static QSet<int> viewIds;
|
2009-01-28 13:34:45 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
Plasma::View *q;
|
|
|
|
Plasma::Containment *containment;
|
|
|
|
int viewId;
|
2008-12-17 01:40:42 +01:00
|
|
|
int lastScreen;
|
|
|
|
int lastDesktop;
|
2009-01-28 13:34:45 +01:00
|
|
|
bool drawWallpaper : 1;
|
|
|
|
bool trackChanges : 1;
|
|
|
|
bool init : 1;
|
2008-11-04 00:08:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
int ViewPrivate::s_maxViewId(0);
|
2009-12-16 23:45:28 +01:00
|
|
|
QSet<int> ViewPrivate::viewIds;
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
View::View(Containment *containment, QWidget *parent)
|
|
|
|
: QGraphicsView(parent),
|
|
|
|
d(new ViewPrivate(this, 0))
|
|
|
|
{
|
|
|
|
d->initGraphicsView();
|
|
|
|
|
|
|
|
if (containment) {
|
|
|
|
setScene(containment->scene());
|
2009-01-28 13:34:45 +01:00
|
|
|
d->containment = containment;
|
|
|
|
QTimer::singleShot(0, this, SLOT(privateInit()));
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
View::View(Containment *containment, int viewId, QWidget *parent)
|
|
|
|
: QGraphicsView(parent),
|
|
|
|
d(new ViewPrivate(this, viewId))
|
|
|
|
{
|
|
|
|
d->initGraphicsView();
|
|
|
|
|
|
|
|
if (containment) {
|
|
|
|
setScene(containment->scene());
|
2009-01-28 13:34:45 +01:00
|
|
|
d->containment = containment;
|
|
|
|
QTimer::singleShot(0, this, SLOT(privateInit()));
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
View::~View()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
// FIXME FIX a focus crash but i wasn't able to reproduce in a simple test case for Qt guys
|
|
|
|
// NB: this is also done in Corona
|
|
|
|
clearFocus();
|
|
|
|
}
|
|
|
|
|
2008-11-17 05:34:55 +01:00
|
|
|
void View::setScreen(int screen, int desktop)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2010-05-19 22:03:31 +02:00
|
|
|
if (screen < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle desktop views
|
|
|
|
// -1 == All desktops
|
|
|
|
if (desktop < -1 || desktop > KWindowSystem::numberOfDesktops() - 1) {
|
|
|
|
desktop = -1;
|
|
|
|
}
|
2008-11-17 05:34:55 +01:00
|
|
|
|
2010-05-19 22:03:31 +02:00
|
|
|
d->lastScreen = screen;
|
|
|
|
d->lastDesktop = desktop;
|
2009-10-29 19:50:18 +01:00
|
|
|
|
2010-06-10 18:22:36 +02:00
|
|
|
// handle views that are working with panel containment types
|
|
|
|
if (d->containment &&
|
2011-12-02 17:00:29 +01:00
|
|
|
(d->containment->containmentType() == Containment::PanelContainment ||
|
|
|
|
d->containment->containmentType() == Containment::CustomPanelContainment)) {
|
2010-06-10 18:22:36 +02:00
|
|
|
d->containment->setScreen(screen, desktop);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-05-19 22:03:31 +02:00
|
|
|
Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene());
|
|
|
|
if (corona) {
|
|
|
|
Containment *containment = corona->containmentForScreen(screen, desktop);
|
2009-10-29 19:50:18 +01:00
|
|
|
|
2010-05-19 22:03:31 +02:00
|
|
|
if (containment) {
|
|
|
|
d->containment = 0; //so that we don't end up on the old containment's screen
|
|
|
|
setContainment(containment);
|
2009-10-29 22:04:42 +01:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int View::screen() const
|
|
|
|
{
|
2008-12-17 01:40:42 +01:00
|
|
|
return d->lastScreen;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int View::desktop() const
|
|
|
|
{
|
2008-11-17 05:44:10 +01:00
|
|
|
if (d->containment) {
|
|
|
|
return d->containment->desktop();
|
|
|
|
}
|
|
|
|
|
2008-12-17 01:40:42 +01:00
|
|
|
return d->lastDesktop;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int View::effectiveDesktop() const
|
|
|
|
{
|
2008-11-17 05:44:10 +01:00
|
|
|
int desk = desktop();
|
|
|
|
return desk > -1 ? desk : KWindowSystem::currentDesktop();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void View::setContainment(Plasma::Containment *containment)
|
|
|
|
{
|
2009-01-28 13:34:45 +01:00
|
|
|
if (d->init && containment == d->containment) {
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->containment) {
|
2008-12-03 23:03:04 +01:00
|
|
|
disconnect(d->containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed()));
|
2008-11-04 00:08:39 +01:00
|
|
|
disconnect(d->containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect()));
|
2012-01-22 03:11:26 +01:00
|
|
|
disconnect(d->containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(containmentScreenChanged(int,int,Plasma::Containment*)));
|
2008-11-04 00:08:39 +01:00
|
|
|
d->containment->removeAssociatedWidget(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!containment) {
|
|
|
|
d->containment = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment *oldContainment = d->containment;
|
|
|
|
|
2010-11-23 23:18:15 +01:00
|
|
|
int screen = d->lastScreen;
|
|
|
|
int desktop = d->lastDesktop;
|
|
|
|
if (oldContainment && oldContainment != containment) {
|
|
|
|
screen = oldContainment->screen();
|
|
|
|
desktop = oldContainment->desktop();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scene() != containment->scene()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
setScene(containment->scene());
|
|
|
|
}
|
|
|
|
|
|
|
|
d->containment = containment;
|
|
|
|
|
|
|
|
//add keyboard-shortcut actions
|
|
|
|
d->containment->addAssociatedWidget(this);
|
|
|
|
|
|
|
|
int otherScreen = containment->screen();
|
2008-11-17 05:44:10 +01:00
|
|
|
int otherDesktop = containment->desktop();
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (screen > -1) {
|
2008-12-17 14:29:40 +01:00
|
|
|
d->lastScreen = screen;
|
|
|
|
d->lastDesktop = desktop;
|
2009-06-01 19:31:58 +02:00
|
|
|
//kDebug() << "set screen from setContainment due to old containment";
|
2010-11-23 23:18:15 +01:00
|
|
|
if (oldContainment && oldContainment != containment) {
|
|
|
|
oldContainment->setScreen(-1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screen != containment->screen() || desktop != containment->desktop()) {
|
|
|
|
containment->setScreen(screen, desktop);
|
|
|
|
}
|
2008-12-17 14:29:40 +01:00
|
|
|
} else {
|
|
|
|
d->lastScreen = otherScreen;
|
|
|
|
d->lastDesktop = otherDesktop;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2010-11-23 23:18:15 +01:00
|
|
|
if (oldContainment && oldContainment != containment && otherScreen > -1 &&
|
|
|
|
(!containment || otherScreen != containment->screen() || otherDesktop != containment->desktop())) {
|
2008-11-17 05:44:10 +01:00
|
|
|
// assign the old containment the old screen/desktop
|
2009-06-01 19:31:58 +02:00
|
|
|
//kDebug() << "set screen from setContainment" << screen << otherScreen << desktop << otherDesktop;
|
2008-11-17 05:44:10 +01:00
|
|
|
oldContainment->setScreen(otherScreen, otherDesktop);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-04-11 23:12:03 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
/*
|
|
|
|
if (oldContainment) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-12-17 14:29:40 +01:00
|
|
|
kDebug() << "old" << (QObject*)oldContainment << screen << oldContainment->screen()
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-12-17 14:29:40 +01:00
|
|
|
<< "new" << (QObject*)containment << otherScreen << containment->screen();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
d->updateSceneRect();
|
|
|
|
connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed()));
|
|
|
|
connect(containment, SIGNAL(geometryChanged()), this, SLOT(updateSceneRect()));
|
2012-01-22 03:11:26 +01:00
|
|
|
connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(containmentScreenChanged(int,int,Plasma::Containment*)));
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Containment *View::containment() const
|
|
|
|
{
|
|
|
|
return d->containment;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment *View::swapContainment(const QString &name, const QVariantList &args)
|
|
|
|
{
|
|
|
|
return swapContainment(d->containment, name, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment *View::swapContainment(Plasma::Containment *existing, const QString &name, const QVariantList &args)
|
|
|
|
{
|
|
|
|
if (!existing) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment *old = existing;
|
|
|
|
Plasma::Corona *corona = old->corona();
|
2010-07-22 22:06:06 +02:00
|
|
|
Plasma::Containment *c = corona->addContainmentDelayed(name, args);
|
2008-11-04 00:08:39 +01:00
|
|
|
if (c) {
|
2010-07-22 22:06:06 +02:00
|
|
|
c->init();
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
KConfigGroup oldConfig = old->config();
|
|
|
|
KConfigGroup newConfig = c->config();
|
|
|
|
|
|
|
|
// ensure that the old containments configuration is up to date
|
|
|
|
old->save(oldConfig);
|
|
|
|
|
2008-11-27 19:31:59 +01:00
|
|
|
// Copy configuration to new containment
|
|
|
|
oldConfig.copyTo(&newConfig);
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (old == d->containment) {
|
2008-11-27 19:55:32 +01:00
|
|
|
// set our containment to the new one, if the the old containment was us
|
2008-11-04 00:08:39 +01:00
|
|
|
setContainment(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
// load the configuration of the old containment into the new one
|
|
|
|
c->restore(newConfig);
|
2010-07-22 22:06:06 +02:00
|
|
|
c->updateConstraints(Plasma::StartupCompletedConstraint);
|
|
|
|
c->flushPendingConstraintsEvents();
|
|
|
|
emit corona->containmentAdded(c);
|
2008-11-04 00:08:39 +01:00
|
|
|
foreach (Applet *applet, c->applets()) {
|
|
|
|
applet->init();
|
|
|
|
// We have to flush the applet constraints manually
|
|
|
|
applet->flushPendingConstraintsEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
// destroy the old one
|
|
|
|
old->destroy(false);
|
|
|
|
|
|
|
|
// and now save the config
|
|
|
|
c->save(newConfig);
|
|
|
|
corona->requestConfigSync();
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
|
|
|
KConfigGroup View::config() const
|
|
|
|
{
|
2012-03-24 19:33:54 +01:00
|
|
|
KConfigGroup views(KSharedConfig::openConfig(), "PlasmaViews");
|
2008-11-04 00:08:39 +01:00
|
|
|
return KConfigGroup(&views, QString::number(d->viewId));
|
|
|
|
}
|
|
|
|
|
2009-03-19 23:49:34 +01:00
|
|
|
void View::configNeedsSaving() const
|
|
|
|
{
|
|
|
|
Plasma::Corona *corona = qobject_cast<Plasma::Corona*>(scene());
|
|
|
|
if (corona) {
|
|
|
|
corona->requestConfigSync();
|
|
|
|
} else {
|
2012-03-24 19:33:54 +01:00
|
|
|
KSharedConfig::openConfig()->sync();
|
2009-03-19 23:49:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-03 20:11:49 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
int View::id() const
|
|
|
|
{
|
|
|
|
return d->viewId;
|
|
|
|
}
|
|
|
|
|
|
|
|
void View::setWallpaperEnabled(bool draw)
|
|
|
|
{
|
|
|
|
d->drawWallpaper = draw;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool View::isWallpaperEnabled() const
|
|
|
|
{
|
|
|
|
return d->drawWallpaper;
|
|
|
|
}
|
|
|
|
|
|
|
|
void View::setTrackContainmentChanges(bool trackChanges)
|
|
|
|
{
|
|
|
|
d->trackChanges = trackChanges;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool View::trackContainmentChanges()
|
|
|
|
{
|
|
|
|
return d->trackChanges;
|
|
|
|
}
|
|
|
|
|
|
|
|
View * View::topLevelViewAt(const QPoint & pos)
|
|
|
|
{
|
|
|
|
QWidget *w = QApplication::topLevelAt(pos);
|
|
|
|
if (w) {
|
|
|
|
Plasma::View *v = qobject_cast<Plasma::View *>(w);
|
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Plasma
|
|
|
|
|
|
|
|
|
2012-02-08 23:33:03 +01:00
|
|
|
|
|
|
|
#include "moc_view.cpp"
|