~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to lib/thumbnailview/thumbnailbarview.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
 
1
// vim: set tabstop=4 shiftwidth=4 expandtab:
2
2
/*
3
3
Gwenview: an image viewer
4
4
Copyright 2008 AurĆ©lien GĆ¢teau <agateau@kde.org>
42
42
#include "lib/thumbnailview/abstractthumbnailviewhelper.h"
43
43
#include "lib/thumbnailview/contextbarbutton.h"
44
44
 
45
 
namespace Gwenview {
 
45
namespace Gwenview
 
46
{
46
47
 
47
48
/**
48
49
 * Duration in ms of the smooth scroll
61
62
/** How many pixels around the thumbnail are shadowed */
62
63
const int SHADOW_SIZE = 4;
63
64
 
64
 
 
65
65
struct ThumbnailBarItemDelegatePrivate {
66
 
        // Key is height * 1000 + width
67
 
        typedef QMap<int, QPixmap> ShadowCache;
68
 
        mutable ShadowCache mShadowCache;
69
 
 
70
 
        ThumbnailBarItemDelegate* mDelegate;
71
 
        ThumbnailView* mView;
72
 
        ContextBarButton* mToggleSelectionButton;
73
 
 
74
 
        QColor mBorderColor;
75
 
        QModelIndex mIndexUnderCursor;
76
 
 
77
 
        void setupToggleSelectionButton() {
78
 
                mToggleSelectionButton = new ContextBarButton("list-add", mView->viewport());
79
 
                mToggleSelectionButton->hide();
80
 
                QObject::connect(mToggleSelectionButton, SIGNAL(clicked(bool)), mDelegate, SLOT(toggleSelection()));
81
 
        }
82
 
 
83
 
        void showToolTip(QHelpEvent* helpEvent) {
84
 
                QModelIndex index = mView->indexAt(helpEvent->pos());
85
 
                if (!index.isValid()) {
86
 
                        return;
87
 
                }
88
 
                QString fullText = index.data().toString();
89
 
                QPoint pos = QCursor::pos();
90
 
                QToolTip::showText(pos, fullText, mView);
91
 
        }
92
 
 
93
 
        void drawShadow(QPainter* painter, const QRect& rect) const {
94
 
                const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
95
 
 
96
 
                int key = rect.height() * 1000 + rect.width();
97
 
 
98
 
                ShadowCache::Iterator it = mShadowCache.find(key);
99
 
                if (it == mShadowCache.end()) {
100
 
                        QSize size = QSize(rect.width() + 2*SHADOW_SIZE, rect.height() + 2*SHADOW_SIZE);
101
 
                        QColor color(0, 0, 0, SHADOW_STRENGTH);
102
 
                        QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
103
 
                        it = mShadowCache.insert(key, shadow);
104
 
                }
105
 
                painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
106
 
        }
107
 
 
108
 
        bool hoverEventFilter(QHoverEvent* event) {
109
 
                QModelIndex index = mView->indexAt(event->pos());
110
 
                if (index != mIndexUnderCursor) {
111
 
                        updateHoverUi(index);
112
 
                }
113
 
                return false;
114
 
        }
115
 
 
116
 
        void updateHoverUi(const QModelIndex& index) {
117
 
                QModelIndex oldIndex = mIndexUnderCursor;
118
 
                mIndexUnderCursor = index;
119
 
 
120
 
                if (mIndexUnderCursor.isValid()) {
121
 
                        updateToggleSelectionButton();
122
 
 
123
 
                        const QRect rect = mView->visualRect(mIndexUnderCursor);
124
 
                        mToggleSelectionButton->move(rect.topLeft() + QPoint(2, 2));
125
 
                        mToggleSelectionButton->show();
126
 
                } else {
127
 
                        mToggleSelectionButton->hide();
128
 
                }
129
 
        }
130
 
 
131
 
