SlideShare une entreprise Scribd logo
1  sur  145
Télécharger pour lire hors ligne
Qt Item Views In Depth
About me

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


                                      2
Contents

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




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




                                       4
   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
Introduction

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




                                                 6
The MVC Design Pattern



               Controller




       View                 Model




                                    7
The Qt Model/View Design

               Delegate




       View                 Model




               Selections



                                    8
Multiple Views on a Model

        View




        View                Model




        View



                                    9
Interchangeable Models

                          Model




     View           ???




                          Other
                          Model


                                  10
Chaining Models




   View           Proxy   Model




                                  11
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
Model vs. Items

   Q3FileDialog
       q3filedialog.cpp: 4512 loc
   QFileDialog
       qfiledialog.cpp: 1639 loc
       qfilesystemmodel.cpp: 1108 loc
            total: 2747 loc




                                         13
Qt 4 Item Views

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




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




                          15
Architecture

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




                                       16
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
Qt 3 Item Views




                  18
Qt 3 Item Views


           Painting           Editing



                       View



          Selections           Data




                                        19
Painting           Editing



             View



Selections                    Data




                                     20
Painting          Editing



                        View



Selections                               Data




                                                21
Painting
                    Editing


             View



Selections           Data




                               22
Qt 4 Item Views


                       Painting
            View
                       Editing




          Selections    Data




                                  23
Qt 3 Item Views


           Painting           Editing



                       View



          Selections           Data




                                        24
Qt 4 Item Views


                       Painting
            View
                       Editing




          Selections    Data




                                  25
Qt 4 Item Views


                  Delegate




         View                  Model




                  Selections


                                       26
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 data
   Trees
       Hierarchies of lists
   Graphs




                                         29
Data Structure Representation

   Lists
       One dimensional arrays of data


                                         ???
   Tables
       Two dimensional arrays of data
   Trees
       Hierarchies of lists
   Graphs




                                               30
A Hierarchy Of Tables




                        31
The First Prototypes (January 2003)




                                      32
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
The Model Index




                  34
The Model Index

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




                                                35
Delegate




View                Model




       Selections


                            36
changed                paint               data
Model               View               Delegate           Model
         index                index               index
                   selected
                    index




                  Selection


                                                                  37
Views




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




                          39
Models In Depth

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

                                   40
Main Model Classes

   QAbstractItemModel
       QAbstractListModel
            QStringListModel
       QAbstractTableModel
            QSqlQueryModel
       QStandardItemModel
       QAbstractProxyModel
            QSortFilterProxyModel




                                     41
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
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
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
QAbstractListModel

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




                                                                  45
List Model




             46
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
The Model Index




                  48
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
The Model Index

                  7

                  6

                  5

                  4

                  3

                  2

                  1

                  0

                      0   1   2   3   4   5   6   7


                                                      50
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
Tree Model




             52
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
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
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
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
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
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
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
Editable Items




                 60
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
Editable Items




                 Pixmap Item
                 Check Item



                               62
Qt::ItemDataRole

   DisplayRole
       usually text
   DecorationRole
       usually an icon
   EditRole
       key data to be edited
   CheckStateRole
       item check box state



                                63
Qt::ItemDataRole

   AccessibleTextRole
   AccessibleDescriptionRole
   SizeHintRole
   TextAlignmentRole
   BackgroundRole
   ForegroundRole
   TextColorRole



                                64
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
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
Qt::ItemFlags

   ItemIsSelectable
   ItemIsEditable
   ItemIsDragEnabled
   ItemIsDropEnabled
   ItemIsUserCheckable
   ItemIsEnabled
   ItemIsTristate



                          67
Inserting And Removing Items




                               68
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
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
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
Inserting And Removing Items




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




                                           72
The Persistent Model Index




                             73
The Persistent Model Index

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




                                        74
The Persistent Model Index




                             75
