// $Id$ // BoilerTreeView.cpp // // CLASSES: // class BoilerTreeView : public QTreeView // class BoilerTreeView::ItemModel : public QAbstractItemModel // class BoilerTreeView::ItemDelegate : public QStyledItemDelegate // // DESCRIPTION: // This boiler plate Qt4 QTreeView class with internal "model" and // "delegate" subclasses is intended for adaptation for application // QTreeView classes. It is concrete (i.e. it can be instantiated), and // -- as coded -- implements a three-column, five-row unsortable list // with the cells in the middle column being editable. // // If column sorting is desired, I recommend handling sorting directly // in the item model class rather than by introducing a QSortFilterProxyModel // subclass. Use of that class creates ambiguities in interpreting // QModelIndex values, and itself has some problems. However, if you // really want to use a QSortFilterProxyModel, I recommend use of our // own "RwQSortFilterProxyModel" to fix those problems. (At least see // the comments at the head of RwQSortFilterProxyModel.cpp). // // To use as a basis for a new QTreeView subclass, copy this file, and the // the accompanying header file, and do a global substitution within the // new files of "Boiler". // // (1) BoilerTreeView.cpp (this file). // (2) BoilerTreeView.hpp (header file). // // This module contains "QObject" classes (all three classes listed above). // So this module needs to be supported as such in the make files; // On Windows: in the two ".pro" files in the containing project (library). // //-- // Replace USES of these symbols with application code (in the item model). static const int DummyRowCnt (5); static const int DummyColCnt (3); // Sample treeview column index symbols static const int COL_Huey (0); static const int COL_Dewey (1); static const int COL_Louie (2); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #ifndef BoilerTreeViewINCLUDED #include "BoilerTreeView.hpp" #endif #ifndef rwErrorINCLUDED #include "rwError.hpp" //--- for rwAssert #endif #include #include #include #include //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // ****************************************** // *** class BoilerTreeView : QTreeView *** // ****************************************** // constructor 1 of 1 BoilerTreeView::BoilerTreeView (QWidget* parentWid) : QTreeView (parentWid), _itemModel (NULL), _itemDelegate (NULL) { static const char* mname ("BoilerTreeView ctor"); std::cout << mname << std::endl; _itemModel = new ItemModel (this); setModel (_itemModel); _itemDelegate = new ItemDelegate (this); setItemDelegate (_itemDelegate); QHeaderView* hdrView = header(); hdrView->setSortIndicatorShown (false); hdrView->setMovable (false); hdrView->setStretchLastSection (false); hdrView->setResizeMode (QHeaderView::ResizeToContents); // hdrView->setResizeMode (COL_Huey, QHeaderView::ResizeToContents); // hdrView->setResizeMode (COL_Dewey, QHeaderView::ResizeToContents); // hdrView->setResizeMode (COL_Louie, QHeaderView::ResizeToContents); setSortingEnabled (false); setAllColumnsShowFocus (true); setMouseTracking (true); // For Status Tips setRootIsDecorated (false); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // destructor BoilerTreeView::~BoilerTreeView() { static const char* mname ("BoilerTreeView dtor"); std::cout << mname << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // ************************************************************** // *** class BoilerTreeView::ItemModel : QAbstractItemModel *** // ************************************************************** // constructor 1 of 1 BoilerTreeView::ItemModel::ItemModel (BoilerTreeView* parentTreeView) : QAbstractItemModel (parentTreeView), _parentTreeView (parentTreeView) { static const char* mname ("BoilerTreeView::ItemModel ctor"); std::cout << mname << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // destructor BoilerTreeView::ItemModel::~ItemModel() { static const char* mname ("BoilerTreeView::ItemModel dtor"); std::cout << mname << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel Qt::ItemFlags BoilerTreeView::ItemModel::flags ( const QModelIndex& modelInx) const { // Qt::NoItemFlags -- Does not have any properties set. // Qt::ItemIsSelectable -- Can be selected. // Qt::ItemIsEditable -- Can be edited. // Qt::ItemIsDragEnabled -- Can be dragged. // Qt::ItemIsDropEnabled -- Can be used as a drop target. // Qt::ItemIsUserCheckable -- Can be checked or unchecked by the user. // Qt::ItemIsEnabled -- The user can interact with the item. // Qt::ItemIsTristate -- Item is checkable with three separate states. Qt::ItemFlags retFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; const int col = modelInx.column(); if (col == COL_Dewey) { retFlags |= Qt::ItemIsEditable; } return (retFlags); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel QModelIndex BoilerTreeView::ItemModel::index (int row, int col, const QModelIndex& parent /*=QModelIndex()*/) const { if (parent == QModelIndex()) { return createIndex (row, col); // [QAbstractItemModel] } return (QModelIndex()); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel int BoilerTreeView::ItemModel::rowCount ( const QModelIndex& parent /*=QModelIndex()*/) const { if (parent == QModelIndex()) { return (DummyRowCnt); // XXX TODO } return (0); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel int BoilerTreeView::ItemModel::columnCount ( const QModelIndex& parent /*=QModelIndex()*/) const { if (parent == QModelIndex()) { return (DummyColCnt); // XXX TODO } return (0); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel QVariant BoilerTreeView::ItemModel::data ( const QModelIndex& modelInx, int role /*=Qt::DisplayRole*/) const { // Note: See enum Qt::ItemDataRole for role values. // http://doc.trolltech.com/4.6/qt.html#ItemDataRole-enum if ( (role == Qt::DisplayRole) || (role == Qt::EditRole) ) { const unsigned int flagsInt = (unsigned int) flags (modelInx); const QString retStr = QString (" [%1, %2] 0x%3 ") .arg (modelInx.row()) .arg (modelInx.column()) .arg (flagsInt, 3, 16, QLatin1Char ('0')); if (role == Qt::EditRole) return QVariant (retStr.trimmed()); return QVariant (retStr); } return QVariant(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel QVariant BoilerTreeView::ItemModel::headerData ( int section, Qt::Orientation orient, int role /*=Qt::DisplayRole*/) const { if (orient == Qt::Horizontal) { if (role == Qt::DisplayRole) { const int col (section); // section is column index [0..] QString retStr = QString ("col %1") .arg (col); // tentative switch (col) { case COL_Huey: retStr = "Huey"; break; case COL_Dewey: retStr = "Dewey"; break; case COL_Louie: retStr = "Louie"; break; } return QVariant (retStr); } } return QVariant(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemModel bool BoilerTreeView::ItemModel::setData (const QModelIndex& modelInx, const QVariant& val, int role /*=Qt::EditRole*/) { static const char* mname ("BoilerTreeView::ItemModel::setData"); //-------------------------------------------------------------------- // Qt Notes: // (1) This method sets the "role" data for the item at index to value. // (2) Returns true if successful; otherwise returns false. // (3) The dataChanged() signal should be emitted if the data was // successfully set. // (4) The base class implementation returns false. This function and // data() must be reimplemented for editable models. //-------------------------------------------------------------------- const bool roleIsEdit = (role == Qt::EditRole); const int row = modelInx.row(); const int col = modelInx.column(); const QString str = val.toString(); std::cout << mname << " [" << row << "," << col << "]" << " " << (roleIsEdit ? "EDIT" : "not-edit") << " '" << qPrintable (str) << "'" << std::endl; QApplication::beep(); return (false); // change was not accepted. } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // ****************************************************************** // *** class BoilerTreeView::ItemDelegate : QStyledItemDelegate *** // ****************************************************************** // constructor BoilerTreeView::ItemDelegate::ItemDelegate ( BoilerTreeView* parentTreeView) : QStyledItemDelegate (parentTreeView), _parentTreeView (parentTreeView) { static const char* mname ("BoilerTreeView::ItemDelegate ctor"); std::cout << mname << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // destructor BoilerTreeView::ItemDelegate::~ItemDelegate() { static const char* mname ("BoilerTreeView::ItemDelegate dtor"); std::cout << mname << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemDelegate QWidget* BoilerTreeView::ItemDelegate::createEditor ( QWidget* parentWid, const QStyleOptionViewItem& styleItem, const QModelIndex& modelInx) const { // Note: when defering to the base class implementation, make sure // to call the direct base class method, i.e. of QStyledItemDelegate. QWidget* customEditor = QStyledItemDelegate::createEditor (parentWid, styleItem, modelInx); return (customEditor); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemDelegate void BoilerTreeView::ItemDelegate::setEditorData ( QWidget* customEditor, const QModelIndex& modelInx) const { // Note: when defering to the base class implementation, make sure // to call the direct base class method, i.e. of QStyledItemDelegate. QStyledItemDelegate::setEditorData (customEditor, modelInx); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // virtual from QAbstractItemDelegate void BoilerTreeView::ItemDelegate::setModelData ( QWidget* customEditor, QAbstractItemModel* itemModel, const QModelIndex& modelInx) const { // Note: when defering to the base class implementation, make sure // to call the direct base class method, i.e. of QStyledItemDelegate. QStyledItemDelegate::setModelData (customEditor, itemModel, modelInx); } //--- (end BoilerTreeView.cpp) ---