Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) QTreeViewExample3

 

QtQt CreatorLubuntu

 

QTreeView example 3: improved undo/redo and added drag/drop is an example to use a QTreeView.

 

Technical facts

 

Application type(s)

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: ./CppQTreeViewExample3/CppQTreeViewExample3.pro

 

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TEMPLATE = app

SOURCES += \
    qtdialog.cpp \
    qtmain.cpp \
    qtaddrowcommand.cpp \
    qtmytreeview.cpp \
    qtmyitem.cpp

HEADERS  += qtdialog.h \
    qtaddrowcommand.h \
    qtmytreeview.h \
    qtmyitem.h

FORMS    += qtdialog.ui

 

 

 

 

 

./CppQTreeViewExample3/qtaddrowcommand.h

 

#ifndef QTADDROWCOMMAND_H
#define QTADDROWCOMMAND_H

#include <QModelIndex>
#include <QUndoCommand>

struct QStandardItemModel;
struct QAbstractItemView;

struct QtAddRowCommand : public QUndoCommand
{
  QtAddRowCommand(
    QStandardItemModel * const model,
    QAbstractItemView * const view,
    const std::string& text = "");
  void redo();
  void undo();

  private:
  QStandardItemModel * const m_model;
  const QModelIndex m_prev_index;
  std::string m_text;
  QAbstractItemView  * const m_view;
};

#endif // QTADDROWCOMMAND_H

 

 

 

 

 

./CppQTreeViewExample3/qtaddrowcommand.cpp

 

#include "qtaddrowcommand.h"

#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QStandardItemModel>

#include "qtmyitem.h"

QtAddRowCommand::QtAddRowCommand(
  QStandardItemModel * const model,
  QAbstractItemView * const view,
  const std::string& text)
  : m_model(model),
    m_prev_index(view->currentIndex()),
    m_text(text),
    m_view(view)
{

}

void QtAddRowCommand::redo()
{
  QtMyItem * const item = new QtMyItem(m_text.c_str());
  item->setText(m_text.c_str());
  m_model->appendRow(item);
  m_view->setCurrentIndex(item->index());
  this->setText("Added row at index " + QString::number(item->index().row()));
}

void QtAddRowCommand::undo()
{
  const int n_rows = m_model->rowCount();
  QtMyItem * const item = dynamic_cast<QtMyItem *>(m_model->item(n_rows - 1));
  if (item) m_text = item->text().toStdString();
  m_model->removeRow(n_rows - 1);
  m_view->setCurrentIndex(m_prev_index);
}

 

 

 

 

 

./CppQTreeViewExample3/qtdialog.h

 

#ifndef QTDIALOG_H
#define QTDIALOG_H

#include <QDialog>

namespace Ui {
  class QtDialog;
}

struct QStandardItemModel;
struct QUndoStack;
struct QtMyTreeView;

class QtDialog : public QDialog
{
  Q_OBJECT
  
public:
  explicit QtDialog(QWidget *parent = 0);
  ~QtDialog();

protected:
  void keyPressEvent(QKeyEvent *);
  
private slots:
  void on_button_clicked();

private:
  Ui::QtDialog *ui;
  QStandardItemModel * const m_model;
  QUndoStack * const m_undo_stack;
  QtMyTreeView * const m_view;
};

#endif // QTDIALOG_H

 

 

 

 

 

./CppQTreeViewExample3/qtdialog.cpp

 

#include "qtdialog.h"

#include <cassert>

#include <boost/lexical_cast.hpp>

#include <QKeyEvent>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QUndoStack>

#include "qtaddrowcommand.h"
#include "ui_qtdialog.h"
#include "qtmytreeview.h"
#include "qtmyitem.h"

QtDialog::QtDialog(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::QtDialog),
  m_model(new QStandardItemModel),
  m_undo_stack(new QUndoStack),
  m_view(new QtMyTreeView)
{
  ui->setupUi(this);
  assert(ui->scrollAreaWidgetContents->layout());
  ui->scrollAreaWidgetContents->layout()->addWidget(m_view);
  m_view->setModel(m_model);
  m_view->setItemDelegate(new QStyledItemDelegate);

  //Initial the QtMyTreeView with some items
  for (int i=0; i!=26; ++i)
  {
    QtAddRowCommand * const cmd
      = new QtAddRowCommand(
        m_model,
        m_view,
        boost::lexical_cast<std::string,char>('A' + i));
    m_undo_stack->push(cmd);
  }

}

QtDialog::~QtDialog()
{
  delete ui;
  delete m_model;
  delete m_undo_stack;
  delete m_view;
}

void QtDialog::keyPressEvent(QKeyEvent * e)
{
  if (e->key() == Qt::Key_Escape) { close(); return; }
  if ( (e->modifiers() & Qt::ControlModifier)
    && !(e->modifiers() & Qt::ShiftModifier)
    && e->key() == Qt::Key_Z)
  {
    m_undo_stack->undo();
    return;
  }
  if ( (e->modifiers() & Qt::ControlModifier)
    && (e->modifiers() & Qt::ShiftModifier)
    && e->key() == Qt::Key_Z)
  {
    m_undo_stack->redo();
    return;
  }
}

void QtDialog::on_button_clicked()
{
  QtAddRowCommand * const cmd = new QtAddRowCommand(m_model,m_view);
  m_undo_stack->push(cmd);

  const int n_rows = m_model->rowCount();
  QtMyItem * const item = dynamic_cast<QtMyItem*>(m_model->item(n_rows - 1));
  assert(item);
  m_view->edit(item->index());

}

 

 

 

 

 

./CppQTreeViewExample3/qtmain.cpp

 

#include <QApplication>
#include "qtdialog.h"

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  QtDialog w;
  w.show();
  
  return a.exec();
}

 

 

 

 

 

./CppQTreeViewExample3/qtmyitem.h

 

#ifndef QTMYITEM_H
#define QTMYITEM_H

#include <QStandardItem>

struct QtMyItem : public QStandardItem
{
  QtMyItem(const QString &text);
};

#endif // QTMYITEM_H

 

 

 

 

 

./CppQTreeViewExample3/qtmyitem.cpp

 

#include "qtmyitem.h"

QtMyItem::QtMyItem(const QString &text)
  : QStandardItem(text)
{
  this->setEditable(true);
  this->setDragEnabled(true);
  this->setDropEnabled(true);
}

 

 

 

 

 

./CppQTreeViewExample3/qtmytreeview.h

 

#ifndef QTMYTREEVIEW_H
#define QTMYTREEVIEW_H

#include <QTreeView>

struct QtMyTreeView : public QTreeView
{
  QtMyTreeView(QWidget * const parent = 0);
};

#endif // QTMYTREEVIEW_H

 

 

 

 

 

./CppQTreeViewExample3/qtmytreeview.cpp

 

#include "qtmytreeview.h"

#include <QDragEnterEvent>
#include <QDropEvent>
#include <QDragMoveEvent>

QtMyTreeView::QtMyTreeView(QWidget * const parent)
  : QTreeView(parent)
{
  this->setAcceptDrops(true);
  this->setAlternatingRowColors(true);
  this->setAnimated(true);
  this->setDragDropMode(QAbstractItemView::InternalMove);
  this->setDragEnabled(true);
  this->setDropIndicatorShown(true);
  this->setExpandsOnDoubleClick(true);
  this->setHeaderHidden(true);
  this->setItemsExpandable(true);
  this->setSelectionMode(QAbstractItemView::SingleSelection);
  this->setWordWrap(true);
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml