SlideShare a Scribd company logo
1 of 71
Download to read offline
PRACTICAL MODEL VIEW
PROGRAMMING



CODE LESS. VIEW MORE.
Marius Bugge Monsen,
MSc (NTNU),
Software Developer
Contents

●   An Overview of the Qt Model View Architecture
●   An Introduction to the Item Model Interface
●   Customized Item Filtering
●   Customized Item Painting
●   More Models and Hierarchies
The Model View Architecture
Item Selections



          User Input                     Item Selection State




                          User Input
      View                                      Item Delegate




Change Notifications                     Data Changes




                           Model
Item Selections




View                     View




           Model
Item Based Views


Table Widget      T Widget
                   ree            List Widget
Item Based View




                  View
What do you get ?
●   Efficiency
●   Flexib ility
●   M aintainab ility
The Model Interface
400 000 000 000 000 cells
Model          Interface   View




Data Structure
0       0   1   2

0       0


1       1

2       2
#include <QtGui>

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

    int rows = 4;
    int columns = 1;
    QStandardItemModel model(rows, columns);

    for (int r = 0; r < model.rowCount(); ++r) {
       QModelIndex index = model.index(r, 0);
       model.setData(index, "hello");
    }

    QTableView view;
    view.setModel(&model);

    view.show();
    return app.exec();
}
Model          Interface   View



                  hello

    ?             hello
                  hello
                  hello
Data Structure
// we start with a 4x1 table
QStandardItemModel model(4, 1);

for (int r = 0; r < model.rowCount(); ++r) {
   QModelIndex index = model.index(r, 0);
   model.setData(index, "hello");

    // let's add a 1x1 sub-table
    QModelIndex parent = index
    model.insertRow(0, parent);
    model.insertColumn(0, parent);

    // then we can set the data in cell [0,0]
    QModelIndex child = mode.index(0, 0, parent);
    model.setData(child, “world”);
}
Model            Interface     View


                          world
                 hello

    ?            hello
                 hello
                          world
                          world
                 hello
                          world
Data Structure
Model



                 Model Interface


                 Custom API
Data Structure
#include <QtGui>

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

    for (int i = 0; i < 4; ++i) {
       QTreeWidgetItem *parent =
          new QTreeWidgetItem(&widget, QStringList("hello"));
       new QTreeWidgetItem(parent, QStringList("world"));
    }

    widget.show();
    app.exec();
}
Model Index

● Row
● Column

● Internal Identifier
Model Index




              Qt4 Logo
Decoration Role          Typ e: Im age File
                         Size: 1 0.5 kB



                                              T ip Role
                                               oolT

                  Qt4 Logo


DisplayRole
QIcon icon(“images/qt4-logo.png”);
QStandardItemModel model(4, 1);

for (int r = 0; r < model.rowCount(); ++r) {
   QModelIndex index = model.index(r, 0);
   model.setData(index, "hello", Qt::DisplayRole);
   model.setData(index, icon, Qt::DecorationRole);
}
QIcon icon(“images/qt4-logo.png”);
QTableWidget table(4, 1);

for (int i = 0; i < 4; ++i)
   table.setItem(i, 0, new QTableWidgetItem(icon, “hello”));
T Model Interface
          he
●   A Generic Interface to Data Structures
●   M od els Are Interchangeab le
●   Views Are Interchangeab le
●   M od els and Selections Are Sharab le
Customized Item Filtering
Model
Model   Proxy   View
Model   Sorting   View
Model   Filtering   View
class CodeModel : public QStringListModel
{
public:
   CodeModel(const QString &fileName, QObject *parent = 0)
     : QStringListModel(parent)
   {
      QFile source(name);
      source.open(QIODevice::ReadOnly);
      QStringList strings = QString().split("n", QString::SkipEmptyParts);
      setStringList(strings);
   }
};
CodeModel model(sourceFile);

QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);

QTreeView view;
view.setModel(&proxy);

