/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mappingtreewidget.h" #include "mappingtreemodel.h" #include "smglobals.h" MappingTreeWidget::MappingTreeWidget(QWidget *parent) : QWidget(parent){ //setup model mModel = static_cast(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(); connect(mModel, SIGNAL(needExpansion()), mTree, SLOT(expandAll())); connect(mTree->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged())); 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())); QHBoxLayout *typesButtonLayout = new QHBoxLayout; typesButtonLayout->addWidget(mDeleteType); typesButtonLayout->addWidget(mAddType); //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 mAddChildA = new QAction(tr("Add..."), this); connect(mAddChildA, SIGNAL(triggered()), this, SLOT(addChild())); mTree->addAction(mAddChildA); 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); mMoveChildA = new QAction(tr("Move..."), this); connect(mMoveChildA, SIGNAL(triggered()), this, SLOT(moveChild())); mTree->addAction(mMoveChildA); //widget layout and tab order QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mTypeBox); mainLayout->addLayout(typesButtonLayout); mainLayout->addWidget(mTree); setLayout(mainLayout); } MappingData MappingTreeWidget::selectedItem() const { MappingData retval; QModelIndex sel = selected(); if(!sel.isValid()){ retval.id = -1; }else{ QModelIndex real = mProxy->mapToSource(sel); if(mModel->childCount(real)){ retval.id = -1; }else{ retval.id = sel.data(MappingTreeModel::IdRole).toInt(); } retval.name = sel.data(MappingTreeModel::NameRole).toString(); QStringList p; QModelIndex parent = sel; while(parent.isValid()){ p << parent.data().toString(); parent = parent.parent(); } std::reverse(p.begin(), p.end()); retval.path = p; } return retval; } void MappingTreeWidget::addChild(){ QModelIndex sel = selected(); QString value = QInputDialog::getText(this, tr("Mapping name"), tr("Enter mapping name")); if(value.isEmpty()){ return; } if(value.contains(mModel->forbidden())){ QString msg = QString(tr("Value contains illegal string \"%1\"")).arg(mModel->forbidden()); QMessageBox::critical(this, tr("Error"), msg); 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(); 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; } QString question = QString(tr("Really delete %1?")).arg(real.data(MappingTreeModel::NameRole).toString()); int retval = QMessageBox::question(this, tr("Question"), question, QMessageBox::Yes | QMessageBox::No); if(retval == QMessageBox::Yes){ if(!mModel->deleteChild(real)){ QString msg = QString(tr("Failed to delete %1. Most likely there are still items mapped.")).arg(real.data().toString()); QMessageBox::critical(this, tr("Error"), msg); } } } 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::selectPath(const QString &path){ QModelIndex pathIdx = mModel->indexFromPath(path); if(!pathIdx.isValid()){ return; } QModelIndex real = mProxy->mapFromSource(pathIdx); mTree->setCurrentIndex(real); } 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); } } void MappingTreeWidget::selectionChanged(){ QModelIndex sel = selected(); QModelIndex real = mProxy->mapToSource(sel); emit mappingChanged(real.data(MappingTreeModel::IdRole).toInt()); } void MappingTreeWidget::moveChild(){ QString path = QInputDialog::getItem(this, tr("Move item"), tr("Move to:"), mModel->paths(), -1, false); if(!path.isEmpty()){ QModelIndex sel = selected(); QModelIndex realSource = mProxy->mapToSource(sel); QModelIndex dest = mModel->indexFromPath(path); if(dest == realSource){ QMessageBox::critical(this, tr("Error"), tr("Destination cannot be the source!")); return; } if(realSource.isValid() && dest.isValid()){ mModel->move(realSource, dest); } } } 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()); } MappingTreeResultView::MappingTreeResultView(QWidget *parent) : QTreeView(parent) {} MappingEditWidget::MappingEditWidget(QWidget *parent) : QWidget(parent){ //the views mMappingTree = new MappingTreeWidget; mMappingResult = new MappingTreeResultView; mResultModel = new MappingTreeResultModel(QStringList() << tr("Name") << tr("Id"), this); mMappingResult->setModel(mResultModel); mMappingResult->setAlternatingRowColors(true); mMappingResult->setColumnHidden(1, true); //buttons mAddMapping = new QPushButton(tr(">>")); connect(mAddMapping, SIGNAL(clicked()), this, SLOT(addMapping())); mRemoveMapping = new QPushButton(tr("<<")); connect(mRemoveMapping, SIGNAL(clicked()), this, SLOT(removeMapping())); //layout QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(mMappingTree); QVBoxLayout *buttonLayout = new QVBoxLayout; buttonLayout->addStretch(); buttonLayout->addWidget(mAddMapping); buttonLayout->addWidget(mRemoveMapping); buttonLayout->addStretch(); mainLayout->addLayout(buttonLayout); mainLayout->addWidget(mMappingResult); setLayout(mainLayout); } QList MappingEditWidget::mappingIds() const { return mResultModel->mappingsIds(); } void MappingEditWidget::addMapping(){ MappingData selected = mMappingTree->selectedItem(); if(selected.id == -1){ return; } mResultModel->addItem(selected); mMappingResult->expandAll(); } void MappingEditWidget::removeMapping(){ QModelIndexList sel = mMappingResult->selectionModel()->selectedRows(); if(sel.isEmpty()){ return; } QModelIndex firstIdx = sel.first(); mResultModel->removeRows(firstIdx.row(), 1, firstIdx.parent()); } void MappingEditWidget::setMappings(const QList &mappings){ if(mappings.isEmpty()){ return; } MappingTreeModel *mModel = static_cast(SmGlobals::instance()->model("MappingTree")); mResultModel->clearData(); foreach(int i, mappings){ MappingData curData = mModel->mappingDataFromId(i); if(curData.id != -1){ mResultModel->addItem(curData); } } mMappingResult->expandAll(); } MappingEditDialog::MappingEditDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ mEditWidget = new MappingEditWidget; mOk = new QPushButton(tr("Ok")); connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); buttonLayout->addWidget(mOk); buttonLayout->addWidget(mCancel); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mEditWidget); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); }