1
/********************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
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.
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.
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
*********************************************************************/
22
#include "tabboxview.h"
24
#include "clientitemdelegate.h"
25
#include "clientmodel.h"
26
#include "desktopitemdelegate.h"
27
#include "desktopmodel.h"
28
#include "tabboxconfig.h"
29
#include "tabboxhandler.h"
32
#include <QTextStream>
33
#include <QGridLayout>
34
#include <QHeaderView>
36
#include <QSizePolicy>
38
#include <QPropertyAnimation>
41
#include <kephal/screens.h>
42
#include <Plasma/FrameSvg>
44
#include <KDE/Plasma/Theme>
45
#include <KDE/Plasma/WindowEffects>
52
TabBoxView::TabBoxView(QWidget* parent)
54
, m_previewUpdate(false)
56
setWindowFlags(Qt::X11BypassWindowManagerHint);
57
setAttribute(Qt::WA_TranslucentBackground);
58
QPalette pal = palette();
59
pal.setColor(backgroundRole(), Qt::transparent);
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);
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);
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);
83
m_animation = new QPropertyAnimation(this, "selectedItem", this);
84
m_animation->setDuration(250);
85
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
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)));
92
TabBoxView::~TabBoxView()
96
void TabBoxView::paintEvent(QPaintEvent* e)
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());
108
m_selectionFrame->paintFrame(&painter,
109
m_tableView->geometry().topLeft() + m_selectedItem.topLeft());
110
QWidget::paintEvent(e);
113
bool TabBoxView::event(QEvent* event)
115
if (event->type() == QEvent::Paint) {
117
p.setCompositionMode(QPainter::CompositionMode_Source);
118
p.fillRect(rect(), Qt::transparent);
120
return QWidget::event(event);
123
void TabBoxView::resizeEvent(QResizeEvent* event)
125
m_frame->resizeFrame(event->size());
126
if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
128
Plasma::WindowEffects::enableBlurBehind(winId(), true, m_frame->mask());
129
Plasma::WindowEffects::overrideShadow(winId(), true);
131
// do not trim to mask with compositing enabled, otherwise shadows are cropped
132
setMask(m_frame->mask());
134
QWidget::resizeEvent(event);
137
void TabBoxView::updateGeometry()
139
if (m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 0)
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;
146
setGeometry(x, y, hint.width(), hint.height());
149
QSize TabBoxView::sizeHint() const
151
if (m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 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);
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());
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;
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);
182
height = height + additionalSize.height();
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));
195
QRect screenRect = Kephal::ScreenUtils::screenGeometry(tabBox->activeScreen());
196
width = qBound(screenRect.width() * tabBox->config().minWidth() / 100, 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();
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);
209
void TabBoxView::setCurrentIndex(QModelIndex index)
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) {
218
m_selectedItem = visualRect;
221
m_animation->setStartValue(m_selectedItem);
222
m_animation->setEndValue(visualRect);
223
m_animation->start();
225
m_selectionFrame->resizeFrame(visualRect.size());
226
m_additionalView->setCurrentIndex(index);
230
void TabBoxView::configChanged()
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);
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);
246
QLayout* old = layout();
248
while (old && (child = old->takeAt(0)) != 0) {
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();
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();
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();
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();
319
layout = new QVBoxLayout();
320
layout->addStretch();
321
layout->addWidget(m_tableView);
322
layout->addStretch();
323
m_additionalView->hide();
329
m_previewUpdate = true;
332
QModelIndex TabBoxView::indexAt(QPoint pos)
334
return m_tableView->indexAt(m_tableView->mapFromParent(pos));
337
void TabBoxView::setPreview(bool preview)
341
m_frame->setImagePath("dialogs/opaque/background");
344
/********************************************************
346
********************************************************/
348
TabBoxMainView::TabBoxMainView(QWidget* parent)
351
setFrameStyle(QFrame::NoFrame);
352
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
353
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
354
viewport()->setAutoFillBackground(false);
356
// adjust table view to needs of tabbox
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);
367
TabBoxMainView::~TabBoxMainView()
371
QSize TabBoxMainView::sizeHint() const
374
int minWidth = sizeHintForColumn(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));
381
for (int i = 0; i < model()->rowCount(); i++) {
382
minHeight = qMin(minHeight, sizeHintForRow(i));
383
maxHeight = qMax(maxHeight, sizeHintForRow(i));
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());
391
QModelIndex TabBoxMainView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
393
Q_UNUSED(cursorAction)
395
return currentIndex();
398
/********************************************************
399
* TabBoxAdditonalView
400
********************************************************/
402
TabBoxAdditionalView::TabBoxAdditionalView(QWidget* parent)
405
setFrameStyle(QFrame::NoFrame);
406
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
407
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
408
viewport()->setAutoFillBackground(false);
410
// adjust table view to needs of tabbox
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);
421
TabBoxAdditionalView::~TabBoxAdditionalView()
425
QSize TabBoxAdditionalView::sizeHint() const
428
int minWidth = sizeHintForColumn(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));
435
for (int i = 0; i < model()->rowCount(); i++) {
436
minHeight = qMin(minHeight, sizeHintForRow(i));
437
maxHeight = qMax(maxHeight, sizeHintForRow(i));
439
qreal columnWidth = (minWidth + qreal(maxWidth - minWidth) / 2.0);
440
qreal rowHeight = (minHeight + qreal(maxHeight - minHeight) / 2.0);
441
return QSize(columnWidth, rowHeight);
444
QModelIndex TabBoxAdditionalView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
446
Q_UNUSED(cursorAction)
448
return currentIndex();
451
void TabBoxAdditionalView::wheelEvent(QWheelEvent* event)
456
} // namespace Tabbox
459
#include "tabboxview.moc"