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

« back to all changes in this revision

Viewing changes to plasma/generic/applets/webbrowser/browserhistorycombobox.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
 *   Copyright 2008 Aaron Seigo <aseigo@kde.org>
 
3
 *
 
4
 *   This program is free software; you can redistribute it and/or modify
 
5
 *   it under the terms of the GNU Library General Public License as
 
6
 *   published by the Free Software Foundation; either version 2, or
 
7
 *   (at your option) any later version.
 
8
 *
 
9
 *   This program is distributed in the hope that it will be useful,
 
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *   GNU General Public License for more details
 
13
 *
 
14
 *   You should have received a copy of the GNU Library General Public
 
15
 *   License along with this program; if not, write to the
 
16
 *   Free Software Foundation, Inc.,
 
17
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#include "browserhistorycombobox.h"
 
21
 
 
22
#include <QPainter>
 
23
#include <QApplication>
 
24
#include <QPropertyAnimation>
 
25
 
 
26
#include <kcombobox.h>
 
27
#include <kmimetype.h>
 
28
#include <kiconeffect.h>
 
29
#include <kiconloader.h>
 
30
 
 
31
#include <plasma/theme.h>
 
32
#include <plasma/framesvg.h>
 
33
#include <plasma/animator.h>
 
34
#include <plasma/paintutils.h>
 
35
#include <Plasma/ComboBox>
 
36
 
 
37
#include <QtGui/QComboBox>
 
38
#include <QtCore/QSharedData>
 
39
#include <QtGui/QStyle>
 
40
 
 
41
namespace Plasma
 
