+ All Categories
Home > Documents > Qt Item Views In Depth

Qt Item Views In Depth

Date post: 09-May-2015
Category:
Upload: marius-bugge-monsen
View: 9,706 times
Download: 6 times
Share this document with a friend
Description:
In depth presentation of the Qt item views architecture. Presented at Qt Developer Days 2007.
145
Qt Item Views In Depth
Transcript
Page 1: Qt Item Views In Depth

Qt Item Views In Depth

Page 2: Qt Item Views In Depth

2

About me

Marius Bugge Monsen Senior Software Engineer 5 years for TT Msc. comp. sci. NTNU Current projects:

Itemviews QtDBus WebKit

Page 3: Qt Item Views In Depth

3

Introduction Architecture Models In Depth Selections In Depth I Just Want To ...

Contents

Page 4: Qt Item Views In Depth

4

Models In Depth List Tree Editable Items Inserting And Removing Items Lazy Initialization Drag And Drop Testing

Page 5: Qt Item Views In Depth

5

I Just Want To... Show Some Data Insert Lots Of Items Fast Do Sorting And Filtering Have Checkable Items Do Custom Item Painting Have A Custom Item Editor Animate Items

Page 6: Qt Item Views In Depth

6

Introduction

Model View Controller (MVC) Design Pattern Qt Model / View Design

Page 7: Qt Item Views In Depth

7

The MVC Design Pattern

ModelView

Controller

Page 8: Qt Item Views In Depth

8

The Qt Model/View Design

ModelView

Delegate

Selections

Page 9: Qt Item Views In Depth

9

Multiple Views on a Model

Model

View

View

View

Page 10: Qt Item Views In Depth

10

Interchangeable Models

???View

Model

OtherModel

Page 11: Qt Item Views In Depth

11

Chaining Models

ProxyView Model

Page 12: Qt Item Views In Depth

12

Using Model / View

#include <QtGui>

int main(int argc, char *argv[]){ QApplication app(argc, argv); QStandardItemModel model(10, 10); QTableView view; view.setModel(&model); view.show(); return app.exec();}

Page 13: Qt Item Views In Depth

13

Model vs. Items

Q3FileDialog q3filedialog.cpp: 4512 loc

QFileDialog qfiledialog.cpp: 1639 loc qfilesystemmodel.cpp: 1108 loc

total: 2747 loc

Page 14: Qt Item Views In Depth

14

Qt 4 Item Views

~29000 lines of code 39 public classes

9 view classes 11 model classes

Page 15: Qt Item Views In Depth

15

Introduction Architecture Models In Depth Selections In Depth I Just Want To ...

Page 16: Qt Item Views In Depth

16

Architecture

Goals Separating Data And Presentation Designing An Interface Look Ma, No Items!

Page 17: Qt Item Views In Depth

17

History

Goals Separate data from the view Handle a large number of items Only care about the data we show Small memory footprint ... Profit!!!

Page 18: Qt Item Views In Depth

18

Qt 3 Item Views

Page 19: Qt Item Views In Depth

19

View

Qt 3 Item Views

Painting

Selections Data

Editing

Page 20: Qt Item Views In Depth

20

View

Painting

Selections

Editing

Data

Page 21: Qt Item Views In Depth

21

View

Data

Painting

Selections

Editing

Page 22: Qt Item Views In Depth

22

View

Selections Data

PaintingEditing

Page 23: Qt Item Views In Depth

23

Qt 4 Item Views

Data

PaintingEditing

Selections

View

Page 24: Qt Item Views In Depth

24

View

Qt 3 Item Views

Painting

Selections Data

Editing

Page 25: Qt Item Views In Depth

25

Qt 4 Item Views

Data

PaintingEditing

Selections

View

Page 26: Qt Item Views In Depth

26

Qt 4 Item Views

Model

Selections

View

Delegate

Page 27: Qt Item Views In Depth

27

Designing An Interface

ModelView

?

Page 28: Qt Item Views In Depth

28

What Do We Want?

Page 29: Qt Item Views In Depth

29

Lists One dimensional arrays of data

Tables Two dimensional arrays of data

Trees Hierarchies of lists

Graphs