        void updateToggleSelectionButton() {
132
 
                bool isSelected = mView->selectionModel()->isSelected(mIndexUnderCursor);
133
 
                mToggleSelectionButton->setIcon(SmallIcon(isSelected ? "list-remove" : "list-add"));
134
 
        }
 
66
    // Key is height * 1000 + width
 
67
    typedef QMap<int, QPixmap> ShadowCache;
 
68
    mutable ShadowCache mShadowCache;
 
69
 
 
70
    ThumbnailBarItemDelegate* q;
 
71
    ThumbnailView* mView;
 
72
    ContextBarButton* mToggleSelectionButton;
 
73
 
 
74
    QColor mBorderColor;
 
75
    QModelIndex mIndexUnderCursor;
 
76
 
 
77
    void setupToggleSelectionButton()
 
78
    {
 
79
        mToggleSelectionButton = new ContextBarButton("list-add", mView->viewport());
 
80
        mToggleSelectionButton->hide();
 
81
        QObject::connect(mToggleSelectionButton, SIGNAL(clicked(bool)), q, SLOT(toggleSelection()));
 
82
    }
 
83
 
 
84
    void showToolTip(QHelpEvent* helpEvent)
 
85
    {
 
86
        QModelIndex index = mView->indexAt(helpEvent->pos());
 
87
        if (!index.isValid()) {
 
88
            return;
 
89
        }
 
90
        QString fullText = index.data().toString();
 
91
        QPoint pos = QCursor::pos();
 
92
        QToolTip::showText(pos, fullText, mView);
 
93
    }
 
94
 
 
95
    void drawShadow(QPainter* painter, const QRect& rect) const
 
96
    {
 
97
        const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
 
98
 
 
99
        int key = rect.height() * 1000 + rect.width();
 
100
 
 
101
        ShadowCache::Iterator it = mShadowCache.find(key);
 
102
        if (it == mShadowCache.end()) {
 
103
            QSize size = QSize(rect.width() + 2 * SHADOW_SIZE, rect.height() + 2 * SHADOW_SIZE);
 
104
            QColor color(0, 0, 0, SHADOW_STRENGTH);
 
105
            QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
 
106
            it = mShadowCache.insert(key, shadow);
 
107
        }
 
108
        painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
 
109
    }
 
110
 
 
111
    bool hoverEventFilter(QHoverEvent* event)
 
112
    {
 
113
        QModelIndex index = mView->indexAt(event->pos());
 
114
        if (index != mIndexUnderCursor) {
 
115
            updateHoverUi(index);
 
116
        }
 
117
        return false;
 
118
    }
 
119
 
 
120
    void updateHoverUi(const QModelIndex& index)
 
121
    {
 
122
        QModelIndex oldIndex = mIndexUnderCursor;
 
123
        mIndexUnderCursor = index;
 
124
 
 
125
        if (mIndexUnderCursor.isValid()) {
 
126
            updateToggleSelectionButton();
 
127
 
 
128
            const QRect rect = mView->visualRect(mIndexUnderCursor);
 
129
            mToggleSelectionButton->move(rect.topLeft() + QPoint(2, 2));
 
130
            mToggleSelectionButton->show();
 
131
        } else {
 
132
            mToggleSelectionButton->hide();
 
133
        }
 
134
    }
 
135
 
 
136
    void updateToggleSelectionButton()
 
137
    {
 
138
        bool isSelected = mView->selectionModel()->isSelected(mIndexUnderCursor);
 
139
        mToggleSelectionButton->setIcon(SmallIcon(isSelected ? "list-remove" : "list-add"));
 
140
    }
135
141
};
136
142
 
137
 
 
138
143
ThumbnailBarItemDelegate::ThumbnailBarItemDelegate(ThumbnailView* view)
139
144
: QAbstractItemDelegate(view)
140
 
, d(new ThumbnailBarItemDelegatePrivate) {
141
 
        d->mDelegate = this;
142
 
        d->mView = view;
143
 
        d->setupToggleSelectionButton();
144
 
        view->viewport()->installEventFilter(this);
145
 
 
146
 
        d->mBorderColor = PaintUtils::alphaAdjustedF(QColor(Qt::white), 0.65);
147
 
}
148
 
 
149
 
 
150
 
