2
* Copyright 2008 Marco Martin <notmart@gmail.com>
3
* Copyright 2009 Aaron Seigo <aseigo@kde.org>
4
* Copyright 2010 Chani Armitage <chani@kde.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU Library General Public License as
8
* published by the Free Software Foundation; either version 2, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details
16
* You should have received a copy of the GNU Library General Public
17
* License along with this program; if not, write to the
18
* Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include "controllerwindow.h"
24
#include <QApplication>
28
#include <kwindowsystem.h>
31
#include <Plasma/Containment>
32
#include <Plasma/Corona>
33
#include <Plasma/Theme>
34
#include <Plasma/FrameSvg>
35
#include <Plasma/Dialog>
36
#include <Plasma/WindowEffects>
38
#include "activitymanager/activitymanager.h"
39
#include "desktopcorona.h"
40
#include "panelview.h"
41
#include "plasmaapp.h"
42
#include "widgetsexplorer/widgetexplorer.h"
44
#include <kephal/screens.h>
46
ControllerWindow::ControllerWindow(QWidget* parent)
48
m_location(Plasma::Floating),
49
m_layout(new QBoxLayout(QBoxLayout::TopToBottom, this)),
50
m_background(new Plasma::FrameSvg(this)),
61
m_background->setImagePath("dialogs/background");
62
m_background->setContainsMultipleImages(true);
64
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
65
KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
66
setAttribute(Qt::WA_DeleteOnClose);
67
setAttribute(Qt::WA_TranslucentBackground);
68
setFocus(Qt::ActiveWindowFocusReason);
69
setLocation(Plasma::BottomEdge);
71
QPalette pal = palette();
72
pal.setBrush(backgroundRole(), Qt::transparent);
75
Plasma::WindowEffects::overrideShadow(winId(), true);
78
m_layout->setContentsMargins(0, 0, 0, 0);
80
connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(onActiveWindowChanged(WId)));
81
connect(m_background, SIGNAL(repaintNeeded()), SLOT(backgroundChanged()));
82
Kephal::Screens *screens = Kephal::Screens::self();
83
connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
84
this, SLOT(adjustAndSetMaxSize()));
85
m_adjustViewTimer = new QTimer(this);
86
m_adjustViewTimer->setSingleShot(true);
87
connect(m_adjustViewTimer, SIGNAL(timeout()), this, SLOT(syncToGraphicsWidget()));
88
adjustAndSetMaxSize();
91
ControllerWindow::~ControllerWindow()
94
if (m_activityManager) {
96
m_corona->removeOffscreenWidget(m_activityManager);
98
//FIXME the qt4.6 comment below applies here too
100
if (m_widgetExplorer) {
102
m_corona->removeOffscreenWidget(m_widgetExplorer);
105
if (m_widgetExplorer->scene()) {
106
//FIXME: causes a crash in Qt 4.6 *sigh*
107
//m_widgetExplorer->scene()->removeItem(m_widgetExplorer);
111
delete m_activityManager;
112
delete m_widgetExplorer;
116
void ControllerWindow::activate()
118
KWindowSystem::activateWindow(winId());
121
void ControllerWindow::adjustAndSetMaxSize()
123
QSize screenSize = PlasmaApp::self()->corona()->screenGeometry(PlasmaApp::self()->corona()->screenId(pos())).size();
124
setMaximumSize(screenSize);
128
void ControllerWindow::backgroundChanged()
130
Plasma::Location l = m_location;
131
m_location = Plasma::Floating;
136
void ControllerWindow::setContainment(Plasma::Containment *containment)
138
if (containment == m_containment.data()) {
143
disconnect(m_containment.data(), 0, this, 0);
146
m_containment = containment;
152
m_corona = containment->corona();
153
m_screen = containment->screen();
155
if (m_widgetExplorer) {
156
m_widgetExplorer->setContainment(containment);
160
Plasma::Containment *ControllerWindow::containment() const
162
return m_containment.data();
165
void ControllerWindow::setGraphicsWidget(QGraphicsWidget *widget)
167
if (m_graphicsWidget == widget) {
171
if (m_graphicsWidget) {
172
m_graphicsWidget->removeEventFilter(this);
173
if (m_graphicsWidget == m_widgetExplorer) {
174
m_widgetExplorer->deleteLater();
175
m_widgetExplorer = 0;
176
} else if (m_graphicsWidget == m_activityManager) {
177
m_activityManager->deleteLater();
178
m_activityManager = 0;
182
m_graphicsWidget = widget;
186
QVBoxLayout *lay = new QVBoxLayout(this);
192
m_view = new QGraphicsView(this);
193
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
194
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
195
m_view->setFrameShape(QFrame::NoFrame);
196
m_view->viewport()->setAutoFillBackground(false);
197
layout()->addWidget(m_view);
200
m_view->setScene(widget->scene());
202
//try to have the proper size -before- showing the dialog
203
m_view->centerOn(widget);
204
if (widget->layout()) {
205
widget->layout()->activate();
207
static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
208
widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
210
syncToGraphicsWidget();
212
//adjustSizeTimer->start(150);
214
widget->installEventFilter(this);
218
if (PlasmaApp::isPanelContainment(containment())) {
219
// try to align it with the appropriate panel view
220
foreach (PanelView * panel, PlasmaApp::self()->panelViews()) {
221
if (panel->containment() == containment()) {
222
move(positionForPanelGeometry(panel->geometry()));
230
// set it to the bottom of the screen as we have no better hints to go by
231
QRect geom = PlasmaApp::self()->corona()->availableScreenRect(m_screen);
232
setGeometry(geom.x(), geom.bottom() - height(), geom.width(), height());
240
void ControllerWindow::syncToGraphicsWidget()
242
m_adjustViewTimer->stop();
243
if (m_view && m_graphicsWidget) {
244
QSize prevSize = size();
246
//set the sizehints correctly:
247
int left, top, right, bottom;
248
getContentsMargins(&left, &top, &right, &bottom);
250
//Try to use the screenId directly from the containment, because it won't fail.
251
//If we dont' have containment. try to get the screen by using QWidget::pos(), but it
252
//may fail if syncToGraphicsWidget is called before a real position is set (so pos() will
253
//just return 0x0, which may lead to the wrong screen
254
const QRect screenRect = m_containment ?
255
PlasmaApp::self()->corona()->screenGeometry(m_containment.data()->screen()) :
256
PlasmaApp::self()->corona()->screenGeometry(PlasmaApp::self()->corona()->screenId(pos()));
258
QSize maxSize = KWindowSystem::workArea().intersect(screenRect).size();
261
if (m_location == Plasma::LeftEdge || m_location == Plasma::RightEdge) {
262
windowSize = QSize(qMin(int(m_graphicsWidget->size().width()) + left + right, maxSize.width()), maxSize.height());
263
m_graphicsWidget->resize(m_graphicsWidget->size().width(), windowSize.height());
265
windowSize = QSize(maxSize.width(), qMin(int(m_graphicsWidget->size().height()) + top + bottom, maxSize.height()));
266
m_graphicsWidget->resize(windowSize.width(), m_graphicsWidget->size().height());
269
setMinimumSize(windowSize);
274
//reposition and resize the view.
275
//force a valid rect, otherwise it will take up the whole scene
276
QRectF sceneRect(m_graphicsWidget->sceneBoundingRect());
278
sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
279
sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
280
m_view->setSceneRect(sceneRect);
282
m_view->centerOn(m_graphicsWidget);
287
bool ControllerWindow::eventFilter(QObject *watched, QEvent *event)
289
if (watched == m_graphicsWidget &&
290
(event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
291
m_adjustViewTimer->start(150);
294
return QWidget::eventFilter(watched, event);
297
void ControllerWindow::setLocation(const Plasma::Location &loc)
299
if (m_location == loc) {
303
Plasma::WindowEffects::slideWindow(this, loc);
308
case Plasma::LeftEdge:
309
m_background->setEnabledBorders(Plasma::FrameSvg::RightBorder);
310
m_layout->setDirection(QBoxLayout::TopToBottom);
311
setContentsMargins(0, 0, m_background->marginSize(Plasma::RightMargin), 0);
314
case Plasma::RightEdge:
315
m_background->setEnabledBorders(Plasma::FrameSvg::LeftBorder);
316
m_layout->setDirection(QBoxLayout::TopToBottom);
317
setContentsMargins(m_background->marginSize(Plasma::LeftMargin), 0, 0, 0);
320
case Plasma::TopEdge:
321
m_background->setEnabledBorders(Plasma::FrameSvg::BottomBorder);
322
m_layout->setDirection(QBoxLayout::BottomToTop);
323
setContentsMargins(0, 0, 0, m_background->marginSize(Plasma::BottomMargin));
326
case Plasma::BottomEdge:
328
m_background->setEnabledBorders(Plasma::FrameSvg::TopBorder);
329
m_layout->setDirection(QBoxLayout::TopToBottom);
330
setContentsMargins(0, m_background->marginSize(Plasma::TopMargin), 0, 0);
334
if (m_watchedWidget) {
335
//FIXME maybe I should make these two inherit from something
336
//or make orientation a slot.
337
if (m_watchedWidget == (QGraphicsWidget*)m_widgetExplorer) {
338
m_widgetExplorer->setLocation(location());
340
m_activityManager->setLocation(location());
345
QPoint ControllerWindow::positionForPanelGeometry(const QRect &panelGeom) const
349
screen = m_containment.data()->screen();
352
screen = PlasmaApp::self()->corona()->screenId(QCursor::pos());
355
QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
357
switch (m_location) {
358
case Plasma::LeftEdge:
359
return QPoint(panelGeom.right(), screenGeom.top());
361
case Plasma::RightEdge:
362
return QPoint(panelGeom.left() - width(), screenGeom.top());
364
case Plasma::TopEdge:
365
return QPoint(screenGeom.left(), panelGeom.bottom());
367
case Plasma::BottomEdge:
369
return QPoint(screenGeom.left(), panelGeom.top() - height());
374
Plasma::Location ControllerWindow::location() const
379
Qt::Orientation ControllerWindow::orientation() const
381
if (m_location == Plasma::LeftEdge || m_location == Plasma::RightEdge) {
385
return Qt::Horizontal;
389
void ControllerWindow::showWidgetExplorer()
391
if (!m_containment) {
395
if (!m_widgetExplorer) {
396
m_widgetExplorer = new Plasma::WidgetExplorer(location());
397
m_watchedWidget = m_widgetExplorer;
398
m_widgetExplorer->setContainment(m_containment.data());
399
m_widgetExplorer->populateWidgetList();
400
m_widgetExplorer->setIconSize(KIconLoader::SizeHuge);
401
QAction *activityAction = new QAction(KIcon("preferences-activities"), i18n("Activities"), m_widgetExplorer);
402
connect(activityAction, SIGNAL(triggered()), this, SLOT(showActivityManager()));
403
m_widgetExplorer->addAction(activityAction);
405
m_containment.data()->corona()->addOffscreenWidget(m_widgetExplorer);
406
m_widgetExplorer->show();
408
m_widgetExplorer->setIconSize(KIconLoader::SizeHuge);
410
if (orientation() == Qt::Horizontal) {
411
m_widgetExplorer->resize(width(), m_widgetExplorer->size().height());
413
m_widgetExplorer->resize(m_widgetExplorer->size().width(), height());
416
setGraphicsWidget(m_widgetExplorer);
418
connect(m_widgetExplorer, SIGNAL(closeClicked()), this, SLOT(close()));
420
m_widgetExplorer->setLocation(location());
421
m_widgetExplorer->show();
422
m_watchedWidget = m_widgetExplorer;
423
setGraphicsWidget(m_widgetExplorer);
425
m_widgetExplorer->setFocus();
428
bool ControllerWindow::showingWidgetExplorer() const
430
return m_widgetExplorer;
433
void ControllerWindow::showActivityManager()
435
if (!m_activityManager) {
436
m_activityManager = new ActivityManager(location());
437
m_watchedWidget = m_activityManager;
439
m_corona->addOffscreenWidget(m_activityManager);
440
m_activityManager->show();
442
if (orientation() == Qt::Horizontal) {
443
m_activityManager->resize(width(), m_activityManager->size().height());
445
m_activityManager->resize(m_activityManager->size().width(), height());
448
m_activityManager->setIconSize(KIconLoader::SizeHuge);
450
setGraphicsWidget(m_activityManager);
452
connect(m_activityManager, SIGNAL(addWidgetsRequested()), this, SLOT(showWidgetExplorer()));
453
connect(m_activityManager, SIGNAL(closeClicked()), this, SLOT(close()));
455
m_activityManager->setLocation(location());
456
m_watchedWidget = m_activityManager;
457
m_activityManager->show();
458
setGraphicsWidget(m_activityManager);
460
m_activityManager->setFlag(QGraphicsItem::ItemIsFocusable);
461
m_activityManager->setFocus();
464
bool ControllerWindow::showingActivityManager() const
466
return m_activityManager;
469
bool ControllerWindow::isControllerViewVisible() const
471
return m_view && m_view->isVisible();
474
Plasma::FrameSvg *ControllerWindow::background() const
479
int ControllerWindow::screen() const
484
void ControllerWindow::setScreen(int screen)
489
void ControllerWindow::onActiveWindowChanged(WId id)
493
// Small delay when closing due to lost focus
494
QTimer::singleShot(300, this, SLOT(closeIfNotFocussed()));
497
void ControllerWindow::closeIfNotFocussed()
499
if (!QApplication::activeWindow()) {
504
void ControllerWindow::paintEvent(QPaintEvent *event)
508
QPainter painter(this);
509
painter.setCompositionMode(QPainter::CompositionMode_Source );
511
m_background->paintFrame(&painter);
514
void ControllerWindow::keyPressEvent(QKeyEvent *event)
516
if (event->key() == Qt::Key_Escape) {
521
void ControllerWindow::resizeEvent(QResizeEvent * event)
523
m_background->resizeFrame(size());
525
Plasma::WindowEffects::enableBlurBehind(effectiveWinId(), true, m_background->mask());
527
qDebug() << "ControllerWindow::resizeEvent" << event->oldSize();
529
QWidget::resizeEvent(event);
532
#include "controllerwindow.moc"