Data Structure Categories

Page 30: Qt Item Views In Depth

30

Lists One dimensional arrays of data

Tables Two dimensional arrays of data

Trees Hierarchies of lists

Graphs

Data Structure Representation

???

Page 31: Qt Item Views In Depth

31

A Hierarchy Of Tables

Page 32: Qt Item Views In Depth

32

The First Prototypes (January 2003)

Page 33: Qt Item Views In Depth

33

Look Ma, No Items!  (Oct. 2003)

Change from QGenericModelItem to QModelIndex--------------------------------------------Why:

- allocating QGenericModelItems on the heap is too slow and we do that a lot

- using a pool/repository is a workaround and not a proper solution

- the QModelIndex is lightweight, have no virtual functions and fast inline constructor and destructor

- we move all functionality to the model itself, which in effect was what happened anyway

Page 34: Qt Item Views In Depth

34

The Model Index

Page 35: Qt Item Views In Depth

35

The Model Index

Not an item Represents a position in a specific table Lightweight Shortlived

Page 36: Qt Item Views In Depth

36

Model

Selections

View

Delegate

Page 37: Qt Item Views In Depth

37

paintindex

Delegate dataindex

ModelModel Viewchangedindex

Selectionselected

index

Page 38: Qt Item Views In Depth

38

Views

Page 39: Qt Item Views In Depth

39

Introduction Architecture Models In Depth Selections In Depth I Just Want To ...

Page 40: Qt Item Views In Depth

40

Models In Depth

Main Model Classes List Tree Editable Items Inserting And Removing Items Lazy Initialization Drag And Drop Testing

Page 41: Qt Item Views In Depth

41

Main Model Classes

QAbstractItemModel QAbstractListModel

QStringListModel QAbstractTableModel

QSqlQueryModel QStandardItemModel QAbstractProxyModel

QSortFilterProxyModel

Page 42: Qt Item Views In Depth

42

QAbstractItemModel

Base class for all models Use when

no existing model fits your use case you need to wrap an existing tree/hierarchical structure

Ignore when only want to show 10 items in a list you can use an existing model or widget

Page 43: Qt Item Views In Depth

43

QAbstractItemModel

5 functions have to be implemented QModelIndex index(int row, int column, const QModelIndex &parent) const QModelIndex parent(const QModelIndex &index) const int rowCount(const QModelIndex &parent) const int columnCount(const QModelIndex &parent) const QVariant data(const QModelIndex &index, int role) const

Page 44: Qt Item Views In Depth

44

QAbstractTableModel

3 functions have to be implemented int rowCount(const QModelIndex &parent) const int columnCount(const QModelIndex &parent) const QVariant data(const QModelIndex &index, int role) const

Page 45: Qt Item Views In Depth

45

QAbstractListModel

2 functions have to be implemented int rowCount(const QModelIndex &parent) const QVariant data(const QModelIndex &index, int role) const

Page 46: Qt Item Views In Depth

46

List Model

Page 47: Qt Item Views In Depth

47

List Model

class MyModel : public QAbstractListModel{public: MyModel(QObject *parent) : QAbstractListModel(parent) {} int rowCount(const QModelIndex&) const { return list.count(); } QVariant data(const QModelIndex &index, int role) const { if (index.isValid() && role == Qt::DisplayRole) return list.at(index.row()); return QVariant(); }private: QList<QString> list;};

Page 48: Qt Item Views In Depth

48

The Model Index

Page 49: Qt Item Views In Depth

49

The Model Index

QVariant MyModel::data(const QModelIndex &index,int role) const

{ int row = index.row(); int column = index.column(); void *ptr = index.internalPointer(); qint64 id = index.internalId(); // same as ptr

MyInternalItem *item = lookup(row, column, id); return item->data(role);}

Page 50: Qt Item Views In Depth

50

The Model Index

3

2

1

0

7

6

5

4

0 1 2 3 4 5 6 7

Page 51: Qt Item Views In Depth

51

3

2

1

0

7

6

5

4

0 1 2 3 4 5 6 7

The Model Index

3

2

1

0

7

6

5

4

0 1 2 3 4 5 6 7

Page 52: Qt Item Views In Depth

