From 9e8cf82ee0a287f50059a9b34488f3d6b8887354 Mon Sep 17 00:00:00 2001 From: Walter Van Herck <w.van.herck@fz-juelich.de> Date: Fri, 21 Feb 2014 13:15:54 +0100 Subject: [PATCH] Changed to QAbstractItemModel and implemented drag and drop in QTreeView --- GUI/coregui/Models/ItemFactory.cpp | 9 +- GUI/coregui/Models/ItemFactory.h | 3 +- GUI/coregui/Models/LayerItem.cpp | 4 +- GUI/coregui/Models/LayerItem.h | 2 +- GUI/coregui/Models/MultiLayerItem.cpp | 4 +- GUI/coregui/Models/MultiLayerItem.h | 2 +- GUI/coregui/Models/ParameterizedItem.cpp | 27 +- GUI/coregui/Models/ParameterizedItem.h | 58 ++- GUI/coregui/Models/ParticleDecorationItem.cpp | 4 +- GUI/coregui/Models/ParticleDecorationItem.h | 2 +- GUI/coregui/Models/SessionModel.cpp | 344 ++++++++++++++++-- GUI/coregui/Models/SessionModel.h | 68 +++- GUI/coregui/Views/SampleView.cpp | 48 ++- GUI/coregui/Views/SampleView.h | 1 + GUI/coregui/Views/SampleViewComponents.cpp | 1 + GUI/coregui/utils/GUIHelpers.h | 15 + 16 files changed, 508 insertions(+), 84 deletions(-) diff --git a/GUI/coregui/Models/ItemFactory.cpp b/GUI/coregui/Models/ItemFactory.cpp index 211fd6c4718..a43f0a3ad00 100644 --- a/GUI/coregui/Models/ItemFactory.cpp +++ b/GUI/coregui/Models/ItemFactory.cpp @@ -23,19 +23,20 @@ QList<QString> ItemFactory::m_all_item_names = QList<QString>() << QString("Layer") << QString("ParticleDecoration"); -ParameterizedItem *ItemFactory::createItem(const QString &model_name) +ParameterizedItem *ItemFactory::createItem(const QString &model_name, + ParameterizedItem *parent) { if (!m_all_item_names.contains(model_name)) { return 0; } if (model_name==QString("MultiLayer")) { - return new MultiLayerItem(); + return new MultiLayerItem(parent); } if (model_name==QString("Layer")) { - return new LayerItem(); + return new LayerItem(parent); } if (model_name==QString("ParticleDecoration")) { - return new ParticleDecorationItem(); + return new ParticleDecorationItem(parent); } return 0; } diff --git a/GUI/coregui/Models/ItemFactory.h b/GUI/coregui/Models/ItemFactory.h index ce4316bbac7..3cf4672fc6c 100644 --- a/GUI/coregui/Models/ItemFactory.h +++ b/GUI/coregui/Models/ItemFactory.h @@ -21,7 +21,8 @@ class ItemFactory { public: - static ParameterizedItem *createItem(const QString &model_name); + static ParameterizedItem *createItem(const QString &model_name, + ParameterizedItem *parent=0); static QList<QString> getAllItemNames() { return m_all_item_names; } diff --git a/GUI/coregui/Models/LayerItem.cpp b/GUI/coregui/Models/LayerItem.cpp index 373fe206f04..48f689a924d 100644 --- a/GUI/coregui/Models/LayerItem.cpp +++ b/GUI/coregui/Models/LayerItem.cpp @@ -15,8 +15,8 @@ #include "LayerItem.h" -LayerItem::LayerItem() - : ParameterizedItem(QString("Layer")) +LayerItem::LayerItem(ParameterizedItem *parent) + : ParameterizedItem(QString("Layer"), parent) { m_parameters[QString("Thickness")] = 0.0; m_valid_children.append(QString("ParticleDecoration")); diff --git a/GUI/coregui/Models/LayerItem.h b/GUI/coregui/Models/LayerItem.h index 0d5f67ac864..a384181506c 100644 --- a/GUI/coregui/Models/LayerItem.h +++ b/GUI/coregui/Models/LayerItem.h @@ -21,7 +21,7 @@ class LayerItem : public ParameterizedItem { public: - explicit LayerItem(); + explicit LayerItem(ParameterizedItem *parent=0); ~LayerItem(); }; diff --git a/GUI/coregui/Models/MultiLayerItem.cpp b/GUI/coregui/Models/MultiLayerItem.cpp index 4963c953a70..99695d96048 100644 --- a/GUI/coregui/Models/MultiLayerItem.cpp +++ b/GUI/coregui/Models/MultiLayerItem.cpp @@ -16,8 +16,8 @@ #include "MultiLayerItem.h" -MultiLayerItem::MultiLayerItem() - : ParameterizedItem(QString("MultiLayer")) +MultiLayerItem::MultiLayerItem(ParameterizedItem *parent) + : ParameterizedItem(QString("MultiLayer"), parent) { m_parameters[QString("Cross Correlation Length")] = 0.0; m_valid_children.append(QString("Layer")); diff --git a/GUI/coregui/Models/MultiLayerItem.h b/GUI/coregui/Models/MultiLayerItem.h index a13e8c137d0..4251d0eeeef 100644 --- a/GUI/coregui/Models/MultiLayerItem.h +++ b/GUI/coregui/Models/MultiLayerItem.h @@ -21,7 +21,7 @@ class MultiLayerItem : public ParameterizedItem { public: - explicit MultiLayerItem(); + explicit MultiLayerItem(ParameterizedItem *parent=0); ~MultiLayerItem(); }; diff --git a/GUI/coregui/Models/ParameterizedItem.cpp b/GUI/coregui/Models/ParameterizedItem.cpp index fd71ec61d02..44691a3406a 100644 --- a/GUI/coregui/Models/ParameterizedItem.cpp +++ b/GUI/coregui/Models/ParameterizedItem.cpp @@ -18,20 +18,34 @@ -ParameterizedItem::ParameterizedItem(const QString &name) - : QStandardItem(name) +ParameterizedItem::ParameterizedItem(const QString &model_type, + ParameterizedItem *parent) + : m_model_type(model_type) + , m_parent(parent) { + if (m_parent) { + m_parent->addChildItem(this); + } } ParameterizedItem::~ParameterizedItem() { + qDeleteAll(m_children); +} + +ParameterizedItem *ParameterizedItem::takeChildItem(int row) +{ + ParameterizedItem *item = m_children.takeAt(row); + item->m_parent = 0; + return item; } double ParameterizedItem::getParameterValue(const QString &name) const { if (!m_parameters.contains(name)) { - throw Exceptions::RuntimeErrorException("ParameterizedItem::getParameterValue: " - "parameter does not exist"); + throw Exceptions::RuntimeErrorException( + "ParameterizedItem::getParameterValue: " + "parameter does not exist"); } return m_parameters[name]; } @@ -39,8 +53,9 @@ double ParameterizedItem::getParameterValue(const QString &name) const void ParameterizedItem::setParameter(const QString &name, double value) { if (!m_parameters.contains(name)) { - throw Exceptions::RuntimeErrorException("ParameterizedItem::getParameterValue: " - "parameter does not exist"); + throw Exceptions::RuntimeErrorException( + "ParameterizedItem::getParameterValue: " + "parameter does not exist"); } m_parameters[name] = value; } diff --git a/GUI/coregui/Models/ParameterizedItem.h b/GUI/coregui/Models/ParameterizedItem.h index 563be4172bb..06ad91acab0 100644 --- a/GUI/coregui/Models/ParameterizedItem.h +++ b/GUI/coregui/Models/ParameterizedItem.h @@ -20,12 +20,53 @@ #include <QList> #include <QMap> -class ParameterizedItem : public QStandardItem +class ParameterizedItem { public: - explicit ParameterizedItem(const QString &name); + explicit ParameterizedItem(const QString &model_type=QString(), + ParameterizedItem *parent=0); ~ParameterizedItem(); + //! retrieves the model type + QString modelType() const { return m_model_type; } + + //! retrieve parent item + ParameterizedItem *getParent() const { return m_parent; } + + //! retrieve child item in given row + ParameterizedItem *getChildAt(int row) const { + return m_children.value(row); + } + + //! get row number of child + int rowOfChild(ParameterizedItem *child) const { + return m_children.indexOf(child); + } + + //! get number of child items + int childItemCount() const { return m_children.count(); } + + //! indicates if item has child items + bool hasChildItems() const { return !m_children.isEmpty(); } + + //! returns the a list of child items + QList<ParameterizedItem *> childItems() const { return m_children; } + + //! inserts a child item at specified row + void insertChildItem(int row, ParameterizedItem *item) + { item->m_parent = this; m_children.insert(row, item); } + + //! append child item + void addChildItem(ParameterizedItem *item) + { item->m_parent = this; m_children << item; } + + //! swap two child items + void swapChildItems(int row_1, int row_2) + { m_children.swap(row_1, row_2); } + + //! take child item (this removes it from the current item) + ParameterizedItem *takeChildItem(int row); + //! retrieves the parameter's value double getParameterValue(const QString &name) const; @@ -33,22 +74,23 @@ public: void setParameter(const QString &name, double value); //! retrieves the whole list of paramaters - QMap<QString, double> &getParameters() { - return m_parameters; - } + QMap<QString, double> &getParameters() { return m_parameters; } //! indicates if the passed item can be set as //! a child item bool acceptsAsChild(const QString &child_name) const; //! get list of acceptable child object names - QList<QString> getAcceptableChildren() const { - return m_valid_children; - } + QList<QString> getAcceptableChildren() const { return m_valid_children; } + protected: QList<QString> m_valid_children; QMap<QString, double> m_parameters; + private: + QString m_model_type; + ParameterizedItem *m_parent; + QList<ParameterizedItem *> m_children; }; diff --git a/GUI/coregui/Models/ParticleDecorationItem.cpp b/GUI/coregui/Models/ParticleDecorationItem.cpp index 387d7a6d406..59a3144a770 100644 --- a/GUI/coregui/Models/ParticleDecorationItem.cpp +++ b/GUI/coregui/Models/ParticleDecorationItem.cpp @@ -15,8 +15,8 @@ #include "ParticleDecorationItem.h" -ParticleDecorationItem::ParticleDecorationItem() - : ParameterizedItem(QString("ParticleDecoration")) +ParticleDecorationItem::ParticleDecorationItem(ParameterizedItem *parent) + : ParameterizedItem(QString("ParticleDecoration"), parent) { // m_valid_children.append(QString("")); } diff --git a/GUI/coregui/Models/ParticleDecorationItem.h b/GUI/coregui/Models/ParticleDecorationItem.h index 2fd010b2b3a..c496ca0e8ca 100644 --- a/GUI/coregui/Models/ParticleDecorationItem.h +++ b/GUI/coregui/Models/ParticleDecorationItem.h @@ -21,7 +21,7 @@ class ParticleDecorationItem : public ParameterizedItem { public: - ParticleDecorationItem(); + explicit ParticleDecorationItem(ParameterizedItem *parent=0); ~ParticleDecorationItem(); }; diff --git a/GUI/coregui/Models/SessionModel.cpp b/GUI/coregui/Models/SessionModel.cpp index b3b109bc923..98bfbb7d31e 100644 --- a/GUI/coregui/Models/SessionModel.cpp +++ b/GUI/coregui/Models/SessionModel.cpp @@ -15,53 +15,353 @@ #include "SessionModel.h" #include "ItemFactory.h" +#include "GUIHelpers.h" +#include <QFile> +#include <QMimeData> + +namespace { +const int MaxCompression = 9; +enum Column { + ModelType, + MaxColumns +}; +const QString MimeType = "application/org.bornagainproject.xml.item.z"; +} SessionModel::SessionModel(QObject *parent) - : QStandardItemModel(parent) + : QAbstractItemModel(parent) + , m_root_item(0) { - initialize(); } SessionModel::~SessionModel() { + delete m_root_item; } -QStandardItem *SessionModel::insertNewItem(QString model_type, const QModelIndex &index) +Qt::ItemFlags SessionModel::flags(const QModelIndex &index) const { - QStandardItem *parent; + Qt::ItemFlags result_flags = QAbstractItemModel::flags(index); if (index.isValid()) { - parent = itemFromIndex(index); - if (!parent) { - return 0; + result_flags |= Qt::ItemIsSelectable|Qt::ItemIsEnabled + |Qt::ItemIsEditable|Qt::ItemIsDragEnabled + |Qt::ItemIsDropEnabled; + } + return result_flags; +} + +QVariant SessionModel::data(const QModelIndex &index, int role) const +{ + if (!m_root_item || !index.isValid() || index.column() < 0 + || index.column() >= MaxColumns) { + return QVariant(); + } + if (ParameterizedItem *item = itemForIndex(index)) { + if (role == Qt::DisplayRole || role == Qt::EditRole) { + switch (index.column()) { + case ModelType: return item->modelType(); + default: return QVariant(); + } } } - else { - parent = invisibleRootItem(); + return QVariant(); +} + +QVariant SessionModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case ModelType: return tr("Model Type"); + } } - return createNewItem(parent, model_type); + return QVariant(); } -void SessionModel::initialize() +int SessionModel::rowCount(const QModelIndex &parent) const { + if (parent.isValid() && parent.column() != 0) return 0; + ParameterizedItem *parent_item = itemForIndex(parent); + return parent_item ? parent_item->childItemCount() : 0; } -QStandardItem *SessionModel::createNewItem(QStandardItem *parent, QString model_type) +int SessionModel::columnCount(const QModelIndex &parent) const { - // Check if child is allowed to be added to parent - if (parent!=invisibleRootItem()) - { - ParameterizedItem *p_par_parent = dynamic_cast<ParameterizedItem *>(parent); - if (!p_par_parent || !p_par_parent->acceptsAsChild(model_type)) { - return 0; + if (parent.isValid() && parent.column() != 0) return 0; + return MaxColumns; +} + +QModelIndex SessionModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!m_root_item || row < 0 || column < 0 || column >= MaxColumns + || (parent.isValid() && parent.column() != 0)) + return QModelIndex(); + ParameterizedItem *parent_item = itemForIndex(parent); + if (ParameterizedItem *item = parent_item->getChildAt(row)) { + return createIndex(row, column, item); + } + return QModelIndex(); +} + +QModelIndex SessionModel::parent(const QModelIndex &child) const +{ + if (!child.isValid()) return QModelIndex(); + if (ParameterizedItem *child_item = itemForIndex(child)) { + if (ParameterizedItem *parent_item = child_item->getParent()) { + if (parent_item == m_root_item) return QModelIndex(); + if (ParameterizedItem *grandparent_item = parent_item->getParent()) { + int row = grandparent_item->rowOfChild(parent_item); + return createIndex(row, 0, parent_item); + } } } + return QModelIndex(); +} - ParameterizedItem *new_item = ItemFactory::createItem(model_type); - if (!new_item) { - return 0; +bool SessionModel::setData(const QModelIndex &index, + const QVariant &value, int role) +{ + (void)index; + (void)value; + (void)role; + return false; +} + +bool SessionModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (!m_root_item) return false; + ParameterizedItem *item = parent.isValid() ? itemForIndex(parent) + : m_root_item; + beginRemoveRows(parent, row, row + count - 1); + for (int i=0; i<count; ++i) { + delete item->takeChildItem(row); + } + endRemoveRows(); + return true; +} + +QStringList SessionModel::mimeTypes() const +{ + return QStringList() << MimeType; +} + +QMimeData *SessionModel::mimeData(const QModelIndexList &indices) const +{ + if (indices.count() != 1) return 0; + if (ParameterizedItem *item = itemForIndex(indices.at(0))) { + QMimeData *mime_data = new QMimeData; + QByteArray xml_data; + QXmlStreamWriter writer(&xml_data); + writeItemAndChildItems(&writer, item); + mime_data->setData(MimeType, qCompress(xml_data, MaxCompression)); + return mime_data; + } + return 0; +} + +bool SessionModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, + const QModelIndex &parent) const +{ + (void)row; + if (action == Qt::IgnoreAction) return true; + if (action != Qt::MoveAction || column > 0 || !data + || !data->hasFormat(MimeType)) return false; + if (!parent.isValid()) return true; + QList<QString> acceptable_child_items = getAcceptableChildItems(parent); + QByteArray xml_data = qUncompress(data->data(MimeType)); + QXmlStreamReader reader(xml_data); + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement()) { + if (reader.name() == SessionXML::ItemTag) { + const QString model_type = reader.attributes() + .value(SessionXML::ModelTypeAttribute).toString(); + return acceptable_child_items.contains(model_type); + } + } + } + return false; +} + +bool SessionModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + if (action == Qt::IgnoreAction) return true; + if (action != Qt::MoveAction || column > 0 || !data + || !data->hasFormat(MimeType)) return false; + if (!canDropMimeData(data, action, row, column, parent)) return false; + if (ParameterizedItem *item = itemForIndex(parent)) { + QByteArray xml_data = qUncompress(data->data(MimeType)); + QXmlStreamReader reader(xml_data); + if (row == -1) row = item->childItemCount(); + beginInsertRows(parent, row, row); + readItems(&reader, item, row); + endInsertRows(); + return true; + } + return false; +} + +QModelIndex SessionModel::indexOfItem(ParameterizedItem *item) const +{ + if (!item || item == m_root_item) return QModelIndex(); + ParameterizedItem *parent_item = item->getParent(); + int row = parent_item->rowOfChild(item); + return createIndex(row, 0, item); +} + +ParameterizedItem *SessionModel::insertNewItem(QString model_type, + const QModelIndex &parent, + int row) +{ + if (!m_root_item) { + m_root_item = new ParameterizedItem; } + ParameterizedItem *parent_item = itemForIndex(parent); + if (row==-1) row = parent_item->childItemCount(); + beginInsertRows(parent, row, row); + ParameterizedItem *new_item = insertNewItem(model_type, parent_item, row); + endInsertRows(); + return new_item; +} + +QList<QString> SessionModel::getAcceptableChildItems( + const QModelIndex &parent) const +{ + QList<QString> result; + if (ParameterizedItem *parent_item = itemForIndex(parent)) { + result = parent_item->getAcceptableChildren(); + } + return result; +} - parent->appendRow(new_item); +void SessionModel::clear() +{ + beginResetModel(); + delete m_root_item; + m_root_item = 0; + endResetModel(); +} + +void SessionModel::load(const QString &filename) +{ + beginResetModel(); + if (!filename.isEmpty()) + m_filename = filename; + if (m_filename.isEmpty()) + throw GUIHelpers::Error(tr("no filename specified")); + QFile file(m_filename); + if (!file.open(QIODevice::ReadOnly)) + throw GUIHelpers::Error(file.errorString()); + clear(); + m_root_item = new ParameterizedItem; + QXmlStreamReader reader(&file); + readItems(&reader, m_root_item); + if (reader.hasError()) + throw GUIHelpers::Error(reader.errorString()); + endResetModel(); +} + +void SessionModel::save(const QString &filename) +{ + if (!filename.isEmpty()) + m_filename = filename; + if (m_filename.isEmpty()) + throw GUIHelpers::Error(tr("no filename specified")); + QFile file(m_filename); + if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) + throw GUIHelpers::Error(file.errorString()); + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.writeStartDocument(); + writer.writeStartElement("BornAgain"); + writer.writeAttribute("Version", "1.9"); + writeItemAndChildItems(&writer, m_root_item); + writer.writeEndElement(); // BornAgain + writer.writeEndDocument(); +} + +ParameterizedItem *SessionModel::insertNewItem(QString model_type, + ParameterizedItem *parent, + int row) +{ + if (!m_root_item) { + m_root_item = new ParameterizedItem; + } + if (!parent) parent = m_root_item; + if (row == -1) row = parent->childItemCount(); + if (row < 0 || row > parent->childItemCount()) return 0; + if (parent != m_root_item) { + if (!parent->acceptsAsChild(model_type)) + return 0; + } + ParameterizedItem *new_item = ItemFactory::createItem(model_type); + parent->insertChildItem(row, new_item); return new_item; } + +ParameterizedItem *SessionModel::itemForIndex(const QModelIndex &index) const +{ + if (index.isValid()) { + if (ParameterizedItem *item = static_cast<ParameterizedItem *>( + index.internalPointer())) + return item; + } + return m_root_item; +} + +void SessionModel::readItems(QXmlStreamReader *reader, ParameterizedItem *item, + int row) +{ + while (!reader->atEnd()) { + reader->readNext(); + if (reader->isStartElement()) { + if (reader->name() == SessionXML::ItemTag) { + const QString model_type = reader->attributes() + .value(SessionXML::ModelTypeAttribute).toString(); + item = insertNewItem(model_type, item, row); + row = -1; // all but the first item should be appended + } + else if (reader->name() == SessionXML::ParameterTag) { + const QString parameter_name = reader->attributes() + .value(SessionXML::ParameterNameAttribute) + .toString(); + double parameter_value = reader->attributes() + .value(SessionXML::ParameterValueAttribute) + .toDouble(); + item->setParameter(parameter_name, parameter_value); + } + } + else if (reader->isEndElement()) { + if (reader->name() == SessionXML::ItemTag) { + item = item->getParent(); + } + } + } +} + +void SessionModel::writeItemAndChildItems(QXmlStreamWriter *writer, ParameterizedItem *item) const +{ + if (item != m_root_item) { + writer->writeStartElement(SessionXML::ItemTag); + writer->writeAttribute(SessionXML::ModelTypeAttribute, item->modelType()); + QMapIterator<QString, double> it(item->getParameters()); + while (it.hasNext()) { + it.next(); + writer->writeStartElement(SessionXML::ParameterTag); + writer->writeAttribute(SessionXML::ParameterNameAttribute, + it.key()); + writer->writeAttribute(SessionXML::ParameterValueAttribute, + QString::number(it.value(), 'g', 12) ); + writer->writeEndElement(); // ParameterTag + } + } + foreach (ParameterizedItem *child_item, item->childItems()) { + writeItemAndChildItems(writer, child_item); + } + if (item != m_root_item) { + writer->writeEndElement(); // ItemTag + } +} diff --git a/GUI/coregui/Models/SessionModel.h b/GUI/coregui/Models/SessionModel.h index 78d97fcabd4..0d4d2736663 100644 --- a/GUI/coregui/Models/SessionModel.h +++ b/GUI/coregui/Models/SessionModel.h @@ -16,31 +16,81 @@ #ifndef SESSIONMODEL_H #define SESSIONMODEL_H -#include <QStandardItemModel> +#include <QAbstractItemModel> +#include <QtCore/QXmlStreamReader> +#include <QtCore/QXmlStreamWriter> + #include "ParameterizedItem.h" -class SessionModel : public QStandardItemModel +namespace SessionXML { +const QString ItemTag("Item"); +const QString ModelTypeAttribute("ModelType"); +const QString ParameterTag("Parameter"); +const QString ParameterNameAttribute("Name"); +const QString ParameterValueAttribute("Value"); +} + +class SessionModel : public QAbstractItemModel { Q_OBJECT + public: explicit SessionModel(QObject *parent=0); ~SessionModel(); + // Begin overriden methods from QAbstractItemModel + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role) const; + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + QModelIndex parent(const QModelIndex &child) const; + + bool setHeaderData(int, Qt::Orientation, const QVariant&, + int=Qt::EditRole) { return false; } + bool setData(const QModelIndex &index, const QVariant &value, int role); + bool removeRows(int row, int count, const QModelIndex &parent); + + Qt::DropActions supportedDragActions() const + { return Qt::MoveAction; } + Qt::DropActions supportedDropActions() const + { return Qt::MoveAction; } + QStringList mimeTypes() const; + QMimeData *mimeData(const QModelIndexList &indexes) const; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) const; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent); + // End overriden methods from QAbstractItemModel + + QModelIndex indexOfItem(ParameterizedItem *item) const; + ParameterizedItem *insertNewItem(QString model_type, + const QModelIndex &parent=QModelIndex(), + int row=-1); QString filename() const { return m_filename; } void setFilename(const QString &filename) { m_filename = filename; } - QStandardItem *insertNewItem(QString model_type, - const QModelIndex &index); -// void load(const QString &filename=QString()); -// void save(const QString &filename=QString()); + QList<QString> getAcceptableChildItems(const QModelIndex &parent) const; + + void clear(); + void load(const QString &filename=QString()); + void save(const QString &filename=QString()); private: - void initialize(); - QStandardItem *createNewItem(QStandardItem *parent, - QString model_type); + ParameterizedItem *insertNewItem(QString model_type, + ParameterizedItem *parent, + int row=-1); + ParameterizedItem *itemForIndex(const QModelIndex &index) const; + void readItems(QXmlStreamReader *reader, ParameterizedItem *item, + int row=-1); + void writeItemAndChildItems(QXmlStreamWriter *writer, + ParameterizedItem *item) const; QString m_filename; + ParameterizedItem *m_root_item; }; #endif // SESSIONMODEL_H diff --git a/GUI/coregui/Views/SampleView.cpp b/GUI/coregui/Views/SampleView.cpp index 4c216f7c34d..d702b030098 100644 --- a/GUI/coregui/Views/SampleView.cpp +++ b/GUI/coregui/Views/SampleView.cpp @@ -82,10 +82,12 @@ void SampleView::initSubWindows() m_session = new SessionModel(); // Temporary for testing - QStandardItem *multilayer = m_session->insertNewItem("MultiLayer", QModelIndex()); - QStandardItem *layer = m_session->insertNewItem("Layer", multilayer->index()); - m_session->insertNewItem("ParticleDecoration", layer->index()); - m_session->insertNewItem("Layer", QModelIndex()); + ParameterizedItem *multilayer = m_session->insertNewItem("MultiLayer"); + ParameterizedItem *layer = m_session->insertNewItem("Layer", + m_session->indexOfItem(multilayer)); + m_session->insertNewItem("ParticleDecoration", + m_session->indexOfItem(layer)); + m_session->insertNewItem("Layer"); // END temporary m_tree_view = SampleViewComponents::createTreeView(m_session, this); m_subWindows[SampleTreeView] = m_tree_view; @@ -135,30 +137,21 @@ void SampleView::resetToDefaultLayout() void SampleView::addItem(const QString &item_name) { QModelIndex currentIndex = getTreeView()->currentIndex(); - getSessionModel()->insertNewItem(item_name, currentIndex); + ParameterizedItem * new_item = getSessionModel()->insertNewItem( + item_name, currentIndex); + if (new_item) setCurrentIndex(getSessionModel()->indexOfItem(new_item)); setDirty(); updateUi(); } - void SampleView::deleteItem() { QModelIndex currentIndex = getTreeView()->currentIndex(); + if (!currentIndex.isValid()) return; + QModelIndex parent_index = getSessionModel()->parent(currentIndex); + int row = currentIndex.row(); if (currentIndex.isValid()) { - QStandardItem *item = getSessionModel()->itemFromIndex(currentIndex); - QString name = item->text(); - int rows = item->rowCount(); - QString message; - if (rows == 0) - message = tr("<p>Delete '%1'").arg(name); - else if (rows == 1) - message = tr("<p>Delete '%1' and its child (and " - "grandchildren etc.)").arg(name); - else if (rows > 1) - message = tr("<p>Delete '%1' and its %2 children (and " - "grandchildren etc.)").arg(name).arg(rows); - if (!GUIHelpers::okToDelete(this, tr("Delete"), message)) return; - getSessionModel()->removeRow(currentIndex.row(), currentIndex.parent()); + getSessionModel()->removeRows(row, 1, parent_index); setDirty(); updateUi(); } @@ -174,9 +167,7 @@ void SampleView::showContextMenu(const QPoint &pnt) if (!parent_index.isValid()) { addItemNames = ItemFactory::getAllItemNames(); } else { - QStandardItem *parent = getSessionModel()->itemFromIndex(parent_index); - ParameterizedItem *parent_par = static_cast<ParameterizedItem *>(parent); - addItemNames = parent_par->getAcceptableChildren(); + addItemNames = getSessionModel()->getAcceptableChildItems(parent_index); } if (addItemNames.size() > 0) { foreach (QString item_name, addItemNames) { @@ -219,13 +210,20 @@ void SampleView::connectSignals() connect(m_toolBar, SIGNAL(sceneToISample()), m_sampleDesigner, SLOT(sceneToISample())); // connect context menu for tree view - QTreeView *tree_view = static_cast<QTreeView *>(m_subWindows[SampleTreeView]); - connect(tree_view, SIGNAL(customContextMenuRequested(const QPoint &)), + connect(m_tree_view, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenu(const QPoint &))); addToolBar(m_toolBar); } +void SampleView::setCurrentIndex(const QModelIndex &index) +{ + if (index.isValid()) { + m_tree_view->scrollTo(index); + m_tree_view->setCurrentIndex(index); + } +} + SessionModel *SampleView::getSessionModel() { return m_session; diff --git a/GUI/coregui/Views/SampleView.h b/GUI/coregui/Views/SampleView.h index ba2c7b2d5d6..f29f6f7147a 100644 --- a/GUI/coregui/Views/SampleView.h +++ b/GUI/coregui/Views/SampleView.h @@ -52,6 +52,7 @@ private: void createActions(); void connectSignals(); void clearSignalMapper(); + void setCurrentIndex(const QModelIndex &index); SessionModel *getSessionModel(); QTreeView *getTreeView(); diff --git a/GUI/coregui/Views/SampleViewComponents.cpp b/GUI/coregui/Views/SampleViewComponents.cpp index 0c7e0481e1e..12d69f765ea 100644 --- a/GUI/coregui/Views/SampleViewComponents.cpp +++ b/GUI/coregui/Views/SampleViewComponents.cpp @@ -47,6 +47,7 @@ QTreeView *SampleViewComponents::createTreeView(SessionModel *session_model, QWi tree_view->setWindowTitle(QString("Object Tree View")); tree_view->setObjectName(QString("ObjectTree")); tree_view->setContextMenuPolicy(Qt::CustomContextMenu); + tree_view->setDragDropMode(QAbstractItemView::InternalMove); return tree_view; } diff --git a/GUI/coregui/utils/GUIHelpers.h b/GUI/coregui/utils/GUIHelpers.h index 2ed035c90df..4222f44d14c 100644 --- a/GUI/coregui/utils/GUIHelpers.h +++ b/GUI/coregui/utils/GUIHelpers.h @@ -19,8 +19,23 @@ #include <QWidget> #include <QString> +#include <exception> + namespace GUIHelpers { +class Error : public std::exception +{ +public: + explicit Error(const QString &message) throw() + : message(message.toUtf8()) {} + ~Error() throw() {} + + const char *what() const throw() { return message; } + +private: + const char *message; +}; + void information(QWidget *parent, const QString &title, const QString &text, const QString &detailedText=QString()); void warning(QWidget *parent, const QString &title, -- GitLab