QObject::connect(lineEdit, SIGNAL(textChanged(const QString&)),
                 &proxy, SLOT(setFilterRegExp(const QString&)));
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();

    if (role == Qt::DecorationRole)
         return QColor((index.row() << 4) & 0xFF,
                         (index.row() << 2) & 0xFF,
                         (index.row() & 0xFF));

    return QVariant();
}
class ColorFilter : public QSortFilterProxyModel
{
   Q_OBJECT
public:
   ColorFilter(QObject *parent = 0);

  bool filterAcceptsRow(int sourceRow,
                          const QModelIndex &sourceParent) const;
public slots:
  void setRedFilter(int value);
  void setGreenFilter(int value);
  void setBlueFilter(int value);

private:
   int red, green, blue;
};
bool ColorFilter::filterAcceptsRow(int sourceRow,
                         const QModelIndex &sourceParent) const
{
  QModelIndex sourceIndex = sourceModel()->index(sourceRow,
                                                 filterKeyColumn(),
                                                 sourceParent);

    QVariant variant = sourceIndex.data(Qt::DecorationRole);
    if (variant.type() == QVariant::Color) {
        QColor c = variant.value<QColor>();
        return (c.red() > red) && (c.green() > green) && (c.blue() > blue);
    }
    return true;
}
...
ListModel model;
ColorFilter filter;
filter.setSourceModel(&model);
...
QSlider *redSlider = new QSlider(Qt::Horizontal);
redSlider->setRange(0, 255);
QObject::connect(redSlider, SIGNAL(valueChanged(int)),
                    &filter, SLOT(setRedFilter(int)));
...
QListView *view = new QListView;
view->setModel(&filter);
view->setItemDelegate(new ColorDelegate(view));
...
Customized Item Painting
Item Selections




View                     Item Delegate




           Model
Qt4 Logo
                      Im age File
                      1 0.5 kB

Qt4 Logo



           Qt4 Logo
class HoverDelegate : public QItemDelegate
{
   Q_OBJECT
public:
   HoverDelegate(QObject *parent = 0) : QItemDelegate(parent) {}

  void paint(QPainter *painter,
              const QStyleOptionViewItem &option,
              const QModelIndex &index) const
  {
    if (option.state & QStyle::State_MouseOver)
        painter->fillRect(option.rect, Qt::lightGray);
    QItemDelegate::paint(painter, option, index);
  }
};
...
view.viewport()->setAttribute(Qt::WA_Hover);
...
Movie Title
<?xml version="1.0" standalone="no"?>
<svg width="100" height="100" viewBox="0 0 100 100"
   xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" version="1.2">
 <title>Play</title>
 <defs>
  <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="100">
    <stop offset="0%" stop-color="#ddddff" />
    <stop offset="50%" stop-color="#000000"/>
  </linearGradient>
 </defs>
 <rect x="20" y="0" width="93" height="130" rx="5" fill="none" stroke="#ffffff" stroke-width="3" />
 <circle cx="50" cy="50" r="50" fill="url(#gradient)" stroke="#000000" stroke-width="2"/>
 <path d="M 30 75 L 30 25 L 80 50 z" fill="#dddddd" stroke="#000000" stroke-width="2" />
</svg>
class DemoDelegate : public QItemDelegate
{
public:
   DemoDelegate(QObject *parent = 0);

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

protected:
  void drawSvg(QPainter *painter,
                const QRect &rect) const;

private:
   mutable QSvgRenderer renderer;
};
void DemoDelegate::paint(QPainter *painter,
                 const QStyleOptionViewItem &option,
                 const QModelIndex &index) const
{
  // draw the item as unselected and without focus rect
  QStyleOptionViewItem opt = option;
  opt.state &= ~QStyle::State_Selected;
  opt.state &= ~QStyle::State_HasFocus;

    QItemDelegate::paint(painter, opt, index);

    // draw svg over the current item
    if (option.state & QStyle::State_HasFocus)
        drawSvg(painter, option.rect);
}
More Models and Hierarchies
struct SimpleNode
{
   SimpleNode(SimpleNode *parent) : parentNode(parent) {
     if (parentNode)
         parentNode->children.append(this);
   }

     ~SimpleNode() {
       foreach(SimpleNode *child, children)
          delete child;
     }

