~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to plasma/desktop/shell/panelcontroller.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2008 Marco Martin <notmart@gmail.com>
 
3
 *
 
4
 *   This program is free software; you can redistribute it and/or modify
 
5
 *   it under the terms of the GNU Library General Public License as
 
6
 *   published by the Free Software Foundation; either version 2, or
 
7
 *   (at your option) any later version.
 
8
 *
 
9
 *   This program is distributed in the hope that it will be useful,
 
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *   GNU General Public License for more details
 
13
 *
 
14
 *   You should have received a copy of the GNU Library General Public
 
15
 *   License along with this program; if not, write to the
 
16
 *   Free Software Foundation, Inc.,
 
17
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#include "panelcontroller.h"
 
21
 
 
22
#include <QAction>
 
23
#include <QApplication>
 
24
#include <QBoxLayout>
 
25
#include <QVBoxLayout>
 
26
#include <QFrame>
 
27
#include <QLabel>
 
28
#include <QMouseEvent>
 
29
#include <QPainter>
 
30
#include <QToolButton>
 
31
#ifdef Q_WS_X11
 
32
#include <QX11Info>
 
33
#endif
 
34
 
 
35
#include <KColorUtils>
 
36
#include <KIconLoader>
 
37
#include <KIcon>
 
38
#include <kwindowsystem.h>
 
39
#include <netwm.h>
 
40
 
 
41
#include <Plasma/Containment>
 
42
#include <Plasma/Corona>
 
43
#include <Plasma/PaintUtils>
 
44
#include <Plasma/Theme>
 
45
#include <Plasma/FrameSvg>
 
46
#include <Plasma/Dialog>
 
47
 
 
48
#include "desktopcorona.h"
 
49
#include "plasmaapp.h"
 
50
#include "positioningruler.h"
 
51
#include "toolbutton.h"
 
52
#include "widgetsexplorer/widgetexplorer.h"
 
53
 
 
54
class PanelController::ButtonGroup: public QFrame
 
55
{
 
56
public:
 
57
    ButtonGroup(QWidget *parent)
 
58
       : QFrame(parent)
 
59
    {
 
60
        background = new Plasma::FrameSvg(this);
 
61
        background->setImagePath("widgets/frame");
 
62
        background->setElementPrefix("plain");
 
63
    }
 
64
 
 
65
    void paintEvent(QPaintEvent *event)
 
66
    {
 
67
        Q_UNUSED(event)
 
68
 
 
69
        QPainter painter(this);
 
70
        background->resizeFrame(size());
 
71
        background->paintFrame(&painter);
 
72
    }
 
73
 
 
74
    Plasma::FrameSvg *background;
 
75
};
 
76
 
 
77
 
 
78
 
 
79
static const int MINIMUM_HEIGHT = 10;
 
80
 
 
81
PanelController::PanelController(QWidget* parent)
 
82
   : ControllerWindow(parent),
 
83
     m_extLayout(0),
 
84
     m_layout(0),
 
85
     m_dragging(NoElement),
 
86
     m_startDragControllerPos(0,0),
 
87
     m_startDragMousePos(0,0),
 
88
     m_optionsDialog(0),
 
89
     m_leftAlignTool(0),
 
90
     m_centerAlignTool(0),
 
91
     m_rightAlignTool(0),
 
92
     m_drawMoveHint(false)
 
93
{
 
94
    Q_UNUSED(parent)
 
95
 
 
96
    setAttribute(Qt::WA_TranslucentBackground);
 
97
    QPalette pal = palette();
 
98
    pal.setBrush(backgroundRole(), Qt::transparent);
 
99
    setPalette(pal);
 
100
 
 
101
    m_iconSvg = new Plasma::Svg(this);
 
102
    m_iconSvg->setImagePath("widgets/configuration-icons");
 
103
    m_iconSvg->setContainsMultipleImages(true);
 
104
    m_iconSvg->resize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
 
105
 
 
106
    //setWindowFlags(Qt::Popup);
 
107
    //setWindowFlags(Qt::FramelessWindowHint);
 
108
    KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
 
109
    setAttribute(Qt::WA_DeleteOnClose);
 
110
    setFocus(Qt::ActiveWindowFocusReason);
 
111
 
 
112
    //layout setup
 
113
    m_configWidget = new QWidget(this);
 
114
    layout()->addWidget(m_configWidget);
 
115
 
 
116
    m_extLayout = new QBoxLayout(QBoxLayout::TopToBottom, m_configWidget);
 
117
    m_extLayout->setContentsMargins(0, background()->marginSize(Plasma::TopMargin), 0, 0);
 
118
 
 
119
    m_layout = new QBoxLayout(QBoxLayout::LeftToRight);
 
120
    m_layout->setContentsMargins(0, 0, 0, 0);
 
121
 
 
122
    if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
123
        m_layout->setDirection(QBoxLayout::RightToLeft);
 
124
    } else {
 
125
        m_layout->setDirection(QBoxLayout::LeftToRight);
 
126
    }
 
127
 
 
128
    m_layout->addStretch();
 
129
    m_extLayout->addLayout(m_layout);
 
130
 
 
131
    //Add buttons
 
132
 
 
133
    //alignment
 
134
    //first the container
 
135
    QFrame *alignFrame = new ButtonGroup(m_configWidget);
 
136
    QVBoxLayout *alignLayout = new QVBoxLayout(alignFrame);
 
137
 
 
138
    m_alignLabel = new QLabel(i18n("Panel Alignment"), m_configWidget);
 
139
    alignLayout->addWidget(m_alignLabel);
 