52

Tree Model

Page 53: Qt Item Views In Depth

53

Models And Hierarchy

struct SimpleNode{ SimpleNode(SimpleNode *parent) : text(“text”), parentNode(parent) { if (parentNode) parentNode->children.append(this); } ~SimpleNode() { foreach(SimpleNode *child, children) delete child; } QVariant data() const { return text; } QString text; SimpleNode *parentNode; QList<SimpleNode*> children;};

Page 54: Qt Item Views In Depth

54

Tree Model

class SimpleModel : public QAbstractItemModel{public: SimpleModel(QObject *parent = 0); ~SimpleModel(); QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex parent(const QModelIndex &child) const; int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const;protected: SimpleNode *nodeForIndex(const QModelIndex &index) const; int rowForNode(SimpleNode *node) const;private: SimpleNode *root;};

Page 55: Qt Item Views In Depth

55

Tree Model

QModelIndex SimpleModel::index(int row, int column, const QModelIndex &parent) const{ if (hasIndex(row, column, parent)) { SimpleNode *parentNode = nodeForIndex(parent); SimpleNode *childNode = parentNode->children.at(row); return createIndex(row, column, childNode); } return QModelIndex();}

Page 56: Qt Item Views In Depth

56

Tree Model

QModelIndex SimpleModel::parent(const QModelIndex &child) const{ SimpleNode *childNode = nodeForIndex(child); SimpleNode *parentNode = childNode->parentNode;

if (parentNode == root) return QModelIndex();

int row = rowForNode(parentNode); int column = 0; return createIndex(row, column, parentNode);}

Page 57: Qt Item Views In Depth

57

Tree Model

int SimpleModel::rowCount(const QModelIndex &parent) const{ SimpleNode *parentNode = nodeForIndex(parent); return parentNode->children.count();}

int SimpleModel::columnCount(const QModelIndex &parent) const{ Q_UNUSED(parent); return 1;}

Page 58: Qt Item Views In Depth

58

Tree Model

QVariant SimpleModel::data(const QModelIndex &index, int role) const{ if (index.isValid() && role == Qt::DisplayRole) { SimpleNode *node = nodeForIndex(index); return node->data(); } return QVariant();}

Page 59: Qt Item Views In Depth

59

Tree Model

SimpleNode *SimpleModel::nodeForIndex(const QModelIndex &index) const{ if (index.isValid()) return static_cast<SimpleNode*>( index.internalPointer()); return root;}

int SimpleModel::rowForNode(SimpleNode *node) const{ return node->parentNode->children.indexOf(node);}

Page 60: Qt Item Views In Depth

60

Editable Items

Page 61: Qt Item Views In Depth

61

Editable Items

class EditableModel : public SimpleModel{ Q_OBJECTpublic: EditableModel(QObject *parent = 0); ~EditableModel();

bool setData(const QModelIndex &index, const QVariant &value, int role);

Qt::ItemFlags flags(const QModelIndex &index) const;};

Page 62: Qt Item Views In Depth

62

Check Item

Editable Items

Pixmap Item

Page 63: Qt Item Views In Depth

63

Qt::ItemDataRole

DisplayRole usually text

DecorationRole usually an icon

EditRole key data to be edited

CheckStateRole item check box state

Page 64: Qt Item Views In Depth

64

Qt::ItemDataRole

AccessibleTextRole AccessibleDescriptionRole SizeHintRole TextAlignmentRole BackgroundRole ForegroundRole TextColorRole

Page 65: Qt Item Views In Depth

65

Editable Items

bool EditableModel::setData(const QModelIndex &index, const QVariant &value, int role){ if (index.isValid() && role == Qt::EditRole) { SimpleNode *node = nodeForIndex(index); node->text = value.toString(); QModelIndex topLeft = index; QModelIndex bottomRight = index; emit dataChanged(topLeft, bottomRight); return true; } return false;}

Page 66: Qt Item Views In Depth

66

Editable Items

Qt::ItemFlags EditableModel::flags(const QModelIndex &index) const{ Qt::ItemFlags defaultFlags = SimpleModel::flags(index); if (index.isValid()) return Qt::ItemIsEditable | defaultFlags; return defaultFlags;}