QSize ThumbnailBarItemDelegate::sizeHint( const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const {
151
 
        return d->mView->gridSize();
152
 
}
153
 
 
154
 
 
155
 
bool ThumbnailBarItemDelegate::eventFilter(QObject*, QEvent* event) {
156
 
        switch (event->type()) {
157
 
        case QEvent::ToolTip:
158
 
                d->showToolTip(static_cast<QHelpEvent*>(event));
159
 
                return true;
160
 
        case QEvent::HoverMove:
161
 
        case QEvent::HoverLeave:
162
 
                return d->hoverEventFilter(static_cast<QHoverEvent*>(event));
163
 
        default:
164
 
                break;
165
 
        }
166
 
 
167
 
        return false;
168
 
}
169
 
 
170
 
 
171
 
void ThumbnailBarItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
172
 
        bool isSelected = option.state & QStyle::State_Selected;
173
 
        bool isCurrent = d->mView->selectionModel()->currentIndex() == index;
174
 
        QPixmap thumbnailPix = d->mView->thumbnailForIndex(index);
175
 
        QRect rect = option.rect;
176
 
 
177
 
        QStyleOptionViewItemV4 opt = option;
178
 
        const QWidget* widget = opt.widget;
179
 
        QStyle* style = widget ? widget->style() : QApplication::style();
180
 
        if (isSelected && !isCurrent) {
181
 
                // Draw selected but not current item backgrounds with some transparency
182
 
                // so that the current item stands out.
183
 
                painter->setOpacity(.33);
184
 
        }
185
 
        style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
186
 
        painter->setOpacity(1);
187
 
 
188
 
        // Draw thumbnail
189
 
        if (!thumbnailPix.isNull()) {
190
 
                QRect thumbnailRect = QRect(
191
 
                        rect.left() + (rect.width() - thumbnailPix.width())/2,
192
 
                        rect.top() + (rect.height() - thumbnailPix.height())/2 - 1,
193
 
                        thumbnailPix.width(),
194
 
                        thumbnailPix.height());
195
 
 
196
 
                if (!thumbnailPix.hasAlphaChannel()) {
197
 
                        d->drawShadow(painter, thumbnailRect);
198
 
                        painter->setPen(d->mBorderColor);
199
 
                        painter->setRenderHint(QPainter::Antialiasing, false);
200
 
                        QRect borderRect = thumbnailRect.adjusted(-1, -1, 0, 0);
201
 
                        painter->drawRect(borderRect);
202
 
                }
203
 
                painter->drawPixmap(thumbnailRect.left(), thumbnailRect.top(), thumbnailPix);
204
 
 
205
 
                // Draw busy indicator
206
 
                if (d->mView->isBusy(index)) {
207
 
                        QPixmap pix = d->mView->busySequenceCurrentPixmap();
208
 
                        painter->drawPixmap(
209
 
                                thumbnailRect.left() + (thumbnailRect.width() - pix.width()) / 2,
210
 
                                thumbnailRect.top() + (thumbnailRect.height() - pix.height()) / 2,
211
 
                                pix);
212
 
                }
213
 
        }
214
 
}
215
 
 
216
 
 
217
 
void ThumbnailBarItemDelegate::toggleSelection() {
218
 
        d->mView->selectionModel()->select(d->mIndexUnderCursor, QItemSelectionModel::Toggle);
219
 
        d->updateToggleSelectionButton();
220
 
}
221
 
 
222
 
 
223
 
ThumbnailBarItemDelegate::~ThumbnailBarItemDelegate() {
224
 
        delete d;
225
 
}
226
 
 
 
145
, d(new ThumbnailBarItemDelegatePrivate)
 
146
{
 
147
    d->q = this;
 
148
    d->mView = view;
 
149
    d->setupToggleSelectionButton();
 
150
    view->viewport()->installEventFilter(this);
 
151
 
 
152
    d->mBorderColor = PaintUtils::alphaAdjustedF(QColor(Qt::white), 0.65);
 
153
}
 