140
 
 
141
    m_leftAlignTool = addTool("format-justify-left", i18n("Left"), alignFrame,  Qt::ToolButtonTextBesideIcon, true);
 
142
    m_leftAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
143
    alignLayout->addWidget(m_leftAlignTool);
 
144
    m_leftAlignTool->setChecked(true);
 
145
    connect(m_leftAlignTool, SIGNAL(toggled(bool)), this, SLOT(alignToggled(bool)));
 
146
 
 
147
    m_centerAlignTool = addTool("format-justify-center", i18n("Center"), alignFrame,  Qt::ToolButtonTextBesideIcon, true);
 
148
    m_centerAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
149
    alignLayout->addWidget(m_centerAlignTool);
 
150
    connect(m_centerAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
 
151
 
 
152
    m_rightAlignTool = addTool("format-justify-right", i18n("Right"), alignFrame,  Qt::ToolButtonTextBesideIcon, true);
 
153
    m_rightAlignTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
154
    alignLayout->addWidget(m_rightAlignTool);
 
155
    connect(m_rightAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
 
156
 
 
157
 
 
158
    //Panel mode
 
159
    //first the container
 
160
    QFrame *modeFrame = new ButtonGroup(m_configWidget);
 
161
    QVBoxLayout *modeLayout = new QVBoxLayout(modeFrame);
 
162
 
 
163
    m_modeLabel = new QLabel(i18n("Visibility"), m_configWidget);
 
164
    modeLayout->addWidget(m_modeLabel);
 
165
 
 
166
    m_normalPanelTool = addTool("layer-visible-on", i18n("Always visible"), modeFrame,  Qt::ToolButtonTextBesideIcon, true);
 
167
    m_normalPanelTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
168
    modeLayout->addWidget(m_normalPanelTool);
 
169
    connect(m_normalPanelTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
 
170
 
 
171
    m_autoHideTool = addTool("video-display", i18n("Auto-hide"), modeFrame,  Qt::ToolButtonTextBesideIcon, true);
 
172
    m_autoHideTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
173
    modeLayout->addWidget(m_autoHideTool);
 
174
    connect(m_autoHideTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
 
175
 
 
176
    m_underWindowsTool = addTool("view-fullscreen", i18n("Windows can cover"), modeFrame,  Qt::ToolButtonTextBesideIcon, true);
 
177
    m_underWindowsTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
178
    modeLayout->addWidget(m_underWindowsTool);
 
179
    connect(m_underWindowsTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
 
180
 
 
181
    m_overWindowsTool = addTool("view-restore", i18n("Windows go below"), modeFrame,  Qt::ToolButtonTextBesideIcon, true);
 
182
    m_overWindowsTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
183
    modeLayout->addWidget(m_overWindowsTool);
 
184
    connect(m_overWindowsTool, SIGNAL(toggled(bool)), this, SLOT(panelVisibilityModeChanged(bool)));
 
185
 
 
186
    m_layout->addStretch();
 
187
    m_moveTool = addTool(QString(), i18n("Screen Edge"), m_configWidget);
 
188
    m_moveTool->setIcon(m_iconSvg->pixmap("move"));
 
189
    m_moveTool->installEventFilter(this);
 
190
    m_moveTool->setCursor(Qt::SizeAllCursor);
 
191
    m_moveTool->setToolTip(i18n("Press left mouse button and drag to a screen edge to change panel edge"));
 
192
    m_layout->addWidget(m_moveTool);
 
193
 
 
194
    m_sizeTool = addTool(QString(), i18n("Height"), m_configWidget);
 
195
    m_sizeTool->installEventFilter(this);
 
196
    m_sizeTool->setCursor(Qt::SizeVerCursor);
 
197
    m_sizeTool->setToolTip(i18n("Press left mouse button and drag vertically to change panel height"));
 
198
    m_layout->addWidget(m_sizeTool);
 
199
    m_layout->addStretch();
 
200
 
 
201
    //other buttons
 
202
    m_layout->addSpacing(20);
 
203
 
 
204
    //Settings popup menu
 
205
    m_settingsTool = addTool("configure", i18n("More Settings"), m_configWidget);
 
206
    m_settingsTool->setToolTip(i18n("Show more options about panel alignment, visibility and other settings"));
 
207
    m_layout->addWidget(m_settingsTool);
 
208
    connect(m_settingsTool, SIGNAL(pressed()), this, SLOT(settingsPopup()));
 
209
    m_optionsDialog = new Plasma::Dialog(0); // don't pass in a parent; breaks with some lesser WMs
 
210
    m_optionsDialog->installEventFilter(this);
 
211
    KWindowSystem::setState(m_optionsDialog->winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
 
212
    m_optDialogLayout = new QVBoxLayout(m_optionsDialog);
 
213
    m_optDialogLayout->setMargin(0);
 
214
    m_optDialogLayout->addWidget(alignFrame);
 
215
    m_optDialogLayout->addWidget(modeFrame);
 
216
 
 
217
 
 
218
    m_expandTool = addTool(QString(), i18n("Maximize Panel"), m_configWidget);
 
219
    m_expandTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
 
220
    m_expandTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
221
    m_optDialogLayout->addWidget(m_expandTool);
 
222
    connect(m_expandTool, SIGNAL(clicked()), this, SLOT(maximizePanel()));
 
223
 
 
224
    m_closeControllerTool = addTool("window-close", i18n("Close this configuration window"), m_configWidget, Qt::ToolButtonIconOnly, false);
 
225
    m_layout->addWidget(m_closeControllerTool);
 
226
    connect(m_closeControllerTool, SIGNAL(clicked()), this, SLOT(close()));
 
227
 
 
228
    m_ruler = new PositioningRuler(m_configWidget);
 
229
    connect(m_ruler, SIGNAL(rulersMoved(int, int, int)), this, SLOT(rulersMoved(int, int, int)));
 
230
    m_extLayout->addWidget(m_ruler);
 
231
 
 
232
    connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(themeChanged()));
 
233
    themeChanged();
 
234
}
 
235
 
 
236
PanelController::~PanelController()
 
237
{
 
238
    //TODO: should we try and only call this when something has actually been
 
239
    //      altered that we care about?
 
240
    PlasmaApp::self()->corona()->requestConfigSync();
 
241
    delete m_optionsDialog;
 
242
}
 
243
 
 
244
void PanelController::setContainment(Plasma::Containment *c)
 
245
{
 
246
    if (!c) {
 
247
        return;
 
248
    }
 
249
 
 
250
    ControllerWindow::setContainment(c);
 
251
    PlasmaApp::self()->hideController(containment()->screen());
 
252
 
 
253
    QWidget *child;
 
254
    while (!m_actionWidgets.isEmpty()) {
 
255
        child = m_actionWidgets.first();
 
256
        //try to remove from both layouts
 
257
        m_layout->removeWidget(child);
 
258
        m_optDialogLayout->removeWidget(child);
 
259
        m_actionWidgets.removeFirst();
 
260
        child->deleteLater();
 
261
    }
 
262
 
 
263
    int insertIndex = m_layout->count() - 3;
 
264
 
 
265
    QAction *action = containment()->action("add widgets");
 
266
    if (action && action->isEnabled()) {
 
267
        ToolButton *addWidgetTool = addTool(action, this);
 
268
        m_layout->insertWidget(insertIndex, addWidgetTool);
 
269
        ++insertIndex;
 
270
        connect(containment(), SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(switchToWidgetExplorer()));
 
271
    }
 
272
 
 
273
    action = new QAction(i18n("Add Spacer"), this);
 
274
    ToolButton *addSpaceTool = addTool(action, this);
 
275
    addSpaceTool->setToolTip(i18n("Add a spacer to the panel useful to add some space between two widgets"));
 
276
    m_layout->insertWidget(insertIndex, addSpaceTool);
 
277
    ++insertIndex;
 
278
    connect(action, SIGNAL(triggered()), this, SLOT(addSpace()));
 
279
 
 
280
    action = containment()->action("lock widgets");
 
281
    if (action && action->isEnabled()) {
 
282
        ToolButton *lockWidgetsTool = addTool(action, this);
 
283
        m_optDialogLayout->addWidget(lockWidgetsTool, m_optDialogLayout->count() - 2);
 
284
        connect(lockWidgetsTool, SIGNAL(clicked()), m_optionsDialog, SLOT(hide()));
 
285
        connect(lockWidgetsTool, SIGNAL(clicked()), this, SLOT(hide()));
 
286
    }
 
287
 
 
288
    action = containment()->action("remove");
 
289
    if (action && action->isEnabled()) {
 
290
        ToolButton *removePanelTool = addTool(action, this);
 
291
        removePanelTool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
292
        m_optDialogLayout->insertWidget(insertIndex, removePanelTool);
 
293
        connect(removePanelTool, SIGNAL(clicked()), this, SLOT(hide()));
 
294
    }
 
295
 
 
296
    syncRuler();
 
297
}
 
298
 
 
299
void PanelController::moveEvent(QMoveEvent *event)
 
300
{
 
301
    //FIXME: this is a glorious hack: it causes the window to be positioned correctly after kwin positions it incorrectly.
 
302
    //TODO: the proper way to do is to give a window type specific to the panel controller, that gets positioned correctly
 
303
    if (((location() == Plasma::BottomEdge || location() == Plasma::TopEdge) &&
 
304
         event->oldPos().x() != event->pos().x()) ||
 
305
        ((location() == Plasma::LeftEdge || location() == Plasma::RightEdge) &&
 
306
         event->oldPos().y() != event->pos().y())) {
 
307
        emit offsetChanged(m_ruler->offset());
 
308
    }
 
309
    ControllerWindow::moveEvent(event);
 
310
}
 
311
 
 
312
void PanelController::showEvent(QShowEvent *event)
 
313
{
 
314
    if (containment()) {
 
315
        setMaximumSize(PlasmaApp::self()->corona()->screenGeometry(containment()->screen()).size());
 
316
        syncToLocation();
 
317
    }
 
318
    ControllerWindow::showEvent(event);
 
319
}
 
320
 
 
321
void PanelController::setLocation(const Plasma::Location &loc)
 
322
{
 
323
    if (location() == loc) {
 
324
        return;
 
325
    }
 
326
 
 
327
    ControllerWindow::setLocation(loc);
 
328
    syncToLocation();
 
329
}
 
330
 
 
331
void PanelController::syncToLocation()
 
332
{
 
333
    const Plasma::Location loc = location();
 
334
    m_ruler->setLocation(loc);
 
335
 
 
336
    //The external layout gwts auto flipped when QApplication::layoutDirection() changes
 
337
    //and it shouldn't, the internal one no and it should, so i must manually invert both
 
338
    switch (loc) {
 
339
    case Plasma::LeftEdge:
 
340
        if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
341
            m_extLayout->setDirection(QBoxLayout::LeftToRight);
 
342
            m_extLayout->setContentsMargins(background()->marginSize(Plasma::LeftMargin), 0, 0, 0);
 
343
 
 
344
        } else {
 
345
            m_extLayout->setDirection(QBoxLayout::RightToLeft);
 
346
            m_extLayout->setContentsMargins(0, 0, background()->marginSize(Plasma::RightMargin), 0);
 
347
        }
 
348
        m_layout->setDirection(QBoxLayout::TopToBottom);
 
349
 
 
350
        break;
 
351
 
 
352
    case Plasma::RightEdge:
 
353
        if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
354
            m_extLayout->setDirection(QBoxLayout::RightToLeft);
 
355
            m_extLayout->setContentsMargins(0, 0, background()->marginSize(Plasma::RightMargin), 0);
 
356
        } else {
 
357
            m_extLayout->setDirection(QBoxLayout::LeftToRight);
 
358
            m_extLayout->setContentsMargins(background()->marginSize(Plasma::LeftMargin), 0, 0, 0);
 
359
        }
 
360
        m_layout->setDirection(QBoxLayout::TopToBottom);
 
361
        break;
 
362
 
 
363
    case Plasma::TopEdge:
 
364
        if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
365
            m_layout->setDirection(QBoxLayout::RightToLeft);
 
366
        } else {
 
367
 
 
368
            m_layout->setDirection(QBoxLayout::LeftToRight);
 
369
        }
 
370
        m_extLayout->setDirection(QBoxLayout::BottomToTop);
 
371
        m_extLayout->setContentsMargins(0, 0, 0, background()->marginSize(Plasma::BottomMargin));
 
372
        break;
 
373
 
 
374
    case Plasma::BottomEdge:
 
375
    default:
 
376
        if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
377
            m_layout->setDirection(QBoxLayout::RightToLeft);
 
378
        } else {
 
379
 
 
380
            m_layout->setDirection(QBoxLayout::LeftToRight);
 
381
        }
 
382
        m_extLayout->setDirection(QBoxLayout::TopToBottom);
 
383
        m_extLayout->setContentsMargins(0, background()->marginSize(Plasma::TopMargin), 0, 0);
 
384
        break;
 
385
    }
 
386
 
 
387
    const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
 
388
 
 
389
    switch (loc) {
 
390
    case Plasma::LeftEdge:
 
391
    case Plasma::RightEdge:
 
392
        m_sizeTool->setCursor(Qt::SizeHorCursor);
 
393
        m_sizeTool->setText(i18n("Width"));
 
394
        m_sizeTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
 
395
        m_expandTool->setIcon(m_iconSvg->pixmap("size-vertical"));
 
396
        m_leftAlignTool->setText(i18n("Top"));
 
397
        m_rightAlignTool->setText(i18n("Bottom"));
 
398
 
 
399
        break;
 
400
    case Plasma::TopEdge:
 
401
    case Plasma::BottomEdge:
 
402
    default:
 
403
        m_sizeTool->setCursor(Qt::SizeVerCursor);
 
404
        m_sizeTool->setText(i18n("Height"));
 
405
        m_sizeTool->setIcon(m_iconSvg->pixmap("size-vertical"));
 
406
        m_expandTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
 
407
        m_leftAlignTool->setText(i18n("Left"));
 
408
        m_rightAlignTool->setText(i18n("Right"));
 
409
    }
 
410
 
 
411
 
 
412
    syncRuler();
 
413
    QSize rulerSize = m_ruler->sizeHint();
 
414
    m_ruler->hide();
 
415
    m_ruler->setFixedSize(rulerSize);
 
416
    m_ruler->show();
 
417
    updateGeometry();
 
418
 
 
419
    setMinimumSize(QSize(0, 0));
 
420
    setMaximumSize(sizeHint());
 
421
    resize(sizeHint());
 
422
}
 
