~ubuntu-branches/debian/sid/kde-baseapps/sid

« back to all changes in this revision

Viewing changes to dolphin/src/kitemviews/kitemlistcontainer.cpp

  • Committer: Package Import Robot
  • Author(s): Modestas Vainius, Eshat Cakar, Pino Toscano
  • Date: 2012-06-09 22:18:08 UTC
  • mfrom: (4.2.1) (6.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20120609221808-h1l0ekd5qmb8nefr
Tags: 4:4.8.4-1
* New upstream release.

[ Eshat Cakar ]
* Add watch file.
* Bump kde-sc-dev-latest build dependency to version 4:4.8.4.
* Update installed files.

[ Pino Toscano ]
* Move files of the konqueror documentation from kde-baseapps-data to
  konqueror itself.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
 
3
 *                                                                         *
 
4
 *   Based on the Itemviews NG project from Trolltech Labs:                *
 
5
 *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
 
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, write to the                         *
 
19
 *   Free Software Foundation, Inc.,                                       *
 
20
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 
21
 ***************************************************************************/
 
22
 
 
23
#include "kitemlistcontainer.h"
 
24
 
 
25
#include "kitemlistcontroller.h"
 
26
#include "kitemlistsmoothscroller_p.h"
 
27
#include "kitemlistview.h"
 
28
#include "kitemmodelbase.h"
 
29
 
 
30
#include <QApplication>
 
31
#include <QGraphicsScene>
 
32
#include <QGraphicsView>
 
33
#include <QPropertyAnimation>
 
34
#include <QScrollBar>
 
35
#include <QStyle>
 
36
#include <QStyleOption>
 
37
 
 
38
#include <KDebug>
 
39
 
 
40
/**
 
41
 * Replaces the default viewport of KItemListContainer by a
 
42
 * non-scrollable viewport. The scrolling is done in an optimized
 
43
 * way by KItemListView internally.
 
44
 */
 
45
class KItemListContainerViewport : public QGraphicsView
 
46
{
 
47
public:
 
48
    KItemListContainerViewport(QGraphicsScene* scene, QWidget* parent);
 
49
protected:
 
50
    virtual void wheelEvent(QWheelEvent* event);
 
51
};
 
52
 
 
53
KItemListContainerViewport::KItemListContainerViewport(QGraphicsScene* scene, QWidget* parent) :
 
54
    QGraphicsView(scene, parent)
 
55
{
 
56
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
57
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
58
    setViewportMargins(0, 0, 0, 0);
 
59
    setFrameShape(QFrame::NoFrame);
 
60
}
 
61
 
 
62
void KItemListContainerViewport::wheelEvent(QWheelEvent* event)
 
63
{
 
64
    // Assure that the wheel-event gets forwarded to the parent
 
65
    // and not handled at all by QGraphicsView.
 
66
    event->ignore();
 
67
}
 
68
 
 
69
 
 
70
 
 
71
KItemListContainer::KItemListContainer(KItemListController* controller, QWidget* parent) :
 
72
    QAbstractScrollArea(parent),
 
73
    m_controller(controller),
 
74
    m_horizontalSmoothScroller(0),
 
75
    m_verticalSmoothScroller(0)
 
76
{
 
77
    Q_ASSERT(controller);
 
78
    controller->setParent(this);
 
79
    initialize();
 
80
}
 
81
 
 
82
KItemListContainer::KItemListContainer(QWidget* parent) :
 
83
    QAbstractScrollArea(parent),
 
84
    m_controller(0),
 
85
    m_horizontalSmoothScroller(0),
 
86
    m_verticalSmoothScroller(0)
 
87
{
 
88
    initialize();
 
89
}
 
90
 
 
91
KItemListContainer::~KItemListContainer()
 
92
{
 
93
}
 
94
 
 
95
KItemListController* KItemListContainer::controller() const
 
96
{
 
97
    return m_controller;
 
98
}
 
99
 
 
100
void KItemListContainer::keyPressEvent(QKeyEvent* event)
 
101
{
 
102
    // TODO: We should find a better way to handle the key press events in the view.
 
103
    // The reasons why we need this hack are:
 
104
    // 1. Without reimplementing keyPressEvent() here, the event would not reach the QGraphicsView.
 
105
    // 2. By default, the KItemListView does not have the keyboard focus in the QGraphicsScene, so
 
106
    //    simply sending the event to the QGraphicsView which is the KItemListContainer's viewport
 
107
    //    does not work.
 
108
    KItemListView* view = m_controller->view();
 
109
    if (view) {
 
110
        QApplication::sendEvent(view, event);
 
111
    }
 
112
}
 
113
 
 
114
void KItemListContainer::showEvent(QShowEvent* event)
 
115
{
 
116
    QAbstractScrollArea::showEvent(event);
 
117
    updateGeometries();
 
118
}
 
119
 
 
120
void KItemListContainer::resizeEvent(QResizeEvent* event)
 
121
{
 
122
    QAbstractScrollArea::resizeEvent(event);
 
123
    updateGeometries();
 
124
}
 
125
 
 
126
void KItemListContainer::scrollContentsBy(int dx, int dy)
 
127
{
 
128
    m_horizontalSmoothScroller->scrollContentsBy(dx);
 
129
    m_verticalSmoothScroller->scrollContentsBy(dy);
 
130
}
 
131
 
 
132
void KItemListContainer::wheelEvent(QWheelEvent* event)
 
133
{
 
134
    if (event->modifiers().testFlag(Qt::ControlModifier)) {
 
135
        event->ignore();
 
136
        return;
 
137
    }
 
138
 
 
139
    KItemListView* view = m_controller->view();
 
140
    if (!view) {
 
141
        event->ignore();
 
142
        return;
 
143
    }
 
144
 
 
145
    const bool scrollHorizontally = (event->orientation() == Qt::Horizontal) ||
 
146
                                    (event->orientation() == Qt::Vertical && !verticalScrollBar()->isVisible());
 
147
    KItemListSmoothScroller* smoothScroller = scrollHorizontally ?
 
148
                                              m_horizontalSmoothScroller : m_verticalSmoothScroller;
 
149
 
 
150
    const int numDegrees = event->delta() / 8;
 
151
    const int numSteps = numDegrees / 15;
 
152
 
 
153
    const QScrollBar* scrollBar = smoothScroller->scrollBar();
 
154
    smoothScroller->scrollTo(scrollBar->value() - numSteps * scrollBar->pageStep() / 4);
 
155
 
 
156
    event->accept();
 
157
}
 
158
 
 
159
void KItemListContainer::slotScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous)
 
