/** ** ** @RDE_HEADER@ ** model_tree_widget.cpp ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Environment: Intel-PC ** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Language ........: C++ 11 ** ** ----------------------------------------------------------------------------------------------- ** ** Author ...........: Jörg Turla, SPD G, Tel. 3132 ** ** ----------------------------------------------------------------------------------------------- ** ** Notes .........: ** ** 14.06.2016, JT : First edition for use with Qt5 ** ** ----------------------------------------------------------------------------------------------- */ #include "model_tree_widget.h" #include "plan_editor.h" #include "plan_editor_internal.h" #include "plan_editor_utils.h" #include "icon_names.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace PlanEditor { class EditNameDelegate : public QStyledItemDelegate { Q_OBJECT PlanEditor &m_planEditor; QTreeWidget *m_treeWidget; public: explicit EditNameDelegate(PlanEditor &planEditor, QTreeWidget *treeWidget) : QStyledItemDelegate(treeWidget) , m_planEditor(planEditor) , m_treeWidget(treeWidget) {;} QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &opt, const QModelIndex &index) const override { if (index.column() == 1) { QWidget *editor = QStyledItemDelegate::createEditor(parent, opt, index); editor->installEventFilter(const_cast(this)); return editor; } return nullptr; } // QWidget * createEditor( QWidget * parent, const QStyleOptionViewItem & opt, const QModelIndex & index ) override void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { if (index.column() == 1) { QStyledItemDelegate::setModelData(editor, model, index); ModelTreeWidgetItem *item = static_cast(m_treeWidget->currentItem()); if (item) item->userDefinedNameChanged(*(m_planEditor.m_internal->m_geoModel)); } } // void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override bool eventFilter(QObject *watchedEditor, QEvent *ev) override { if (ev == nullptr) return false; if (watchedEditor == nullptr) return false; QWidget *widget = dynamic_cast(watchedEditor); if (widget == nullptr) return false; if (QEvent::KeyRelease == ev->type()) { QKeyEvent *kev = static_cast(ev); if (Qt::Key_Return == kev->key()) { emit commitData(widget); emit closeEditor(widget, QAbstractItemDelegate::EditNextItem); } if (Qt::Key_Escape == kev->key()) emit closeEditor(widget, QAbstractItemDelegate::EditNextItem); } if (QEvent::FocusOut == ev->type()) { if (widget->isActiveWindow() || (QApplication::focusWidget() != widget)) { QWidget *w = QApplication::focusWidget(); while (w) { // don't worry about focus changes internally in the editor if (w == widget) return false; w = w->parentWidget(); } // Opening a modal dialog will start a new eventloop // that will process the deleteLater event. if (QApplication::activeModalWidget() && !QApplication::activeModalWidget()->isAncestorOf(widget)) return false; emit commitData(widget); emit closeEditor(widget); } } return false; } // bool eventFilter(QObject * watchedEditor, QEvent * e) override }; // EditNameDelegate bool ModelTreeWidget::isEmpty() const { return ((nullptr == m_treeWidget->model()) || (m_treeWidget->model()->rowCount() < 1)); } // bool ModelTreeWidget::isEmpty() const void ModelTreeWidget::showNeedSaveFlag(bool on) { m_needSaveFlag = on; buildTitle(); // QString title = tr("Plan Model Tree"); // m_treeGroup->setTitle(on ? title + QStringLiteral(" [*]") : title); } // void ModelTreeWidget::showNeedSaveFlag( bool on ) void ModelTreeWidget::setNameOfPlan( const QString & nameOfPlan ) { m_nameOfPlan = nameOfPlan; buildTitle(); } // void ModelTreeWidget::setNameOfPlan( const QString & nameOfPlan ) void ModelTreeWidget::buildTitle() { QString title = tr("Plan Model Tree"); if (!m_nameOfPlan.isEmpty()) title += QStringLiteral(" [%1]").arg(m_nameOfPlan); m_treeGroup->setTitle(m_needSaveFlag ? title + QStringLiteral(" [*]") : title); } // void ModelTreeWidget::buildTitle() ModelTreeWidget::ModelTreeWidget(PlanEditor *planEditor, QWidget *parent) : Dialog(parent, LtsWidgets::ButtonCombination::SeamlessDialog) , m_treeWidget(nullptr) , m_itemTreeRoot(nullptr) { setUnchangeable(); m_planEditor = planEditor; //setTitle(tr("Plan Model Tree")); QVBoxLayout *treeBaseLayout = new QVBoxLayout(this); QGroupBox *treeGroup = m_treeGroup = new QGroupBox(this); QVBoxLayout *treeLayer = new QVBoxLayout(treeGroup); showNeedSaveFlag(false); m_treeWidget = new QTreeWidget(treeGroup); m_treeWidget -> setColumnCount(2); m_treeWidget -> setHeaderLabels(QStringList() << tr("Graphic Node") << tr("User Defined Name")); m_treeWidget -> setSelectionMode(QAbstractItemView::ExtendedSelection); m_treeWidget -> setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | QAbstractItemView::AnyKeyPressed); m_treeWidget -> setItemDelegate(new EditNameDelegate(*planEditor, m_treeWidget)); m_treeWidget -> setUniformRowHeights(false); m_itemTreeRoot = m_treeWidget->invisibleRootItem(); connect(m_treeWidget, &QTreeWidget::itemSelectionChanged, this, [this, planEditor]() // lambda slot function to select items { m_treeWidget->blockSignals(true); { ModelTreeWidgetItem *currentItem = static_cast(m_treeWidget->currentItem()); if (currentItem) { bool isSelected = currentItem->isSelected(); QTreeWidgetItem *parent = currentItem->parent(); // first go up to top level group while (parent && (rootItem() != parent)) { currentItem = static_cast(parent); parent = currentItem->parent(); } // now select or deselect all children of top level group currentItem->setGroupSelected(isSelected); } for (int i = 0; i < m_itemTreeRoot->childCount(); ++i) { ModelTreeWidgetItem *treeItem = static_cast(m_itemTreeRoot->child(i)); if (treeItem) treeItem->selectionChanged(*planEditor, *(planEditor->m_internal->m_geoModel)); } } m_treeWidget->blockSignals(false); }); connect(m_treeWidget, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem * item, int column) { if (!item) return; if (column == ModelTreeWidgetItem::nameColumn) { m_treeWidget -> editItem(item, ModelTreeWidgetItem::nameColumn); return; } }); connect(m_treeWidget, &QTreeWidget::itemChanged, [](QTreeWidgetItem * item, int column) { if (!item) return; ModelTreeWidgetItem *treeItem = dynamic_cast(item); if ((ModelTreeWidgetItem::itemColumn == column) && (treeItem)) treeItem->setGroupSelected(treeItem->checkState(ModelTreeWidgetItem::itemColumn) == Qt::Checked); }); QToolBar *toolBar = new QToolBar(treeGroup); QAction *toolAction; toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(GROUP_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onGroup); toolAction -> setToolTip(tr("Group selected feature")); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(UNGROUP_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onUngroup); toolAction -> setToolTip(tr("Ungroup selected feature")); toolBar->addSeparator(); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(DRAW_SYMBOL_ICON_NAME)), QString(), planEditor, &PlanEditor::onChooseSymbol ); toolAction->setToolTip(tr("Choose and draw symbol from symbol dictionary")); toolBar->addSeparator(); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(EDIT_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onEditGraphicGeometry); toolAction -> setToolTip(tr("Edit geometry of selected feature")); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(ATTR_EDIT_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onEditAttributes); toolAction->setToolTip(tr("Edit Attributes of selected feature")); toolBar->addSeparator(); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(CENTER_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onCenterViewSelected); toolAction -> setToolTip(tr("Center Map to selected features")); toolBar->addSeparator(); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(DELETE_SELECTED_ICON_NAME)), QString(), planEditor, &PlanEditor::onDelete); toolAction -> setToolTip(tr("Delete selected features")); toolBar->addSeparator(); toolAction = toolBar->addAction(Utils::getIcon(QLatin1String(HELP_SYMBOL_ICON_NAME)), QString(), planEditor, &PlanEditor::onShowHelp); toolAction -> setToolTip(tr("Help")); treeLayer -> addWidget(toolBar, 0); treeLayer -> addWidget(m_treeWidget, 2); treeBaseLayout -> addWidget(treeGroup, 2); setObjectName(QLatin1String("PlanItemTree")); } // ModelTreeWidget::ModelTreeWidget(PlanEditor *planEditor, QWidget *parent) void ModelTreeWidget::haveChanges(bool on) { if (hasUnsavedChanges() != on) { on ? slotChangesMade() : __unchange__(); showNeedSaveFlag(on); } } // void ModelTreeWidget::haveChanges(bool on) void ModelTreeWidget::keyPressEvent(QKeyEvent *event) { if ((event->key() == Qt::Key_Delete) && (m_planEditor)) { m_planEditor->onDelete(); // Qt-Doc 5.12: // Note that QKeyEvent starts with isAccepted() == true, so you do not need // to call QKeyEvent::accept() - just do not call the base class // implementation if you act upon the key. return; } BaseClass::keyPressEvent(event); } } // namespace PlanEditor #include "model_tree_widget.moc"