423
 
 
424
void PanelController::setOffset(int newOffset)
 
425
{
 
426
    if (newOffset != m_ruler->offset()) {
 
427
        m_ruler->setOffset(newOffset);
 
428
    }
 
429
}
 
430
 
 
431
int PanelController::offset() const
 
432
{
 
433
    return m_ruler->offset();
 
434
}
 
435
 
 
436
void PanelController::setAlignment(const Qt::Alignment &newAlignment)
 
437
{
 
438
    if (newAlignment != m_ruler->alignment()) {
 
439
        if (newAlignment == Qt::AlignLeft) {
 
440
            m_leftAlignTool->setChecked(true);
 
441
        } else if (newAlignment == Qt::AlignCenter) {
 
442
            m_centerAlignTool->setChecked(true);
 
443
        } else if (newAlignment == Qt::AlignRight) {
 
444
            m_rightAlignTool->setChecked(true);
 
445
        }
 
446
 
 
447
        m_ruler->setAlignment(newAlignment);
 
448
    }
 
449
}
 
450
 
 
451
Qt::Alignment PanelController::alignment() const
 
452
{
 
453
    return m_ruler->alignment();
 
454
}
 
455
 
 
456
void PanelController::setVisibilityMode(PanelView::VisibilityMode mode)
 