     QVariant data() const {
       return "node data";
     }

     SimpleNode *parentNode;
     QList<SimpleNode*> children;
};
Model          Interface   View




Data Structure
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:
  QModelIndex indexForNode(SimpleNode *node) const;
  SimpleNode *nodeForIndex(const QModelIndex &index) const;
  int rowForNode(SimpleNode *node) const;

private:
   SimpleNode *root;
};
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;
}
SimpleModel::SimpleModel(QObject *parent)
  : QAbstractItemModel(parent)
{
  // Initialize the data structure
  root = new SimpleNode(0);
  for (int i = 0; i < 10; ++i) {
      SimpleNode *topLevel = new SimpleNode(root);
      for (int j = 0; j < 5; ++j) {
         SimpleNode *secondLevel = new SimpleNode(topLevel);
         for (int k = 0; k < 3; ++k) {
             (void) new SimpleNode(secondLevel);
         }
      }
  }
}

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




              Qt4 Logo
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 indexForNode(childNode);
  }
  return QModelIndex();
}
QModelIndex SimpleModel::parent(const QModelIndex &child) const
{
  SimpleNode *childNode = nodeForIndex(child);
  SimpleNode *parentNode = childNode->parentNode;
  if (parentNode == root)
      return QModelIndex();
  return indexForNode(parentNode);
}
QModelIndex SimpleModel::indexForNode(SimpleNode *node) const
{
  if (node == root)
      return QModelIndex();
  int row = rowForNode(node);
  int column = 0;
  return createIndex(row, column, node);
}
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);
}
int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   SimpleModel model;

    QTreeView view;
    view.setModel(&model);
    view.show();

    return app.exec();
}
What we have covered

●   The Qt Model View Architecture
●   The Item Model Interface
●   Customized Item Filtering
●   Customized Item Painting
●   Hierarchical Models
More Information

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

More Related Content

What's hot

Svcc Java2D And Groovy
Svcc Java2D And GroovySvcc Java2D And Groovy
Svcc Java2D And GroovyAndres Almiray
 
05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics05 - Qt External Interaction and Graphics
05 - Qt External Interaction and GraphicsAndreas Jakl
 
Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)Marius Bugge Monsen
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinJorge Ortiz
 
Using Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data VisualisationUsing Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data VisualisationAlex Hardman
 
The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185Mahmoud Samir Fayed
 
Qt Memory Management & Signal and Slots
Qt Memory Management & Signal and SlotsQt Memory Management & Signal and Slots
Qt Memory Management & Signal and SlotsJussi Pohjolainen
 
Reflection in Go
Reflection in GoReflection in Go
Reflection in Gostrikr .
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)Yeshwanth Kumar
 
Let the type system be your friend
Let the type system be your friendLet the type system be your friend
Let the type system be your friendThe Software House
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinIain Hull
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming heroThe Software House
 
Improving Correctness with Types
Improving Correctness with TypesImproving Correctness with Types
Improving Correctness with TypesIain Hull
 
Spring data access
Spring data accessSpring data access
Spring data access명철 강
 

What's hot (20)

Svcc Java2D And Groovy
Svcc Java2D And GroovySvcc Java2D And Groovy
Svcc Java2D And Groovy
 
05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics
 
Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)Qt Itemviews, The Next Generation (Bossa09)
Qt Itemviews, The Next Generation (Bossa09)
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 
Treinamento Qt básico - aula III
Treinamento Qt básico - aula IIITreinamento Qt básico - aula III
Treinamento Qt básico - aula III
 
Using Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data VisualisationUsing Arbor/ RGraph JS libaries for Data Visualisation
Using Arbor/ RGraph JS libaries for Data Visualisation
 
OpenXR 1.0 Reference Guide
OpenXR 1.0 Reference GuideOpenXR 1.0 Reference Guide
OpenXR 1.0 Reference Guide
 
The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185
 
Qt Memory Management & Signal and Slots
Qt Memory Management & Signal and SlotsQt Memory Management & Signal and Slots
Qt Memory Management & Signal and Slots
 
Reflection in Go
Reflection in GoReflection in Go
Reflection in Go
 
