aboutsummaryrefslogtreecommitdiff
path: root/src/views/mlistview_p.h
blob: 26c7a2a17476a84eb4e3c3a8a7aca122e4e5674f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#ifndef MLISTVIEWPRIVATE_H__
#define MLISTVIEWPRIVATE_H__

#include <QObject>
#include <QHash>
#include <QModelIndex>
#include <QVector>
#include <QRectF>
#include <QTimer>
#include <QSet>
#include <MLabel>
#include <MList>
#include "mabstractcellcreator.h"
#include "private/mwidgetview_p.h"

class MWidget;
class MListView;
class MListIndex;
class MPannableViewport;
class MSideBar;
class MWidgetRecycler;
class QAbstractItemModel;
class QItemSelectionModel;
class QItemSelection;
class QTimeLine;

namespace MListViewPrivateNamespace
{
    template<class T>
    T *findParentWidgetOfType(QGraphicsItem *widget)
    {
        T *targetWidget = NULL;
        QGraphicsWidget *parentWidget = widget->parentWidget();
        while (parentWidget && targetWidget == NULL) {
            targetWidget = qobject_cast<T *>(parentWidget);
            parentWidget = parentWidget->parentWidget();
        }

        return targetWidget;
    }

    template <typename T>
    inline int dFindLowerIndex(const QVector<T> &vec, const T &item)
    {
        int start = 0, end = vec.size() - 1;
        int i = (start + end + 1) >> 1;
        while (end - start > 0) {
            if (vec.at(i) > item)
                end = i - 1;
            else
                start = i;
            i = (start + end + 1) >> 1;
        }
        return i;
    }
}

class MListViewPrivate : public QObject
{
    Q_OBJECT

public:
    MListViewPrivate();
    virtual ~MListViewPrivate();

    void updateItemHeight();

    MWidget *createCell(int row);
    void deleteItem(MWidget *widget);

    void setSeparator(MWidget *separator);
    void setHeadersCreator(MCellCreator *headersCreator);

    MWidget *findCellAtRow(int row);

    void viewportRectChanged(const QRectF &viewportRect);
    void connectPannableViewport();
    void updateViewportRect(const QPointF &position, const QSizeF &size);
    void updatePannableViewportPosition();

    void updateFirstVisibleRow(const QModelIndex &index);
    void updateLastVisibleRow(const QModelIndex &index);

    void drawHorizontalSeparator(const int row, QPainter *painter, const QStyleOptionGraphicsItem *option);

    QPointF locateScrollToPosition(const QModelIndex &index, MList::ScrollHint hint);
    QPointF calculateViewportNextPosition();
    void updateScrollToTargetPosition();

public:
    virtual void createSeparators();
    virtual void updateSeparators();
    virtual void updateHeaders();

    virtual void createVisibleItems();
    virtual void clearVisibleItemsArray();
    virtual void clearFirstAndLastVisibleRows();
    virtual void removeInvisibleItems(const QPoint &firstVisibleItemCoord, const QPoint &lastVisibleItemCoord);
    virtual void cellClicked(MWidget *source);
    virtual void cellLongTapped(const QModelIndex &index);
    virtual void selectionChange(const QItemSelection &selected, const QItemSelection &deselected);
    virtual void updateItemSize();
    virtual void updateSeparatorSize();
    virtual QSizeF cellSize(int row) const;
    virtual void resetModel(MListModel *controllerModel);
    virtual int locateVisibleRowAt(int y, int x = 0) = 0;

    virtual int locatePosOfItem(int row) = 0;
    virtual int locatePosOfItem(const QModelIndex &index) = 0;
    virtual int itemsCount() const = 0;
    virtual QModelIndex flatRowToIndex(int row) const = 0;
    virtual int indexToFlatRow(const QModelIndex &index) const = 0;
    virtual void createVisibleItems(int firstVisibleRow, int lastVisibleRow);
    virtual void createVisibleItems(const QModelIndex &firstVisibleRow,
                                    const QModelIndex &lastVisibleRow) = 0;

    virtual MWidget *createItem(int row) = 0;
    virtual int totalHeight() = 0;
    virtual int hseparatorsCount() const = 0;
    virtual QModelIndex locateVisibleIndexAt(int pos) = 0;
    virtual bool isGroupHeader(const QModelIndex &index);
    virtual void layoutChanged();