457
{
 
458
    switch (mode) {
 
459
    case PanelView::AutoHide:
 
460
        m_autoHideTool->setChecked(true);
 
461
        break;
 
462
    case PanelView::LetWindowsCover:
 
463
        m_underWindowsTool->setChecked(true);
 
464
        break;
 
465
    case PanelView::WindowsGoBelow:
 
466
        m_overWindowsTool->setChecked(true);
 
467
        break;
 
468
    case PanelView::NormalPanel:
 
469
    default:
 
470
        m_normalPanelTool->setChecked(true);
 
471
        break;
 
472
    }
 
473
}
 
474
 
 
475
PanelView::VisibilityMode PanelController::panelVisibilityMode() const
 
476
{
 
477
    if (m_underWindowsTool->isChecked()) {
 
478
        return PanelView::LetWindowsCover;
 
479
    } else if (m_overWindowsTool->isChecked()) {
 
480
        return PanelView::WindowsGoBelow;
 
481
    } else if (m_autoHideTool->isChecked()) {
 
482
        return PanelView::AutoHide;
 
483
    } else {
 
484
        return PanelView::NormalPanel;
 
485
    }
 
486
}
 
487
 
 
488
void PanelController::themeChanged()
 
489
{
 
490
    QColor color = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
 
491
    QPalette p = m_alignLabel->palette();
 
492
    p.setColor(QPalette::Normal, QPalette::WindowText, color);
 
493
    p.setColor(QPalette::Inactive, QPalette::WindowText, color);
 
494
    m_alignLabel->setPalette(p);
 
495
    m_modeLabel->setPalette(p);
 
496
 
 
497
    m_sizeTool->setIcon(m_iconSvg->pixmap("move"));
 
498
 
 
499
    if (orientation() == Qt::Horizontal) {
 
500
        m_sizeTool->setIcon(m_iconSvg->pixmap("size-vertical"));
 
501
    } else {
 
502
        m_sizeTool->setIcon(m_iconSvg->pixmap("size-horizontal"));
 
503
    }
 
504
}
 