154
 
 
155
QSize ThumbnailBarItemDelegate::sizeHint(const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const
 
156
{
 
157
    return d->mView->gridSize();
 
158
}
 
159
 
 
160
bool ThumbnailBarItemDelegate::eventFilter(QObject*, QEvent* event)
 
161
{
 
162
    switch (event->type()) {
 
163
    case QEvent::ToolTip:
 
164
        d->showToolTip(static_cast<QHelpEvent*>(event));
 
165
        return true;
 
166
    case QEvent::HoverMove:
 
167
    case QEvent::HoverLeave:
 
168
        return d->hoverEventFilter(static_cast<QHoverEvent*>(event));
 
169
    default:
 
170
        break;
 
171
    }
 
172
 
 
173
    return false;
 
174
}
 
175
 
 
176
void ThumbnailBarItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
 
177
{
 
178
    bool isSelected = option.state & QStyle::State_Selected;
 
179
    bool isCurrent = d->mView->selectionModel()->currentIndex() == index;
 
180
    QPixmap thumbnailPix = d->mView->thumbnailForIndex(index);
 
181
    QRect rect = option.rect;
 
182
 
 
183
    QStyleOptionViewItemV4 opt = option;
 
184
    const QWidget* widget = opt.widget;
 
185
    QStyle* style = widget ? widget->style() : QApplication::style();
 
186
    if (isSelected && !isCurrent) {
 
187
        // Draw selected but not current item backgrounds with some transparency
 
188
        // so that the current item stands out.
 
189
        painter->setOpacity(.33);
 
190
    }
 
191
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
 
192
    painter->setOpacity(1);
 
193
 
 
194
    // Draw thumbnail
 
195
    if (!thumbnailPix.isNull()) {
 
196
        QRect thumbnailRect = QRect(
 
197
                                  rect.left() + (rect.width() - thumbnailPix.width()) / 2,
 
198
                                  rect.top() + (rect.height() - thumbnailPix.height()) / 2 - 1,
 
199
                                  thumbnailPix.width(),
 
200
                                  thumbnailPix.height());
 
201
 
 
202
        if (!thumbnailPix.hasAlphaChannel()) {
 
203
            d->drawShadow(painter, thumbnailRect);
 
204
            painter->setPen(d->mBorderColor);
 
205
            painter->setRenderHint(QPainter::Antialiasing, false);
 
206
            QRect borderRect = thumbnailRect.adjusted(-1, -1, 0, 0);
 
207
            painter->drawRect(borderRect);
 
208
        }
 
209
        painter->drawPixmap(thumbnailRect.left(), thumbnailRect.top(), thumbnailPix);
 
210
 
 
211
        // Draw busy indicator
 
212
        if (d->mView->isBusy(index)) {
 
213
            QPixmap pix = d->mView->busySequenceCurrentPixmap();
 
214
            painter->drawPixmap(
 
215
                thumbnailRect.left() + (thumbnailRect.width() - pix.width()) / 2,
 
216
                thumbnailRect.top() + (thumbnailRect.height() - pix.height()) / 2,
 
217
                pix);
 
218
        }
 
219
    }
 
220
}
 
221
 
 
222
void ThumbnailBarItemDelegate::toggleSelection()
 
223
{
 
224
    d->mView->selectionModel()->select(d->mIndexUnderCursor, QItemSelectionModel::Toggle);
 
225
    d->updateToggleSelectionButton();
 
226
}
 
227
 
 
228
ThumbnailBarItemDelegate::~ThumbnailBarItemDelegate()
 
229
{
 
230
    delete d;
 
231
}
227
232
 
228
233
/**
229
234
 * This proxy style makes it possible to override the value returned by
230
235
 * styleHint() which leads to not-so-nice results with some styles.
231
236
 */
232
 
class ProxyStyle : public QWindowsStyle {
 
237
class ProxyStyle : public QWindowsStyle
 
238
{
233
239
public:
234
 
        ProxyStyle(QStyle* baseStyle) : QWindowsStyle() {
235
 
                mBaseStyle = baseStyle;
236
 
        }
237
 
 
238
 
        void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w = 0) const {
239
 
                mBaseStyle->drawPrimitive(pe, opt, p, w);
240
 
        }
241
 
 
242
 
        void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w = 0) const {
243
 
                mBaseStyle->drawControl(element, opt, p, w);
244
 
        }
245
 
 
246
 
        void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *w = 0) const {
247
 
                mBaseStyle->drawComplexControl(cc, opt, p, w);
248
 
        }
249
 
 
250
 
        int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, QStyleHintReturn *shret = 0) const {
251
 
                switch (sh) {
252
 
                case SH_ItemView_ShowDecorationSelected:
253
 
                        return true;
254
 
                case SH_ScrollView_FrameOnlyAroundContents:
255
 
                        return false;
256
 
                default:
257
 
                        return QWindowsStyle::styleHint(sh, opt, w, shret);
258
 
                }
259
 
        }
260
 
 
261
 
        void polish(QApplication* application) {
262
 
                mBaseStyle->polish(application);
263
 
        }
264
 
 
265
 
        void polish(QPalette& palette) {
266
 
                mBaseStyle->polish(palette);
267
 
        }
268
 
 
269
 
        void polish(QWidget* widget) {
270
 
                mBaseStyle->polish(widget);
271
 
        }
272
 
 
273
 
        void unpolish(QWidget* widget) {
274
 
                mBaseStyle->unpolish(widget);
275
 
        }
