diff options
author | Arno <am@disconnect.de> | 2012-02-24 20:35:27 +0100 |
---|---|---|
committer | Arno <am@disconnect.de> | 2012-02-24 20:35:27 +0100 |
commit | b8e16c3bddb706ecc195e86eaafb89ed90f9bfc3 (patch) | |
tree | b14578ba8f801f701777b73d3dbb22730570585a /mappingtreewidget.cpp | |
parent | e82af6117dfcf4ccbebb712caaf1b8f9c68599ba (diff) | |
download | SheMov-b8e16c3bddb706ecc195e86eaafb89ed90f9bfc3.tar.gz SheMov-b8e16c3bddb706ecc195e86eaafb89ed90f9bfc3.tar.bz2 SheMov-b8e16c3bddb706ecc195e86eaafb89ed90f9bfc3.zip |
Implement MappingTreeWidget
This is a rather large commit. It implements MappingTreeWidget using
MappingTreeModel unsurprisingly this uncovered some exciting bugs.
Fixes the following bugs in MappingTreeModel:
* use insertRows() and removeRows() when addings children, because
dataChanged() won't do it.
* don't use a prepared QSqlQuery when fetching children recursively.
This won't work because the query is still active when we invoke
ourselves again. Put the query on the stack instead
* Keep the model sorted.
Also add an entry for a MappingTreeEditor to the File-Menu.
Diffstat (limited to 'mappingtreewidget.cpp')
-rw-r--r-- | mappingtreewidget.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/mappingtreewidget.cpp b/mappingtreewidget.cpp new file mode 100644 index 0000000..e5b1f90 --- /dev/null +++ b/mappingtreewidget.cpp @@ -0,0 +1,199 @@ +/* + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. +*/ + +#include <QSortFilterProxyModel> +#include <QComboBox> +#include <QPushButton> +#include <QLineEdit> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QInputDialog> +#include <QStringListModel> +#include <QMessageBox> +#include <QSettings> +#include <QHideEvent> +#include <QAction> +#include <QMenu> + +#include "mappingtreewidget.h" +#include "mappingtreemodel.h" +#include "smglobals.h" + +MappingTreeWidget::MappingTreeWidget(QWidget *parent) : QWidget(parent){ + //setup model + mModel = static_cast<MappingTreeModel*>(SmGlobals::instance()->model("MappingTree")); + mProxy = new QSortFilterProxyModel(this); + mProxy->setSourceModel(mModel); + mTypesModel = new QStringListModel(this); + mTypesModel->setStringList(mModel->mappingTypeNames()); + + //setup gui + mTree = new MappingTreeView; + mTree->setModel(mProxy); + mTree->setColumnHidden(1, true); + mTree->setColumnHidden(2, true); + mTree->setAlternatingRowColors(true); + mTree->expandAll(); + mTypeBox = new QComboBox; + mTypeBox->setModel(mTypesModel); + connect(mTypeBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(typeChanged(QString))); + mAddType = new QPushButton(tr("Add &type")); + connect(mAddType, SIGNAL(clicked()), this, SLOT(addType())); + mDeleteType = new QPushButton(tr("Delete type")); + connect(mDeleteType, SIGNAL(clicked()), this, SLOT(deleteType())); + mEdit = new QLineEdit; + mAddChild = new QPushButton(tr("&Add")); + connect(mAddChild, SIGNAL(clicked()), this, SLOT(addChild())); + mDeleteChild = new QPushButton(tr("Delete")); + connect(mDeleteChild, SIGNAL(clicked()), this, SLOT(deleteChild())); + QHBoxLayout *typesButtonLayout = new QHBoxLayout; + typesButtonLayout->addWidget(mDeleteType); + typesButtonLayout->addWidget(mAddType); + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + buttonLayout->addWidget(mDeleteChild); + buttonLayout->addWidget(mAddChild); + + //select type and populate model + QSettings s; + QString lastType = s.value("ui/mappingtreetype").toString(); + if(lastType.isEmpty()){ + if(!mTypesModel->stringList().isEmpty()){ + lastType = mTypesModel->stringList().at(0); + } + } + int typeId = mModel->mappingTypeIdFromName(lastType); + if(typeId != -1){ + mModel->setType(typeId); + mTypeBox->setCurrentIndex(mTypeBox->findText(lastType)); + typeChanged(lastType); + } + + //setup actions + mDeleteChildA = new QAction(tr("Delete"), this); + connect(mDeleteChildA, SIGNAL(triggered()), this, SLOT(deleteChild())); + mTree->addAction(mDeleteChildA); + mEditChildA = new QAction(tr("Edit..."), this); + connect(mEditChildA, SIGNAL(triggered()), this, SLOT(editChild())); + mTree->addAction(mEditChildA); + + //widget layout and tab order + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(mTypeBox); + mainLayout->addLayout(typesButtonLayout); + mainLayout->addWidget(mTree); + mainLayout->addWidget(mEdit); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); + mEdit->setFocus(); + setTabOrder(mEdit, mAddChild); +} + +void MappingTreeWidget::addChild(){ + QModelIndex sel = selected(); + if(!sel.isValid()){ + QMessageBox::critical(this, tr("Error"), tr("No parent item selected!")); + return; + } + QString value = mEdit->text().toLower().trimmed(); + if(value.isEmpty()){ + return; + } + QModelIndex real = mProxy->mapToSource(sel); + mModel->addChild(value, real); +} + +void MappingTreeWidget::addType(){ + QString typeName = QInputDialog::getText(this, tr("Enter type name"), tr("Name")).toLower().trimmed(); + if(typeName.isEmpty()){ + return; + } + if(mModel->addMappingType(typeName)){ + mTypesModel->setStringList(mModel->mappingTypeNames()); + int idxOf = mTypeBox->findText(typeName); + if(idxOf != -1){ + mTypeBox->setCurrentIndex(idxOf); + } + } +} + +void MappingTreeWidget::deleteChild(){ + QModelIndex sel = selected(); + if(!sel.isValid()){ + QMessageBox::critical(this, tr("Error"), tr("No item selected!")); + return; + } + QModelIndex real = mProxy->mapToSource(sel); + if(mModel->rowCount(real) > 0){ + QString msg = QString(tr("Cannot delete item %1, because it has %2 children!")).arg(real.data().toString()).arg(QString::number(mModel->rowCount(real))); + QMessageBox::critical(this, tr("Error"), msg); + return; + } + mModel->deleteChild(real); +} + +void MappingTreeWidget::deleteType(){ + QString curText = mTypeBox->currentText(); + if(curText.isEmpty()){ + return; + } + QString msg = QString(tr("Really delete %1?")).arg(curText); + int retval = QMessageBox::question(this, tr("Question"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + if(retval == QMessageBox::Yes){ + int typeId = mModel->mappingTypeIdFromName(curText); + if(typeId != -1){ + if(mModel->deleteMappingType(typeId)){ + mTypesModel->setStringList(mModel->mappingTypeNames()); + if(mTypesModel->stringList().count() > 0){ + mTypeBox->setCurrentIndex(0); + } + } + } + } +} + +void MappingTreeWidget::hideEvent(QHideEvent *event){ + QString type = mTypeBox->currentText(); + if(!type.isEmpty()){ + QSettings s; + s.setValue("ui/mappingtreetype", type); + } + event->accept(); +} + +void MappingTreeWidget::typeChanged(QString type){ + int typeId = mModel->mappingTypeIdFromName(type); + if(typeId != -1){ + mModel->setType(typeId); + mModel->populate(); + mTree->expandAll(); + } +} + +void MappingTreeWidget::editChild(){ + QModelIndex sel = selected(); + if(sel.isValid()){ + mTree->edit(sel); + } +} + +const QModelIndex MappingTreeWidget::selected() const{ + QModelIndexList sel = mTree->selectionModel()->selectedRows(); + if(sel.isEmpty()){ + return QModelIndex(); + } + return sel.first(); +} + + +MappingTreeView::MappingTreeView(QWidget *parent) : QTreeView(parent) {} + +void MappingTreeView::contextMenuEvent(QContextMenuEvent *e){ + QMenu ctxMenu(this); + ctxMenu.addActions(actions()); + ctxMenu.exec(e->globalPos()); +} |