505
 
 
506
void PanelController::switchToWidgetExplorer()
 
507
{
 
508
    m_configWidget->hide();
 
509
    showWidgetExplorer();
 
510
}
 
511
 
 
512
void PanelController::switchToController()
 
513
{
 
514
    setGraphicsWidget(0);
 
515
    m_configWidget->show();
 
516
    syncToLocation();
 
517
}
 
518
 
 
519
bool PanelController::eventFilter(QObject *watched, QEvent *event)
 
520
{
 
521
    ControllerWindow::eventFilter(watched, event);
 
522
 
 
523
    if (event->type() == QEvent::MouseButtonPress) {
 
524
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
 
525
        m_lastPos = mouseEvent->globalPos();
 
526
    }
 
527
 
 
528
    if (watched == m_optionsDialog && event->type() == QEvent::WindowDeactivate && (!isControllerViewVisible())) {
 
529
        if (!m_settingsTool->underMouse()) {
 
530
            m_optionsDialog->hide();
 
531
        }
 
532
 
 
533
        if (!isActiveWindow()) {
 
534
            close();
 
535
        }
 
536
        return true;
 
537
    } else if (watched == m_moveTool) {
 
538
        if (event->type() == QEvent::MouseButtonPress) {
 
539
            m_dragging = MoveButtonElement;
 
540
            m_moveTool->grabMouse();
 
541
        } else if (event->type() == QEvent::MouseButtonRelease) {
 
542
            m_dragging = NoElement;
 
543
            m_moveTool->releaseMouse();
 
544
            emit locationChanged(location());
 
545
        } else if (event->type() == QEvent::MouseMove) {
 
546
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
 
547
            mouseMoveFilter(mouseEvent);
 
548
        }
 
549
    } else if (watched == m_sizeTool) {
 
550
        if (event->type() == QEvent::MouseButtonPress) {
 
551
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
 
552
            m_startDragMousePos = mouseEvent->globalPos();
 
553
            m_startDragControllerPos = pos(); // the global position of the controller window
 
554
            m_dragging = ResizeButtonElement;
 
555
        } else if (event->type() == QEvent::MouseButtonRelease) {
 
556
            //resets properties saved during the drag
 
557
            m_startDragMousePos = QPoint(0, 0);
 
558
            m_startDragControllerPos = QPoint(0, 0);
 
559
            m_dragging = NoElement;
 
560
            setCursor(Qt::ArrowCursor);
 
561
        } else if (event->type() == QEvent::MouseMove) {
 
562
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
 
563
            mouseMoveFilter(mouseEvent);
 
564
        }
 
565
    }
 
566
 
 
567
    return false;
 
568
}
 
569
 
 
570
void PanelController::mouseMoveFilter(QMouseEvent *event)
 