Page 67: Qt Item Views In Depth

67

Qt::ItemFlags

ItemIsSelectable ItemIsEditable ItemIsDragEnabled ItemIsDropEnabled ItemIsUserCheckable ItemIsEnabled ItemIsTristate

Page 68: Qt Item Views In Depth

68

Inserting And Removing Items

Page 69: Qt Item Views In Depth

69

Inserting And Removing Items

class InsertRemoveModel : public EditableModel{public: InsertRemoveModel(QObject *parent = 0); ~InsertRemoveModel();

// specialized insert and remove functions void insertNode(int i, SimpleNode *parentNode, SimpleNode *node); void removeNode(SimpleNode *node); void removeAllNodes();};

Page 70: Qt Item Views In Depth

70

Inserting And Removing Items

void InsertRemoveModel::insertNode(int i, SimpleNode *parentNode, SimpleNode *node){ const QModelIndex parent = indexForNode(parentNode); int firstRow = i; int lastRow = i;

beginInsertRows(parent, firstRow, lastRow); parentNode->children.insert(i, node); endInsertRows();}

Page 71: Qt Item Views In Depth

71

Inserting And Removing Items

void InsertRemoveModel::removeNode(SimpleNode *node){ SimpleNode *parentNode = node->parent; const QModelIndex parent = indexForNode(parentNode); int i = rowForNode(node); int firstRow = i; int lastRow = i; beginRemoveRows(parent, firstRow, lastRow); parentNode->children.remove(i); endRemoveRows();}

Page 72: Qt Item Views In Depth

72

Inserting And Removing Items

void InsertRemoveModel::removeAllNodes()

{

root->children.clear();

reset();

}

Page 73: Qt Item Views In Depth

73

The Persistent Model Index

Page 74: Qt Item Views In Depth

74

The Persistent Model Index

A Model Index Persistent (i.e. not short lived) Updated By The Model

Page 75: Qt Item Views In Depth

75

The Persistent Model Index

Page 76: Qt Item Views In Depth

76

Persistent Model Index

class Q_CORE_EXPORT QPersistentModelIndexData

{

public:

QPersistentModelIndexData();

QPersistentModelIndexData(const QModelIndex &idx);

QModelIndex index;

QAtomicInt ref;

const QAbstractItemModel *model;

...

};

Page 77: Qt Item Views In Depth

77

The Persistent Model Index

0

1

2

3

1

0

2

3

4

0

1

2

3

0

1

2

3

1

beginInsertRows endInsertRows

1

Page 78: Qt Item Views In Depth

78

Persistent Model Index

void changePersistentIndex(const QModelIndex &from,

const QModelIndex &to);

void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);

QModelIndexList persistentIndexList() const;

Page 79: Qt Item Views In Depth

79

Lazy Initialization

Page 80: Qt Item Views In Depth

80

Lazy Initialization

class LazyModel : public SimpleModel

{

public:

LazyModel(QObject *parent = 0);

~LazyModel();

bool hasChildren(const QModelIndex &parent) const;

bool canFetchMore(const QModelIndex &parent) const;

void fetchMore(const QModelIndex &parent)

};

Page 81: Qt Item Views In Depth

81

Lazy Initialization

bool LazyModel::hasChildren(const QModelIndex &parent) const

{

int depth = 0;

SimpleNode *parentNode = nodeForIndex(parent);

while (parentNode) {

parentNode = parentNode->parentNode;

++depth;

}

return (depth <= 3);

}

Page 82: Qt Item Views In Depth

82

Lazy Initialization

bool LazyModel::canFetchMore(const QModelIndex &parent) const

{

static const int maxChildren = 100;

SimpleNode *parentNode = nodeForIndex(parent);

return parentNode->children.count() < maxChildren;

}

Page 83: Qt Item Views In Depth

83

Lazy Initialization

void LazyModel::fetchMore(const QModelIndex &parent)

{

static const int maxChildren = 100;

SimpleNode *parentNode = nodeForIndex(parent);

int count = parentNode->children.count();

if (count < maxChildren) {

beginInsertRows(parent, count, maxChildren - count);

while (parentNode->children.count() < maxChildren)

new SimpleNode(parentNode);

endInsertRows();

}

}

