Files
qt5-legatus-legacy/Lts/Plugins/PlanEditor/plan_editor_internal.h
T
2026-08-13 18:33:10 +02:00

426 lines
14 KiB
C++
Executable File

/**
**
** @RDE_HEADER@
** plan_editor_internal.h
** $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 .........:
**
** 09.12.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include "plan_editor.h"
#include "plan_editor_const.h"
#include "plan_editor_session.h"
#include "drop_event_manager.h"
#include "attribute_dialog_manager.h"
#include "favourites_action_manager.h"
#include "lookup_symbol_manager.h"
#include "model_tree_widget.h"
#include "logging.h"
#include "icon_names.h"
#include "setting_keys.h"
#include <ngltranslator/ngltranslator.h>
#include <LtsWidgets/lts_drag_icon.h>
#include <LtsWidgets/lts_drop_handler.h>
#include <LtsWidgets/lts_frameless_dialog.h>
#include <LtsWidgets/lts_grid_layout.h>
#include <LtsWidgets/lts_text_edit_dialog.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <Map/map.h>
#include <Map/abstract_map_object.h>
#include <Map/drop_event_manager.h>
#include <Map/object_factory.h>
#include <Map/coord_translation_functor.h>
#include <Map/geometry_model_renderer.h>
#include <Rubberbands/rubberband_transform.h>
#include <GeometryModel/geometry_model_factory.h>
#include <GeometryModel/geometry_pixelTextBox.h>
#include <Map/pixel_based_textbox_handler.h>
#include <QtCore/QPropertyAnimation>
#include <QtCore/QSettings>
#include <QtCore/QTimer>
#include <QtCore/QUrl>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QColorDialog>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDial>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QGraphicsView>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QTextBrowser>
#include <QtWidgets/QToolButton>
#include <QtWebEngineWidgets/QWebEngineView>
#include <QApplication>
#include <QtWidgets/QTableView>
#include <QtWidgets/QTextEdit>
#include <QtWidgets/QTreeWidget>
#include <QtPrintSupport/QPrinter>
namespace PlanEditor
{
enum class UpdateViewMode
{
Scheduled,
Immediately,
Manually
};
enum class SelectionMode
{
Picking,
Line,
Lasso,
Rectangle,
PickingAndEdit
};
class PlanEditor::InternalData : public QObject
{
Q_OBJECT
friend class DropCreateLine;
public:
QString m_title;
PlanEditorSession m_session;
QPointer<SituationMap::Map> m_map;
QString m_logicalLayername;
SituationMap::GeometryModel *m_geoModel;
SituationMap::GeometryModelRenderer *m_geoModelRenderer;
QList<SituationMap::GeometryModel::Node> m_nodeClipboard;
SituationMap::GeometryModel *m_modelClipboard;
AttributeDialogManager *m_attributeDialogManager;
FavouritesActionManager *m_favouritesActionManager;
LookupSymbolManager *m_lookupSymbolManager;
UpdateViewMode m_updateViewMode;
SelectionMode m_selectionMode;
QList<LtsWidgets::LtsDragIcon *> m_ltsItems;
QList<QWidget *> m_symbolWidgets;
QPointer<LtsWidgets::LtsDialog> m_dlgDebug;
LtsWidgets::LtsDragIcon *m_btnUndo;
LtsWidgets::LtsDragIcon *m_btnRedo;
QPointer<QFileDialog> m_fileDialog; // using QPointer because the dialog can be removed by widget hierarchy and will get invalid
QString m_currentFileName;
QWebEngineView *m_viewHelp;
QGroupBox *m_gbPlanEditorMain;
QPointer<ModelTreeWidget> m_modelTreeWidget;
bool m_symbolDictLoaded;
QLineEdit *m_leSidc;
QPushButton *m_pbCreateSymb;
QTimer *m_delayedUpdateTimer;
QTimer *m_autosaveTimer;
QPointer<LtsWidgets::LtsFramelessDialog> m_dlgUndoHistory;
QPointer<LtsWidgets::LtsFramelessDialog> m_dlgRedoHistory;
QTreeWidget *m_lwUndoHistory;
QTreeWidget *m_lwRedoHistory;
QTextEdit *m_teDebug;
SituationMap::RefPointer<DropEventManager> m_dropEventManager;
QList<SituationMap::UniqueMapId> m_selectionList;
QString m_defaultPlanDirectory;
bool m_readStyleAttributesFromModel;
QString m_symbolCurrentSidc;
SituationMap::RB::RubberbandTransform *m_currentBboxRubberband;
std::function<void()> m_saveFunction;
QList<QPointF> m_rbBackupNodeCoordinates;
QVector<SituationMap::PBTB_ID> m_ourTextBoxIds; // relevant for PlanEditor
// while Editing:
SituationMap::PBTB_ID m_textBoxIdInEditing; // currentId
QPointer<QTextEdit> m_textBoxTextEdit; // display
QString m_htmlTextForCancelation; // cancel purpose
QPointer<LtsWidgets::LtsTextEditDialog> m_textEditorDialog; // editor
void resetTextBoxData()
{
m_textBoxIdInEditing.init();
m_textBoxTextEdit.clear();
m_htmlTextForCancelation.clear();
delete m_textEditorDialog;
m_textEditorDialog.clear();
}
QTimer *m_textBoxNotifyTimer{nullptr};
Logger &m_logger;
InternalData(SituationMap::Map *map, const PlanEditorSession &session, PlanEditor *me)
: QObject()
, m_title(QStringLiteral("PlanEditor"))
, m_session(session)
, m_map(map)
// , m_logicalLayername
, m_geoModel(SituationMap::GeometryModelFactory::singleton()->create())
, m_geoModelRenderer(nullptr) // -> initLogicalLayernameAndRenderer
, m_nodeClipboard()
, m_modelClipboard(SituationMap::GeometryModelFactory::singleton()->create())
, m_attributeDialogManager(new AttributeDialogManager(me, map, m_geoModel, m_session))
, m_favouritesActionManager(new FavouritesActionManager(me, map, m_session))
, m_lookupSymbolManager(nullptr)
, m_updateViewMode(UpdateViewMode::Scheduled)
, m_selectionMode(SelectionMode::Picking)
, m_ltsItems()
, m_symbolWidgets()
, m_dlgDebug() // type = QPointer
, m_btnUndo(nullptr)
, m_btnRedo(nullptr)
, m_fileDialog(new QFileDialog(m_session.topLevelWidget()))
, m_currentFileName()
, m_viewHelp(nullptr)
, m_gbPlanEditorMain(nullptr)
, m_modelTreeWidget() // type = QPointer
, m_symbolDictLoaded(false)
, m_leSidc(nullptr)
, m_pbCreateSymb(nullptr)
, m_delayedUpdateTimer(new QTimer(me))
, m_autosaveTimer(new QTimer(me))
, m_dlgUndoHistory() // type = QPointer
, m_dlgRedoHistory() // type = QPointer
, m_lwUndoHistory(nullptr)
, m_lwRedoHistory(nullptr)
, m_teDebug(nullptr)
, m_dropEventManager(new DropEventManager())
, m_selectionList()
, m_defaultPlanDirectory()
, m_readStyleAttributesFromModel(false)
, m_symbolCurrentSidc()
, m_currentBboxRubberband(nullptr)
, m_saveFunction()
, m_rbBackupNodeCoordinates()
, m_logger(getLogger("PlanEditor"))
{
this->initLogicalLayernameAndRenderer(QStringLiteral("PlanEditorLayer"), me); // default, may be overwritten in context of snapshot
// m_geoModel->setMaxUndoSteps(10);
m_lookupSymbolManager = new LookupSymbolManager(me, map, m_session);
// Make sure that the symbol model exists and has loaded symbol before enabling the gui ...
// Use a queued connect type because later updates of the model could be very expensive (see
// FavouritesActionManager::initFromDefaultSettings) and should not be done more than necessary!
//
connect(m_lookupSymbolManager, &LookupSymbolManager::readModelFinished, me, &PlanEditor::onEnableSymbolWidgets, Qt::ConnectionType::QueuedConnection);
m_geoModelRenderer -> setEditorMode(true);
QSettings settings;
QStringList fileHistoryList = settings.value(QLatin1String(FILEDIALOG_HISTORY_LIST_KEY)).toStringList();
QStringList fileFilter;
fileFilter << QLatin1String("Plan Geometry Model (*.plan)");
fileFilter << tr("Any files (*)");
m_fileDialog -> setFilter(QDir::AllDirs | QDir::Files | QDir::Drives);
m_fileDialog -> setHistory(fileHistoryList);
m_fileDialog -> setNameFilters(fileFilter);
m_fileDialog -> setWindowTitle(tr("Plan Editor - File Selection"));
QString locale(QString::fromLatin1(NGL::translationLocale()));
QString urlName= QStringLiteral("index.html");
// if (locale == QLatin1String("de_DE"))
// urlName = QStringLiteral("Start_de.htm");
// else
// urlName = QStringLiteral("Start_eng.htm");
QString url(QStringLiteral("file:///%1/%2/%3")); // dir, locale, filename
QString filePath(QStringLiteral("%1/../share/Lts/help/").arg(QApplication::applicationDirPath()));
m_viewHelp = new QWebEngineView(m_session.topLevelWidget());
m_viewHelp->setWindowFlag( Qt::WindowType::Dialog );
m_viewHelp->setWindowTitle(tr("Plan Editor - View Online Help"));
url = url.arg(filePath, locale, urlName);
m_viewHelp->page()->load(QUrl(url));
if (m_session.isLtsSession())
{
// QWebView in Qt5.9 doesn't like to be destroyed immediatelly - deleteLater is needed...
QObject::connect(m_session.ltsSession().data(), &LtsSession::LtsSession::sessionAboutToBeDestroyed,
me, [this]()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
m_viewHelp->setParent(nullptr);
m_viewHelp->deleteLater();
#else
// N.Thoden, 24.01.2020
// should avoid memleak / warnings of AddressSanitizer (asan)
// (but the waring still exists :-()
delete m_viewHelp;;
#endif
m_viewHelp = nullptr;
});
}
if (m_geoModel == nullptr)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Creating Geometry Model failed.";
return;
}
if (m_geoModelRenderer == nullptr)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Creating Geometry Model Renderer failed.";
return;
}
m_map -> installDropEventManager(m_dropEventManager.get());
me -> connect(m_lookupSymbolManager, &LookupSymbolManager::addToSymbolFavourites
, m_favouritesActionManager, &FavouritesActionManager::onSymbolFavouriteAdd);
me -> connect(m_favouritesActionManager, &FavouritesActionManager::updateSymbolScopes
, m_lookupSymbolManager, &LookupSymbolManager::onUpdateSymbolScopes);
me -> connect(m_geoModel, &SituationMap::GeometryModel::typeError, me, &PlanEditor::onNoticeGeoModelTypeError);
me -> connect(m_geoModel, &SituationMap::GeometryModel::attributeError, me, &PlanEditor::onNoticeGeoModelAttributeError);
me -> connect(m_geoModel, &SituationMap::GeometryModel::modelError, me, &PlanEditor::onNoticeGeoModelModelError);
me -> connect(m_geoModel, &SituationMap::GeometryModel::criticalError, me, &PlanEditor::onNoticeGeoModelError);
me -> connect(m_geoModel, &SituationMap::GeometryModel::changed, me, &PlanEditor::onNoticeGeoModelUpdate);
me -> connect(m_geoModel, &SituationMap::GeometryModel::modificationCount, me, &PlanEditor::onGeoModelModified);
me -> connect(m_delayedUpdateTimer, &QTimer::timeout, me, &PlanEditor::onUpdateView);
me -> connect(m_autosaveTimer, &QTimer::timeout, me, &PlanEditor::onPlanAutoSave);
m_delayedUpdateTimer -> setSingleShot(true);
} /* InternalData */
void initLogicalLayernameAndRenderer(const QString &logicalLayername, QObject *parent)
{
m_logicalLayername = logicalLayername;
delete m_geoModelRenderer;
m_geoModelRenderer = m_map->createGeometryModelRenderer(m_logicalLayername, m_geoModel, parent);
}
void removeAutosaveFile()
{
const QString &tmp = QStringLiteral("/tmp/plan_") + QString::number(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
if (QFile::exists(tmp))
QFile::remove(tmp);
}
~InternalData()
{
m_favouritesActionManager->onSaveFavouritesToSettings();
m_favouritesActionManager->removeActionItems();
m_favouritesActionManager = nullptr; // it is child of planEditor and is delete by hierarchy when delete planEditor.
if (m_fileDialog)
{
// ToDo: Find a better way to shutdown the editor and store file history every time.
QSettings settings;
settings.setValue(QLatin1String(FILEDIALOG_HISTORY_LIST_KEY), m_fileDialog->history());
}
delete m_modelClipboard; m_modelClipboard = nullptr;
delete m_geoModel; m_geoModel = nullptr;
delete m_geoModelRenderer; m_geoModelRenderer = nullptr;
// ToDo
for (const auto &item : qAsConst(m_ltsItems))
m_session.removeMenuAction(item);
m_ltsItems.clear();
if (m_modelTreeWidget) { m_modelTreeWidget -> deleteLater(); m_modelTreeWidget = nullptr; }
if (m_dlgDebug) { m_dlgDebug -> deleteLater(); m_dlgDebug = nullptr; }
if (m_gbPlanEditorMain) { m_gbPlanEditorMain -> deleteLater(); m_gbPlanEditorMain = nullptr; }
m_autosaveTimer->stop();
delete m_autosaveTimer;
m_delayedUpdateTimer->stop();
delete m_delayedUpdateTimer;
} // ~InternalData()
InternalData(const InternalData &) = delete;
InternalData operator = (const InternalData &) = delete;
}; // InternalData
} // namespace PlanEditor