571
{
 
572
    if (m_dragging == NoElement || !containment()) {
 
573
        return;
 
574
    }
 
575
 
 
576
    DesktopCorona *corona = PlasmaApp::self()->corona();
 
577
    const QRect screenGeom = corona->screenGeometry(containment()->screen());
 
578
 
 
579
    if (m_dragging == MoveButtonElement) {
 
580
 
 
581
        if (!screenGeom.contains(event->globalPos())) {
 
582
            //move panel to new screen if dragged there
 
583
            int targetScreen = corona->screenId(event->globalPos());
 
584
 
 
585
            //kDebug() << "Moving panel from screen" << containment()->screen() << "to screen" << targetScreen;
 
586
            containment()->setScreen(targetScreen);
 
587
            return;
 
588
        }
 
589
 
 
590
        if (location() == Plasma::BottomEdge || location() == Plasma::TopEdge) {
 
591
            emit partialMove(QPoint(0, m_lastPos.y() - event->globalY()));
 
592
        } else if (location() == Plasma::LeftEdge || location() == Plasma::RightEdge) {
 
593
            emit partialMove(QPoint(m_lastPos.x() - event->globalX(), 0));
 
594
        }
 
595
        m_lastPos = event->globalPos();
 
596
 
 
597
        //create a dead zone so you can go across the middle without having it hop to one side
 
598
        float dzFactor = 0.35;
 
599
        QPoint offset = QPoint(screenGeom.width()*dzFactor,screenGeom.height()*dzFactor);
 
600
        QRect deadzone = QRect(screenGeom.topLeft()+offset, screenGeom.bottomRight()-offset);
 
601
        if (deadzone.contains(event->globalPos())) {
 
602
            //kDebug() << "In the deadzone:" << deadzone;
 
603
            return;
 
604
        }
 
605
 
 
606
        const Plasma::Location oldLocation = containment()->location();
 
607
        Plasma::Location newLocation = oldLocation;
 
608
        float screenAspect = float(screenGeom.height())/screenGeom.width();
 
609
 
 
610
        /* Use diagonal lines so we get predictable behavior when moving the panel
 
611
         * y=topleft.y+(x-topleft.x)*aspectratio   topright < bottomleft
 
612
         * y=bottomleft.y-(x-topleft.x)*aspectratio   topleft < bottomright
 
613
         */
 
614
        if (event->globalY() < screenGeom.y()+(event->globalX()-screenGeom.x())*screenAspect) {
 
615
            if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
 
616
                if (containment()->location() == Plasma::TopEdge) {
 
617
                    return;
 
618
                } else {
 
619
                    newLocation = Plasma::TopEdge;
 
620
                }
 
621
            } else if (containment()->location() == Plasma::RightEdge) {
 
622
                    return;
 
623
            } else {
 
624
                newLocation = Plasma::RightEdge;
 
625
            }
 
626
        } else {
 
627
            if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
 
628
                if (containment()->location() == Plasma::LeftEdge) {
 
629
                    return;
 
630
                } else {
 
631
                    newLocation = Plasma::LeftEdge;
 
632
                }
 
633
            } else if(containment()->location() == Plasma::BottomEdge) {
 
634
                    return;
 
635
            } else {
 
636
                newLocation = Plasma::BottomEdge;
 
637
            }
 
638
        }
 
639
 
 
640
 
 
641
        //If the orientation changed swap width and height
 
642
        if (oldLocation != newLocation) {
 
643
            emit locationChanged(newLocation);
 
644
        }
 
645
 
 
646
        return;
 
647
    }
 
648
 
 
649
    //Resize handle moved
 
650
    switch (location()) {
 
651
    case Plasma::LeftEdge: {
 
652
        int newX = m_startDragControllerPos.x() + event->globalX() - m_startDragMousePos.x();
 
653
        newX = qMax(newX, screenGeom.left() + MINIMUM_HEIGHT);
 
654
        newX = qMin(newX, screenGeom.left() + screenGeom.width()/3);
 
655
        move(newX, pos().y());
 
656
        resizeFrameHeight(geometry().left() - screenGeom.left());
 
657
        break;
 
658
    }
 
659
    case Plasma::RightEdge: {
 
660
        int newX = m_startDragControllerPos.x() + event->globalX() - m_startDragMousePos.x();
 
661
        newX = qMin(newX, screenGeom.right() - MINIMUM_HEIGHT - width());
 
662
        newX = qMax(newX, screenGeom.left() + 2*(screenGeom.width()/3) - width());
 
663
        move(newX, pos().y());
 
664
        resizeFrameHeight(screenGeom.right() - geometry().right());
 
665
        break;
 
666
    }
 
667
    case Plasma::TopEdge: {
 
668
        int newY = m_startDragControllerPos.y() + event->globalY() - m_startDragMousePos.y();
 
669
        newY = qMax(newY, screenGeom.top() + MINIMUM_HEIGHT);
 
670
        newY = qMin(newY, screenGeom.top() + screenGeom.height()/3);
 
671
        move(pos().x(), newY);
 
672
        resizeFrameHeight(geometry().top() - screenGeom.top());
 
673
        break;
 
674
    }
 
675
    case Plasma::BottomEdge:
 
676
    default: {
 
677
        int newY = m_startDragControllerPos.y() + event->globalY() - m_startDragMousePos.y();
 
678
        newY = qMin(newY, screenGeom.bottom() - MINIMUM_HEIGHT - height());
 
679
        newY = qMax(newY, screenGeom.top() + 2*(screenGeom.height()/3) - height());
 
680
        move(pos().x(), newY);
 
681
        resizeFrameHeight(screenGeom.bottom() - geometry().bottom());
 
682
        break;
 
683
    }
 
684
    }
 
685
}
 
686
 
 
687
void PanelController::focusOutEvent(QFocusEvent * event)
 
688
{
 
689
    Q_UNUSED(event)
 
690
    if (!m_optionsDialog->isActiveWindow() && !isControllerViewVisible() && !isActiveWindow()) {
 
691
        m_optionsDialog->hide();
 
692
        close();
 
693
    }
 
694
}
 
695
 
 
696
ToolButton *PanelController::addTool(QAction *action, QWidget *parent, Qt::ToolButtonStyle style)
 
697
{
 
698
    ToolButton *tool = new ToolButton(parent);
 
699
    tool->setToolButtonStyle(style);
 
700
    tool->setAction(action);
 
701
    m_actionWidgets.append(tool);
 
702
 
 
703
    return tool;
 
704
}
 
705
 
 
706
ToolButton *PanelController::addTool(const QString iconName, const QString iconText, QWidget *parent, Qt::ToolButtonStyle style, bool checkButton)
 
707
{
 
708
    //TODO take advantage of setDefaultAction using the containment's actions if possible
 
709
    ToolButton *tool = new ToolButton(parent);
 
710
 
 
711
    KIcon icon = KIcon(iconName);
 
712
    if (!icon.isNull() && !iconName.isNull()) {
 
713
        tool->setIcon(icon);
 
714
    }
 
715
 
 
716
    tool->setText(iconText);
 
717
    tool->setToolButtonStyle(style);
 
718
 
 
719
    if (style == Qt::ToolButtonIconOnly) {
 
720
        tool->setToolTip(iconText);
 
721
    }
 
722
 
 
723
    tool->setCheckable(checkButton);
 
724
    tool->setAutoExclusive(checkButton);
 
725
 
 
726
    return tool;
 
727
}
 
