Qt/ModelView/ListViewComboBox

From ProgrammingExamples
< Qt
Jump to: navigation, search

main.cpp

#include <QApplication>
 
#include "form.h"
 
int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  Form form;
 
  form.show();
  return app.exec();
}

ComboBoxDelegate.h

#ifndef COMBOBOXDELEGATE_H
#define COMBOBOXDELEGATE_H
 
#include <string>
#include <vector>
 
#include <QItemDelegate>
 
class QModelIndex;
class QWidget;
class QVariant;
 
class ComboBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
  ComboBoxDelegate(QObject *parent = 0);
 
  QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
  void setEditorData(QWidget *editor, const QModelIndex &index) const;
  void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
  void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
  void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
 
private:
  std::vector<std::string> Items;
 
};
#endif

ComboBoxDelegate.cpp

#include "ComboBoxDelegate.h"
 
#include <QComboBox>
#include <QWidget>
#include <QModelIndex>
#include <QApplication>
#include <QString>
 
#include <iostream>
 
ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
:QItemDelegate(parent)
{
  Items.push_back("Test0");
  Items.push_back("Test1");
  Items.push_back("Test2");
}
 
 
QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
{
  QComboBox* editor = new QComboBox(parent);
  for(unsigned int i = 0; i < Items.size(); ++i)
    {
    editor->addItem(Items[i].c_str());
    }
  return editor;
}
 
void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  int value = index.model()->data(index, Qt::EditRole).toUInt();
  comboBox->setCurrentIndex(value);
}
 
void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  model->setData(index, comboBox->currentIndex(), Qt::EditRole);
}
 
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
  editor->setGeometry(option.rect);
}
 
void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
  QStyleOptionViewItemV4 myOption = option;
  QString text = Items[index.row()].c_str();
 
  myOption.text = text;
 
  QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &myOption, painter);
}

form.h

#ifndef FORM_H
#define FORM_H
 
#include "ui_form.h"
 
#include <QMainWindow>
 
#include "ComboBoxDelegate.h"
 
class QStringListModel;
 
class Form : public QMainWindow, private Ui::MainWindow
{
  Q_OBJECT
 
public:
  Form(QWidget *parent = 0);
 
public slots:
  void on_btnAdd_clicked();
  void slot_modelChanged(const QModelIndex  &topLeft, const QModelIndex  &bottomRight);
 
protected:
  QStringListModel* Model;
  ComboBoxDelegate Delegate;
};
 
#endif

form.cpp

#include <QtGui>
 
#include <iostream>
 
#include "form.h"
 
Form::Form(QWidget *parent)
    : QMainWindow(parent)
{
  setupUi(this);
 
  this->Model = new QStringListModel;
  this->listView->setModel(this->Model);
  connect(this->Model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(slot_modelChanged(QModelIndex,QModelIndex)));
 
  this->listView->setItemDelegate(&this->Delegate);
}
 
void Form::on_btnAdd_clicked()
{
  this->Model->insertRows(this->Model->rowCount(), 1);
  this->Model->setData(this->Model->index(this->Model->rowCount()-1), "new line " + QString::number(this->Model->rowCount()));
}
 
void Form::slot_modelChanged(const QModelIndex &topLeft, const QModelIndex  &bottomRight)
{
  std::cout << "Model changed." << std::endl;
 
  // Make the combo boxes always displayed.
  for ( int i = 0; i < this->Model->rowCount(); ++i )
    {
    this->listView->openPersistentEditor( this->Model->index(i) );
    }
}

form.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>232</width>
    <height>489</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QListView" name="listView"/>
    </item>
    <item>
     <widget class="QPushButton" name="btnAdd">
      <property name="text">
       <string>Add</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>232</width>
     <height>20</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFile">
    <property name="title">
     <string>File</string>
    </property>
    <addaction name="actionSave"/>
   </widget>
   <addaction name="menuFile"/>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
  <action name="actionSave">
   <property name="text">
    <string>Save</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections/>
</ui>

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
 
PROJECT(ListViewSubclass)
 
FIND_PACKAGE(Qt4 REQUIRED)
INCLUDE(${QT_USE_FILE})
 
QT4_WRAP_UI(ListViewSubclass_UI form.ui)
QT4_WRAP_CPP(ListViewSubclass_MOC form.h ComboBoxDelegate.h)
 
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
 
ADD_EXECUTABLE(ListViewSubclass main.cpp form.h form.cpp ComboBoxDelegate.cpp ${ListViewSubclass_UI} ${ListViewSubclass_MOC})
TARGET_LINK_LIBRARIES(ListViewSubclass ${QT_LIBRARIES})