Persistent Model Index


  class Q_CORE_EXPORT QPersistentModelIndexData
  {
  public:
       QPersistentModelIndexData();
       QPersistentModelIndexData(const QModelIndex &idx);
       QModelIndex index;
       QAtomicInt ref;
       const QAbstractItemModel *model;
       ...
  };




                                                            76
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
Persistent Model Index



void changePersistentIndex(const QModelIndex &from,
                          const QModelIndex &to);


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


QModelIndexList persistentIndexList() const;




                                                              78
Lazy Initialization




                      79
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
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
Lazy Initialization
bool LazyModel::canFetchMore(const QModelIndex &parent) const
{
    static const int maxChildren = 100;
    SimpleNode *parentNode = nodeForIndex(parent);
    return parentNode->children.count() < maxChildren;
}




                                                                82
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
Drag And Drop




                84
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
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
Drag And Drop



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


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




                                                         87
Drag And Drop



QStringList DndModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list";
    return types;
}




                                            88
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
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
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
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
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
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
Testing

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




                                                                     95
Testing

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




                                       96
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
   Introduction
   Architecture
   Models In Depth
   Selections In Depth
   I Just Want To ...




                          98
Selections In Depth

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




                           99
Selections In Depth




                      100
Selection Range




                  101
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
Selections

            Selection Range
                Top Left Index
                Bottom Right Index
            Selection
                List of Ranges
            Selection Model
                Lost of Selections
                Current Selection
                Current Index

                                      103
Views And Selections




          View         Selections




                                    104
Making Selections




void select(const QItemSelection &selection,
            QItemSelectionModel::SelectionFlags command)




                                                     105
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
View Selection Properties

   SelectionMode
   SelectionBehavior




                            107
View Selection Properties

   SelectionBehavior
       SelectItems
       SelectRows
       SelectColumns




                            108
View Selection Properties

   SelectionMode
       NoSelection
       SingleSelection
       MultiSelection
       ContigousSelection
       ExtendedSelection




                             109
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
View Selection Properties

   SelectionMode
       NoSelection
       SingleSelection
       MultiSelection
       ContigousSelection
            Clears existing selections before selecting
            Shift + selecting will update the current selection only
       ExtendedSelection




                                                                        111
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
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
   Introduction
   Architecture
   Models In Depth
   Selections In Depth
   I Just Want To ...




                          114
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
Showing Data

   Widgets
       QListWidget
       QTableWidget
       QTreeWidget
   Models
       QStringListModel
       QStandardItemModel




                             116
Showing Data

   The General Rules (tm)
       Models
            Faster
            Less Overhead
            Harder To Implement
       Widgets
            Slower
            More Overhead
            Easier To Use


                                   117
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
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
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
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
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
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
Sorting And Filtering

   Sorting
       QListWidget
       QTableWidget
       QTreeWidget
       QSortFilterProxyModel
   Filtering
       QSortFilterProxyModel




                                124
QSortFilterProxyModel




   View         Proxy   Model




                                125
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
Checkable Items

   Qt::ItemDataRoles
       ItemCheckStateRole
   Qt::ItemFlags
       ItemIsUserCheckable
       ItemIsTristate
   Qt::CheckedState
       Unchecked
       PartiallyChecked
       Checked

                              127
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
Custom Item Painting


                Delegate




         View                Model




                Selections


                                     129
Custom Item Painting

   QAbstractItemDelegate
       QItemDelegate
            QSqlRelationalDelegate




                                      130
Custom Item Painting

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




                                          131
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
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
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
Custom Item Editor

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




                                               135
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
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
Animated Items


   update(index)   Delegate




            View                Model




                   Selections


                                        138
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
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
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
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
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
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
That's all folks!
 Questions ?




                    145

Contenu connexe

Tendances

ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで増田 亨
 
MvcのFatモデルに立ち向かう
MvcのFatモデルに立ち向かうMvcのFatモデルに立ち向かう
MvcのFatモデルに立ち向かうShun Hikita
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門増田 亨
 
社内のマニュアルをSphinxで作ってみた
社内のマニュアルをSphinxで作ってみた社内のマニュアルをSphinxで作ってみた
社内のマニュアルをSphinxで作ってみたIosif Takakura
 