728
 
 
729
void PanelController::resizeFrameHeight(const int newHeight)
 
730
{
 
731
    if (!containment()) {
 
732
        return;
 
733
    }
 
734
 
 
735
    switch (location()) {
 
736
        case Plasma::LeftEdge:
 
737
        case Plasma::RightEdge:
 
738
            containment()->setMinimumSize(QSize(newHeight, (int)containment()->minimumSize().height()));
 
739
            containment()->setMaximumSize(QSize(newHeight, (int)containment()->maximumSize().height()));
 
740
            containment()->resize(QSize(newHeight, (int)containment()->size().height()));
 
741
            break;
 
742
        case Plasma::TopEdge:
 
743
        case Plasma::BottomEdge:
 
744
        default:
 
745
            containment()->setMinimumSize(QSize((int)containment()->minimumSize().width(), newHeight));
 
746
            containment()->setMaximumSize(QSize((int)containment()->maximumSize().width(), newHeight));
 
747
            containment()->resize(QSize((int)containment()->size().width(), newHeight));
 
748
            break;
 
749
    }
 
750
}
 
751
 
 
752
void PanelController::rulersMoved(int offset, int minLength, int maxLength)
 
753
{
 
754
    if (!containment()) {
 
755
        return;
 
756
    }
 
757
 
 
758
    QSize preferredSize(containment()->preferredSize().toSize());
 
759
 
 
760
    switch (location()) {
 
761
        case Plasma::LeftEdge:
 
762
        case Plasma::RightEdge:
 
763
            containment()->resize(QSize((int)containment()->size().width(), qBound(minLength, preferredSize.height(), maxLength)));
 
764
            containment()->setMinimumSize(QSize((int)containment()->minimumSize().width(), minLength));
 
765
            containment()->setMaximumSize(QSize((int)containment()->maximumSize().width(), maxLength));
 
766
            break;
 
767
        case Plasma::TopEdge:
 
768
        case Plasma::BottomEdge:
 
769
        default:
 
770
            containment()->resize(QSize(qBound(minLength, preferredSize.width(), maxLength), (int)containment()->size().height()));
 
771
            containment()->setMinimumSize(QSize(minLength, (int)containment()->minimumSize().height()));
 
772
            containment()->setMaximumSize(QSize(maxLength, (int)containment()->maximumSize().height()));
 
773
            break;
 
774
    }
 
775
 
 
776
    emit offsetChanged(offset);
 
777
}
 
778
 
 
779
void PanelController::alignToggled(bool toggle)
 
780
{
 
781
    if (!toggle) {
 
782
        return;
 
783
    }
 
784
 
 
785
    if (sender() == m_leftAlignTool) {
 
786
        emit alignmentChanged(Qt::AlignLeft);
 
787
        m_ruler->setAlignment(Qt::AlignLeft);
 
788
    } else if (sender() == m_centerAlignTool) {
 
789
        emit alignmentChanged(Qt::AlignCenter);
 
790
        m_ruler->setAlignment(Qt::AlignCenter);
 
791
    } else if (sender() == m_rightAlignTool) {
 
792
        emit alignmentChanged(Qt::AlignRight);
 
793
        m_ruler->setAlignment(Qt::AlignRight);
 
794
    }
 
795
 
 
796
    emit offsetChanged(0);
 
797
    m_ruler->setOffset(0);
 
798
}
 
799
 
 
800
void PanelController::panelVisibilityModeChanged(bool toggle)
 
801
{
 
802
    if (!toggle) {
 
803
        return;
 
804
    }
 
805
 
 
806
    if (sender() == m_normalPanelTool) {
 
807
        emit panelVisibilityModeChanged(PanelView::NormalPanel);
 
808
    } else if (sender() == m_autoHideTool) {
 
809
        emit panelVisibilityModeChanged(PanelView::AutoHide);
 
810
    } else if (sender() == m_underWindowsTool) {
 
811
        emit panelVisibilityModeChanged(PanelView::LetWindowsCover);
 
812
    } else if (sender() == m_overWindowsTool) {
 
813
        emit panelVisibilityModeChanged(PanelView::WindowsGoBelow);
 
814
    }
 
815
}
 
816
 
 
817
void PanelController::settingsPopup()
 