Page 84: Qt Item Views In Depth

84

Drag And Drop

Page 85: Qt Item Views In Depth

85

Drag And Drop

class DndModel : public InsertRemoveModel

{

...

Qt::ItemFlags flags(const QModelIndex &index) const;

Qt::DropActions supportedDragActions() const;

Qt::DropActions supportedDropActions() const;

QStringList mimeTypes() const;

QMimeData *mimeData(const QModelIndexList &indexes) const;

...

};

Page 86: Qt Item Views In Depth

86

Drag And Drop

Qt::ItemFlags DndModel::flags(const QModelIndex &index) const

{

if (index.isValid())

return Qt::ItemIsDragEnabled

| Qt::ItemIsDropEnabled

| InsertRemoveModel::flags(index);

// we allow dropping in the empty area (invalid index)

return Qt::ItemIsDropEnabled

| InsertRemoveModel::flags(index);

}

Page 87: Qt Item Views In Depth

87

Drag And Drop

Qt::DropActions DndModel::supportedDragActions() const

{

return Qt::CopyAction | Qt::MoveAction;

}

Qt::DropActions DndModel::supportedDropActions() const

{

return Qt::CopyAction | Qt::MoveAction;

}

Page 88: Qt Item Views In Depth

88

Drag And Drop

QStringList DndModel::mimeTypes() const

{

QStringList types;

types << "application/vnd.text.list";

return types;

}

Page 89: Qt Item Views In Depth

89

Drag And DropQMimeData *DndModel::mimeData(const QModelIndexList &indexes) const

{

QByteArray encodedData;

QDataStream stream(&encodedData, QIODevice::WriteOnly);

foreach (QModelIndex index, indexes) {

if (index.isValid()) {

QString text = data(index, Qt::DisplayRole).toString();

stream << text;

}

}

QMimeData *mimeData = new QMimeData();

mimeData->setData("application/vnd.text.list", encodedData);

return mimeData;

}

Page 90: Qt Item Views In Depth

90

Drag And Drop

bool insertRows(int row, int count, const QModelIndex &parent);

bool insertColumns(int column, int count,

const QModelIndex &parent);

bool removeRows(int row, int count, const QModelIndex &parent);

bool removeColumns(int column, int count,

const QModelIndex &parent);

Page 91: Qt Item Views In Depth

91

Drag And Drop

class DndModel : public InsertRemoveModel

{

...

bool dropMimeData(const QMimeData *data,

Qt::DropAction action,

int row, int column,

const QModelIndex &parent);

bool removeRows(int row, int count,

const QModelIndex &parent);

};

Page 92: Qt Item Views In Depth

92

Drag And Drop

bool DndModel::dropMimeData(const QMimeData *data,

Qt::DropAction action,

int row, int column,

const QModelIndex &parent)

{

if (action == Qt::IgnoreAction)

return true;

if (!data->asFormat("application/vnd.text.list"))

return false;

if (column >= columnCount(parent))

return false;

Page 93: Qt Item Views In Depth

93

Drag And Drop // find where to insert the new items

SimpleNode *parentNode = nodeForIndex(parent);

// get the data

QByteArray encodedData = data->data("application/vnd.text.list");

QDataStream stream(&encodedData, QIODevice::ReadOnly);

while (!stream.atEnd()) {

QString text;

stream >> text;

SimpleNode *node = new SimpleNode(0);

node->text = text;

insertNode(row, parentNode, node);

}

return true;

}

Page 94: Qt Item Views In Depth

94

Drag And Dropbool DndModel::removeRows(int row, int count,

const QModelIndex &parent)

{

beginRemoveRows(row, row + count - 1, parent);

SimpleNode *parentNode = nodeForIndex(parent);

for (int i = 0; i < count; ++i) {

if (row < parentNode->children.count()) {

SimpleNode *node = parentNode->children.at(row);

parentNode->children.remove(row);

node->parentNode = 0;

}

}

endRemoveRows();

}

Page 95: Qt Item Views In Depth

95

Testing

QtTestLibrary ModelTest

http://labs.trolltech.com/page/Projects/Itemview/Modeltest