160
{
 
161
    Q_UNUSED(previous);
 
162
    updateSmoothScrollers(current);
 
163
}
 
164
 
 
165
void KItemListContainer::slotModelChanged(KItemModelBase* current, KItemModelBase* previous)
 
166
{
 
167
    Q_UNUSED(current);
 
168
    Q_UNUSED(previous);
 
169
}
 
170
 
 
171
void KItemListContainer::slotViewChanged(KItemListView* current, KItemListView* previous)
 
172
{
 
173
    QGraphicsScene* scene = static_cast<QGraphicsView*>(viewport())->scene();
 
174
    if (previous) {
 
175
        scene->removeItem(previous);
 
176
        disconnect(previous, SIGNAL(scrollOrientationChanged(Qt::Orientation,Qt::Orientation)), this, SLOT(slotScrollOrientationChanged(Qt::Orientation,Qt::Orientation)));
 
177
        disconnect(previous, SIGNAL(scrollOffsetChanged(qreal,qreal)),        this, SLOT(updateScrollOffsetScrollBar()));
 
178
        disconnect(previous, SIGNAL(maximumScrollOffsetChanged(qreal,qreal)), this, SLOT(updateScrollOffsetScrollBar()));
 
179
        disconnect(previous, SIGNAL(itemOffsetChanged(qreal,qreal)),          this, SLOT(updateItemOffsetScrollBar()));
 
180
        disconnect(previous, SIGNAL(maximumItemOffsetChanged(qreal,qreal)),   this, SLOT(updateItemOffsetScrollBar()));
 
181
        disconnect(previous, SIGNAL(scrollTo(qreal)),                         this, SLOT(scrollTo(qreal)));
 
182
        m_horizontalSmoothScroller->setTargetObject(0);
 
183
        m_verticalSmoothScroller->setTargetObject(0);
 
184
    }
 
185
    if (current) {
 
186
        scene->addItem(current);
 
187
        connect(current, SIGNAL(scrollOrientationChanged(Qt::Orientation,Qt::Orientation)), this, SLOT(slotScrollOrientationChanged(Qt::Orientation,Qt::Orientation)));
 
188
        connect(current, SIGNAL(scrollOffsetChanged(qreal,qreal)),        this, SLOT(updateScrollOffsetScrollBar()));
 
189
        connect(current, SIGNAL(maximumScrollOffsetChanged(qreal,qreal)), this, SLOT(updateScrollOffsetScrollBar()));
 
190
        connect(current, SIGNAL(itemOffsetChanged(qreal,qreal)),          this, SLOT(updateItemOffsetScrollBar()));
 
191
        connect(current, SIGNAL(maximumItemOffsetChanged(qreal,qreal)),   this, SLOT(updateItemOffsetScrollBar()));
 
192
        connect(current, SIGNAL(scrollTo(qreal)),                         this, SLOT(scrollTo(qreal)));
 
193
        m_horizontalSmoothScroller->setTargetObject(current);
 
194
        m_verticalSmoothScroller->setTargetObject(current);
 
195
        updateSmoothScrollers(current->scrollOrientation());
 
196
    }
 
197
}
 
198
 
 
199
void KItemListContainer::scrollTo(qreal offset)
 
200
{
 
201
    const KItemListView* view = m_controller->view();
 
202
    if (view) {
 
203
        if (view->scrollOrientation() == Qt::Vertical) {
 
204
            m_verticalSmoothScroller->scrollTo(offset);
 
205
        } else {
 
206
            m_horizontalSmoothScroller->scrollTo(offset);
 
207
        }
 
208
    }
 
209
}
 
210
 
 
211
void KItemListContainer::updateScrollOffsetScrollBar()
 
212
{
 
213
    const KItemListView* view = m_controller->view();
 
214
    if (!view) {
 
215
        return;
 
216
    }
 
217
 
 
218
    KItemListSmoothScroller* smoothScroller = 0;
 
219
    QScrollBar* scrollOffsetScrollBar = 0;
 
220
    int singleStep = 0;
 
221
    int pageStep = 0;
 
222
    if (view->scrollOrientation() == Qt::Vertical) {
 
223
        smoothScroller = m_verticalSmoothScroller;
 
224
        scrollOffsetScrollBar = verticalScrollBar();
 
225
        singleStep = view->itemSize().height();
 
226
        pageStep = view->size().height();
 
227
    } else {
 
228
        smoothScroller = m_horizontalSmoothScroller;
 
229
        scrollOffsetScrollBar = horizontalScrollBar();
 
230
        singleStep = view->itemSize().width();
 
231
        pageStep = view->size().width();
 
232
    }
 
233
 
 
234
    const int value = view->scrollOffset();
 
235
    const int maximum = qMax(0, int(view->maximumScrollOffset() - pageStep));
 
236
    if (smoothScroller->requestScrollBarUpdate(maximum)) {
 
237
        const bool updatePolicy = (scrollOffsetScrollBar->maximum() > 0 && maximum == 0)
 
238
                                  || horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOn;
 
239
 
 
240
        scrollOffsetScrollBar->setSingleStep(singleStep);
 
241
        scrollOffsetScrollBar->setPageStep(pageStep);
 
242
        scrollOffsetScrollBar->setMinimum(0);
 
243
        scrollOffsetScrollBar->setMaximum(maximum);
 
244
        scrollOffsetScrollBar->setValue(value);
 
245
 
 
246
        if (updatePolicy) {
 
247
            // Prevent a potential endless layout loop (see bug #293318).
 
248
            updateScrollOffsetScrollBarPolicy();
 
249
        }
 
250
    }
 
251
}
 
252
 
 
253
void KItemListContainer::updateItemOffsetScrollBar()
 
254
{
 
255
    const KItemListView* view = m_controller->view();
 
256
    if (!view) {
 
257
        return;
 
258
    }
 
259
 
 
260
    KItemListSmoothScroller* smoothScroller = 0;
 
261
    QScrollBar* itemOffsetScrollBar = 0;
 
262
    int singleStep = 0;
 
263
    int pageStep = 0;
 
264
    if (view->scrollOrientation() == Qt::Vertical) {
 
265
        smoothScroller = m_horizontalSmoothScroller;
 
266
        itemOffsetScrollBar = horizontalScrollBar();
 
267
        singleStep = view->size().width() / 10;
 
268
        pageStep = view->size().width();
 
269
    } else {
 
270
        smoothScroller = m_verticalSmoothScroller;
 
271
        itemOffsetScrollBar = verticalScrollBar();
 
272
        singleStep = view->size().height() / 10;
 
273
        pageStep = view->size().height();
 
274
    }
 
275
 
 
276
    const int value = view->itemOffset();
 
277
    const int maximum = qMax(0, int(view->maximumItemOffset()) - pageStep);
 
278
    if (smoothScroller->requestScrollBarUpdate(maximum)) {
 
279
        itemOffsetScrollBar->setSingleStep(singleStep);
 
280
        itemOffsetScrollBar->setPageStep(pageStep);
 
281
        itemOffsetScrollBar->setMinimum(0);
 
282
        itemOffsetScrollBar->setMaximum(maximum);
 
283
        itemOffsetScrollBar->setValue(value);
 
284
    }
 
285
}
 