Introduction to Design Pattern
Introduction to Design  PatternIntroduction to Design  Pattern
Introduction to Design PatternSanae BEKKAR
 
DDD sample code explained in Java
DDD sample code explained in JavaDDD sample code explained in Java
DDD sample code explained in Java増田 亨
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行gree_tech
 
System engineering
System engineeringSystem engineering
System engineeringLisa Elisa
 
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptx
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptxವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptx
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptxManjuManjunathC
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようDQNEO
 
Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Kenjiro Kubota
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325Yoshihisa Ozaki
 
xv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読むxv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読むmfumi
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方信之 岩永
 
LR parsing
LR parsingLR parsing
LR parsingichikaz3
 

Tendances (20)

ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで
 
MvcのFatモデルに立ち向かう
MvcのFatモデルに立ち向かうMvcのFatモデルに立ち向かう
MvcのFatモデルに立ち向かう
 
Software Design Patterns
Software Design PatternsSoftware Design Patterns
Software Design Patterns
 
凝集度と責務
凝集度と責務凝集度と責務
凝集度と責務
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門
 
社内のマニュアルをSphinxで作ってみた
社内のマニュアルをSphinxで作ってみた社内のマニュアルをSphinxで作ってみた
社内のマニュアルをSphinxで作ってみた
 
Oose lab notes
Oose lab notesOose lab notes
Oose lab notes
 
Introduction to Design Pattern
Introduction to Design  PatternIntroduction to Design  Pattern
Introduction to Design Pattern
 
DDD sample code explained in Java
DDD sample code explained in JavaDDD sample code explained in Java
DDD sample code explained in Java
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
 
System engineering
System engineeringSystem engineering
System engineering
 
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptx
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptxವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptx
ವಿಕಾಸದ ತತ್ವಗಳು ಹಾಗೂ ಶೈಕ್ಷಣಿಕ ಮಹತ್ವ.pptx
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみよう
 
Bonfire API #1 APIのリトライ処理
Bonfire API #1 APIのリトライ処理Bonfire API #1 APIのリトライ処理
Bonfire API #1 APIのリトライ処理
 
Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325
 
xv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読むxv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読む
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方
 
LR parsing
LR parsingLR parsing
LR parsing
 
Requirements Engineering
Requirements EngineeringRequirements Engineering
Requirements Engineering
 

En vedette

Creating a game using C++, OpenGL and Qt
Creating a game using C++, OpenGL and QtCreating a game using C++, OpenGL and Qt
Creating a game using C++, OpenGL and Qtguestd5d4ce
 
Best Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIBest Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIICS
 
Best Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIBest Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIICS
 
Best Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IVBest Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IVICS
 
Best Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part IBest Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part IICS
 
ISSA Journal Paper - JavaScript Infection Model
ISSA Journal Paper - JavaScript Infection ModelISSA Journal Paper - JavaScript Infection Model
ISSA Journal Paper - JavaScript Infection ModelAditya K Sood
 
Audio recording evaluration unit 4
Audio recording evaluration unit 4Audio recording evaluration unit 4
Audio recording evaluration unit 4Sophia Gent
 
A guide to prayer
A guide to prayerA guide to prayer
A guide to prayerHelmon Chan
 
Annualreport slideshow 2015_v12_reducedsize
Annualreport slideshow 2015_v12_reducedsizeAnnualreport slideshow 2015_v12_reducedsize
Annualreport slideshow 2015_v12_reducedsizemyheroproject
 
Back to School 2011
Back to School 2011Back to School 2011
Back to School 2011jmu101211
 
2006增刊目录
2006增刊目录2006增刊目录
2006增刊目录guest2bb2c
 
Eye Catching Photos
Eye Catching PhotosEye Catching Photos
Eye Catching PhotosYee Seng Gan
 
XY Lao Tablet
XY Lao TabletXY Lao Tablet
XY Lao Tabletlaonux
 