Page 96: Qt Item Views In Depth

96

Testing

ModelTest Signal emission Hierarchy Row and column count Parent / Child relationships Much more...

Page 97: Qt Item Views In Depth

97

Testing

int main(int argc, char *argv[])

{

SimpleModel model;

ModelTest test(&model);

return 0;

}

Add to the project (.pro) file: include(../path/to/dir/modeltest.pri)

Page 98: Qt Item Views In Depth

98

Introduction Architecture Models In Depth Selections In Depth I Just Want To ...

Page 99: Qt Item Views In Depth

99

Selections In Depth

Selection Ranges Making Selections Selection Properties Tips When Selecting

Page 100: Qt Item Views In Depth

100

Selections In Depth

Page 101: Qt Item Views In Depth

101

Selection Range

Page 102: Qt Item Views In Depth

102

Selection Ranges

Benefits Selecting consecutive items is fast Memory efficient (with few or no selections) Fast (with few or no selections)

Problems Selecting many individual items is slow Slow (with many selection ranges)

Page 103: Qt Item Views In Depth

103

Selections

Selection Range Top Left Index Bottom Right Index

Selection List of Ranges

Selection Model Lost of Selections Current Selection Current Index

Page 104: Qt Item Views In Depth

104

Views And Selections

SelectionsView

Page 105: Qt Item Views In Depth

105

Making Selections

void select(const QItemSelection &selection,

QItemSelectionModel::SelectionFlags command)

Page 106: Qt Item Views In Depth

106

Making Selections

SelectionFlags NoUpdate ­ don't change the selections Clear ­ clear existing selections Select – select the given ranges Deselect – unselect the given ranges Toggle – reverse the selection state of the given ranges Current – set the current selection Rows – expand the given ranges to rows Columns – expand the given ranges to to columns

Page 107: Qt Item Views In Depth

107

View Selection Properties

SelectionMode SelectionBehavior

Page 108: Qt Item Views In Depth

108

View Selection Properties

SelectionBehavior SelectItems SelectRows SelectColumns

Page 109: Qt Item Views In Depth

109

View Selection Properties

SelectionMode NoSelection SingleSelection MultiSelection ContigousSelection ExtendedSelection

Page 110: Qt Item Views In Depth

110

View Selection Properties

SelectionMode NoSelection

No selection ranges SingleSelection

Single item (may be expanded by SelectionBehavior) MultiSelection

Multiple selection ranges Toggles existing selected items

ContiguousSelection ExtendedSelection

Page 111: Qt Item Views In Depth

111

View Selection Properties

SelectionMode NoSelection SingleSelection MultiSelection ContigousSelection

Clears existing selections before selecting Shift + selecting will update the current selection only

ExtendedSelection

Page 112: Qt Item Views In Depth

112

View Selection Properties

SelectionMode NoSelection SingleSelection MultiSelection ContiguousSelection ExtendedSelection

Clears existing selections before selecting Shift + selecting will select the current selection only Ctrl + selecting will toggle the current selection range

Page 113: Qt Item Views In Depth

113

Tips When Selecting

Select Using Ranges Compile Ranges in Selection Objects Clear When Possible

avoid merging selection ranges Avoid Toggle

avoids splitting selection ranges

Page 114: Qt Item Views In Depth

114

Introduction Architecture Models In Depth Selections In Depth I Just Want To ...

Page 115: Qt Item Views In Depth

115

I Just Want To...

Show Some Data Insert Lots Of Items Fast Do Sorting And Filtering Have Checkable Items Do Custom Item Painting Have A Custom Item Editor Animate Items

Page 116: Qt Item Views In Depth

116

Showing Data

Widgets QListWidget QTableWidget QTreeWidget

Models QStringListModel QStandardItemModel

Page 117: Qt Item Views In Depth

117

Showing Data

The General Rules (tm) Models

Faster Less Overhead Harder To Implement

Widgets Slower More Overhead Easier To Use

Page 118: Qt Item Views In Depth

118

Showing Data Using A Widget

