P R A C T IC A L M O D EL V IEW
PR O GR A M M IN G
C O D E LESS . V I EW M O R E.
Marius Bugge Monsen,
MSc (N TN U),
Software D eveloper
C ontents

●   An O verview of the Q t Model View Architecture
●   An Introduction to The Model Interface
●   Advanced Model View Techniques (Q t 4.1+)
A n O verview of the Q t M odel V iew A rchitecture
I tem S elections



         U ser I nput                        I tem Selection State




                            U ser I nput
       V iew                                       I tem D elegate




C hange N otif cations
             i                                D ata C hanges




                              M odel
Item B ased V iews (Q t 3 and 4)


Table W idget    T ree W idget    List W idget
I tem S elections




V iew                       V iew




             M odel
int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  QDirModel model;
  QTableView view1;
  QTreeView view2;

    view1.setModel(&model);
    view2.setModel(&model);

    view1.setRootIndex(model.index(0, 0));
    view1.show();
    view2.show();
    app.exec();
}
W hat do you get ?

    Eff ciency
      i
    Flexibility
   Maintainability
A n I ntroduction To T he M odel Interface
class ListModel : public QAbstractListModel
{
   Q_OBJECT
public:
   ListModel(QObject *parent = 0);
   ~ListModel();

     int rowCount(const QModelIndex &parent) const;
     QVariant data(const QModelIndex &index, int role) const;
};
ListModel::ListModel(QObject *parent)
   : QAbstractListModel(parent) {}
ListModel::~ListModel() {}

int ListModel::rowCount(const QModelIndex &) const
{
   return 10000;
}

QVariant ListModel::data(const QModelIndex &index,
                          int role) const
{
   if (role == Qt::DisplayRole)
      return index.row();
   return QVariant();
}
0       0   1   2

0       0


1       1

2       2
int main(int, char *[])
{
   ListModel model;

    QModelIndex index = model.index(2);
    QVariant data = model.data(index, Qt::DisplayRole);

    qDebug() << data;
}
D ecoration R ole
                            Type:Image File
                            Size: 1.2 Mb



                                        ToolT ip R ole

                    M y W orld


D isplay R ole
QVariant ListModel::data(const QModelIndex &index,
                          int role) const
{
   if (role == Qt::DisplayRole)
      return index.row();

    if (role == Qt::DecorationRole)
       return QColor(Qt::green);

    return QVariant();
}
class ColorDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    ColorDelegate(QObject *parent = 0);
protected:
    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
};
void ColorDelegate::paint(QPainter *painter,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
{
    const QAbstractItemModel *model = index.model();
    QVariant decoration = model->data(index, Qt::DecorationRole);
    if (decoration.type() == QVariant::Color) {
        QLinearGradient gradient(option.rect.left(), 0,
                                 option.rect.width(), 0);
        QColor left = option.palette.color(QPalette::Background);
        gradient.setColorAt(0, left);
        QColor right = qvariant_cast<QColor>(decoration);
        gradient.setColorAt(1, right);
        painter->fillRect(option.rect, gradient);
    }
    QItemDelegate::paint(painter, option, index);
}
One     100   -300   500
Two     599   300    233
Three   33    -34    -55
Four    200   502    200
class TableModel : public QAbstractTableModel
{
   Q_OBJECT
public:
   TableModel(QObject *parent = 0);
   ~TableModel();
   int rowCount(const QModelIndex &parent) const;
   int columnCount(const QModelIndex &parent) const;
   QVariant data(const QModelIndex &index, int role) const;
   bool setData(const QModelIndex &index,
                const QVariant &value, int role);
   Qt::ItemFlags flags(const QModelIndex &index) const;
   // not part of the model interface
   bool load(const QString &fileName);
   bool save(const QString &fileName) const;
private:
   int rows, columns;
   QVector<QVariant> table;
};
QVariant TableModel::data(const QModelIndex &index,
                          int role) const
{
   int i = index.row() * columns + index.column();
   QVariant value = table.at(i);

    if (role == Qt::EditRole || role == Qt::DisplayRole)
       return value;

    if (role == Qt::TextColorRole
       && value.type() == QVariant::Int) {
    if (value.toInt() < 0)
       return QColor(Qt::red);
       return QColor(Qt::blue);
    }
    return QVariant();
}
bool TableModel::setData(const QModelIndex &index,
                     const QVariant &value, int role)
{
   int i = index.row() * columns + index.column();
   if (role == Qt::EditRole) {
      table[i] = value;
      QModelIndex topLeft = index;
      QModelIndex bottomRight = index;
      emit dataChanged(topLeft, bottomRight);// <<< important!
      return true;
   }
   return false;
}
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
   return QAbstractTableModel::flags(index)|Qt::ItemIsEditable;
}
bool TableModel::load(const QString &fileName)
{
   QFile file(fileName);
   if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
      return false;
   rows = columns = 0;
   table.clear();
   QTextStream in(&file);
   bool result = parse(in);

    reset();// <<< important!

    return result;
}
A dvanced M odel V iew Techniques (Q t 4.1+)
M odel   P roxy   V iew
M odel   S orting   V iew
int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   TableModel model;
   model.load("table.data");

    QSortingProxyModel sorter;
    sorter.setSourceModel(&model);
    QTreeView treeview;
    treeview.setModel(&sorter);

    treeview.header()->setClickable(true);
    treeview.header()->setSortIndicatorShown(true);
    treeview.show();
    return app.exec();
}
M odel   Filtering   V iew
int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   QWidget widget;
   QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom,
                                        &widget);
   QLineEdit *lineedit = new QLineEdit;
   layout->addWidget(lineedit);
   TableModel model;
   model.load("table.data");
   QStringFilterModel filter;
   filter.setSourceModel(&model);
   QObject::connect(lineedit,SIGNAL(textChanged(const QString&)),
                    &filter,SLOT(setPattern(const QString&)));
   QTableView *tableview = new QTableView;
   tableview->setModel(&filter);
   layout->addWidget(tableview);
   widget.show();
   return app.exec();
}
M odel
  1


         A gg regating   V iew
