1
/********************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
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
*********************************************************************/
21
#include "declarative.h"
22
#include "tabboxhandler.h"
23
#include "clientmodel.h"
25
#include <QtDeclarative/qdeclarative.h>
26
#include <QtDeclarative/QDeclarativeContext>
27
#include <QtDeclarative/QDeclarativeEngine>
28
#include <QtGui/QGraphicsObject>
29
#include <QtGui/QResizeEvent>
32
#include <KDE/KIconEffect>
33
#include <KDE/KIconLoader>
34
#include <KDE/KStandardDirs>
35
#include <KDE/Plasma/FrameSvg>
36
#include <KDE/Plasma/Theme>
37
#include <KDE/Plasma/WindowEffects>
38
#include <kdeclarative.h>
39
#include <kephal/screens.h>
41
#include "thumbnailitem.h"
48
ImageProvider::ImageProvider(QAbstractItemModel *model)
49
: QDeclarativeImageProvider(QDeclarativeImageProvider::Pixmap)
54
QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
57
QStringList parts = id.split('/');
58
const int row = parts.first().toInt(&ok);
60
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
62
const QModelIndex index = m_model->index(row, 0);
63
if (!index.isValid()) {
64
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
66
if (index.model()->data(index, ClientModel::EmptyRole).toBool()) {
67
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
69
TabBoxClient* client = static_cast< TabBoxClient* >(index.model()->data(index, ClientModel::ClientRole).value<void *>());
71
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
75
if (requestedSize.isValid()) {
79
QPixmap icon = client->icon(s);
80
if (s.width() > icon.width() || s.height() > icon.height()) {
81
// icon is smaller than what we requested - QML would scale it which looks bad
83
temp.fill(Qt::transparent);
85
p.drawPixmap(s.width()/2 - icon.width()/2, s.height()/2 - icon.height()/2, icon);
88
if (parts.size() > 2) {
89
KIconEffect *effect = KIconLoader::global()->iconEffect();
90
KIconLoader::States state = KIconLoader::DefaultState;
91
if (parts.at(2) == QLatin1String("selected")) {
92
state = KIconLoader::ActiveState;
93
} else if (parts.at(2) == QLatin1String("disabled")) {
94
state = KIconLoader::DisabledState;
96
icon = effect->apply(icon, KIconLoader::Desktop, state);
101
DeclarativeView::DeclarativeView(QAbstractItemModel *model, QWidget *parent)
102
: QDeclarativeView(parent)
104
, m_currentScreenGeometry()
105
, m_frame(new Plasma::FrameSvg(this))
108
setAttribute(Qt::WA_TranslucentBackground);
109
setWindowFlags(Qt::X11BypassWindowManagerHint);
110
setResizeMode(QDeclarativeView::SizeViewToRootObject);
111
QPalette pal = palette();
112
pal.setColor(backgroundRole(), Qt::transparent);
114
foreach (const QString &importPath, KGlobal::dirs()->findDirs("module", "imports")) {
115
engine()->addImportPath(importPath);
117
engine()->addImageProvider(QLatin1String("client"), new ImageProvider(model));
118
KDeclarative kdeclarative;
119
kdeclarative.setDeclarativeEngine(engine());
120
kdeclarative.initialize();
121
kdeclarative.setupBindings();
122
qmlRegisterType<ThumbnailItem>("org.kde.kwin", 0, 1, "ThumbnailItem");
123
rootContext()->setContextProperty("viewId", static_cast<qulonglong>(winId()));
124
rootContext()->setContextProperty("clientModel", model);
125
setSource(QUrl(KStandardDirs::locate("data", "kwin/tabbox/tabbox.qml")));
128
m_frame->setImagePath("dialogs/background");
129
m_frame->setCacheAllRenderedFrames(true);
130
m_frame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
132
connect(tabBox, SIGNAL(configChanged()), SLOT(updateQmlSource()));
135
void DeclarativeView::showEvent(QShowEvent *event)
138
m_currentScreenGeometry = Kephal::ScreenUtils::screenGeometry(tabBox->activeScreen());
139
rootObject()->setProperty("screenWidth", m_currentScreenGeometry.width());
140
rootObject()->setProperty("screenHeight", m_currentScreenGeometry.height());
141
rootObject()->setProperty("allDesktops", tabBox->config().tabBoxMode() == TabBoxConfig::ClientTabBox &&
142
((tabBox->config().clientListMode() == TabBoxConfig::AllDesktopsClientList) ||
143
(tabBox->config().clientListMode() == TabBoxConfig::AllDesktopsApplicationList)));
144
rootObject()->setProperty("longestCaption", static_cast<ClientModel*>(m_model)->longestCaption());
146
if (QObject *item = rootObject()->findChild<QObject*>("listView")) {
147
item->setProperty("currentIndex", tabBox->first().row());
148
connect(item, SIGNAL(currentIndexChanged(int)), SLOT(currentIndexChanged(int)));
150
slotUpdateGeometry();
151
QGraphicsView::showEvent(event);
154
void DeclarativeView::resizeEvent(QResizeEvent *event)
156
m_frame->resizeFrame(event->size());
157
if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
159
Plasma::WindowEffects::enableBlurBehind(winId(), true, m_frame->mask());
160
Plasma::WindowEffects::overrideShadow(winId(), true);
162
// do not trim to mask with compositing enabled, otherwise shadows are cropped
163
setMask(m_frame->mask());
165
QDeclarativeView::resizeEvent(event);
168
void DeclarativeView::slotUpdateGeometry()
170
const int width = rootObject()->property("width").toInt();
171
const int height = rootObject()->property("height").toInt();
172
setGeometry(m_currentScreenGeometry.x() + static_cast<qreal>(m_currentScreenGeometry.width()) * 0.5 - static_cast<qreal>(width) * 0.5,
173
m_currentScreenGeometry.y() + static_cast<qreal>(m_currentScreenGeometry.height()) * 0.5 - static_cast<qreal>(height) * 0.5,
177
void DeclarativeView::setCurrentIndex(const QModelIndex &index, bool disableAnimation)
179
if (QObject *item = rootObject()->findChild<QObject*>("listView")) {
180
QVariant durationRestore;
181
if (disableAnimation) {
182
durationRestore = item->property("highlightMoveDuration");
183
item->setProperty("highlightMoveDuration", QVariant(1));
185
item->setProperty("currentIndex", index.row());
186
if (disableAnimation) {
187
item->setProperty("highlightMoveDuration", durationRestore);
192
QModelIndex DeclarativeView::indexAt(const QPoint &pos) const
194
if (QObject *item = rootObject()->findChild<QObject*>("listView")) {
195
QVariant returnedValue;
196
QVariant xPos(pos.x());
197
QVariant yPos(pos.y());
198
QMetaObject::invokeMethod(item, "indexAtMousePos", Q_RETURN_ARG(QVariant, returnedValue), Q_ARG(QVariant, QVariant(pos)));
199
if (!returnedValue.canConvert<int>()) {
200
return QModelIndex();
202
return m_model->index(returnedValue.toInt(), 0);
204
return QModelIndex();
207
void DeclarativeView::currentIndexChanged(int row)
209
tabBox->setCurrentIndex(m_model->index(row, 0));
212
void DeclarativeView::updateQmlSource()
214
if (tabBox->config().layoutName() == m_currentLayout) {
217
m_currentLayout = tabBox->config().layoutName();
218
QString file = KStandardDirs::locate("data", "kwin/tabbox/" + m_currentLayout.toLower().replace(' ', '_') + ".qml");
220
// fallback to default
221
file = KStandardDirs::locate("data", "kwin/tabbox/informative.qml");
223
rootObject()->setProperty("source", QUrl(file));
226
} // namespace TabBox