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

« back to all changes in this revision

Viewing changes to kwin/tabbox/desktopitemdelegate.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
//own
 
21
#include "desktopitemdelegate.h"
 
22
// tabbox
 
23
#include "clientitemdelegate.h"
 
24
#include "clientmodel.h"
 
25
#include "desktopmodel.h"
 
26
#include "tabboxconfig.h"
 
27
// Qt
 
28
#include <QPainter>
 
29
// KDE
 
30
#include <KGlobalSettings>
 
31
#include <KIcon>
 
32
#include <KIconEffect>
 
33
#include <KIconLoader>
 
34
#include <Plasma/FrameSvg>
 
35
#include <Plasma/Theme>
 
36
 
 
37
namespace KWin
 
38
{
 
39
namespace TabBox
 
40
{
 
41
 
 
42
DesktopItemDelegate::DesktopItemDelegate(QObject* parent)
 
43
    : QAbstractItemDelegate(parent)
 
44
{
 
45
    m_frame = new Plasma::FrameSvg(this);
 
46
    m_frame->setImagePath("widgets/viewitem");
 
47
    m_frame->setElementPrefix("hover");
 
48
    m_frame->setCacheAllRenderedFrames(true);
 
49
    m_frame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
50
    m_clientDelegate = new ClientItemDelegate(this);
 
51
}
 
52
 
 
53
DesktopItemDelegate::~DesktopItemDelegate()
 
54
{
 
55
}
 
56
 
 
57
void DesktopItemDelegate::setConfig(const KWin::TabBox::ItemLayoutConfig& config)
 
58
{
 
59
    m_config = config;
 
60
}
 
61
 
 
62
void DesktopItemDelegate::setLayouts(QMap< QString, ItemLayoutConfig >& layouts)
 
63
{
 
64
    m_layouts = layouts;
 
65
}
 
66
 
 
67
QSize DesktopItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
 
68
{
 
69
    Q_UNUSED(option)
 
70
    if (!index.isValid())
 
71
        return QSize(0, 0);
 
72
 
 
73
    qreal width = 0.0;
 
74
    qreal height = 0.0;
 
75
    for (int i = 0; i < m_config.count(); i++) {
 
76
        QSizeF row = rowSize(index, i);
 
77
        width = qMax<qreal>(width, row.width());
 
78
        height += row.height();
 
79
    }
 
80
    qreal left, top, right, bottom;
 
81
    m_frame->getMargins(left, top, right, bottom);
 
82
 
 
83
    // find icon elements which have a row span
 
84
    for (int i = 0; i < m_config.count(); i++) {
 
85
        ItemLayoutConfigRow row = m_config.row(i);
 
86
        for (int j = 0; j < row.count(); j++) {
 
87
            ItemLayoutConfigRowElement element = row.element(j);
 
88
            if (element.type() == ItemLayoutConfigRowElement::ElementIcon && element.isRowSpan())
 
89
                height = qMax<qreal>(height, element.iconSize().height());
 
90
        }
 
91
    }
 
92
    return QSize(width + left + right, height + top + bottom);
 
93
}
 
94
 
 
95
void DesktopItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
96
{
 
97
    if (!index.isValid())
 
98
        return;
 
99
    qreal left, top, right, bottom;
 
100
    m_frame->getMargins(left, top, right, bottom);
 
101
 
 
102
    qreal y = option.rect.top() + top;
 
103
    for (int i = 0; i < m_config.count(); i++) {
 
104
        qreal rowHeight = rowSize(index, i).height();
 
105
        qreal x = option.rect.left() + left ;
 
106
        ItemLayoutConfigRow row = m_config.row(i);
 
107
        for (int j = 0; j < row.count(); j++) {
 
108
            ItemLayoutConfigRowElement element = row.element(j);
 
109
            switch(element.type()) {
 
110
            case ItemLayoutConfigRowElement::ElementDesktopName: {
 
111
                x += paintTextElement(painter, option, element, x, y, rowHeight,
 
112
                                      index.model()->data(index, Qt::DisplayRole).toString());
 
113
                break;
 
114
            }
 
115
            case ItemLayoutConfigRowElement::ElementIcon: {
 
116
                qreal rectWidth = (qreal)option.rect.width();
 
117
                qreal maxWidth = qMin<qreal>(element.width(), rectWidth);
 
118
                if (element.isStretch())
 
119
                    maxWidth = qMax<qreal>(maxWidth, option.rect.left() + option.rect.width() - x);
 
120
                qreal iconX = x + maxWidth * 0.5 - element.iconSize().width() * 0.5;
 
121
                qreal iconY = y + rowHeight * 0.5 - element.iconSize().height() * 0.5;
 
122
                if (element.isRowSpan())
 
123
                    iconY = option.rect.top() + option.rect.height() * 0.5 - element.iconSize().height() * 0.5;
 
124
                QRectF iconRect = QRectF(iconX, iconY, element.iconSize().width(), element.iconSize().height());
 
125
 
 
126
                // icon
 
127
                painter->save();
 
128
                KIcon icon("user-desktop");
 
129
                QPixmap iconPixmap = icon.pixmap(QSize(64, 64));
 
130
                if (m_config.isHighlightSelectedIcons() && option.state & QStyle::State_Selected) {
 
131
                    KIconEffect *effect = KIconLoader::global()->iconEffect();
 
132
                    iconPixmap = effect->apply(iconPixmap, KIconLoader::Desktop, KIconLoader::ActiveState);
 
133
                }
 
134
                if (m_config.isGrayscaleDeselectedIcons() && !(option.state & QStyle::State_Selected)) {
 
135
                    KIconEffect *effect = KIconLoader::global()->iconEffect();
 
136
                    iconPixmap = effect->apply(iconPixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
 
137
                }
 
138
                QRectF sourceRect = QRectF(0.0, 0.0, iconPixmap.width(), iconPixmap.height());
 
139
                painter->drawPixmap(iconRect, iconPixmap, sourceRect);
 
140
                painter->restore();
 
141
                x += element.width();
 
142
                break;
 
143
            }
 
144
            case ItemLayoutConfigRowElement::ElementEmpty:
 
145
                x += element.width();
 
146
                break;
 
147
            case ItemLayoutConfigRowElement::ElementClientList: {
 
148
                m_clientDelegate->setConfig(m_layouts[ element.clientListLayoutName()]);
 
149
                ClientModel* clientModel = static_cast< ClientModel* >(
 
150
                                               index.model()->data(index, DesktopModel::ClientModelRole).value< void* >());
 
151
                TabBoxClientList clients = clientModel->clientList();
 
152
                qreal partX = 0.0;
 
153
                qreal partY = 0.0;
 
154
                qreal itemWidth = element.width();
 
155
                if (element.isStretch())
 
156
                    itemWidth = option.rect.x() + option.rect.width() - x;
 
157
                foreach (TabBoxClient * client, clients) {
 
158
                    if (!client)
 
159
                        continue;
 
160
                    QModelIndex clientIndex = clientModel->index(client);
 
161
                    QStyleOptionViewItem itemOption = option;
 
162
                    itemOption.state = QStyle::State_Item;
 
163
                    QSizeF itemSize = m_clientDelegate->sizeHint(itemOption, clientIndex);
 
164
                    // TabBoxHandler gives the same config to the client models as used here
 
165
                    // so row and column do not represent the actual used layout for this list
 
166
                    switch(element.clientListLayoutMode()) {
 
167
                    case TabBoxConfig::HorizontalLayout:
 
168
                        itemOption.rect = QRect(partX + x, y, itemWidth - partX, rowHeight);
 
169
                        partX += qMin(itemWidth - partX, itemSize.width());
 
170
                        break;
 
171
                    case TabBoxConfig::VerticalLayout:
 
172
                        itemOption.rect = QRect(x, y + partY, itemWidth, itemSize.height());
 
173
                        partY += itemSize.height();
 
174
                        break;
 
175
                    case TabBoxConfig::HorizontalVerticalLayout:
 
176
                        // TODO: complicated
 
177
                        break;
 
178
                    default:
 
179
                        break; // nothing
 
180
                    }
 
181
                    if ((partX > itemWidth) || (partX + x > option.rect.x() + option.rect.width())) {
 
182
                        partX = itemWidth;
 
183
                        break;
 
184
                    }
 
185
                    if ((partY > rowHeight) || (y + partY > option.rect.y() + option.rect.height())) {
 
186
                        partY = rowHeight;
 
187
                        break;
 
188
                    }
 
189
                    m_clientDelegate->paint(painter, itemOption, clientIndex);
 
190
                }
 
191
                x += itemWidth;
 
192
                break;
 
193
            }
 
194
            default:
 
195
                break; // do nothing
 
196
            }
 
197
        }
 
198
        y += rowHeight;
 
199
    }
 
200
}
 
201
 
 
202
qreal DesktopItemDelegate::paintTextElement(QPainter* painter, const QStyleOptionViewItem& option,
 
203
        const ItemLayoutConfigRowElement& element,
 
204
        const qreal& x, const qreal& y, const qreal& rowHeight, QString text) const
 
205
{
 
206
    painter->save();
 
207
    QFont font = KGlobalSettings::generalFont();
 
208
    if (element.isSmallTextSize())
 
209
        font = KGlobalSettings::smallestReadableFont();
 
210
    font.setBold(element.isBold());
 
211
    font.setItalic(element.isItalic());
 
212
    text = element.prefix() + text + element.suffix();
 
213
    painter->setFont(font);
 
214
    painter->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
 
215
    qreal width = element.width();
 
216
    if (element.isStretch()) {
 
217
        qreal left, top, right, bottom;
 
218
        m_frame->getMargins(left, top, right, bottom);
 
219
        width = option.rect.left() + option.rect.width() - x - right;
 
220
    }
 
221
    text = QFontMetricsF(font).elidedText(text, Qt::ElideRight, width);
 
222
    QRectF rect = QRectF(x, y, width, rowHeight);
 
223
    painter->drawText(rect, element.alignment() | Qt::TextSingleLine, text);
 
224
    painter->restore();
 
225
    return width;
 
226
}
 
227
 
 
228
QSizeF DesktopItemDelegate::rowSize(const QModelIndex& index, int row) const
 
229
{
 
230
    ItemLayoutConfigRow currentRow = m_config.row(row);
 
231
    qreal rowWidth = 0.0;
 
232
    qreal rowHeight = 0.0;
 
233
    for (int j = 0; j < currentRow.count(); j++) {
 
234
        ItemLayoutConfigRowElement element = currentRow.element(j);
 
235
        switch(element.type()) {
 
236
        case ItemLayoutConfigRowElement::ElementDesktopName: {
 
237
            QSizeF size = textElementSizeHint(index, element,
 
238
                                              index.model()->data(index, Qt::DisplayRole).toString());
 
239
            rowWidth += size.width();
 
240
            rowHeight = qMax<qreal>(rowHeight, size.height());
 
241
            break;
 
242
        }
 
243
        case ItemLayoutConfigRowElement::ElementIcon:
 
244
            rowWidth += qMax<qreal>(element.iconSize().width(), element.width());
 
245
            if (!element.isRowSpan())
 
246
                rowHeight = qMax<qreal>(rowHeight, element.iconSize().height());
 
247
            break;
 
248
        case ItemLayoutConfigRowElement::ElementEmpty:
 
249
            rowWidth += element.width();
 
250
            break;
 
251
        case ItemLayoutConfigRowElement::ElementClientList: {
 
252
            m_clientDelegate->setConfig(m_layouts[ element.clientListLayoutName()]);
 
253
            ClientModel* clientModel = static_cast< ClientModel* >(
 
254
                                           index.model()->data(index, DesktopModel::ClientModelRole).value< void* >());
 
255
            TabBoxClientList clients = clientModel->clientList();
 
256
            qreal elementWidth = 0.0;
 
257
            qreal elementHeight = 0.0;
 
258
            foreach (TabBoxClient * client, clients) {
 
259
                if (!client)
 
260
                    continue;
 
261
                QModelIndex clientIndex = clientModel->index(client);
 
262
                QStyleOptionViewItem itemOption = QStyleOptionViewItem();
 
263
                QSizeF itemSize = m_clientDelegate->sizeHint(itemOption, clientIndex);
 
264
                switch(element.clientListLayoutMode()) {
 
265
                case TabBoxConfig::HorizontalLayout:
 
266
                    elementWidth += itemSize.width();
 
267
                    elementHeight = qMax<qreal>(elementHeight, itemSize.height());
 
268
                    break;
 
269
                case TabBoxConfig::VerticalLayout:
 
270
                    elementWidth = qMax<qreal>(elementWidth, itemSize.width());
 
271
                    elementHeight += itemSize.height();
 
272
                    break;
 
273
                case TabBoxConfig::HorizontalVerticalLayout:
 
274
                    // TODO: complicated
 
275
                    break;
 
276
                default:
 
277
                    break; // nothing
 
278
                }
 
279
            }
 
280
            if (element.isStretch())
 
281
                rowWidth += elementWidth;
 
282
            else
 
283
                rowWidth += qMin(elementWidth, element.width());
 
284
            rowHeight = qMax<qreal>(rowHeight, elementHeight);
 
285
            break;
 
286
        }
 
287
        default:
 
288
            break; // do nothing
 
289
        }
 
290
    }
 
291
    return QSizeF(rowWidth, rowHeight);
 
292
}
 
293
 
 
294
QSizeF DesktopItemDelegate::textElementSizeHint(const QModelIndex& index, const ItemLayoutConfigRowElement& element, QString text) const
 
295
{
 
296
    Q_UNUSED(index)
 
297
    QFont font = KGlobalSettings::generalFont();
 
298
    if (element.isSmallTextSize())
 
299
        font = KGlobalSettings::smallestReadableFont();
 
300
    font.setBold(element.isBold());
 
301
    font.setItalic(element.isItalic());
 
302
    text = element.prefix() + text + element.suffix();
 
303
    QFontMetricsF fm(font);
 
304
    qreal width = element.width();
 
305
    if (element.isStretch())
 
306
        width = fm.width(text);
 
307
    qreal height = fm.boundingRect(text).height();
 
308
    return QSizeF(width, height);
 
309
}
 
310
 
 
311
} // namespace Tabbox
 
312
} // namespace KWin