276
 
 
277
 
        void unpolish(QApplication* application) {
278
 
                mBaseStyle->unpolish(application);
279
 
        }
280
 
 
281
 
        int pixelMetric(PixelMetric pm, const QStyleOption* opt, const QWidget* widget) const {
282
 
                switch (pm) {
283
 
                case PM_MaximumDragDistance:
284
 
                        return -1;
285
 
                default:
286
 
                        return QWindowsStyle::pixelMetric(pm, opt, widget);
287
 
                }
288
 
        }
 
240
    ProxyStyle(QStyle* baseStyle) : QWindowsStyle() {
 
241
        mBaseStyle = baseStyle;
 
242
    }
 
243
 
 
244
    void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w = 0) const
 
245
    {
 
246
        mBaseStyle->drawPrimitive(pe, opt, p, w);
 
247
    }
 
248
 
 
249
    void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w = 0) const
 
250
    {
 
251
        mBaseStyle->drawControl(element, opt, p, w);
 
252
    }
 
253
 
 
254
    void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *w = 0) const
 
255
    {
 
256
        mBaseStyle->drawComplexControl(cc, opt, p, w);
 
257
    }
 
258
 
 
259
    int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, QStyleHintReturn *shret = 0) const {
 
260
        switch (sh) {
 
261
        case SH_ItemView_ShowDecorationSelected:
 
262
            return true;
 
263
        case SH_ScrollView_FrameOnlyAroundContents:
 
264
            return false;
 
265
        default:
 
266
            return QWindowsStyle::styleHint(sh, opt, w, shret);
 
267
        }
 
268
    }
 
269
 
 
270
    void polish(QApplication* application)
 
271
    {
 
272
        mBaseStyle->polish(application);
 
273
    }
 
274
 
 
275
    void polish(QPalette& palette)
 
276
    {
 
277
        mBaseStyle->polish(palette);
 
278
    }
 
279
 
 
280
    void polish(QWidget* widget)
 
281
    {
 
282
        mBaseStyle->polish(widget);
 
283
    }
 
284
 
 
285
    void unpolish(QWidget* widget)
 
286
    {
 
287
        mBaseStyle->unpolish(widget);
 
288
    }
 
289
 
 
290
    void unpolish(QApplication* application)
 
291
    {
 
292
        mBaseStyle->unpolish(application);
 
293
    }
 
294
 
 
295
    int pixelMetric(PixelMetric pm, const QStyleOption* opt, const QWidget* widget) const {
 
296
        switch (pm) {
 
297
        case PM_MaximumDragDistance:
 
298
            return -1;
 
299
        default:
 
300
            return QWindowsStyle::pixelMetric(pm, opt, widget);
 
301
        }
 
302
    }
289
303
 
290
304
private:
291
 
        QStyle* mBaseStyle;
 
305
    QStyle* mBaseStyle;
292
306
};
293
307
 
294
 
 
295
 
 
296
308
typedef int (QSize::*QSizeDimension)() const;
297
309
 
298
310
struct ThumbnailBarViewPrivate {
299
 
        ThumbnailBarView* q;
300
 
        QStyle* mStyle;
301
 
        QTimeLine* mTimeLine;
302
 
 
303
 
        Qt::Orientation mOrientation;
304
 
        int mRowCount;
305
 
 
306
 
 
307
 
        QScrollBar* scrollBar() const {
308
 
                return mOrientation == Qt::Horizontal ? q->horizontalScrollBar() : q->verticalScrollBar();
309
 
        }
310
 
 
311
 
 
312
 
        QSizeDimension mainDimension() const {
313
 
                return mOrientation == Qt::Horizontal ? &QSize::width : &QSize::height;
314
 
        }
315
 
 
316
 
 
317
 
        QSizeDimension oppositeDimension() const {
318
 
                return mOrientation == Qt::Horizontal ? &QSize::height : &QSize::width;
319
 
        }
320
 
 
321
 
 
322
 
        void smoothScrollTo(const QModelIndex& index) {
323
 
                if (!index.isValid()) {
324
 
                        return;
325
 
                }
326
 
 
327
 
                const QRect rect = q->visualRect(index);
328
 
 
329
 
                int oldValue = scrollBar()->value();
330
 
                int newValue = scrollToValue(rect);
331
 
                if (mTimeLine->state() == QTimeLine::Running) {
332
 
                        mTimeLine->stop();
333
 
                }
334
 
                mTimeLine->setFrameRange(oldValue, newValue);
335
 
                mTimeLine->start();
336
 
        }
337
 
 
338
 
 
339
 