Ignition toyota igt
Ignition toyota igtIgnition toyota igt
Ignition toyota igtToni Gim
 
Technology In Schools What Is Changing
Technology  In  Schools  What  Is  ChangingTechnology  In  Schools  What  Is  Changing
Technology In Schools What Is ChangingYarmouth Schools
 

En vedette (20)

Creating a game using C++, OpenGL and Qt
Creating a game using C++, OpenGL and QtCreating a game using C++, OpenGL and Qt
Creating a game using C++, OpenGL and Qt
 
PDM Riberalta
PDM RiberaltaPDM Riberalta
PDM Riberalta
 
Best Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIBest Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part II
 
Best Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part IIIBest Practices in Qt Quick/QML - Part III
Best Practices in Qt Quick/QML - Part III
 
Best Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IVBest Practices in Qt Quick/QML - Part IV
Best Practices in Qt Quick/QML - Part IV
 
Best Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part IBest Practices in Qt Quick/QML - Part I
Best Practices in Qt Quick/QML - Part I
 
ISSA Journal Paper - JavaScript Infection Model
ISSA Journal Paper - JavaScript Infection ModelISSA Journal Paper - JavaScript Infection Model
ISSA Journal Paper - JavaScript Infection Model
 
Casă din Haran grafică 3 D [ obedeya d.d.a.ben aharon cohen]
Casă din Haran grafică 3 D [ obedeya d.d.a.ben aharon cohen]Casă din Haran grafică 3 D [ obedeya d.d.a.ben aharon cohen]
Casă din Haran grafică 3 D [ obedeya d.d.a.ben aharon cohen]
 
Ppt32
Ppt32Ppt32
Ppt32
 
Audio recording evaluration unit 4
Audio recording evaluration unit 4Audio recording evaluration unit 4
Audio recording evaluration unit 4
 
A guide to prayer
A guide to prayerA guide to prayer
A guide to prayer
 
Annualreport slideshow 2015_v12_reducedsize
Annualreport slideshow 2015_v12_reducedsizeAnnualreport slideshow 2015_v12_reducedsize
Annualreport slideshow 2015_v12_reducedsize
 
Back to School 2011
Back to School 2011Back to School 2011
Back to School 2011
 
2006增刊目录
2006增刊目录2006增刊目录
2006增刊目录
 
Eye Catching Photos
Eye Catching PhotosEye Catching Photos
Eye Catching Photos
 
XY Lao Tablet
XY Lao TabletXY Lao Tablet
XY Lao Tablet
 
Gramatika5
Gramatika5Gramatika5
Gramatika5
 
Lesson #3
Lesson #3Lesson #3
Lesson #3
 
Ignition toyota igt
Ignition toyota igtIgnition toyota igt
Ignition toyota igt
 
Technology In Schools What Is Changing
Technology  In  Schools  What  Is  ChangingTechnology  In  Schools  What  Is  Changing
Technology In Schools What Is Changing
 

Similaire à Qt Item Views In Depth

Software System Architecture-Lecture 6.pptx
Software System Architecture-Lecture 6.pptxSoftware System Architecture-Lecture 6.pptx
Software System Architecture-Lecture 6.pptxssuser9a23691
 
Model view-delegates-whitepaper
Model view-delegates-whitepaperModel view-delegates-whitepaper
Model view-delegates-whitepapernilus
 
Python Raster Function - Esri Developer Conference - 2015
Python Raster Function - Esri Developer Conference - 2015Python Raster Function - Esri Developer Conference - 2015
Python Raster Function - Esri Developer Conference - 2015akferoz07
 
Catia product enhancement_overview_v5r16
Catia product enhancement_overview_v5r16Catia product enhancement_overview_v5r16
Catia product enhancement_overview_v5r16Jimmy Chang
 
Sql Performance Tuning For Developers
Sql Performance Tuning For DevelopersSql Performance Tuning For Developers
Sql Performance Tuning For Developerssqlserver.co.il
 
Dotnet differences
Dotnet differencesDotnet differences
Dotnet differencesUmar Ali
 