    virtual void drawSeparators(QPainter *painter, const QStyleOptionGraphicsItem *option);
    virtual void drawSeparator(const int row, QPainter *painter, const QStyleOptionGraphicsItem *option);

    virtual void updateListIndexVisibility();

    virtual void disconnectSignalsFromModelToListView();
    virtual void connectSignalsFromModelToListView();

public Q_SLOTS:
    void movingDetectionTimerTimeout();
    void viewportPositionChanged(const QPointF &pos);
    void viewportSizeChanged(const QSizeF &size);
    void viewportRangeChanged(const QRectF &range);
    void controllerParentChanged();
    void updateListGeometry();

    void _q_moveViewportToNextPosition(int frame);

public:
    MListView *q_ptr;
    MList *controller;
    MListModel *controllerModel;
    QAbstractItemModel *model;
    QItemSelectionModel *selectionModel;
    MWidgetRecycler *recycler;
    MWidget *hseparator;
    int hseparatorHeight;
    MCellCreator *headersCreator;

    QVector<MWidget *> visibleItems;
    QPointF viewportTopLeft;
    int viewportVisibleHeight;

    int itemHeight;
    int rowCount;
    int viewWidth;
    int hdrHeight;

    bool forceRepaint;

    bool clearVisibleOnRelayout;

    // Section for panning detection
    QPointF oldViewportRectPosition;
    bool moving;
    QTimer movingDetectorTimer;
    MPannableViewport *pannableViewport;
    QPointF listPosition;

    // Scroll animation
    QTimeLine *scrollToTimeLine;
    QPointF targetPosition;
    qreal frictionK;
};

class MPlainListViewPrivate : public MListViewPrivate
{
public:
    MPlainListViewPrivate();
    virtual ~MPlainListViewPrivate();

public:
    virtual int totalHeight();

    virtual QModelIndex locateVisibleIndexAt(int pos);
    virtual int locateVisibleRowAt(int y, int x = 0);

    virtual int locatePosOfItem(int row);
    virtual int locatePosOfItem(const QModelIndex &index);
    virtual int hseparatorsCount() const;
    virtual int itemsCount() const;
    virtual int indexToFlatRow(const QModelIndex &index) const;
    virtual QModelIndex flatRowToIndex(int row) const;
    virtual void createVisibleItems(const QModelIndex &firstVisibleRow,
                                    const QModelIndex &lastVisibleRow);
    virtual MWidget *createItem(int row);
};

class MPlainMultiColumnListViewPrivate : public MPlainListViewPrivate
{
public:
    MPlainMultiColumnListViewPrivate();
    virtual ~MPlainMultiColumnListViewPrivate();

public:
    void setVerticalSeparator(MWidget *separator);
    int itemsToRows(int items) const;
    int flatRowToColumn(int row) const;

public:
    virtual void createSeparators();
    virtual void updateSeparators();

    virtual void createVisibleItems();
    virtual void clearVisibleItemsArray();
    virtual void removeInvisibleItems(const QPoint &firstVisibleItemCoord, const QPoint &lastVisibleItemCoord);
    virtual int locatePosOfItem(int row);
    virtual int hseparatorsCount() const;
    virtual int totalHeight();
    virtual MWidget *createItem(int row);
    virtual int locateVisibleRowAt(int y, int x = 0);
    virtual void updateItemSize();
    virtual void updateSeparatorSize();
    virtual QSizeF cellSize(int row) const;
    virtual void cellClicked(MWidget *source);
    virtual void selectionChange(const QItemSelection &selected, const QItemSelection &deselected);
    virtual void createVisibleItems(const QModelIndex &firstVisibleRow,
                                    const QModelIndex &lastVisibleRow);

    virtual void drawSeparator(const int row, QPainter *painter, const QStyleOptionGraphicsItem *option);
    virtual void drawVerticalSeparator(int row, int column, QPainter *painter, const QStyleOptionGraphicsItem *option);
public:
    QHash<MWidget *, int> widgetFlatRows;
    MWidget *vseparator;
    int vseparatorWidth;
};