        int scrollToValue(const QRect& rect) {
340
 
                // This code is a much simplified version of
341
 
                // QListViewPrivate::horizontalScrollToValue()
342
 
                const QRect area = q->viewport()->rect();
343
 
                int value = scrollBar()->value();
344
 
 
345
 
                if (mOrientation == Qt::Horizontal) {
346
 
                        if (q->isRightToLeft()) {
347
 
                                value += (area.width() - rect.width()) / 2 - rect.left();
348
 
                        } else {
349
 
                                value += rect.left() - (area.width()- rect.width()) / 2;
350
 
                        }
351
 
                } else {
352
 
                        value += rect.top() - (area.height() - rect.height()) / 2;
353
 
                }
354
 
                return value;
355
 
        }
356
 
 
357
 
 
358
 
        void updateMinMaxSizes() {
359
 
                QSizeDimension dimension = oppositeDimension();
360
 
                int scrollBarSize = (scrollBar()->sizeHint().*dimension)();
361
 
                QSize minSize(0, mRowCount * 48 + scrollBarSize);
362
 
                QSize maxSize(QWIDGETSIZE_MAX, mRowCount * 256 + scrollBarSize);
363
 
                if (mOrientation == Qt::Vertical) {
364
 
                        minSize.transpose();
365
 
                        maxSize.transpose();
366
 
                }
367
 
                q->setMinimumSize(minSize);
368
 
                q->setMaximumSize(maxSize);
369
 
        }
370
 
 
371
 
 
372
 
        void updateThumbnailSize() {
373
 
                QSizeDimension dimension = oppositeDimension();
374
 
                int scrollBarSize = (scrollBar()->sizeHint().*dimension)();
375
 
                int widgetSize = (q->size().*dimension)();
376
 
 
377
 
                if (mRowCount > 1) {
378
 
                        // Decrease widgetSize because otherwise the view sometimes wraps at
379
 
                        // mRowCount-1 instead of mRowCount. Probably because gridSize *
380
 
                        // mRowCount is too close to widgetSize.
381
 
                        --widgetSize;
382
 
                }
383
 
 
384
 
                int gridSize = (widgetSize - scrollBarSize - 2 * q->frameWidth()) / mRowCount;
385
 
 
386
 
                q->setGridSize(QSize(gridSize, gridSize));
387
 
                q->setThumbnailSize(gridSize - ITEM_MARGIN * 2);
388
 
        }
 
311
    ThumbnailBarView* q;
 
312
    QStyle* mStyle;
 
313
    QTimeLine* mTimeLine;
 
314
 
 
315
    Qt::Orientation mOrientation;
 
316
    int mRowCount;
 
317
 
 
318
    QScrollBar* scrollBar() const {
 
319
        return mOrientation == Qt::Horizontal ? q->horizontalScrollBar() : q->verticalScrollBar();
 
320
    }
 
321
 
 
322
    QSizeDimension mainDimension() const {
 
323
        return mOrientation == Qt::Horizontal ? &QSize::width : &QSize::height;
 
324
    }
 
325
 
 
326
    QSizeDimension oppositeDimension() const {
 
327
        return mOrientation == Qt::Horizontal ? &QSize::height : &QSize::width;
 
328
    }
 
329
 
 
330
    void smoothScrollTo(const QModelIndex& index)
 
331
    {
 
332
        if (!index.isValid()) {
 
333
            return;
 
334
        }
 
335
 
 
336
        const QRect rect = q->visualRect(index);
 
337
 
 
338
        int oldValue = scrollBar()->value();
 
339
        int newValue = scrollToValue(rect);
 
340
        if (mTimeLine->state() == QTimeLine::Running) {
 
341
            mTimeLine->stop();
 
342
        }
 
343
        mTimeLine->setFrameRange(oldValue, newValue);
 
344
        mTimeLine->start();
 
345
    }
 
346
 
 
347
    int scrollToValue(const QRect& rect)
 
348
    {
 
349
        // This code is a much simplified version of
 
350
        // QListViewPrivate::horizontalScrollToValue()
 
351
        const QRect area = q->viewport()->rect();
 
352
        int value = scrollBar()->value();
 
353
 
 
354
        if (mOrientation == Qt::Horizontal) {
 
355
            if (q->isRightToLeft()) {
 
356
                value += (area.width() - rect.width()) / 2 - rect.left();
 
357
            } else {
 
358
                value += rect.left() - (area.width() - rect.width()) / 2;
 
359
            }
 
360
        } else {
 
361
            value += rect.top() - (area.height() - rect.height()) / 2;
 
362
        }
 
363
        return value;
 
364
    }
 
365
 
 
366
    void updateMinMaxSizes()
 
367
    {
 
368
        QSizeDimension dimension = oppositeDimension();
 
369
        int scrollBarSize = (scrollBar()->sizeHint().*dimension)();
 
370
        QSize minSize(0, mRowCount * 48 + scrollBarSize);
 
371
        QSize maxSize(QWIDGETSIZE_MAX, mRowCount * 256 + scrollBarSize);
 
372
        if (mOrientation == Qt::Vertical) {
 
373
            minSize.transpose();
 
374
            maxSize.transpose();
 
375
        }
 
376
        q->setMinimumSize(minSize);
 
377
        q->setMaximumSize(maxSize);
 
378
    }
 
379
 
 
380
    void updateThumbnailSize()
 
381
    {
 
382
        QSizeDimension dimension = oppositeDimension();
 
383
        int scrollBarSize = (scrollBar()->sizeHint().*dimension)();
 
384
        int widgetSize = (q->size().*dimension)();
 
385
 
 
386
        if (mRowCount > 1) {
 
387
            // Decrease widgetSize because otherwise the view sometimes wraps at
 
388
            // mRowCount-1 instead of mRowCount. Probably because gridSize *
 
389
            // mRowCount is too close to widgetSize.
 
390
            --widgetSize;
 
391
        }
 
392
 
 
393
        int gridSize = (widgetSize - scrollBarSize - 2 * q->frameWidth()) / mRowCount;
 
394
 
 
395
        q->setGridSize(QSize(gridSize, gridSize));
 
396
        q->setThumbnailSize(gridSize - ITEM_MARGIN * 2);
 
397
    }
389
398
};
390
399
 