The Next Generation Qt Item Views
The Next Generation Qt Item ViewsThe Next Generation Qt Item Views
The Next Generation Qt Item Viewsaccount inactive
 
Qt Itemviews, The Next Generation
Qt Itemviews, The Next GenerationQt Itemviews, The Next Generation
Qt Itemviews, The Next GenerationMarius Bugge Monsen
 
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB Rakuten Group, Inc.
 
Basics of Model/View Qt programming
Basics of Model/View Qt programmingBasics of Model/View Qt programming
Basics of Model/View Qt programmingICS
 
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-Hattab
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-HattabTechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-Hattab
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-HattabAyman El-Hattab
 
Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Marius Bugge Monsen
 
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...upendramaurya11
 
JS Single-Page Web App Essentials
JS Single-Page Web App EssentialsJS Single-Page Web App Essentials
JS Single-Page Web App EssentialsSergey Bolshchikov
 
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2Antonios Giannopoulos
 

Similaire à Qt Item Views In Depth (20)

Patterns go f
Patterns go fPatterns go f
Patterns go f
 
Software System Architecture-Lecture 6.pptx
Software System Architecture-Lecture 6.pptxSoftware System Architecture-Lecture 6.pptx
Software System Architecture-Lecture 6.pptx
 
Uml3
Uml3Uml3
Uml3
 
Model view-delegates-whitepaper
Model view-delegates-whitepaperModel view-delegates-whitepaper
Model view-delegates-whitepaper
 
Python Raster Function - Esri Developer Conference - 2015
Python Raster Function - Esri Developer Conference - 2015Python Raster Function - Esri Developer Conference - 2015
Python Raster Function - Esri Developer Conference - 2015
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Catia product enhancement_overview_v5r16
Catia product enhancement_overview_v5r16Catia product enhancement_overview_v5r16
Catia product enhancement_overview_v5r16
 
Doodads quickref
Doodads quickrefDoodads quickref
Doodads quickref
 
Sql Performance Tuning For Developers
Sql Performance Tuning For DevelopersSql Performance Tuning For Developers
Sql Performance Tuning For Developers
 
Microstation brochure
Microstation brochureMicrostation brochure
Microstation brochure
 
Dotnet differences
Dotnet differencesDotnet differences
Dotnet differences
 
The Next Generation Qt Item Views
The Next Generation Qt Item ViewsThe Next Generation Qt Item Views
The Next Generation Qt Item Views
 
Qt Itemviews, The Next Generation
Qt Itemviews, The Next GenerationQt Itemviews, The Next Generation
Qt Itemviews, The Next Generation
 
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB
KVSの性能、RDBMSのインデックス、更にMapReduceを併せ持つAll-in-One NoSQL: MongoDB
 
Basics of Model/View Qt programming
Basics of Model/View Qt programmingBasics of Model/View Qt programming
Basics of Model/View Qt programming
 
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-Hattab
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-HattabTechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-Hattab
TechDays Tunisia - Visual Studio & SQL Server, Better Together - Ayman El-Hattab
 
Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)
 
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...
Luciano Ramalho - Fluent Python_ Clear, Concise, and Effective Programming-O'...
 
JS Single-Page Web App Essentials
JS Single-Page Web App EssentialsJS Single-Page Web App Essentials
JS Single-Page Web App Essentials
 
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2
New Indexing and Aggregation Pipeline Capabilities in MongoDB 4.2
 

Plus de Marius Bugge Monsen

Plus de Marius Bugge Monsen (10)

The Anatomy of Real World Apps - Dissecting cross-platform apps written using...
The Anatomy of Real World Apps - Dissecting cross-platform apps written using...The Anatomy of Real World Apps - Dissecting cross-platform apps written using...
The Anatomy of Real World Apps - Dissecting cross-platform apps written using...
 
About Cutehacks
About CutehacksAbout Cutehacks
About Cutehacks
 
How to hire and keep good people
How to hire and keep good peopleHow to hire and keep good people
How to hire and keep good people
 
