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

« back to all changes in this revision

Viewing changes to kwin/tabbox/tabboxview.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
 KWin - the KDE window manager
 
3
 This file is part of the KDE project.
 
4
 
 
5
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or
 
10
(at your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*********************************************************************/
 
20
 
 
21
// own
 
22
#include "tabboxview.h"
 
23
// tabbox
 
24
#include "clientitemdelegate.h"
 
25
#include "clientmodel.h"
 
26
#include "desktopitemdelegate.h"
 
27
#include "desktopmodel.h"
 
28
#include "tabboxconfig.h"
 
29
#include "tabboxhandler.h"
 
30
 
 
31
// Qt
 
32
#include <QTextStream>
 
33
#include <QGridLayout>
 
34
#include <QHeaderView>
 
35
#include <QKeyEvent>
 
36
#include <QSizePolicy>
 
37
#include <QPainter>
 
38
#include <QPropertyAnimation>
 
39
 
 
40
// KDE
 
41
#include <kephal/screens.h>
 
42
#include <Plasma/FrameSvg>
 
43
#include <KDebug>
 
44
#include <KDE/Plasma/Theme>
 
45
#include <KDE/Plasma/WindowEffects>
 
46
 
 
47
namespace KWin
 
48
{
 
49
namespace TabBox
 
50
{
 
51
 
 
52
TabBoxView::TabBoxView(QWidget* parent)
 
53
    : QWidget(parent)
 
54
    , m_previewUpdate(false)
 
55
{
 
56
    setWindowFlags(Qt::X11BypassWindowManagerHint);
 
57
    setAttribute(Qt::WA_TranslucentBackground);
 
58
    QPalette pal = palette();
 
59
    pal.setColor(backgroundRole(), Qt::transparent);
 
60
    setPalette(pal);
 
61
    m_clientModel = new ClientModel(this);
 
62
    m_desktopModel = new DesktopModel(this);
 
63
    m_delegate = new ClientItemDelegate(this);
 
64
    m_additionalClientDelegate = new ClientItemDelegate(this);
 
65
    m_additionalClientDelegate->setShowSelection(false);
 
66
    m_desktopItemDelegate = new DesktopItemDelegate(this);
 
67
    m_additionalDesktopDelegate = new DesktopItemDelegate(this);
 
68
    m_tableView = new TabBoxMainView(this);
 
69
    m_additionalView = new TabBoxAdditionalView(this);
 
70
 
 
71
    // FrameSvg
 
72
    m_frame = new Plasma::FrameSvg(this);
 
73
    m_frame->setImagePath("dialogs/background");
 
74
    m_frame->setCacheAllRenderedFrames(true);
 
75
    m_frame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
76
 
 
77
    m_selectionFrame = new Plasma::FrameSvg(this);
 
78
    m_selectionFrame->setImagePath("widgets/viewitem");
 
79
    m_selectionFrame->setElementPrefix("hover");
 
80
    m_selectionFrame->setCacheAllRenderedFrames(true);
 
81
    m_selectionFrame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
82
 
 
83
    m_animation = new QPropertyAnimation(this, "selectedItem", this);
 
84
    m_animation->setDuration(250);
 
85
    m_animation->setEasingCurve(QEasingCurve::InOutQuad);
 
86
 
 
87
    connect(tabBox, SIGNAL(configChanged()), this, SLOT(configChanged()));
 
88
    connect(m_animation, SIGNAL(valueChanged(QVariant)), SLOT(update()));
 
89
    connect(m_tableView, SIGNAL(activated(QModelIndex)), SLOT(setCurrentIndex(QModelIndex)));
 
90
}
 
91
 
 
92
TabBoxView::~TabBoxView()
 
93
{
 
94
}
 
95
 
 
96
void TabBoxView::paintEvent(QPaintEvent* e)
 
97
{
 
98
    // paint the background
 
99
    QPainter painter(this);
 
100
    painter.setRenderHint(QPainter::Antialiasing);
 
101
    painter.setClipRect(e->rect());
 
102
    m_frame->paintFrame(&painter);
 
103
    // and the selection item
 
104
    if (m_previewUpdate) {
 
105
        m_previewUpdate = false;
 
106
        setCurrentIndex(m_tableView->currentIndex());
 
107
    }
 
108
    m_selectionFrame->paintFrame(&painter,
 
109
                                 m_tableView->geometry().topLeft() + m_selectedItem.topLeft());
 
110
    QWidget::paintEvent(e);
 
111
}
 
112
 
 
113
bool TabBoxView::event(QEvent* event)
 
114
{
 
115
    if (event->type() == QEvent::Paint) {
 
116
        QPainter p(this);
 
117
        p.setCompositionMode(QPainter::CompositionMode_Source);
 
118
        p.fillRect(rect(), Qt::transparent);
 
119
    }
 
120
    return QWidget::event(event);
 
121
}
 
122
 
 
123
void TabBoxView::resizeEvent(QResizeEvent* event)
 
124
{
 
125
    m_frame->resizeFrame(event->size());
 
126
    if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
 
127
        // blur background
 
128
        Plasma::WindowEffects::enableBlurBehind(winId(), true, m_frame->mask());
 
129
        Plasma::WindowEffects::overrideShadow(winId(), true);
 
130
    } else {
 
131
        // do not trim to mask with compositing enabled, otherwise shadows are cropped
 
132
        setMask(m_frame->mask());
 
133
    }
 
134
    QWidget::resizeEvent(event);
 
135
}
 
136
 
 
137
void TabBoxView::updateGeometry()
 
138
{
 
139
    if (m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 0)
 
140
        return;
 
141
    QSize hint = sizeHint();
 
142
    QRect screenRect = Kephal::ScreenUtils::screenGeometry(tabBox->activeScreen());
 
143
    int x = screenRect.x() + screenRect.width() * 0.5 - hint.width() * 0.5;
 
144
    int y = screenRect.y() + screenRect.height() * 0.5 - hint.height() * 0.5;
 
145
 
 
146
    setGeometry(x, y, hint.width(), hint.height());
 
147
}
 
148
 
 
149
QSize TabBoxView::sizeHint() const
 
150
{
 
151
    if (m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 0)
 
152
        return QSize(0, 0);
 
153
    // calculate width and height
 
154
    QSize tabBoxSize = m_tableView->sizeHint();
 
155
    qreal columnWidth = tabBoxSize.width() / m_tableView->model()->columnCount();
 
156
    qreal rowHeight = tabBoxSize.height() / m_tableView->model()->rowCount();
 
157
    for (int i = 0; i < m_tableView->model()->rowCount(); i++)
 
158
        m_tableView->setRowHeight(i, rowHeight);
 
159
 
 
160
    // additional view
 
161
    QSize additionalSize = m_additionalView->sizeHint();
 
162
    for (int i = 0; i < m_additionalView->model()->columnCount(); i++)
 
163
        m_additionalView->setColumnWidth(i, additionalSize.width());
 
164
    for (int i = 0; i < m_additionalView->model()->rowCount(); i++)
 
165
        m_additionalView->setRowHeight(i, additionalSize.height());
 
166
 
 
167
    // reserve some space for borders
 
168
    qreal top, bottom, left, right;
 
169
    m_frame->getMargins(left, top, right, bottom);
 
170
    int width = columnWidth * m_tableView->model()->columnCount() + left + right;
 
171
    int height = rowHeight * m_tableView->model()->rowCount() + top + bottom;
 
172
    qreal addedWidth = left + right;
 
173
 
 
174
    // depending on layout of additional view we have to add some width or height
 
175
    switch(tabBox->config().selectedItemViewPosition()) {
 
176
    case TabBoxConfig::AbovePosition: // fall through
 
177
    case TabBoxConfig::BelowPosition:
 
178
        if (additionalSize.width() + int(left + right) > width) {
 
179
            addedWidth += (additionalSize.width() + int(left + right) - width);
 
180
            width = additionalSize.width() + int(left + right);
 
181
        }
 
182
        height = height + additionalSize.height();
 
183
        break;
 
184
    case TabBoxConfig::LeftPosition: // fall through
 
185
    case TabBoxConfig::RightPosition:
 
186
        width = width + additionalSize.width();
 
187
        addedWidth += additionalSize.width();
 
188
        height = qMax(height, additionalSize.height() + int(top + bottom));
 
189
        break;
 
190
    default:
 
191
        // don't add
 
192
        break;
 
193
    }
 
194
 
 
195
    QRect screenRect = Kephal::ScreenUtils::screenGeometry(tabBox->activeScreen());
 
196
    width = qBound(screenRect.width() * tabBox->config().minWidth() / 100, width,
 
197
                   screenRect.width());
 
198
    height = qBound(screenRect.height() * tabBox->config().minHeight() / 100, height,
 
199
                    screenRect.height());
 
200
    if (width - addedWidth > tabBoxSize.width()) {
 
201
        columnWidth = (width - addedWidth) / m_tableView->model()->columnCount();
 
202
    }
 
203
    m_tableView->setMinimumWidth(width - addedWidth);
 
204
    for (int i = 0; i < m_tableView->model()->columnCount(); i++)
 
205
        m_tableView->setColumnWidth(i, columnWidth);
 
206
    return QSize(width, height);
 
207
}
 
208
 
 
209
void TabBoxView::setCurrentIndex(QModelIndex index)
 
210
{
 
211
    if (index.isValid()) {
 
212
        m_tableView->setCurrentIndex(index);
 
213
        const QRect visualRect = m_tableView->visualRect(index);
 
214
        if (m_selectedItem.isNull())
 
215
            m_selectedItem = visualRect;
 
216
        if (m_animation->state() == QPropertyAnimation::Running) {
 
217
            m_animation->stop();
 
218
            m_selectedItem = visualRect;
 
219
            update();
 
220
        } else {
 
221
            m_animation->setStartValue(m_selectedItem);
 
222
            m_animation->setEndValue(visualRect);
 
223
            m_animation->start();
 
224
        }
 
225
        m_selectionFrame->resizeFrame(visualRect.size());
 
226
        m_additionalView->setCurrentIndex(index);
 
227
    }
 
228
}
 
229
 
 
230
void TabBoxView::configChanged()
 
231
{
 
232
    switch(tabBox->config().tabBoxMode()) {
 
233
    case TabBoxConfig::ClientTabBox:
 
234
        m_tableView->setModel(m_clientModel);
 
235
        m_tableView->setItemDelegate(m_delegate);
 
236
        m_additionalView->setModel(m_clientModel);
 
237
        m_additionalView->setItemDelegate(m_additionalClientDelegate);
 
238
        break;
 
239
    case TabBoxConfig::DesktopTabBox:
 
240
        m_tableView->setModel(m_desktopModel);
 
241
        m_tableView->setItemDelegate(m_desktopItemDelegate);
 
242
        m_additionalView->setModel(m_desktopModel);
 
243
        m_additionalView->setItemDelegate(m_additionalDesktopDelegate);
 
244
        break;
 
245
    }
 
246
    QLayout* old = layout();
 
247
    QLayoutItem *child;
 
248
    while (old && (child = old->takeAt(0)) != 0) {
 
249
        delete child;
 
250
    }
 
251
    delete old;
 
252
    QBoxLayout *layout;
 
253
    switch(tabBox->config().selectedItemViewPosition()) {
 
254
    case TabBoxConfig::AbovePosition: {
 
255
        layout = new QVBoxLayout();
 
256
        QHBoxLayout* horizontalLayout1 = new QHBoxLayout();
 
257
        horizontalLayout1->addStretch();
 
258
        horizontalLayout1->addWidget(m_additionalView);
 
259
        horizontalLayout1->addStretch();
 
260
        layout->addLayout(horizontalLayout1);
 
261
        layout->addStretch();
 
262
        QHBoxLayout* horizontalLayout2 = new QHBoxLayout();
 
263
        horizontalLayout2->addStretch();
 
264
        horizontalLayout2->addWidget(m_tableView);
 
265
        horizontalLayout2->addStretch();
 
266
        layout->addLayout(horizontalLayout2);
 
267
        m_additionalView->show();
 
268
        break;
 
269
    }
 
270
    case TabBoxConfig::BelowPosition: {
 
271
        layout = new QVBoxLayout();
 
272
        QHBoxLayout* horizontalLayout1 = new QHBoxLayout();
 
273
        horizontalLayout1->addStretch();
 
274
        horizontalLayout1->addWidget(m_tableView);
 
275
        horizontalLayout1->addStretch();
 
276
        layout->addLayout(horizontalLayout1);
 
277
        layout->addStretch();
 
278
        QHBoxLayout* horizontalLayout2 = new QHBoxLayout();
 
279
        horizontalLayout2->addStretch();
 
280
        horizontalLayout2->addWidget(m_additionalView);
 
281
        horizontalLayout2->addStretch();
 
282
        layout->addLayout(horizontalLayout2);
 
283
        m_additionalView->show();
 
284
        break;
 
285
    }
 
286
    case TabBoxConfig::LeftPosition: {
 
287
        layout = new QHBoxLayout();
 
288
        QVBoxLayout* verticalLayout1 = new QVBoxLayout();
 
289
        verticalLayout1->addStretch();
 
290
        verticalLayout1->addWidget(m_additionalView);
 
291
        verticalLayout1->addStretch();
 
292
        layout->addLayout(verticalLayout1);
 
293
        layout->addStretch();
 
294
        QVBoxLayout* verticalLayout2 = new QVBoxLayout();
 
295
        verticalLayout2->addStretch();
 
296
        verticalLayout2->addWidget(m_tableView);
 
297
        verticalLayout2->addStretch();
 
298
        layout->addLayout(verticalLayout2);
 
299
        m_additionalView->show();
 
300
        break;
 
301
    }
 
302
    case TabBoxConfig::RightPosition: {
 
303
        layout = new QHBoxLayout();
 
304
        QVBoxLayout* verticalLayout1 = new QVBoxLayout();
 
305
        verticalLayout1->addStretch();
 
306
        verticalLayout1->addWidget(m_tableView);
 
307
        verticalLayout1->addStretch();
 
308
        layout->addLayout(verticalLayout1);
 
309
        layout->addStretch();
 
310
        QVBoxLayout* verticalLayout2 = new QVBoxLayout();
 
311
        verticalLayout2->addStretch();
 
312
        verticalLayout2->addWidget(m_additionalView);
 
313
        verticalLayout2->addStretch();
 
314
        layout->addLayout(verticalLayout2);
 
315
        m_additionalView->show();
 
316
        break;
 
317
    }
 
318
    default: {
 
319
        layout = new QVBoxLayout();
 
320
        layout->addStretch();
 
321
        layout->addWidget(m_tableView);
 
322
        layout->addStretch();
 
323
        m_additionalView->hide();
 
324
        break;
 
325
    }
 
326
    }
 
327
    setLayout(layout);
 
328
    if (m_preview)
 
329
        m_previewUpdate = true;
 
330
}
 
331
 
 
332
QModelIndex TabBoxView::indexAt(QPoint pos)
 
333
{
 
334
    return m_tableView->indexAt(m_tableView->mapFromParent(pos));
 
335
}
 
336
 
 
337
void TabBoxView::setPreview(bool preview)
 
338
{
 
339
    m_preview = preview;
 
340
    if (preview)
 
341
        m_frame->setImagePath("dialogs/opaque/background");
 
342
}
 
343
 
 
344
/********************************************************
 
345
* TabBoxMainView
 
346
********************************************************/
 
347
 
 
348
TabBoxMainView::TabBoxMainView(QWidget* parent)
 
349
    : QTableView(parent)
 
350
{
 
351
    setFrameStyle(QFrame::NoFrame);
 
352
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
353
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
354
    viewport()->setAutoFillBackground(false);
 
355
 
 
356
    // adjust table view to needs of tabbox
 
357
    setShowGrid(false);
 
358
    horizontalHeader()->hide();
 
359
    verticalHeader()->hide();
 
360
    setSelectionMode(QAbstractItemView::SingleSelection);
 
361
    setSelectionBehavior(QAbstractItemView::SelectItems);
 
362
    setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
 
363
    setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
 
364
    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
 
365
}
 
366
 
 
367
TabBoxMainView::~TabBoxMainView()
 
368
{
 
369
}
 
370
 
 
371
QSize TabBoxMainView::sizeHint() const
 
372
{
 
373
    int maxWidth = 0;
 
374
    int minWidth = sizeHintForColumn(0);
 
375
    int maxHeight = 0;
 
376
    int minHeight = sizeHintForRow(0);
 
377
    for (int i = 0; i < model()->columnCount(); i++) {
 
378
        minWidth = qMin(minWidth, sizeHintForColumn(i));
 
379
        maxWidth = qMax(maxWidth, sizeHintForColumn(i));
 
380
    }
 
381
    for (int i = 0; i < model()->rowCount(); i++) {
 
382
        minHeight = qMin(minHeight, sizeHintForRow(i));
 
383
        maxHeight = qMax(maxHeight, sizeHintForRow(i));
 
384
    }
 
385
    qreal columnWidth = (minWidth + qreal(maxWidth - minWidth) / 2.0);
 
386
    qreal rowHeight = (minHeight + qreal(maxHeight - minHeight) / 2.0);
 
387
    return QSize(columnWidth * model()->columnCount(),
 
388
                 rowHeight * model()->rowCount());
 
389
}
 
390
 
 
391
QModelIndex TabBoxMainView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
 
392
{
 
393
    Q_UNUSED(cursorAction)
 
394
    Q_UNUSED(modifiers)
 
395
    return currentIndex();
 
396
}
 
397
 
 
398
/********************************************************
 
399
* TabBoxAdditonalView
 
400
********************************************************/
 
401
 
 
402
TabBoxAdditionalView::TabBoxAdditionalView(QWidget* parent)
 
403
    : QTableView(parent)
 
404
{
 
405
    setFrameStyle(QFrame::NoFrame);
 
406
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
407
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
408
    viewport()->setAutoFillBackground(false);
 
409
 
 
410
    // adjust table view to needs of tabbox
 
411
    setShowGrid(false);
 
412
    horizontalHeader()->hide();
 
413
    verticalHeader()->hide();
 
414
    setSelectionMode(QAbstractItemView::SingleSelection);
 
415
    setSelectionBehavior(QAbstractItemView::SelectItems);
 
416
    setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
 
417
    setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
 
418
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 
419
}
 
420
 
 
421
TabBoxAdditionalView::~TabBoxAdditionalView()
 
422
{
 
423
}
 
424
 
 
425
QSize TabBoxAdditionalView::sizeHint() const
 
426
{
 
427
    int maxWidth = 0;
 
428
    int minWidth = sizeHintForColumn(0);
 
429
    int maxHeight = 0;
 
430
    int minHeight = sizeHintForRow(0);
 
431
    for (int i = 0; i < model()->columnCount(); i++) {
 
432
        minWidth = qMin(minWidth, sizeHintForColumn(i));
 
433
        maxWidth = qMax(maxWidth, sizeHintForColumn(i));
 
434
    }
 
435
    for (int i = 0; i < model()->rowCount(); i++) {
 
436
        minHeight = qMin(minHeight, sizeHintForRow(i));
 
437
        maxHeight = qMax(maxHeight, sizeHintForRow(i));
 
438
    }
 
439
    qreal columnWidth = (minWidth + qreal(maxWidth - minWidth) / 2.0);
 
440
    qreal rowHeight = (minHeight + qreal(maxHeight - minHeight) / 2.0);
 
441
    return QSize(columnWidth, rowHeight);
 
442
}
 
443
 
 
444
QModelIndex TabBoxAdditionalView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
 
445
{
 
446
    Q_UNUSED(cursorAction)
 
447
    Q_UNUSED(modifiers)
 
448
    return currentIndex();
 
449
}
 
450
 
 
451
void TabBoxAdditionalView::wheelEvent(QWheelEvent* event)
 
452
{
 
453
    Q_UNUSED(event)
 
454
}
 
455
 
 
456
} // namespace Tabbox
 
457
} // namespace KWin
 
458
 
 
459
#include "tabboxview.moc"