391
 
 
392
 
 
393
400
ThumbnailBarView::ThumbnailBarView(QWidget* parent)
394
401
: ThumbnailView(parent)
395
 
, d(new ThumbnailBarViewPrivate) {
396
 
        d->q = this;
397
 
        d->mTimeLine = new QTimeLine(SMOOTH_SCROLL_DURATION, this);
398
 
        connect(d->mTimeLine, SIGNAL(frameChanged(int)),
399
 
                SLOT(slotFrameChanged(int)));
400
 
 
401
 
        d->mRowCount = 1;
402
 
        d->mOrientation = Qt::Vertical; // To pass value-has-changed check in setOrientation()
403
 
        setOrientation(Qt::Horizontal);
404
 
 
405
 
        setObjectName( QLatin1String("thumbnailBarView" ));
406
 
        setUniformItemSizes(true);
407
 
        setWrapping(true);
408
 
 
409
 
        d->mStyle = new ProxyStyle(style());
410
 
        setStyle(d->mStyle);
411
 
}
412
 
 
413
 
 
414
 
ThumbnailBarView::~ThumbnailBarView() {
415
 
        delete d->mStyle;
416
 
        delete d;
417
 
}
418
 
 
419
 
 
420
 
Qt::Orientation ThumbnailBarView::orientation() const {
421
 
        return d->mOrientation;
422
 
}
423
 
 
424
 
 
425
 
void ThumbnailBarView::setOrientation(Qt::Orientation orientation) {
426
 
        if (d->mOrientation == orientation) {
427
 
                return;
428
 
        }
429
 
        d->mOrientation = orientation;
430
 
 
431
 
        if (d->mOrientation == Qt::Vertical) {
432
 
                setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
433
 
                setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
434
 
                setFlow(LeftToRight);
435
 
        } else {
436
 
                setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
437
 
                setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
438
 
                setFlow(TopToBottom);
439
 
        }
440
 
 
441
 
        d->updateMinMaxSizes();
442
 
}
443
 
 
444
 
 
445
 
void ThumbnailBarView::slotFrameChanged(int value) {
446
 
        d->scrollBar()->setValue(value);
447
 
}
448
 
 
449
 
 
450
 