818
{
 
819
    if (m_optionsDialog->isVisible()) {
 
820
        m_optionsDialog->hide();
 
821
    } else {
 
822
        KWindowSystem::setState(m_optionsDialog->winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
 
823
        QPoint pos = mapToGlobal(m_settingsTool->pos());
 
824
        m_optionsDialog->layout()->activate();
 
825
        m_optionsDialog->resize(m_optionsDialog->sizeHint());
 
826
        QSize s = m_optionsDialog->size();
 
827
 
 
828
        switch (location()) {
 
829
            case Plasma::BottomEdge:
 
830
                pos = QPoint(pos.x(), pos.y() - s.height());
 
831
                break;
 
832
            case Plasma::TopEdge:
 
833
                pos = QPoint(pos.x(), pos.y() + m_settingsTool->size().height());
 
834
                break;
 
835
            case Plasma::LeftEdge:
 
836
                pos = QPoint(pos.x() + m_settingsTool->size().width(), pos.y());
 
837
                break;
 
838
            case Plasma::RightEdge:
 
839
                pos = QPoint(pos.x() - s.width(), pos.y());
 
840
                break;
 
841
            default:
 
842
                if (pos.y() - s.height() > 0) {
 
843
                    pos = QPoint(pos.x(), pos.y() - s.height());
 
844
                } else {
 
845
                    pos = QPoint(pos.x(), pos.y() + m_settingsTool->size().height());
 
846
                }
 
847
        }
 
848
 
 
849
        const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
 
850
 
 
851
        if (pos.rx() + s.width() > screenGeom.right()) {
 
852
            pos.rx() -= ((pos.rx() + s.width()) - screenGeom.right());
 
853
        }
 
854
 
 
855
        if (pos.ry() + s.height() > screenGeom.bottom()) {
 
856
            pos.ry() -= ((pos.ry() + s.height()) - screenGeom.bottom());
 
857
        }
 
858
 
 
859
        pos.rx() = qMax(0, pos.rx());
 
860
        m_optionsDialog->move(pos);
 
861
        m_optionsDialog->show();
 
862
    }
 
863
}
 
864
 
 
865
void PanelController::syncRuler()
 
866
{
 
867
    const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
 
868
 
 
869
    switch (location()) {
 
870
        case Plasma::LeftEdge:
 
871
        case Plasma::RightEdge:
 
872
            m_ruler->setAvailableLength(screenGeom.height());
 
873
            m_ruler->setMaxLength(qMin((int)containment()->maximumSize().height(), screenGeom.height()));
 
874
            m_ruler->setMinLength(containment()->minimumSize().height());
 
875
            break;
 
876
        case Plasma::TopEdge:
 
877
        case Plasma::BottomEdge:
 
878
        default:
 
879
            m_ruler->setAvailableLength(screenGeom.width());
 
880
            m_ruler->setMaxLength(qMin((int)containment()->maximumSize().width(), screenGeom.width()));
 
881
            m_ruler->setMinLength(containment()->minimumSize().width());
 
882
            break;
 
883
    }
 
884
}
 
885
 
 
886
void PanelController::resizeEvent(QResizeEvent *event)
 
887
{
 
888
    bool showText = true;
 
889
 
 
890
    switch (location()) {
 
891
        case Plasma::LeftEdge:
 
892
        case Plasma::RightEdge:
 
893
            showText = true;
 
894
            break;
 
895
        case Plasma::TopEdge:
 
896
        case Plasma::BottomEdge:
 
897
        default: {
 
898
            const int screen = containment()->screen();
 
899
            const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
 
900
            QRegion availGeom(screenGeom);
 
901
            if (m_extLayout->sizeHint().width() > screenGeom.width()) {
 
902
                showText = false;
 
903
            }
 
904
            break;
 
905
        }
 
906
    }
 
907
 
 
908
    //FIXME: better (and faster) way to do that?
 
909
    for (int i=0; i < m_layout->count(); ++i) {
 
910
        ToolButton *button = qobject_cast<ToolButton *>(m_layout->itemAt(i)->widget());
 
911
        if(button)
 
912
        if (button) {
 
913
            if (showText && button != m_closeControllerTool) {
 
914
                button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
 
915
            } else {
 
916
                button->setToolButtonStyle(Qt::ToolButtonIconOnly);
 
917
            }
 
918
        }
 
919
    }
 
920
 
 
921
    ControllerWindow::resizeEvent(event);
 
922
}
 
923
 
 
924
void PanelController::maximizePanel()
 
925
{
 
926
    const int length = m_ruler->availableLength();
 
927
    const int screen = containment()->screen();
 
928
    const QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
 
929
    QRegion availGeom(screenGeom);
 
930
    foreach (PanelView *view, PlasmaApp::self()->panelViews()) {
 
931
        if (view->containment() != containment() &&
 
932
            view->screen() == screen && view->visibilityMode() == PanelView::NormalPanel) {
 
933
            availGeom = availGeom.subtracted(view->geometry());
 
934
        }
 
935
    }
 
936
    int offset = 0;
 
937
    const int w = containment()->size().width();
 
938
    const int h = containment()->size().height();
 
939
 
 
940
    switch (location()) {
 
941
        case Plasma::LeftEdge: {
 
942
            QRect r = availGeom.intersected(QRect(0, 0, w, length)).boundingRect();
 
943
            offset = r.top();
 
944
        }
 
945
        break;
 
946
 
 
947
        case Plasma::RightEdge: {
 
948
            QRect r = availGeom.intersected(QRect(screenGeom.right() - w, 0, w, length)).boundingRect();
 
949
            offset = r.top();
 
950
        }
 
951
        break;
 
952
 
 
953
        case Plasma::TopEdge: {
 
954
            QRect r = availGeom.intersected(QRect(0, 0, length, h)).boundingRect();
 
955
            offset = r.left();
 
956
        }
 
957
        break;
 
958
 
 
959
        case Plasma::BottomEdge:
 
960
        default: {
 
961
            QRect r = availGeom.intersected(QRect(0, screenGeom.bottom() - h, length, h)).boundingRect();
 
962
            offset = r.left();
 
963
        }
 
964
        break;
 
965
    }
 
966
 
 
967
    rulersMoved(offset, length, length);
 
968
    m_ruler->setMaxLength(length);
 
969
    m_ruler->setMinLength(length);
 
970
}
 
971
 
 
972
void PanelController::addSpace()
 
973
{
 
974
    Plasma::Applet *spacer = containment()->addApplet("panelspacer_internal");
 
975
    if (spacer) {
 
976
        QMetaObject::invokeMethod(spacer, "updateConfigurationMode", Q_ARG(bool, true));
 
977
    }
 
978
}
 
979
 
 
980
#include "panelcontroller.moc"