Composite Pattern
Composite PatternComposite Pattern
Composite Pattern
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
Let the type system be your friend
Let the type system be your friendLet the type system be your friend
Let the type system be your friend
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con Berlin
 
OpenGL 4.4 Reference Card
OpenGL 4.4 Reference CardOpenGL 4.4 Reference Card
OpenGL 4.4 Reference Card
 
OpenVG 1.1 Reference Card
OpenVG 1.1 Reference Card OpenVG 1.1 Reference Card
OpenVG 1.1 Reference Card
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming hero
 
Improving Correctness with Types
Improving Correctness with TypesImproving Correctness with Types
Improving Correctness with Types
 
Spring data access
Spring data accessSpring data access
Spring data access
 

Similar to PRACTICAL MODEL VIEW PROGRAMMING

In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QMLICS
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4ICS
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Eyal Vardi
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularIlia Idakiev
 
Basics of Model/View Qt programming
Basics of Model/View Qt programmingBasics of Model/View Qt programming
Basics of Model/View Qt programmingICS
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersBartosz Kosarzycki
 
.NET Database Toolkit
.NET Database Toolkit.NET Database Toolkit
.NET Database Toolkitwlscaudill
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196Mahmoud Samir Fayed
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...Oleksandr Tarasenko
 
Scala in practice
Scala in practiceScala in practice
Scala in practicepatforna
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189Mahmoud Samir Fayed
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Dimitrios Platis
 
The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202Mahmoud Samir Fayed
 

Similar to PRACTICAL MODEL VIEW PROGRAMMING (20)

Treinamento Qt básico - aula II
Treinamento Qt básico - aula IITreinamento Qt básico - aula II
Treinamento Qt básico - aula II
 
greenDAO
greenDAOgreenDAO
greenDAO
 
In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QML
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
 
Qt Workshop
Qt WorkshopQt Workshop
Qt Workshop
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With Angular
 
Basics of Model/View Qt programming
Basics of Model/View Qt programmingBasics of Model/View Qt programming
Basics of Model/View Qt programming
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developers
 
Bw14
Bw14Bw14
Bw14
 
.NET Database Toolkit
.NET Database Toolkit.NET Database Toolkit
.NET Database Toolkit
 
droidparts
droidpartsdroidparts
droidparts
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...How to separate frontend from a highload python project with no problems - Py...
How to separate frontend from a highload python project with no problems - Py...
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
 
The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202
 

More from Marius Bugge Monsen

More from Marius Bugge Monsen (8)

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
 
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
 
Qt Widgets In Depth
Qt Widgets In DepthQt Widgets In Depth
Qt Widgets In Depth
 
Qt Itemviews, The Next Generation
Qt Itemviews, The Next GenerationQt Itemviews, The Next Generation
Qt Itemviews, The Next Generation
 