class MGroupHeaderListViewPrivate : public MListViewPrivate
{
public:
    MGroupHeaderListViewPrivate();
    virtual ~MGroupHeaderListViewPrivate();

public:
    MWidget *createHeader(int headerIndex);
    int headerHeight();
    int headersCount() const;
    int itemsCount(int index) const;
    void updateHeadersPositions();
    void updateHeadersRows();
    void updateHeadersIndexes();

public:
    virtual int indexToFlatRow(const QModelIndex &index) const;
    virtual int locatePosOfItem(int headerIndex, int itemIndex); // groups only
    virtual int groupSize(int headerIndex) const;
    virtual void resetModel(MListModel *controllerModel);
    virtual int totalHeight();
    virtual QSizeF cellSize(int row) const;

    virtual QModelIndex locateVisibleIndexAt(int pos);
    virtual int locateVisibleRowAt(int y, int x = 0);

    virtual int locatePosOfItem(int row);
    virtual int locatePosOfItem(const QModelIndex &index);
    virtual int hseparatorsCount() const;
    virtual int itemsCount() const;
    virtual QModelIndex flatRowToIndex(int row) const;

    void createVisibleItems(int firstVisibleRow, int lastVisibleRow);
    virtual void createVisibleItems(const QModelIndex &firstVisibleRow,
                                    const QModelIndex &lastVisibleRow);
    virtual MWidget *createItem(int row);
    virtual bool isGroupHeader(const QModelIndex &index);
    virtual void layoutChanged();

    virtual void drawSeparator(const int row, QPainter *painter, const QStyleOptionGraphicsItem *option);

    virtual void updateListIndexVisibility();

public:
    QVector<int> headersPositions;
    QVector<int> headersRows;

    MListIndex *listIndexWidget;
};

class MMultiColumnListViewPrivate : public MGroupHeaderListViewPrivate
{
public:
    MMultiColumnListViewPrivate();
    virtual ~MMultiColumnListViewPrivate();

public:
    void setVerticalSeparator(MWidget *separator);
    int itemsToRows(int items) const;
    int rowsInGroup(int headerIndex) const;
    int flatRowToColumn(int row) const;

public:
    virtual void createSeparators();
    virtual void updateSeparators();

    virtual void createVisibleItems();
    virtual void clearVisibleItemsArray();
    virtual void removeInvisibleItems(const QPoint &firstVisibleItemCoord, const QPoint &lastVisibleItemCoord);
    virtual void updateItemSize();
    virtual void updateSeparatorSize();
    virtual QSizeF cellSize(int row) const;
    virtual void cellClicked(MWidget *source);
    virtual void selectionChange(const QItemSelection &selected, const QItemSelection &deselected);
    virtual int locatePosOfItem(int headerIndex, int itemIndex);
    virtual int locatePosOfItem(const QModelIndex &index);
    virtual int hseparatorsCount() const;
    virtual int groupSize(int headerIndex) const;
    virtual int totalHeight();
    virtual int locateVisibleRowAt(int y, int x = 0);
    virtual int locatePosOfItem(int row);
    virtual void createVisibleItems(const QModelIndex &firstVisibleRow,
                                    const QModelIndex &lastVisibleRow);
    virtual MWidget *createItem(int row);

    virtual void drawSeparator(const int row, QPainter *painter, const QStyleOptionGraphicsItem *option);
    virtual void drawVerticalSeparator(int row, int column, QPainter *painter, const QStyleOptionGraphicsItem *option);
public:
    QHash<MWidget *, int> widgetFlatRows;
    MWidget *vseparator;
    int vseparatorWidth;
};

class MDefaultHeadersCreator : public MAbstractCellCreator<MLabel>
{
public:
    MDefaultHeadersCreator(const QString &headerObjectName) {
        setHeaderObjectName(headerObjectName);
    }

    virtual ~MDefaultHeadersCreator() {

    }

    virtual MWidget *createCell(const QModelIndex &index, MWidgetRecycler &recycler) const {
        MLabel *header = dynamic_cast<MLabel *>(recycler.take(MLabel::staticMetaObject.className()));
        if (header == NULL) {
            header = new MLabel;
            header->setObjectName(headerObjectName);
        }
        updateCell(index, header);

        return header;
    }

    virtual void updateCell(const QModelIndex &index, MWidget *cell) const {
        MLabel *header = dynamic_cast<MLabel *>(cell);
        QString title = index.data(Qt::DisplayRole).toString();
        header->setText(title);
    }

    virtual void setHeaderObjectName(const QString &headerObjectName) {
        this->headerObjectName = headerObjectName;
    }

private:
    QString headerObjectName;
};

#endif