42
{
 
43
 
 
44
class ComboBoxPrivate
 
45
{
 
46
public:
 
47
    ComboBoxPrivate(BrowserHistoryComboBox *comboBox)
 
48
         : q(comboBox),
 
49
           background(0),
 
50
           customFont(false),
 
51
           underMouse(false)
 
52
    {
 
53
    }
 
54
 
 
55
    ~ComboBoxPrivate()
 
56
    {
 
57
    }
 
58
 
 
59
    void syncActiveRect();
 
60
    void syncBorders();
 
61
    void animationUpdate(qreal progress);
 
62
 
 
63
    BrowserHistoryComboBox *q;
 
64
 
 
65
    FrameSvg *background;
 
66
    FrameSvg *lineEditBackground;
 
67
    int animId;
 
68
    QPropertyAnimation *animation;
 
69
    qreal opacity;
 
70
    QRectF activeRect;
 
71
    QStyle *style;
 
72
    bool customFont;
 
73
    bool underMouse;
 
74
    Plasma::ComboBox *styleParent;
 
75
    int progressValue;
 
76
    bool displayProgress;
 
77
};
 
78
 
 
79
void ComboBoxPrivate::syncActiveRect()
 
80
{
 
81
    background->setElementPrefix("normal");
 
82
 
 
83
    qreal left, top, right, bottom;
 
84
    background->getMargins(left, top, right, bottom);
 
85
 
 
86
    background->setElementPrefix("active");
 
87
    qreal activeLeft, activeTop, activeRight, activeBottom;
 
88
    background->getMargins(activeLeft, activeTop, activeRight, activeBottom);
 
89
 
 
90
    activeRect = QRectF(QPointF(0, 0), q->size());
 
91
    activeRect.adjust(left - activeLeft, top - activeTop,
 
92
                      -(right - activeRight), -(bottom - activeBottom));
 
93
 
 
94
    background->setElementPrefix("normal");
 
95
}
 
96
 
 
97
void ComboBoxPrivate::syncBorders()
 
98
{
 
99
    //set margins from the normal element
 
100
    qreal left, top, right, bottom;
 
101
 
 
102
    background->setElementPrefix("normal");
 
103
    background->getMargins(left, top, right, bottom);
 
104
    q->setContentsMargins(left, top, right, bottom);
 
105
 
 
106
    //calc the rect for the over effect
 
107
    syncActiveRect();
 
108
 
 
109
    KComboBox *native = q->nativeWidget();
 
110
    if (customFont) {
 
111
        native->setFont(q->font());
 
112
    } else {
 
113
        native->setFont(Theme::defaultTheme()->font(Theme::DefaultFont));
 
114
    }
 
115
}
 
116
 
 
117
void ComboBoxPrivate::animationUpdate(qreal progress)
 
118
{
 
119
    opacity = progress;
 
120
 
 
121
    // explicit update
 
122
    q->update();
 
123
}
 
124
 
 
125
BrowserHistoryComboBox::BrowserHistoryComboBox(QGraphicsWidget *parent)
 
126
    : QGraphicsProxyWidget(parent),
 
127
      d(new ComboBoxPrivate(this))
 
128
{
 
129
    d->background = new FrameSvg(this);
 
130
    d->background->setImagePath("widgets/button");
 
131
    d->background->setCacheAllRenderedFrames(true);
 
132
    d->background->setElementPrefix("normal");
 
133
    d->lineEditBackground = new FrameSvg(this);
 
134
    d->lineEditBackground->setImagePath("widgets/lineedit");
 
135
    d->lineEditBackground->setCacheAllRenderedFrames(true);
 
136
    setZValue(900);
 
137
 
 
138
    setAcceptHoverEvents(true);
 
139
 
 
140
    d->styleParent = new Plasma::ComboBox();
 
141
    d->style = d->styleParent->nativeWidget()->style();
 
142
 
 
143
    setNativeWidget(new KComboBox);
 
144
 
 
145
    d->animation = new QPropertyAnimation(this, "animationUpdate", this);
 
146
    d->animation->setStartValue(0);
 
147
    d->animation->setEndValue(1);
 
148
 
 
149
    connect(Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(syncBorders()));
 
150
    
 
151
    d->displayProgress = false;
 
152
    d->progressValue = 0;
 
153
}
 
154
 
 
155
BrowserHistoryComboBox::~BrowserHistoryComboBox()
 
156
{
 
157
    delete d->styleParent;
 
158
    delete d;
 
159
}
 
160
 
 
161
QString BrowserHistoryComboBox::text() const
 
162
{
 
163
    return static_cast<KComboBox*>(widget())->currentText();
 
164
}
 
165
 
 
166
void BrowserHistoryComboBox::setStyleSheet(const QString &stylesheet)
 
167
{
 
168
    widget()->setStyleSheet(stylesheet);
 
169
}
 
170
 
 
171
QString BrowserHistoryComboBox::styleSheet()
 
172
{
 
173
    return widget()->styleSheet();
 
174
}
 
175
 
 
176
void BrowserHistoryComboBox::setNativeWidget(KComboBox *nativeWidget)
 
177
{
 
178
    if (widget()) {
 
179
        widget()->deleteLater();
 
180
    }
 
181
 
 
182
    connect(nativeWidget, SIGNAL(activated(const QString &)), this, SIGNAL(activated(const QString &)));
 
183
    connect(nativeWidget, SIGNAL(currentIndexChanged(const QString &)),
 
184
            this, SIGNAL(textChanged(const QString &)));
 
185
 
 
186
    setWidget(nativeWidget);
 
187
 
 
188
    nativeWidget->setAttribute(Qt::WA_NoSystemBackground);
 
189
    nativeWidget->setStyle(d->style);
 
190
 
 
191
    d->syncBorders();
 
192
}
 
193
 
 
194
KComboBox *BrowserHistoryComboBox::nativeWidget() const
 
195
{
 
196
    return static_cast<KComboBox*>(widget());
 
197
}
 
198
 
 
199
void BrowserHistoryComboBox::addItem(const QString &text)
 
200
{
 
201
    static_cast<KComboBox*>(widget())->addItem(text);
 
202
}
 
203
 
 
204
void BrowserHistoryComboBox::clear()
 
205
{
 
206
    static_cast<KComboBox*>(widget())->clear();
 
207
}
 
208
 
 
209
void BrowserHistoryComboBox::resizeEvent(QGraphicsSceneResizeEvent *event)
 
210
{
 
211
   if (d->background) {
 
212
        //resize needed panels
 
213
        d->syncActiveRect();
 
214
 
 
215
        d->background->setElementPrefix("focus");
 
216
        d->background->resizeFrame(size());
 
217
 
 
218
        d->background->setElementPrefix("active");
 
219
        d->background->resizeFrame(d->activeRect.size());
 
220
 
 
221
        d->background->setElementPrefix("normal");
 
222
        d->background->resizeFrame(size());
 
223
   }
 
224
 
 
225
   QGraphicsProxyWidget::resizeEvent(event);
 
226
}
 
227
 
 
228
void BrowserHistoryComboBox::paint(QPainter *painter,
 
229
                     const QStyleOptionGraphicsItem *option,
 
230
                     QWidget *widget)
 
231
{
 
232
    QAbstractAnimation::State animState = d->animation->state();
 
233
 
 
234
    if (!styleSheet().isNull() ||
 
235
        Theme::defaultTheme()->useNativeWidgetStyle()) {
 
236
        QGraphicsProxyWidget::paint(painter, option, widget);
 
237
        return;
 
238
    }
 
239
 
 
240
    if (nativeWidget()->isEditable()) {
 
241
        if (animState != QAbstractAnimation::Stopped || hasFocus() || d->underMouse) {
 
242
            if (hasFocus()) {
 
243
                d->lineEditBackground->setElementPrefix("focus");
 
244
            } else {
 
245
                d->lineEditBackground->setElementPrefix("hover");
 
246
            }
 
247
            qreal left, top, right, bottom;
 
248
            d->lineEditBackground->getMargins(left, top, right, bottom);
 
249
            d->lineEditBackground->resizeFrame(size()+QSizeF(left+right, top+bottom));
 
250
            if (qFuzzyCompare(d->opacity, (qreal)1.0)) {
 
251
                d->lineEditBackground->paintFrame(painter, QPoint(-left, -top));
 
252
            } else {
 
253
                QPixmap bufferPixmap = d->lineEditBackground->framePixmap();
 
254
                QPainter buffPainter(&bufferPixmap);
 
255
                buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 
256
                buffPainter.fillRect(bufferPixmap.rect(), QColor(0, 0, 0, 256*d->opacity));
 
257
                buffPainter.end();
 
258
                painter->drawPixmap(bufferPixmap.rect().translated(QPoint(-left, -top)), bufferPixmap, bufferPixmap.rect());
 
259
            }
 
260
        }
 
261
        if (d->displayProgress){
 
262
            painter->fillRect(QRectF(option->rect.x() + 2, option->rect.y() + 3, (int) (((qreal) (option->rect.width() - 4) / 100) * d->progressValue), option->rect.height() - 4), Theme::defaultTheme()->color(Theme::LinkColor));
 
263
        }
 
264
        QGraphicsProxyWidget::paint(painter, option, widget);
 
265
        return;
 
266
    }
 
267
 
 
268
    QPixmap bufferPixmap;
 
269
 
 
270
    //normal button
 
271
    if (isEnabled()) {
 
272
        d->background->setElementPrefix("normal");
 
273
 
 
274
        if (animState == QAbstractAnimation::Stopped) {
 
275
            d->background->paintFrame(painter);
 
276
        }
 
277
    //disabled widget
 
278
    } else {
 
279
        bufferPixmap = QPixmap(rect().size().toSize());
 
280
        bufferPixmap.fill(Qt::transparent);
 
281
 
 
282
        QPainter buffPainter(&bufferPixmap);
 
283
        d->background->paintFrame(&buffPainter);
 
284
        buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 
285
        buffPainter.fillRect(bufferPixmap.rect(), QColor(0, 0, 0, 128));
 
286
 
 
287
        painter->drawPixmap(0, 0, bufferPixmap);
 
288
    }
 
289
 
 
290
    //if is under mouse draw the animated glow overlay
 
291
    if (isEnabled() && acceptHoverEvents()) {
 
292
        if (animState!= QAbstractAnimation::Stopped) {
 
293
            d->background->setElementPrefix("normal");
 
294
            QPixmap normalPix = d->background->framePixmap();
 
295
            d->background->setElementPrefix("active");
 
296
            painter->drawPixmap(
 
297
                d->activeRect.topLeft(),
 
298
                PaintUtils::transition(d->background->framePixmap(), normalPix, 1 - d->opacity));
 
299
        } else if (isUnderMouse()) {
 
300
            d->background->setElementPrefix("active");
 
301
            d->background->paintFrame(painter, d->activeRect.topLeft());
 
302
        }
 
303
    }
 
304
 
 
305
    if (nativeWidget()->hasFocus()) {
 
306
        d->background->setElementPrefix("focus");
 
307
        d->background->paintFrame(painter);
 
308
    }
 
309
 
 
310
    painter->setPen(Theme::defaultTheme()->color(Theme::ButtonTextColor));
 
311
 
 
312
    QStyleOptionComboBox comboOpt;
 
313
 
 
314
    comboOpt.initFrom(nativeWidget());
 
315
 
 
316
    comboOpt.palette.setColor(
 
317
        QPalette::ButtonText, Theme::defaultTheme()->color(Theme::ButtonTextColor));
 
318
    comboOpt.currentIcon = nativeWidget()->itemIcon(
 
319
        nativeWidget()->currentIndex());
 
320
    comboOpt.currentText = nativeWidget()->itemText(
 
321
        nativeWidget()->currentIndex());
 
322
    comboOpt.editable = false;
 
323
 
 
324
    nativeWidget()->style()->drawControl(
 
325
        QStyle::CE_ComboBoxLabel, &comboOpt, painter, nativeWidget());
 
326
    comboOpt.rect = nativeWidget()->style()->subControlRect(
 
327
        QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxArrow, nativeWidget());
 
328
    nativeWidget()->style()->drawPrimitive(
 
329
        QStyle::PE_IndicatorArrowDown, &comboOpt, painter, nativeWidget());
 
330
}
 
331
 
 
332
void BrowserHistoryComboBox::setAnimationUpdate(qreal progress)
 
333
{
 
334
    d->animationUpdate(progress);
 
335
}
 
336
 
 
337
qreal BrowserHistoryComboBox::animationUpdate() const
 
338
{
 
339
    return d->opacity;
 
340
}
 
341
 
 
342
void BrowserHistoryComboBox::focusInEvent(QFocusEvent *event)
 
343
{
 
344
    if (nativeWidget()->isEditable() && !d->underMouse) {
 
345
        const int FadeInDuration = 75;
 
346
 
 
347
        if (d->animation->state() != QAbstractAnimation::Stopped) {
 
348
            d->animation->stop();
 
349
        }
 
350
        d->animation->setDuration(FadeInDuration);
 
351
        d->animation->setDirection(QAbstractAnimation::Forward);
 
352
        d->animation->start();
 
353
    }
 
354
 
 
355
    QGraphicsProxyWidget::focusInEvent(event);
 
356
}
 
357
 
 
358
void BrowserHistoryComboBox::focusOutEvent(QFocusEvent *event)
 
359
{
 
360
    if (nativeWidget()->isEditable() && !d->underMouse) {
 
361
        const int FadeOutDuration = 150;
 
362
 
 
363
        if (d->animation->state() != QAbstractAnimation::Stopped) {
 
364
            d->animation->stop();
 
365
        }
 
366
        d->animation->setDuration(FadeOutDuration);
 
367
        d->animation->setDirection(QAbstractAnimation::Backward);
 
368
        d->animation->start();
 
369
    }
 
370
 
 
371
 
 
372
    QGraphicsProxyWidget::focusInEvent(event);
 
373
}
 
374
 
 
375
void BrowserHistoryComboBox::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
 
376
{
 
377
    d->underMouse = true;
 
378
    if (nativeWidget()->isEditable() && hasFocus()) {
 
379
        return;
 
380
    }
 
381
    const int FadeInDuration = 75;
 
382
 
 
383
    if (d->animation->state() != QAbstractAnimation::Stopped) {
 
384
        d->animation->stop();
 
385
    }
 
386
    d->animation->setDuration(FadeInDuration);
 
387
    d->animation->setDirection(QAbstractAnimation::Forward);
 
388
    d->animation->start();
 
389
 
 
390
    d->background->setElementPrefix("active");
 
391
 
 
392
    QGraphicsProxyWidget::hoverEnterEvent(event);
 
393
}
 
394
 
 
395
void BrowserHistoryComboBox::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
 
396
{
 
397
    d->underMouse = false;
 
398
    if (nativeWidget()->isEditable() && hasFocus()) {
 
399
        return;
 
400
    }
 
401
 
 
402
    const int FadeOutDuration = 150;
 
403
 
 
404
    if (d->animation->state() != QAbstractAnimation::Stopped) {
 
405
        d->animation->stop();
 
406
    }
 
407
    d->animation->setDuration(FadeOutDuration);
 
408
    d->animation->setDirection(QAbstractAnimation::Backward);
 
409
    d->animation->start();
 
410
 
 
411
    d->background->setElementPrefix("active");
 
412
 
 
413
    QGraphicsProxyWidget::hoverLeaveEvent(event);
 
414
}
 
415
 
 
416
void BrowserHistoryComboBox::changeEvent(QEvent *event)
 
417
{
 
418
    if (event->type() == QEvent::FontChange) {
 
419
        d->customFont = true;
 
420
        nativeWidget()->setFont(font());
 
421
    }
 
422
 
 
423
    QGraphicsProxyWidget::changeEvent(event);
 
424
}
 
425
 
 
426
void BrowserHistoryComboBox::setProgressValue(int value)
 
427
{
 
428
    d->progressValue = value;
 
429
    update();
 
430
}
 
431
 
 
432
void BrowserHistoryComboBox::setDisplayProgress(bool enable)
 
433
{
 
434
  d->displayProgress = enable;
 
435
  update();
 
436
}
 
437
 
 
438
} // namespace Plasma
 
439
 
 
440
#include "browserhistorycombobox.moc"
 
441