1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*********************************************************************/
20
21#include "thumbnailitem.h"
22// KWin
23#include "client.h"
24#include "composite.h"
25#include "effects.h"
26#include "workspace.h"
27#include "composite.h"
28// Qt
29#include <QtDeclarative/QDeclarativeContext>
30#include <QtDeclarative/QDeclarativeEngine>
31#include <QtDeclarative/QDeclarativeView>
32// KDE
33#include <KDE/KDebug>
34
35namespace KWin
36{
37
38AbstractThumbnailItem::AbstractThumbnailItem(QDeclarativeItem *parent)
39 : QDeclarativeItem(parent)
40 , m_clip(true)
41 , m_parent(QWeakPointer<EffectWindowImpl>())
42 , m_parentWindow(0)
43 , m_brightness(1.0)
44 , m_saturation(1.0)
45{
46 setFlags(flags() & ~QGraphicsItem::ItemHasNoContents);
47 Q_ASSERT(Compositor::isCreated());
48 connect(Compositor::self(), SIGNAL(compositingToggled(bool)), SLOT(compositingToggled()));
49 compositingToggled();
50 QTimer::singleShot(0, this, SLOT(init()));
51}
52
53AbstractThumbnailItem::~AbstractThumbnailItem()
54{
55}
56
57void AbstractThumbnailItem::compositingToggled()
58{
59 m_parent.clear();
60 if (effects) {
61 connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), SLOT(effectWindowAdded()));
62 connect(effects, SIGNAL(windowDamaged(KWin::EffectWindow*,QRect)), SLOT(repaint(KWin::EffectWindow*)));
63 effectWindowAdded();
64 }
65}
66
67void AbstractThumbnailItem::init()
68{
69 findParentEffectWindow();
70 if (!m_parent.isNull()) {
71 m_parent.data()->registerThumbnail(this);
72 }
73}
74
75void AbstractThumbnailItem::setParentWindow(qulonglong parentWindow)
76{
77 m_parentWindow = parentWindow;
78 findParentEffectWindow();
79 if (!m_parent.isNull()) {
80 m_parent.data()->registerThumbnail(this);
81 }
82}
83
84void AbstractThumbnailItem::findParentEffectWindow()
85{
86 if (effects) {
87 if (m_parentWindow) {
88 if (EffectWindowImpl *w = static_cast<EffectWindowImpl*>(effects->findWindow(m_parentWindow))) {
89 m_parent = QWeakPointer<EffectWindowImpl>(w);
90 return;
91 }
92 }
93 QDeclarativeContext *ctx = QDeclarativeEngine::contextForObject(this);
94 if (!ctx) {
95 kDebug(1212) << "No Context";
96 return;
97 }
98 const QVariant variant = ctx->engine()->rootContext()->contextProperty("viewId");
99 if (!variant.isValid()) {
100 kDebug(1212) << "Required context property 'viewId' not found";
101 return;
102 }
103 if (EffectWindowImpl *w = static_cast<EffectWindowImpl*>(effects->findWindow(variant.value<qulonglong>()))) {
104 m_parent = QWeakPointer<EffectWindowImpl>(w);
105 m_parentWindow = variant.value<qulonglong>();
106 }
107 }
108}
109
110void AbstractThumbnailItem::setClip(bool clip)
111{
112 m_clip = clip;
113 emit clipChanged(clip);
114}
115
116void AbstractThumbnailItem::effectWindowAdded()
117{
118 // the window might be added before the EffectWindow is created
119 // by using this slot we can register the thumbnail when it is finally created
120 if (m_parent.isNull()) {
121 findParentEffectWindow();
122 if (!m_parent.isNull()) {
123 m_parent.data()->registerThumbnail(this);
124 }
125 }
126}
127
128void AbstractThumbnailItem::setBrightness(qreal brightness)
129{
130 if (qFuzzyCompare(brightness, m_brightness)) {
131 return;
132 }
133 m_brightness = brightness;
134 update();
135 emit brightnessChanged();
136}
137
138void AbstractThumbnailItem::setSaturation(qreal saturation)
139{
140 if (qFuzzyCompare(saturation, m_saturation)) {
141 return;
142 }
143 m_saturation = saturation;
144 update();
145 emit saturationChanged();
146}
147
148
149WindowThumbnailItem::WindowThumbnailItem(QDeclarativeItem* parent)
150 : AbstractThumbnailItem(parent)
151 , m_wId(0)
152 , m_client(NULL)
153{
154}
155
156WindowThumbnailItem::~WindowThumbnailItem()
157{
158}
159
160void WindowThumbnailItem::setWId(qulonglong wId)
161{
162 if (m_wId == wId) {
163 return;
164 }
165 m_wId = wId;
166 if (m_wId != 0) {
167 setClient(Workspace::self()->findClient(WindowMatchPredicate(m_wId)));
168 } else if (m_client) {
169 m_client = NULL;
170 emit clientChanged();
171 }
172 emit wIdChanged(wId);
173}
174
175void WindowThumbnailItem::setClient(Client *client)
176{
177 if (m_client == client) {
178 return;
179 }
180 m_client = client;
181 if (m_client) {
182 setWId(m_client->window());
183 } else {
184 setWId(0);
185 }
186 emit clientChanged();
187}
188
189void WindowThumbnailItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
190{
191 if (effects) {
192 QDeclarativeItem::paint(painter, option, widget);
193 return;
194 }
195 Client *client = Workspace::self()->findClient(WindowMatchPredicate(m_wId));
196 if (!client) {
197 QDeclarativeItem::paint(painter, option, widget);
198 return;
199 }
200 QPixmap pixmap = client->icon(boundingRect().size().toSize());
201 const QSize size(boundingRect().size().toSize() - pixmap.size());
202 painter->drawPixmap(boundingRect().adjusted(size.width()/2.0, size.height()/2.0, -size.width()/2.0, -size.height()/2.0).toRect(),
203 pixmap);
204}
205
206void WindowThumbnailItem::repaint(KWin::EffectWindow *w)
207{
208 if (static_cast<KWin::EffectWindowImpl*>(w)->window()->window() == m_wId) {
209 update();
210 }
211}
212
213DesktopThumbnailItem::DesktopThumbnailItem(QDeclarativeItem *parent)
214 : AbstractThumbnailItem(parent)
215 , m_desktop(0)
216{
217}
218
219DesktopThumbnailItem::~DesktopThumbnailItem()
220{
221}
222
223void DesktopThumbnailItem::setDesktop(int desktop)
224{
225 desktop = qBound<int>(1, desktop, VirtualDesktopManager::self()->count());
226 if (desktop == m_desktop) {
227 return;
228 }
229 m_desktop = desktop;
230 update();
231 emit desktopChanged(m_desktop);
232}
233
234void DesktopThumbnailItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
235{
236 if (effects) {
237 QDeclarativeItem::paint(painter, option, widget);
238 return;
239 }
240 // TODO: render icon
241}
242
243void DesktopThumbnailItem::repaint(EffectWindow *w)
244{
245 if (w->isOnDesktop(m_desktop)) {
246 update();
247 }
248}
249
250} // namespace KWin
251