int main(int argc, char *argv[]){ QApplication app(argc, argv); QStringList entryList = QDir::current().entryList();

QListWidget widget; foreach (QString entry, entryList) { QListWidgetItem *item = new QListWidgetItem(entry); widget.addItem(item); }

widget.show(); return app.exec();}

Page 119: Qt Item Views In Depth

119

Showing Data Using A Widget

int main(int argc, char *argv[]){ QApplication app(argc, argv); QStringList entryList = QDir::current().entryList();

QListWidget widget; widget.addItems(entryList);

widget.show(); return app.exec();}

Page 120: Qt Item Views In Depth

120

Showing Data Using A Model

int main(int argc, char *argv[]){ QApplication app(argc, argv); QStringList entryList = QDir::current().entryList();

QStringListModel model(entryList); QListView view; view.setModel(&model); view.show(); return app.exec();}

Page 121: Qt Item Views In Depth

121

Insert Lots Of Items Fast

Bottlenecks Converting Items To Model Indexes Laying Out Items In The Views

Workaround Insert Items Before Setting The Model On The View Insert Before Showing The View Insert Lists Of Items Q*Widgets – set the item data before you set the view

Page 122: Qt Item Views In Depth

122

Inserting Lots Of Items Fastint main(int argc, char *argv[])

{

QApplication app(argc, argv);

QTreeView view;

QStandardItemModel model;

QStandardItem *parent = model.invisibleRootItem();

for (int i = 0; i < 100000; ++i) {

QStandardItem *item = new QStandartModelItem();

item->setText(“test”);

parent->appendRow(item);

}

view.setModel(&model);

view.show();

app.exec();

}

Page 123: Qt Item Views In Depth

123

Inserting Lots Of Items Fastint main(int argc, char *argv[])

{

QApplication app(argc, argv);

QTreeWidget widget;

QList<QTreeWidgetItem*> items;

for (int i = 0; i < 100000; ++i) {

QTreeWidgetItem *item = new QTreeWidgetItem();

item->setText(0, “test”);

items.append(item);

}

widget.invisibleRootItem()->addChildren(items);

widget.show();

app.exec();

}

Page 124: Qt Item Views In Depth

124

Sorting And Filtering

Sorting QListWidget QTableWidget QTreeWidget QSortFilterProxyModel

Filtering QSortFilterProxyModel

Page 125: Qt Item Views In Depth

125

QSortFilterProxyModel

ProxyView Model

Page 126: Qt Item Views In Depth

126

Sorting And Filtering

int main(int argc, char *argv[]){ QApplication app(argc, argv);

QStringListModel model; model.setStringList(QDir::current().entryList());

QSortFilterProxyModel filter; filter.setSourceModel(&model);

QListView view; view.setModel(&filter); view.show();

return app.exec();}

Page 127: Qt Item Views In Depth

127

Checkable Items

Qt::ItemDataRoles ItemCheckStateRole

Qt::ItemFlags ItemIsUserCheckable ItemIsTristate

Qt::CheckedState Unchecked PartiallyChecked Checked

Page 128: Qt Item Views In Depth

128

Checkable Items

int main(int argc, char *argv[]){ QApplication app(argc, argv); QTreeWidget widget;

for (int i = 0; i < 100; ++i) { QTreeWidgetItem *item = new QTreeWidgetItem; item->setText(0, “hello”); item->setCheckState(0, Qt::Unchecked); widget.invisibleRootItem()->addChild(item); }

widget.show; return app.exec();}

Page 129: Qt Item Views In Depth

129

Custom Item Painting

Model

Selections

View

Delegate

Page 130: Qt Item Views In Depth

130

Custom Item Painting

QAbstractItemDelegate QItemDelegate

QSqlRelationalDelegate

Page 131: Qt Item Views In Depth

131

Custom Item Painting

Item Delegate Painting Clipping Size Hint Creating Editor Widget Managing Editor Widget Geometry

Page 132: Qt Item Views In Depth

132

Custom Item Painting

class CustomDelegate : public QItemDelegate{public: CustomDelegate(QObject *parent = 0) : QItemDelegate(parent) {} ~CustomDelegate() {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->fillRect(option.rect, Qt::green); painter->drawText(option.rect, index.data().toString()); }};

Page 133: Qt Item Views In Depth

133