PRACTICAL MODEL VIEW PROGRAMMING

  • 2. Marius Bugge Monsen, MSc (NTNU), Software Developer
  • 3. Contents ● An Overview of the Qt Model View Architecture ● An Introduction to the Item Model Interface ● Customized Item Filtering ● Customized Item Painting ● More Models and Hierarchies
  • 4.
  • 5. The Model View Architecture
  • 6. Item Selections User Input Item Selection State User Input View Item Delegate Change Notifications Data Changes Model
  • 7. Item Selections View View Model
  • 8. Item Based Views Table Widget T Widget ree List Widget
  • 10.
  • 11. What do you get ? ● Efficiency ● Flexib ility ● M aintainab ility
  • 13. 400 000 000 000 000 cells
  • 14. Model Interface View Data Structure
  • 15. 0 0 1 2 0 0 1 1 2 2
  • 16. #include <QtGui> int main(int argc, char *argv[]) { QApplication app(argc, argv); int rows = 4; int columns = 1; QStandardItemModel model(rows, columns); for (int r = 0; r < model.rowCount(); ++r) { QModelIndex index = model.index(r, 0); model.setData(index, "hello"); } QTableView view; view.setModel(&model); view.show(); return app.exec(); }
  • 17. Model Interface View hello ? hello hello hello Data Structure
  • 18.
  • 19.
  • 20.
  • 21. // we start with a 4x1 table QStandardItemModel model(4, 1); for (int r = 0; r < model.rowCount(); ++r) { QModelIndex index = model.index(r, 0); model.setData(index, "hello"); // let's add a 1x1 sub-table QModelIndex parent = index model.insertRow(0, parent); model.insertColumn(0, parent); // then we can set the data in cell [0,0] QModelIndex child = mode.index(0, 0, parent); model.setData(child, “world”); }
  • 22. Model Interface View world hello ? hello hello world world hello world Data Structure
  • 23. Model Model Interface Custom API Data Structure
  • 24. #include <QtGui> int main(int argc, char *argv[]) { QApplication app(argc, argv); QTreeWidget widget; for (int i = 0; i < 4; ++i) { QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("hello")); new QTreeWidgetItem(parent, QStringList("world")); } widget.show(); app.exec(); }
  • 25. Model Index ● Row ● Column ● Internal Identifier
  • 26. Model Index Qt4 Logo
  • 27. Decoration Role Typ e: Im age File Size: 1 0.5 kB T ip Role oolT Qt4 Logo DisplayRole
  • 28. QIcon icon(“images/qt4-logo.png”); QStandardItemModel model(4, 1); for (int r = 0; r < model.rowCount(); ++r) { QModelIndex index = model.index(r, 0); model.setData(index, "hello", Qt::DisplayRole); model.setData(index, icon, Qt::DecorationRole); }
  • 29. QIcon icon(“images/qt4-logo.png”); QTableWidget table(4, 1); for (int i = 0; i < 4; ++i) table.setItem(i, 0, new QTableWidgetItem(icon, “hello”));
  • 30. T Model Interface he ● A Generic Interface to Data Structures ● M od els Are Interchangeab le ● Views Are Interchangeab le ● M od els and Selections Are Sharab le
  • 32. Model
  • 33. Model Proxy View
  • 34. Model Sorting View
  • 35. Model Filtering View
  • 36. class CodeModel : public QStringListModel { public: CodeModel(const QString &fileName, QObject *parent = 0) : QStringListModel(parent) { QFile source(name); source.open(QIODevice::ReadOnly); QStringList strings = QString().split("n", QString::SkipEmptyParts); setStringList(strings); } };
  • 37. CodeModel model(sourceFile); QSortFilterProxyModel proxy; proxy.setSourceModel(&model); QTreeView view; view.setModel(&proxy); QObject::connect(lineEdit, SIGNAL(textChanged(const QString&)), &proxy, SLOT(setFilterRegExp(const QString&)));
  • 38. 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; };
  • 39. ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) {} ListModel::~ListModel() {} int ListModel::rowCount(const QModelIndex &) const { return 10000; }
  • 40. QVariant ListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return index.row(); if (role == Qt::DecorationRole) return QColor((index.row() << 4) & 0xFF, (index.row() << 2) & 0xFF, (index.row() & 0xFF)); return QVariant(); }
  • 41.
  • 42. class ColorFilter : public QSortFilterProxyModel { Q_OBJECT public: ColorFilter(QObject *parent = 0); bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; public slots: void setRedFilter(int value); void setGreenFilter(int value); void setBlueFilter(int value); private: int red, green, blue; };
  • 43. bool ColorFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex sourceIndex = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent); QVariant variant = sourceIndex.data(Qt::DecorationRole); if (variant.type() == QVariant::Color) { QColor c = variant.value<QColor>(); return (c.red() > red) && (c.green() > green) && (c.blue() > blue); } return true; }
  • 44. ... ListModel model; ColorFilter filter; filter.setSourceModel(&model); ... QSlider *redSlider = new QSlider(Qt::Horizontal); redSlider->setRange(0, 255); QObject::connect(redSlider, SIGNAL(valueChanged(int)), &filter, SLOT(setRedFilter(int))); ... QListView *view = new QListView; view->setModel(&filter); view->setItemDelegate(new ColorDelegate(view)); ...
  • 45.
  • 47. Item Selections View Item Delegate Model
  • 48. Qt4 Logo Im age File 1 0.5 kB Qt4 Logo Qt4 Logo
  • 49.
  • 50. class HoverDelegate : public QItemDelegate { Q_OBJECT public: HoverDelegate(QObject *parent = 0) : QItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (option.state & QStyle::State_MouseOver) painter->fillRect(option.rect, Qt::lightGray); QItemDelegate::paint(painter, option, index); } }; ... view.viewport()->setAttribute(Qt::WA_Hover); ...
  • 52. <?xml version="1.0" standalone="no"?> <svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" version="1.2"> <title>Play</title> <defs> <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="100"> <stop offset="0%" stop-color="#ddddff" /> <stop offset="50%" stop-color="#000000"/> </linearGradient> </defs> <rect x="20" y="0" width="93" height="130" rx="5" fill="none" stroke="#ffffff" stroke-width="3" /> <circle cx="50" cy="50" r="50" fill="url(#gradient)" stroke="#000000" stroke-width="2"/> <path d="M 30 75 L 30 25 L 80 50 z" fill="#dddddd" stroke="#000000" stroke-width="2" /> </svg>
  • 53. class DemoDelegate : public QItemDelegate { public: DemoDelegate(QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; protected: void drawSvg(QPainter *painter, const QRect &rect) const; private: mutable QSvgRenderer renderer; };
  • 54. void DemoDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { // draw the item as unselected and without focus rect QStyleOptionViewItem opt = option; opt.state &= ~QStyle::State_Selected; opt.state &= ~QStyle::State_HasFocus; QItemDelegate::paint(painter, opt, index); // draw svg over the current item if (option.state & QStyle::State_HasFocus) drawSvg(painter, option.rect); }
  • 55.
  • 56. More Models and Hierarchies
  • 57. struct SimpleNode { SimpleNode(SimpleNode *parent) : parentNode(parent) { if (parentNode) parentNode->children.append(this); } ~SimpleNode() { foreach(SimpleNode *child, children) delete child; } QVariant data() const { return "node data"; } SimpleNode *parentNode; QList<SimpleNode*> children; };
  • 58. Model Interface View Data Structure
  • 59.
  • 60. 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: QModelIndex indexForNode(SimpleNode *node) const; SimpleNode *nodeForIndex(const QModelIndex &index) const; int rowForNode(SimpleNode *node) const; private: SimpleNode *root; };
  • 61. 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; }
  • 62. SimpleModel::SimpleModel(QObject *parent) : QAbstractItemModel(parent) { // Initialize the data structure root = new SimpleNode(0); for (int i = 0; i < 10; ++i) { SimpleNode *topLevel = new SimpleNode(root); for (int j = 0; j < 5; ++j) { SimpleNode *secondLevel = new SimpleNode(topLevel); for (int k = 0; k < 3; ++k) { (void) new SimpleNode(secondLevel); } } } } SimpleModel::~SimpleModel() { delete root; }
  • 63. QVariant SimpleModel::data(const QModelIndex &index, int role) const { if (index.isValid() && role == Qt::DisplayRole) { SimpleNode *node = nodeForIndex(index); return node->data(); } return QVariant(); }
  • 64. Model Index Qt4 Logo
  • 65. 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 indexForNode(childNode); } return QModelIndex(); }
  • 66. QModelIndex SimpleModel::parent(const QModelIndex &child) const { SimpleNode *childNode = nodeForIndex(child); SimpleNode *parentNode = childNode->parentNode; if (parentNode == root) return QModelIndex(); return indexForNode(parentNode); }
  • 67. QModelIndex SimpleModel::indexForNode(SimpleNode *node) const { if (node == root) return QModelIndex(); int row = rowForNode(node); int column = 0; return createIndex(row, column, node); }
  • 68. 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); }
  • 69. int main(int argc, char *argv[]) { QApplication app(argc, argv); SimpleModel model; QTreeView view; view.setModel(&model); view.show(); return app.exec(); }
  • 70. What we have covered ● The Qt Model View Architecture ● The Item Model Interface ● Customized Item Filtering ● Customized Item Painting ● Hierarchical Models