I can see your house from here
I can see your house from hereI can see your house from here
I can see your house from here
 
Practical Model View Programming
Practical Model View ProgrammingPractical Model View Programming
Practical Model View Programming
 
The Qt 4 Item Views
The Qt 4 Item ViewsThe Qt 4 Item Views
The Qt 4 Item Views
 
IPC with Qt
IPC with QtIPC with Qt
IPC with Qt
 
The Future of Qt Widgets
The Future of Qt WidgetsThe Future of Qt Widgets
The Future of Qt Widgets
 
Qt Widgets In Depth
Qt Widgets In DepthQt Widgets In Depth
Qt Widgets In Depth
 
Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)
 

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 2
  • 3. Contents  Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 3
  • 4. Models In Depth  List  Tree  Editable Items  Inserting And Removing Items  Lazy Initialization  Drag And Drop  Testing 4
  • 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. Introduction  Model View Controller (MVC) Design Pattern  Qt Model / View Design 6
  • 7. The MVC Design Pattern Controller View Model 7
  • 8. The Qt Model/View Design Delegate View Model Selections 8
  • 9. Multiple Views on a Model View View Model View 9
  • 10. Interchangeable Models Model View ??? Other Model 10
  • 11. Chaining Models View Proxy Model 11
  • 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. Model vs. Items  Q3FileDialog  q3filedialog.cpp: 4512 loc  QFileDialog  qfiledialog.cpp: 1639 loc  qfilesystemmodel.cpp: 1108 loc  total: 2747 loc 13
  • 14. Qt 4 Item Views  ~29000 lines of code  39 public classes  9 view classes  11 model classes 14
  • 15. Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 15
  • 16. Architecture  Goals  Separating Data And Presentation  Designing An Interface  Look Ma, No Items! 16
  • 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
  • 19. Qt 3 Item Views Painting Editing View Selections Data 19
  • 20. Painting Editing View Selections Data 20
  • 21. Painting Editing View Selections Data 21
  • 22. Painting Editing View Selections Data 22
  • 23. Qt 4 Item Views Painting View Editing Selections Data 23
  • 24. Qt 3 Item Views Painting Editing View Selections Data 24
  • 25. Qt 4 Item Views Painting View Editing Selections Data 25
  • 26. Qt 4 Item Views Delegate View Model Selections 26
  • 27. Designing An Interface ? View Model 27
  • 29. Data Structure Categories  Lists  One dimensional arrays of data  Tables  Two dimensional arrays of data  Trees  Hierarchies of lists  Graphs 29
  • 30. Data Structure Representation  Lists  One dimensional arrays of data ???  Tables  Two dimensional arrays of data  Trees  Hierarchies of lists  Graphs 30
  • 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
  • 35. The Model Index  Not an item  Represents a position in a specific table  Lightweight  Shortlived 35
  • 36. Delegate View Model Selections 36
  • 37. changed paint data Model View Delegate Model index index index selected index Selection 37
  • 38. Views 38
  • 39. Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 39
  • 40. Models In Depth  Main Model Classes  List  Tree  Editable Items  Inserting And Removing Items  Lazy Initialization  Drag And Drop  Testing 40
  • 41. Main Model Classes  QAbstractItemModel  QAbstractListModel  QStringListModel  QAbstractTableModel  QSqlQueryModel  QStandardItemModel  QAbstractProxyModel  QSortFilterProxyModel 41
  • 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. 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. 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. QAbstractListModel  2 functions have to be implemented  int rowCount(const QModelIndex &parent) const  QVariant data(const QModelIndex &index, int role) const 45
  • 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
  • 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. The Model Index 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 50
  • 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
  • 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. 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. 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. 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. 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. 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. 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
  • 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. Editable Items Pixmap Item Check Item 62
  • 63. Qt::ItemDataRole  DisplayRole  usually text  DecorationRole  usually an icon  EditRole  key data to be edited  CheckStateRole  item check box state 63
  • 64. Qt::ItemDataRole  AccessibleTextRole  AccessibleDescriptionRole  SizeHintRole  TextAlignmentRole  BackgroundRole  ForegroundRole  TextColorRole 64
  • 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. 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. Qt::ItemFlags  ItemIsSelectable  ItemIsEditable  ItemIsDragEnabled  ItemIsDropEnabled  ItemIsUserCheckable  ItemIsEnabled  ItemIsTristate 67
  • 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. 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. 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
  • 74. The Persistent Model Index  A Model Index  Persistent (i.e. not short lived)  Updated By The Model 74
  • 76. Persistent Model Index class Q_CORE_EXPORT QPersistentModelIndexData { public: QPersistentModelIndexData(); QPersistentModelIndexData(const QModelIndex &idx); QModelIndex index; QAtomicInt ref; const QAbstractItemModel *model; ... }; 76
  • 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. Persistent Model Index void changePersistentIndex(const QModelIndex &from, const QModelIndex &to); void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; 78
  • 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. 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. 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. 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
  • 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. 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. 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. Drag And Drop QStringList DndModel::mimeTypes() const { QStringList types; types << "application/vnd.text.list"; return types; } 88
  • 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. 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. 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. 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. 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. 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. Testing  QtTestLibrary  ModelTest  http://labs.trolltech.com/page/Projects/Itemview/Modeltest 95
  • 96. Testing  ModelTest  Signal emission  Hierarchy  Row and column count  Parent / Child relationships  Much more... 96
  • 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. Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 98
  • 99. Selections In Depth  Selection Ranges  Making Selections  Selection Properties  Tips When Selecting 99
  • 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. Selections  Selection Range  Top Left Index  Bottom Right Index  Selection  List of Ranges  Selection Model  Lost of Selections  Current Selection  Current Index 103
  • 104. Views And Selections View Selections 104
  • 105. Making Selections void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) 105
  • 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. View Selection Properties  SelectionMode  SelectionBehavior 107
  • 108. View Selection Properties  SelectionBehavior  SelectItems  SelectRows  SelectColumns 108
  • 109. View Selection Properties  SelectionMode  NoSelection  SingleSelection  MultiSelection  ContigousSelection  ExtendedSelection 109
  • 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. View Selection Properties  SelectionMode  NoSelection  SingleSelection  MultiSelection  ContigousSelection  Clears existing selections before selecting  Shift + selecting will update the current selection only  ExtendedSelection 111
  • 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. 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. Introduction  Architecture  Models In Depth  Selections In Depth  I Just Want To ... 114
  • 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. Showing Data  Widgets  QListWidget  QTableWidget  QTreeWidget  Models  QStringListModel  QStandardItemModel 116
  • 117. Showing Data  The General Rules (tm)  Models  Faster  Less Overhead  Harder To Implement  Widgets  Slower  More Overhead  Easier To Use 117
  • 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. 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. 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. 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. 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. 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. Sorting And Filtering  Sorting  QListWidget  QTableWidget  QTreeWidget  QSortFilterProxyModel  Filtering  QSortFilterProxyModel 124
  • 125. QSortFilterProxyModel View Proxy Model 125
  • 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. Checkable Items  Qt::ItemDataRoles  ItemCheckStateRole  Qt::ItemFlags  ItemIsUserCheckable  ItemIsTristate  Qt::CheckedState  Unchecked  PartiallyChecked  Checked 127
  • 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. Custom Item Painting Delegate View Model Selections 129
  • 130. Custom Item Painting  QAbstractItemDelegate  QItemDelegate  QSqlRelationalDelegate 130
  • 131. Custom Item Painting  Item Delegate  Painting  Clipping  Size Hint  Creating Editor Widget  Managing Editor Widget Geometry 131
  • 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. 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. 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. Custom Item Editor  QAbstractItemDelegate::createEditor(...)  QItemEditorFactory  QItemEditorCreatorBase 135
  • 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. 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. Animated Items update(index) Delegate View Model Selections 138
  • 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. 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. 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. 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. 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. 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