Your SlideShare is downloading. ×
0
Qt Item Views In Depth
About me

              Marius Bugge Monsen
              Senior Software Engineer
              5 years for TT
       ...
Contents

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




       ...
   Models In Depth
       List
       Tree
       Editable Items
       Inserting And Removing Items
       Lazy Ini...
   I Just Want To...
    
        Show Some Data
    
        Insert Lots Of Items Fast
    
        Do Sorting And Fi...
Introduction

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




                              ...
The MVC Design Pattern



               Controller




       View                 Model




                            ...
The Qt Model/View Design

               Delegate




       View                 Model




               Selections



 ...
Multiple Views on a Model

        View




        View                Model




        View



                        ...
Interchangeable Models

                          Model




     View           ???




                          Other
  ...
Chaining Models




   View           Proxy   Model




                                  11
Using Model / View
#include <QtGui>

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

    QStandardIt...
Model vs. Items

   Q3FileDialog
       q3filedialog.cpp: 4512 loc
   QFileDialog
       qfiledialog.cpp: 1639 loc
   ...
Qt 4 Item Views

   ~29000 lines of code
   39 public classes
       9 view classes
       11 model classes




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




                 ...
Architecture

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




       ...
History

   Goals
       Separate data from the view
       Handle a large number of items
       Only care about the ...
Qt 3 Item Views




                  18
Qt 3 Item Views


           Painting           Editing



                       View



          Selections           D...
Painting           Editing



             View



Selections                    Data




                                ...
Painting          Editing



                        View



Selections                               Data




           ...
Painting
                    Editing


             View



Selections           Data




                               22
Qt 4 Item Views


                       Painting
            View
                       Editing




          Selections...
Qt 3 Item Views


           Painting           Editing



                       View



          Selections           D...
Qt 4 Item Views


                       Painting
            View
                       Editing




          Selections...
Qt 4 Item Views


                  Delegate




         View                  Model




                  Selections


 ...
Designing An Interface




                  ?
          View           Model




                                 27
What Do We Want?




                   28
Data Structure Categories

   Lists
       One dimensional arrays of data
   Tables
       Two dimensional arrays of d...
Data Structure Representation

   Lists
       One dimensional arrays of data


                                        ...
A Hierarchy Of Tables




                        31
The First Prototypes (January 2003)




                                      32
Look Ma, No Items!  (Oct. 2003)
Change from QGenericModelItem to QModelIndex
--------------------------------------------
...
The Model Index




                  34
The Model Index

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




        ...
Delegate




View                Model




       Selections


                            36
changed                paint               data
Model               View               Delegate           Model
         i...
Views




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




                 ...
Models In Depth

   Main Model Classes
   List
   Tree
   Editable Items
   Inserting And Removing Items
   Lazy Ini...
Main Model Classes

   QAbstractItemModel
       QAbstractListModel
            QStringListModel
       QAbstractTable...
QAbstractItemModel

   Base class for all models
   Use when
       no existing model fits your use case
       you ne...