M odel
  2
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTreeView treeview;
    QStringListModel model_1(QStringList()
                             << "ALPHA" << "BRAVO"
                             << "CHARLIE" << "DELTA");
    QDirModel model_2;
    QAggregatingProxyModel aggregator;
    aggregator.appendSourceModel(&model_1);
    aggregator.appendSourceModel(&model_2);
    treeview.setModel(&aggregator);
    treeview.show();
    return app.exec();
}
W hat we have covered

●   Q t Model View Architecture O verview
●   The Model Interface Introduction
●   Advanced Techniques Using the Model Interface
M ore Inform ation


http://doc.trolltech.com/4.0/model-view-programming.html
http://doc.trolltech.com/4.0/model-view.html

Practical Model View Programming

  • 1.
    P R AC T IC A L M O D EL V IEW PR O GR A M M IN G C O D E LESS . V I EW M O R E.
  • 2.
    Marius Bugge Monsen, MSc(N TN U), Software D eveloper
  • 3.
    C ontents ● An O verview of the Q t Model View Architecture ● An Introduction to The Model Interface ● Advanced Model View Techniques (Q t 4.1+)
  • 4.
    A n Overview of the Q t M odel V iew A rchitecture
  • 6.
    I tem Selections U ser I nput I tem Selection State U ser I nput V iew I tem D elegate C hange N otif cations i D ata C hanges M odel
  • 7.
    Item B asedV iews (Q t 3 and 4) Table W idget T ree W idget List W idget
  • 8.
    I tem Selections V iew V iew M odel
  • 9.
    int main(int argc,char *argv[]) { QApplication app(argc, argv); QDirModel model; QTableView view1; QTreeView view2; view1.setModel(&model); view2.setModel(&model); view1.setRootIndex(model.index(0, 0)); view1.show(); view2.show(); app.exec(); }
  • 11.
    W hat doyou get ? Eff ciency i Flexibility Maintainability
  • 12.
    A n Introduction To T he M odel Interface
  • 13.
    class ListModel :public QAbstractListModel { Q_OBJECT public: ListModel(QObject *parent = 0); ~ListModel(); int rowCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; };
  • 14.
    ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) {} ListModel::~ListModel() {} int ListModel::rowCount(const QModelIndex &) const { return 10000; } QVariant ListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return index.row(); return QVariant(); }
  • 16.
    0 0 1 2 0 0 1 1 2 2
  • 18.
    int main(int, char*[]) { ListModel model; QModelIndex index = model.index(2); QVariant data = model.data(index, Qt::DisplayRole); qDebug() << data; }
  • 19.
    D ecoration Role Type:Image File Size: 1.2 Mb ToolT ip R ole M y W orld D isplay R ole
  • 20.
    QVariant ListModel::data(const QModelIndex&index, int role) const { if (role == Qt::DisplayRole) return index.row(); if (role == Qt::DecorationRole) return QColor(Qt::green); return QVariant(); }
  • 22.
    class ColorDelegate :public QItemDelegate { Q_OBJECT public: ColorDelegate(QObject *parent = 0); protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; };
  • 23.
    void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QAbstractItemModel *model = index.model(); QVariant decoration = model->data(index, Qt::DecorationRole); if (decoration.type() == QVariant::Color) { QLinearGradient gradient(option.rect.left(), 0, option.rect.width(), 0); QColor left = option.palette.color(QPalette::Background); gradient.setColorAt(0, left); QColor right = qvariant_cast<QColor>(decoration); gradient.setColorAt(1, right); painter->fillRect(option.rect, gradient); } QItemDelegate::paint(painter, option, index); }
  • 25.
    One 100 -300 500 Two 599 300 233 Three 33 -34 -55 Four 200 502 200
  • 26.
    class TableModel :public QAbstractTableModel { Q_OBJECT public: TableModel(QObject *parent = 0); ~TableModel(); int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; // not part of the model interface bool load(const QString &fileName); bool save(const QString &fileName) const; private: int rows, columns; QVector<QVariant> table; };
  • 27.
    QVariant TableModel::data(const QModelIndex&index, int role) const { int i = index.row() * columns + index.column(); QVariant value = table.at(i); if (role == Qt::EditRole || role == Qt::DisplayRole) return value; if (role == Qt::TextColorRole && value.type() == QVariant::Int) { if (value.toInt() < 0) return QColor(Qt::red); return QColor(Qt::blue); } return QVariant(); }
  • 28.
    bool TableModel::setData(const QModelIndex&index, const QVariant &value, int role) { int i = index.row() * columns + index.column(); if (role == Qt::EditRole) { table[i] = value; QModelIndex topLeft = index; QModelIndex bottomRight = index; emit dataChanged(topLeft, bottomRight);// <<< important! return true; } return false; } Qt::ItemFlags TableModel::flags(const QModelIndex &index) const { return QAbstractTableModel::flags(index)|Qt::ItemIsEditable; }
  • 29.
    bool TableModel::load(const QString&fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) return false; rows = columns = 0; table.clear(); QTextStream in(&file); bool result = parse(in); reset();// <<< important! return result; }
  • 31.
    A dvanced Model V iew Techniques (Q t 4.1+)
  • 32.
    M odel P roxy V iew
  • 33.
    M odel S orting V iew
  • 34.
    int main(int argc,char *argv[]) { QApplication app(argc, argv); TableModel model; model.load("table.data"); QSortingProxyModel sorter; sorter.setSourceModel(&model); QTreeView treeview; treeview.setModel(&sorter); treeview.header()->setClickable(true); treeview.header()->setSortIndicatorShown(true); treeview.show(); return app.exec(); }
  • 36.
    M odel Filtering V iew
  • 37.
    int main(int argc,char *argv[]) { QApplication app(argc, argv); QWidget widget; QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, &widget); QLineEdit *lineedit = new QLineEdit; layout->addWidget(lineedit); TableModel model; model.load("table.data"); QStringFilterModel filter; filter.setSourceModel(&model); QObject::connect(lineedit,SIGNAL(textChanged(const QString&)), &filter,SLOT(setPattern(const QString&))); QTableView *tableview = new QTableView; tableview->setModel(&filter); layout->addWidget(tableview); widget.show(); return app.exec(); }
  • 39.
    M odel 1 A gg regating V iew M odel 2
  • 40.
    int main(int argc,char *argv[]) { QApplication app(argc, argv); QTreeView treeview; QStringListModel model_1(QStringList() << "ALPHA" << "BRAVO" << "CHARLIE" << "DELTA"); QDirModel model_2; QAggregatingProxyModel aggregator; aggregator.appendSourceModel(&model_1); aggregator.appendSourceModel(&model_2); treeview.setModel(&aggregator); treeview.show(); return app.exec(); }
  • 42.
    W hat wehave covered ● Q t Model View Architecture O verview ● The Model Interface Introduction ● Advanced Techniques Using the Model Interface
  • 43.
    M ore Information http://doc.trolltech.com/4.0/model-view-programming.html http://doc.trolltech.com/4.0/model-view.html