Custom Item Painting

int main(int argc, char *argv[]){ QApplication app(argc, argv); QListWidget widget; widget.addItems(QDir::current().entryList()); CustomDelegate *delegate = new CustomDelegate(&widget); widget.setItemDelegate(delegate); widget.show(); return app.exec();}

Page 134: Qt Item Views In Depth

134

Custom Item Painting

class CustomDelegate : public QItemDelegate{public: CustomDelegate(QObject *parent = 0) : QItemDelegate(parent) {} ~CustomDelegate() {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->fillRect(option.rect, Qt::green); painter->drawText(option.rect, index.data().toString()); }};

Page 135: Qt Item Views In Depth

135

Custom Item Editor

QAbstractItemDelegate::createEditor(...) QItemEditorFactory

QItemEditorCreatorBase

Page 136: Qt Item Views In Depth

136

Custom Item Editor

class Button : public QPushButton{ Q_OBJECTpublic: Button(QWidget *parent) : QPushButton(parent) { setCheckable(true); connect(this, SIGNAL(toggled(bool)), this, SLOT(showState(bool))); }protected slots: void showState(bool checked) { setText(checked ? "true" : "false"); }};

Page 137: Qt Item Views In Depth

137

Custom Item Editorint main(int argc, char *argv[]){ ... QItemDelegate *delegate = qobject_cast<QItemDelegate*>(view.itemDelegate())

QItemEditorCreatorBase *creator = new QItemEditorCreator<Button>("checked");

QItemEditorFactory factory; factory.registerEditor(QVariant::Bool, creator); delegate->setItemEditorFactory(&factory);

view.show(); return app.exec();}

Page 138: Qt Item Views In Depth

138

Animated Items

Model

Selections

View

Delegateupdate(index)

Page 139: Qt Item Views In Depth

139

Animated Itemsclass Delegate : public QItemDelegate{ Q_OBJECTpublic: Delegate(QObject *parent = 0); ~Delegate();

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;

signals: void update(const QModelIndex &index); ...

Page 140: Qt Item Views In Depth

140

Animated Items ...private: struct Animation { enum Type { Incrementing, Decrementing }; inline Animation(const QModelIndex &idx = QModelIndex()) : frame(0), type(Incrementing) { index = idx; } int frame; Type type; QPersistentModelIndex index; };

int frameCount; int increment; int timerId; mutable QList<Animation> animations;};

Page 141: Qt Item Views In Depth

141

Animated Items

void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{ bool mouseOver = option.state & QStyle::State_MouseOver; int f = animationFrame(index, mouseOver); QColor color(f, f, f); painter->save(); painter->setBrush(color); painter->drawRoundRect(option.rect); painter->restore();}

Page 142: Qt Item Views In Depth

142

Animated Itemsvoid Delegate::timerEvent(QTimerEvent *event){ if (event->timerId() == timerId && !animations.isEmpty()) { for (int i = animations.count() - 1; i >= 0; --i) { emit update(animations.at(i).index); if (animations.at(i).type == Animation::Incrementing) { // increment frame if (animations.at(i).frame < frameCount) animations[i].frame += increment; } else { // decrement frame if (animations.at(i).frame <= 0) animations.removeAt(i); else animations[i].frame -= increment; } } }}

Page 143: Qt Item Views In Depth

143

Animated Items

int Delegate::animationFrame(const QModelIndex &index, bool mouseOver) const{ int i = animationIndex(index); if (i != -1) { // we have a running animation if (!mouseOver // but the mouse is no longer over && animations.at(i).type == Animation::Incrementing) // reverse the animation animations[i].type = Animation::Decrementing;

return qBound(0, animations.at(i).frame, frameCount); }

// no running animation if (mouseOver) animations.append(Animation(index)); return 0;}

Page 144: Qt Item Views In Depth

144

Resources

     http://en.wikipedia.org/wiki/Model­view­controller     http://doc.trolltech.com/4.3/model­view.html

http://doc.trolltech.com/4.3/model­view­programming.htmlhttp://labs.trolltech.com/page/Projects/Itemview/Modeltest

Page 145: Qt Item Views In Depth

145

That's all folks!Questions ?


Recommended