void ThumbnailBarView::resizeEvent(QResizeEvent *event) {
451
 
        ThumbnailView::resizeEvent(event);
452
 
        d->updateThumbnailSize();
453
 
}
454
 
 
455
 
 
456
 
void ThumbnailBarView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
457
 
        QListView::selectionChanged(selected, deselected);
458
 
 
459
 
        QModelIndexList list = selected.indexes();
460
 
        if (list.count() == 1 && isVisible()) {
461
 
                d->smoothScrollTo(list.first());
462
 
        }
463
 
}
464
 
 
465
 
 
466
 
void ThumbnailBarView::wheelEvent(QWheelEvent* event) {
467
 
        d->scrollBar()->setValue(d->scrollBar()->value() - event->delta());
468
 
}
469
 
 
470
 
 
471
 
int ThumbnailBarView::rowCount() const {
472
 
        return d->mRowCount;
473
 
}
474
 
 
475
 
 
476
 
void ThumbnailBarView::setRowCount(int rowCount) {
477
 
        Q_ASSERT(rowCount > 0);
478
 
        d->mRowCount = rowCount;
479
 
        d->updateMinMaxSizes();
480
 
        d->updateThumbnailSize();
481
 
}
482
 
 
 
402
, d(new ThumbnailBarViewPrivate)
 
403
{
 
404
    d->q = this;
 
405
    d->mTimeLine = new QTimeLine(SMOOTH_SCROLL_DURATION, this);
 
406
    connect(d->mTimeLine, SIGNAL(frameChanged(int)),
 
407
            SLOT(slotFrameChanged(int)));
 
408
 
 
409
    d->mRowCount = 1;
 
410
    d->mOrientation = Qt::Vertical; // To pass value-has-changed check in setOrientation()
 
411
    setOrientation(Qt::Horizontal);
 
412
 
 
413
    setObjectName(QLatin1String("thumbnailBarView"));
 
414
    setUniformItemSizes(true);
 
415
    setWrapping(true);
 
416
 
 
417
    d->mStyle = new ProxyStyle(style());
 
418
    setStyle(d->mStyle);
 
419
}
 
420
 
 
421
ThumbnailBarView::~ThumbnailBarView()
 
422
{
 
423
    delete d->mStyle;
 
424
    delete d;
 
425
}
 
426
 
 
427
Qt::Orientation ThumbnailBarView::orientation() const
 
428
{
 
429
    return d->mOrientation;
 
430
}
 
431
 
 
432
void ThumbnailBarView::setOrientation(Qt::Orientation orientation)
 
433
{
 
434
    if (d->mOrientation == orientation) {
 
435
        return;
 
436
    }
 
437
    d->mOrientation = orientation;
 
438
 
 
439
    if (d->mOrientation == Qt::Vertical) {
 
440
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
441
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
 
442
        setFlow(LeftToRight);
 
443
    } else {
 
444
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
 
445
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
446
        setFlow(TopToBottom);
 
447
    }
 
448
 
 
449
    d->updateMinMaxSizes();
 
450
}
 
451
 
 
452
void ThumbnailBarView::slotFrameChanged(int value)
 
453
{
 
454
    d->scrollBar()->setValue(value);
 
455
}
 
456
 
 
457
void ThumbnailBarView::resizeEvent(QResizeEvent *event)
 
458
{
 
459
    ThumbnailView::resizeEvent(event);
 
460
    d->updateThumbnailSize();
 
461
}
 
462
 
 
463
void ThumbnailBarView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
 
464
{
 
465
    QListView::selectionChanged(selected, deselected);
 
466
 
 
467
    QModelIndexList list = selected.indexes();
 
468
    if (list.count() == 1 && isVisible()) {
 
469
        d->smoothScrollTo(list.first());
 
470
    }
 
471
}
 
472
 
 
473
void ThumbnailBarView::wheelEvent(QWheelEvent* event)
 
474
{
 
475
    d->scrollBar()->setValue(d->scrollBar()->value() - event->delta());
 
476
}
 
477
 
 
478
int ThumbnailBarView::rowCount() const
 
479
{
 
480
    return d->mRowCount;
 
481
}
 
482
 
 
483
void ThumbnailBarView::setRowCount(int rowCount)
 
484
{
 
485
    Q_ASSERT(rowCount > 0);
 
486
    d->mRowCount = rowCount;
 
487
    d->updateMinMaxSizes();
 
488
    d->updateThumbnailSize();
 
489
}
483
490
 
484
491
} // namespace