/** ** ** @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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 m_map; QString m_logicalLayername; SituationMap::GeometryModel *m_geoModel; SituationMap::GeometryModelRenderer *m_geoModelRenderer; QList m_nodeClipboard; SituationMap::GeometryModel *m_modelClipboard; AttributeDialogManager *m_attributeDialogManager; FavouritesActionManager *m_favouritesActionManager; LookupSymbolManager *m_lookupSymbolManager; UpdateViewMode m_updateViewMode; SelectionMode m_selectionMode; QList m_ltsItems; QList m_symbolWidgets; QPointer m_dlgDebug; LtsWidgets::LtsDragIcon *m_btnUndo; LtsWidgets::LtsDragIcon *m_btnRedo; QPointer 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 m_modelTreeWidget; bool m_symbolDictLoaded; QLineEdit *m_leSidc; QPushButton *m_pbCreateSymb; QTimer *m_delayedUpdateTimer; QTimer *m_autosaveTimer; QPointer m_dlgUndoHistory; QPointer m_dlgRedoHistory; QTreeWidget *m_lwUndoHistory; QTreeWidget *m_lwRedoHistory; QTextEdit *m_teDebug; SituationMap::RefPointer m_dropEventManager; QList m_selectionList; QString m_defaultPlanDirectory; bool m_readStyleAttributesFromModel; QString m_symbolCurrentSidc; SituationMap::RB::RubberbandTransform *m_currentBboxRubberband; std::function m_saveFunction; QList m_rbBackupNodeCoordinates; QVector m_ourTextBoxIds; // relevant for PlanEditor // while Editing: SituationMap::PBTB_ID m_textBoxIdInEditing; // currentId QPointer m_textBoxTextEdit; // display QString m_htmlTextForCancelation; // cancel purpose QPointer 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