286
 
 
287
void KItemListContainer::updateGeometries()
 
288
{
 
289
    QRect rect = geometry();
 
290
 
 
291
    int extra = frameWidth() * 2;
 
292
    QStyleOption option;
 
293
    option.initFrom(this);
 
294
    if (style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &option, this)) {
 
295
        extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &option, this);
 
296
    }
 
297
 
 
298
    const int widthDec = verticalScrollBar()->isVisible()
 
299
                         ? extra + style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, this)
 
300
                         : extra;
 
301
 
 
302
    const int heightDec = horizontalScrollBar()->isVisible()
 
303
                          ? extra + style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, this)
 
304
                          : extra;
 
305
 
 
306
    rect.adjust(0, 0, -widthDec, -heightDec);
 
307
 
 
308
    const QRectF newGeometry(0, 0, rect.width(), rect.height());
 
309
    if (m_controller->view()->geometry() != newGeometry) {
 
310
        m_controller->view()->setGeometry(newGeometry);
 
311
 
 
312
        static_cast<KItemListContainerViewport*>(viewport())->scene()->setSceneRect(0, 0, rect.width(), rect.height());
 
313
        static_cast<KItemListContainerViewport*>(viewport())->viewport()->setGeometry(QRect(0, 0, rect.width(), rect.height()));
 
314
 
 
315
        updateScrollOffsetScrollBar();
 
316
        updateItemOffsetScrollBar();
 
317
    }
 
318
}
 
319
 
 
320
void KItemListContainer::updateSmoothScrollers(Qt::Orientation orientation)
 
321
{
 
322
    if (orientation == Qt::Vertical) {
 
323
        m_verticalSmoothScroller->setPropertyName("scrollOffset");
 
324
        m_horizontalSmoothScroller->setPropertyName("itemOffset");
 
325
    } else {
 
326
        m_horizontalSmoothScroller->setPropertyName("scrollOffset");
 
327
        m_verticalSmoothScroller->setPropertyName("itemOffset");
 
328
    }
 
329
}
 
330
 
 
331
void KItemListContainer::updateScrollOffsetScrollBarPolicy()
 
332
{
 
333
    const KItemListView* view = m_controller->view();
 
334
    Q_ASSERT(view);
 
335
    const bool vertical = (view->scrollOrientation() == Qt::Vertical);
 
336
 
 
337
    QStyleOption option;
 
338
    option.initFrom(this);
 
339
    const int scrollBarInc = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, this);
 
340
 
 
341
    QSizeF newViewSize = m_controller->view()->size();
 
342
    if (vertical) {
 
343
        newViewSize.rwidth() += scrollBarInc;
 
344
    } else {
 
345
        newViewSize.rheight() += scrollBarInc;
 
346
    }
 
347
 
 
348
    const Qt::ScrollBarPolicy policy = view->scrollBarRequired(newViewSize)
 
349
                                       ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded;
 
350
    if (vertical) {
 
351
        setVerticalScrollBarPolicy(policy);
 
352
    } else {
 
353
        setHorizontalScrollBarPolicy(policy);
 
354
    }
 
355
}
 
356
 
 
357
void KItemListContainer::initialize()
 
358
{
 
359
    if (m_controller) {
 
360
        if (m_controller->model()) {
 
361
            slotModelChanged(m_controller->model(), 0);
 
362
        }
 
363
        if (m_controller->view()) {
 
364
            slotViewChanged(m_controller->view(), 0);
 
365
        }
 
366
    } else {
 
367
        m_controller = new KItemListController(this);
 
368
    }
 
369
 
 
370
    connect(m_controller, SIGNAL(modelChanged(KItemModelBase*,KItemModelBase*)),
 
371
            this, SLOT(slotModelChanged(KItemModelBase*,KItemModelBase*)));
 
372
    connect(m_controller, SIGNAL(viewChanged(KItemListView*,KItemListView*)),
 
373
            this, SLOT(slotViewChanged(KItemListView*,KItemListView*)));
 
374
 
 
375
    QGraphicsView* graphicsView = new KItemListContainerViewport(new QGraphicsScene(this), this);
 
376
    setViewport(graphicsView);
 
377
 
 
378
    m_horizontalSmoothScroller = new KItemListSmoothScroller(horizontalScrollBar(), this);
 
379
    m_verticalSmoothScroller = new KItemListSmoothScroller(verticalScrollBar(), this);
 
380
}
 
381
 
 
382
#include "kitemlistcontainer.moc"