QAbstractItemModel

   5 functions have to be implemented
       QModelIndex index(int row, int column,
               ...
QAbstractTableModel

   3 functions have to be implemented
       int rowCount(const QModelIndex &parent) const
       ...
QAbstractListModel

   2 functions have to be implemented
       int rowCount(const QModelIndex &parent) const
       Q...
List Model




             46
List Model
class MyModel : public QAbstractListModel
{
public:
    MyModel(QObject *parent) : QAbstractListModel(parent) {...
The Model Index




                  48
The Model Index

QVariant MyModel::data(const QModelIndex &index,
                       int role) const
{
    int row = i...
The Model Index

                  7

                  6

                  5

                  4

                  3

...
The Model Index

7

6                                   7

                                    6
5                        ...
Tree Model




             52
Models And Hierarchy
struct SimpleNode
{
    SimpleNode(SimpleNode *parent)
        : text(“text”), parentNode(parent) {
 ...
Tree Model
class SimpleModel : public QAbstractItemModel
{
public:
    SimpleModel(QObject *parent = 0);
    ~SimpleModel(...
Tree Model

QModelIndex SimpleModel::index(int row, int column,
                               const QModelIndex &parent) ...
Tree Model

QModelIndex SimpleModel::parent(const QModelIndex &child) const
{
    SimpleNode *childNode = nodeForIndex(chi...
Tree Model

int SimpleModel::rowCount(const QModelIndex &parent) const
{
    SimpleNode *parentNode = nodeForIndex(parent)...
Tree Model

QVariant SimpleModel::data(const QModelIndex &index,
                           int role) const
{
    if (inde...
Tree Model

SimpleNode *SimpleModel::nodeForIndex(const QModelIndex &index)
const
{
    if (index.isValid())
        retur...
Editable Items




                 60
Editable Items


class EditableModel : public SimpleModel
{
    Q_OBJECT
public:
    EditableModel(QObject *parent = 0);
 ...
Editable Items




                 Pixmap Item
                 Check Item



                               62
Qt::ItemDataRole

   DisplayRole
       usually text
   DecorationRole
       usually an icon
   EditRole
       key...
Qt::ItemDataRole

   AccessibleTextRole
   AccessibleDescriptionRole
   SizeHintRole
   TextAlignmentRole
   Backgrou...
Editable Items


bool EditableModel::setData(const QModelIndex &index,
                            const QVariant &value, ...
Editable Items


Qt::ItemFlags EditableModel::flags(const QModelIndex &index)
const
{
    Qt::ItemFlags defaultFlags = Sim...
Qt::ItemFlags

   ItemIsSelectable
   ItemIsEditable
   ItemIsDragEnabled
   ItemIsDropEnabled
   ItemIsUserCheckable...
Inserting And Removing Items




                               68
Inserting And Removing Items

class InsertRemoveModel : public EditableModel
{
public:
    InsertRemoveModel(QObject *pare...
Inserting And Removing Items


void InsertRemoveModel::insertNode(int i,
                                   SimpleNode *pa...
Inserting And Removing Items


void InsertRemoveModel::removeNode(SimpleNode *node)
{
    SimpleNode *parentNode = node->p...
Inserting And Removing Items




void InsertRemoveModel::removeAllNodes()
{
    root->children.clear();
    reset();
}



...
The Persistent Model Index




                             73
The Persistent Model Index

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




         ...
The Persistent Model Index




                             75
Persistent Model Index


  class Q_CORE_EXPORT QPersistentModelIndexData
  {
  public:
       QPersistentModelIndexData();...
The Persistent Model Index


       beginInsertRows           endInsertRows


   0                 0       0              ...
Persistent Model Index



void changePersistentIndex(const QModelIndex &from,
                          const QModelIndex ...
Lazy Initialization




                      79
Lazy Initialization
class LazyModel : public SimpleModel
{
public:
     LazyModel(QObject *parent = 0);
     ~LazyModel();...
Lazy Initialization
bool LazyModel::hasChildren(const QModelIndex &parent) const
{
    int depth = 0;
    SimpleNode *pare...
Lazy Initialization
bool LazyModel::canFetchMore(const QModelIndex &parent) const
{
    static const int maxChildren = 100...
Lazy Initialization
void LazyModel::fetchMore(const QModelIndex &parent)
{
    static const int maxChildren = 100;
    Sim...
Drag And Drop




                84
Drag And Drop
class DndModel : public InsertRemoveModel
{
     ...
     Qt::ItemFlags flags(const QModelIndex &index) cons...
Drag And Drop

Qt::ItemFlags DndModel::flags(const QModelIndex &index) const
{
    if (index.isValid())
       return Qt::...
Drag And Drop



Qt::DropActions DndModel::supportedDragActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}


...
Drag And Drop



QStringList DndModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list"...
Drag And Drop
QMimeData *DndModel::mimeData(const QModelIndexList &indexes) const
{
    QByteArray encodedData;
    QDataS...
Drag And Drop



bool insertRows(int row, int count, const QModelIndex &parent);
bool insertColumns(int column, int count,...
Drag And Drop
class DndModel : public InsertRemoveModel
{
     ...
     bool dropMimeData(const QMimeData *data,
         ...
Drag And Drop

bool DndModel::dropMimeData(const QMimeData *data,
                           Qt::DropAction action,
      ...
Drag And Drop
    // find where to insert the new items
    SimpleNode *parentNode = nodeForIndex(parent);
    // get the ...
Drag And Drop
bool DndModel::removeRows(int row, int count,
                         const QModelIndex &parent)
{
    begi...
Testing

   QtTestLibrary
   ModelTest
       http://labs.trolltech.com/page/Projects/Itemview/Modeltest




          ...
Testing

   ModelTest
       Signal emission
       Hierarchy
       Row and column count
       Parent / Child relat...
Testing

    int main(int argc, char *argv[])
    {
            SimpleModel model;
            ModelTest test(&model);
   ...
   Introduction
   Architecture
   Models In Depth
   Selections In Depth
   I Just Want To ...




                 ...
Selections In Depth

   Selection Ranges
   Making Selections
   Selection Properties
   Tips When Selecting




     ...
Selections In Depth




                      100
Selection Range




                  101
Selection Ranges

      Benefits
          Selecting consecutive items is fast
          Memory efficient (with few or ...
Selections

            Selection Range
                Top Left Index
                Bottom Right Index
            ...
Views And Selections




          View         Selections




                                    104
Making Selections




void select(const QItemSelection &selection,
            QItemSelectionModel::SelectionFlags command...
Making Selections

   SelectionFlags
       NoUpdate ­ don't change the selections
       Clear ­ clear existing select...
View Selection Properties

   SelectionMode
   SelectionBehavior




                            107
View Selection Properties

   SelectionBehavior
       SelectItems
       SelectRows
       SelectColumns




        ...
View Selection Properties

   SelectionMode
       NoSelection
       SingleSelection
       MultiSelection
       Co...
View Selection Properties

   SelectionMode
       NoSelection
            No selection ranges
       SingleSelection
...
View Selection Properties

   SelectionMode
       NoSelection
       SingleSelection
       MultiSelection
       Co...
View Selection Properties

   SelectionMode
       NoSelection
       SingleSelection
       MultiSelection
       Co...
Tips When Selecting

   Select Using Ranges
   Compile Ranges in Selection Objects
   Clear When Possible
       avoid...
   Introduction
   Architecture
   Models In Depth
   Selections In Depth
   I Just Want To ...




                 ...
I Just Want To...

 
     Show Some Data
 
     Insert Lots Of Items Fast
 
     Do Sorting And Filtering
 
     Have ...
Showing Data

   Widgets
       QListWidget
       QTableWidget
       QTreeWidget
   Models
       QStringListModel...
Showing Data

   The General Rules (tm)
       Models
            Faster
            Less Overhead
            Harder...
Showing Data Using A Widget

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QStringList entryLis...
Showing Data Using A Widget


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QStringList entryLi...
Showing Data Using A Model

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QStringList entryList...
Insert Lots Of Items Fast

   Bottlenecks
       Converting Items To Model Indexes
       Laying Out Items In The Views...
Inserting Lots Of Items Fast
  int main(int argc, char *argv[])
  {
      QApplication app(argc, argv);
      QTreeView vi...
Inserting Lots Of Items Fast
  int main(int argc, char *argv[])
  {
      QApplication app(argc, argv);
      QTreeWidget ...
Sorting And Filtering

   Sorting
       QListWidget
       QTableWidget
       QTreeWidget
       QSortFilterProxyMo...
QSortFilterProxyModel




   View         Proxy   Model




                                125
Sorting And Filtering
int main(int argc, char *argv[])
{
   QApplication app(argc, argv);

    QStringListModel model;
   ...
Checkable Items

   Qt::ItemDataRoles
       ItemCheckStateRole
   Qt::ItemFlags
       ItemIsUserCheckable
       It...
Checkable Items
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTreeWidget widget;

    for (int...
Custom Item Painting


                Delegate




         View                Model




                Selections


  ...
Custom Item Painting

   QAbstractItemDelegate
       QItemDelegate
            QSqlRelationalDelegate




            ...
Custom Item Painting

   Item Delegate
       Painting
       Clipping
       Size Hint
       Creating Editor Widget...
Custom Item Painting
class CustomDelegate : public QItemDelegate
{
public:
    CustomDelegate(QObject *parent = 0)
       ...
Custom Item Painting

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QListWidget widget;
    wid...
Custom Item Painting
class CustomDelegate : public QItemDelegate
{
public:
    CustomDelegate(QObject *parent = 0)
       ...
Custom Item Editor

   QAbstractItemDelegate::createEditor(...)
   QItemEditorFactory
       QItemEditorCreatorBase



...
Custom Item Editor

class Button : public QPushButton
{
    Q_OBJECT
public:
    Button(QWidget *parent) : QPushButton(par...
Custom Item Editor
int main(int argc, char *argv[])
{
    ...
    QItemDelegate *delegate =
        qobject_cast<QItemDele...
Animated Items


   update(index)   Delegate




            View                Model




                   Selections

...
Animated Items
class Delegate : public QItemDelegate
{
    Q_OBJECT
public:
    Delegate(QObject *parent = 0);
    ~Delega...
Animated Items
    ...
private:
    struct Animation {
        enum Type { Incrementing, Decrementing };
        inline An...
Animated Items
void Delegate::paint(QPainter *painter,
                     const QStyleOptionViewItem &option,
          ...
Animated Items
void Delegate::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == timerId && !animations.isEmpty(...
Animated Items
int Delegate::animationFrame(const QModelIndex &index,
                             bool mouseOver) const
{...
Resources


     http://en.wikipedia.org/wiki/Model­view­controller
     http://doc.trolltech.com/4.3/model­view.html
   h...
That's all folks!
 Questions ?




                    145
Upcoming SlideShare
Loading in...5
×

Qt Item Views In Depth

9,915

Published on

In depth presentation of the Qt item views architecture. Presented at Qt Developer Days 2007.

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
9,915
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
243
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Transcript of "Qt Item Views In Depth"

  1. 1. Qt Item Views In Depth
  2. 2. About me  Marius Bugge Monsen  Senior Software Engineer  5 years for TT  Msc. comp. sci. NTNU  Current projects:  Itemviews  QtDBus  WebKit 2
  3. 3. Contents  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 3
  4. 4.  Models In Depth  List  Tree  Editable Items  Inserting And Removing Items  Lazy Initialization  Drag And Drop  Testing 4
  5. 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 5
  6. 6. Introduction  Model View Controller (MVC) Design Pattern  Qt Model / View Design 6
  7. 7. The MVC Design Pattern Controller View Model 7
  8. 8. The Qt Model/View Design Delegate View Model Selections 8
  9. 9. Multiple Views on a Model View View Model View 9
  10. 10. Interchangeable Models Model View ??? Other Model 10
  11. 11. Chaining Models View Proxy Model 11
  12. 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(); } 12
  13. 13. Model vs. Items  Q3FileDialog  q3filedialog.cpp: 4512 loc  QFileDialog  qfiledialog.cpp: 1639 loc  qfilesystemmodel.cpp: 1108 loc  total: 2747 loc 13
  14. 14. Qt 4 Item Views  ~29000 lines of code  39 public classes  9 view classes  11 model classes 14
  15. 15.  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 15
  16. 16. Architecture  Goals  Separating Data And Presentation  Designing An Interface  Look Ma, No Items! 16
  17. 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!!! 17
  18. 18. Qt 3 Item Views 18
  19. 19. Qt 3 Item Views Painting Editing View Selections Data 19
  20. 20. Painting Editing View Selections Data 20
  21. 21. Painting Editing View Selections Data 21
  22. 22. Painting Editing View Selections Data 22
  23. 23. Qt 4 Item Views Painting View Editing Selections Data 23
  24. 24. Qt 3 Item Views Painting Editing View Selections Data 24
  25. 25. Qt 4 Item Views Painting View Editing Selections Data 25
  26. 26. Qt 4 Item Views Delegate View Model Selections 26
  27. 27. Designing An Interface ? View Model 27
  28. 28. What Do We Want? 28
  29. 29. Data Structure Categories  Lists  One dimensional arrays of data  Tables  Two dimensional arrays of data  Trees  Hierarchies of lists  Graphs 29
  30. 30. Data Structure Representation  Lists  One dimensional arrays of data ???  Tables  Two dimensional arrays of data  Trees  Hierarchies of lists  Graphs 30
  31. 31. A Hierarchy Of Tables 31
  32. 32. The First Prototypes (January 2003) 32
  33. 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 33
  34. 34. The Model Index 34
  35. 35. The Model Index  Not an item  Represents a position in a specific table  Lightweight  Shortlived 35
  36. 36. Delegate View Model Selections 36
  37. 37. changed paint data Model View Delegate Model index index index selected index Selection 37
  38. 38. Views 38
  39. 39.  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 39
  40. 40. Models In Depth  Main Model Classes  List  Tree  Editable Items  Inserting And Removing Items  Lazy Initialization  Drag And Drop  Testing 40
  41. 41. Main Model Classes  QAbstractItemModel  QAbstractListModel  QStringListModel  QAbstractTableModel  QSqlQueryModel  QStandardItemModel  QAbstractProxyModel  QSortFilterProxyModel 41
  42. 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 42
  43. 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 43
  44. 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 44
  45. 45. QAbstractListModel  2 functions have to be implemented  int rowCount(const QModelIndex &parent) const  QVariant data(const QModelIndex &index, int role) const 45
  46. 46. List Model 46
  47. 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; }; 47
  48. 48. The Model Index 48
  49. 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); } 49
  50. 50. The Model Index 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 50
  51. 51. The Model Index 7 6 7 6 5 5 4 4 3 2 3 1 0 2 0 1 2 3 4 5 6 7 1 0 0 1 2 3 4 5 6 7 51
  52. 52. Tree Model 52
  53. 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; }; 53
  54. 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; }; 54
  55. 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(); } 55
  56. 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); } 56
  57. 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; } 57
  58. 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(); } 58
  59. 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); } 59
  60. 60. Editable Items 60
  61. 61. Editable Items class EditableModel : public SimpleModel { Q_OBJECT public: EditableModel(QObject *parent = 0); ~EditableModel(); bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; }; 61
  62. 62. Editable Items Pixmap Item Check Item 62
  63. 63. Qt::ItemDataRole  DisplayRole  usually text  DecorationRole  usually an icon  EditRole  key data to be edited  CheckStateRole  item check box state 63
  64. 64. Qt::ItemDataRole  AccessibleTextRole  AccessibleDescriptionRole  SizeHintRole  TextAlignmentRole  BackgroundRole  ForegroundRole  TextColorRole 64
  65. 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; } 65
  66. 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; } 66
  67. 67. Qt::ItemFlags  ItemIsSelectable  ItemIsEditable  ItemIsDragEnabled  ItemIsDropEnabled  ItemIsUserCheckable  ItemIsEnabled  ItemIsTristate 67
  68. 68. Inserting And Removing Items 68
  69. 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(); }; 69
  70. 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(); } 70
  71. 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(); } 71
  72. 72. Inserting And Removing Items void InsertRemoveModel::removeAllNodes() { root->children.clear(); reset(); } 72
  73. 73. The Persistent Model Index 73
  74. 74. The Persistent Model Index  A Model Index  Persistent (i.e. not short lived)  Updated By The Model 74
  75. 75. The Persistent Model Index 75
  76. 76. Persistent Model Index class Q_CORE_EXPORT QPersistentModelIndexData { public: QPersistentModelIndexData(); QPersistentModelIndexData(const QModelIndex &idx); QModelIndex index; QAtomicInt ref; const QAbstractItemModel *model; ... }; 76
  77. 77. The Persistent Model Index beginInsertRows endInsertRows 0 0 0 0 1 1 1 1 1 2 1 2 2 3 2 3 3 3 4 77
  78. 78. Persistent Model Index void changePersistentIndex(const QModelIndex &from, const QModelIndex &to); void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; 78
  79. 79. Lazy Initialization 79
  80. 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) }; 80
  81. 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); } 81
  82. 82. Lazy Initialization bool LazyModel::canFetchMore(const QModelIndex &parent) const { static const int maxChildren = 100; SimpleNode *parentNode = nodeForIndex(parent); return parentNode->children.count() < maxChildren; } 82
  83. 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(); } } 83
  84. 84. Drag And Drop 84
  85. 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; ... }; 85
  86. 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); } 86
  87. 87. Drag And Drop Qt::DropActions DndModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions DndModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } 87
  88. 88. Drag And Drop QStringList DndModel::mimeTypes() const { QStringList types; types << "application/vnd.text.list"; return types; } 88
  89. 89. Drag And Drop QMimeData *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; } 89
  90. 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); 90
  91. 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); }; 91
  92. 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; 92
  93. 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; } 93
  94. 94. Drag And Drop bool 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(); } 94
  95. 95. Testing  QtTestLibrary  ModelTest  http://labs.trolltech.com/page/Projects/Itemview/Modeltest 95
  96. 96. Testing  ModelTest  Signal emission  Hierarchy  Row and column count  Parent / Child relationships  Much more... 96
  97. 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) 97
  98. 98.  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 98
  99. 99. Selections In Depth  Selection Ranges  Making Selections  Selection Properties  Tips When Selecting 99
  100. 100. Selections In Depth 100
  101. 101. Selection Range 101
  102. 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) 102
  103. 103. Selections  Selection Range  Top Left Index  Bottom Right Index  Selection  List of Ranges  Selection Model  Lost of Selections  Current Selection  Current Index 103
  104. 104. Views And Selections View Selections 104
  105. 105. Making Selections void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) 105
  106. 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 106
  107. 107. View Selection Properties  SelectionMode  SelectionBehavior 107
  108. 108. View Selection Properties  SelectionBehavior  SelectItems  SelectRows  SelectColumns 108
  109. 109. View Selection Properties  SelectionMode  NoSelection  SingleSelection  MultiSelection  ContigousSelection  ExtendedSelection 109
  110. 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 110
  111. 111. View Selection Properties  SelectionMode  NoSelection  SingleSelection  MultiSelection  ContigousSelection  Clears existing selections before selecting  Shift + selecting will update the current selection only  ExtendedSelection 111
  112. 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 112
  113. 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 113
  114. 114.  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 114
  115. 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 115
  116. 116. Showing Data  Widgets  QListWidget  QTableWidget  QTreeWidget  Models  QStringListModel  QStandardItemModel 116
  117. 117. Showing Data  The General Rules (tm)  Models  Faster  Less Overhead  Harder To Implement  Widgets  Slower  More Overhead  Easier To Use 117
  118. 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(); } 118
  119. 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(); } 119
  120. 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(); } 120
  121. 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 121
  122. 122. Inserting Lots Of Items Fast int 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(); } 122
  123. 123. Inserting Lots Of Items Fast int 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(); } 123
  124. 124. Sorting And Filtering  Sorting  QListWidget  QTableWidget  QTreeWidget  QSortFilterProxyModel  Filtering  QSortFilterProxyModel 124
  125. 125. QSortFilterProxyModel View Proxy Model 125
  126. 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(); } 126
  127. 127. Checkable Items  Qt::ItemDataRoles  ItemCheckStateRole  Qt::ItemFlags  ItemIsUserCheckable  ItemIsTristate  Qt::CheckedState  Unchecked  PartiallyChecked  Checked 127
  128. 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(); } 128
  129. 129. Custom Item Painting Delegate View Model Selections 129
  130. 130. Custom Item Painting  QAbstractItemDelegate  QItemDelegate  QSqlRelationalDelegate 130
  131. 131. Custom Item Painting  Item Delegate  Painting  Clipping  Size Hint  Creating Editor Widget  Managing Editor Widget Geometry 131
  132. 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()); } }; 132
  133. 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(); } 133
  134. 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()); } }; 134
  135. 135. Custom Item Editor  QAbstractItemDelegate::createEditor(...)  QItemEditorFactory  QItemEditorCreatorBase 135
  136. 136. Custom Item Editor class Button : public QPushButton { Q_OBJECT public: 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"); } }; 136
  137. 137. Custom Item Editor int 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(); } 137
  138. 138. Animated Items update(index) Delegate View Model Selections 138
  139. 139. Animated Items class Delegate : public QItemDelegate { Q_OBJECT public: 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); ... 139
  140. 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; }; 140
  141. 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(); } 141
  142. 142. Animated Items void 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; } } } } 142
  143. 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; } 143
  144. 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.html http://labs.trolltech.com/page/Projects/Itemview/Modeltest 144
  145. 145. That's all folks! Questions ? 145
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×