328 lines
11 KiB
C++
Executable File
328 lines
11 KiB
C++
Executable File
/**
|
|
**
|
|
** @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 <QtCore/QEvent>
|
|
|
|
#include <QtGui/QKeyEvent>
|
|
|
|
#include <QtWidgets/QAbstractItemView>
|
|
#include <QtWidgets/QAction>
|
|
#include <QtWidgets/QApplication>
|
|
#include <QtWidgets/QGroupBox>
|
|
#include <QtWidgets/QHBoxLayout>
|
|
#include <QtWidgets/QLabel>
|
|
#include <QtWidgets/QLineEdit>
|
|
#include <QtWidgets/QPushButton>
|
|
#include <QtWidgets/QStyledItemDelegate>
|
|
#include <QtWidgets/QTableView>
|
|
#include <QtWidgets/QTextEdit>
|
|
#include <QtWidgets/QToolBar>
|
|
#include <QtWidgets/QTreeWidgetItem>
|
|
#include <QtWidgets/QTreeWidget>
|
|
#include <QtWidgets/QVBoxLayout>
|
|
|
|
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<EditNameDelegate *>(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<ModelTreeWidgetItem *>(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<QWidget *>(watchedEditor);
|
|
if (widget == nullptr) return false;
|
|
|
|
if (QEvent::KeyRelease == ev->type())
|
|
{
|
|
QKeyEvent *kev = static_cast<QKeyEvent *>(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<ModelTreeWidgetItem *>(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<ModelTreeWidgetItem *>(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<ModelTreeWidgetItem *>(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<ModelTreeWidgetItem *>(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"
|