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

596 lines
21 KiB
C++
Executable File

/**
**
** @RDE_HEADER@
** Do all the work for complex selection operations.
** $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 .........:
**
** 25.07.2016, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "plan_editor.h"
#include "plan_editor_const.h"
#include "plan_editor_session.h"
#include "dialog.h"
#include "favourites_action_manager.h"
#include "favourite_result_watcher.h"
#include "symbol_favourites.h"
#include "plan_editor_utils.h"
#include "setting_keys.h"
#include <LtsWidgets/lts_message_dialog.h>
#include <Map/map.h>
#include <Symbology/sidc_builder_base.h>
#include <QtCore/QMap>
#include <QtCore/QFile>
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtGui/QPixmap>
#include <QtGui/QIcon>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QFrame>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMenu>
#include <QtWidgets/QWidget>
namespace PlanEditor
{
const char *const ScopeFileSuffix = "FavouriteScope.xml";
class FavouriteProps
{
public:
FavouriteProps() = default;
~FavouriteProps() = default;
LtsWidgets::LtsDragIcon *m_actionWidget = nullptr;
QPixmap m_actionIcon;
QString m_scope;
QString m_sidc;
}; // FavouriteProps
class ScopeProps
{
public:
ScopeProps() = default;
~ScopeProps() = default;
QAction *m_storeMenuAction = nullptr;
QAction *m_saveMenuAction = nullptr;
unsigned int m_symbolCount = 0;
}; // ScopeProps
class FavouritesActionManager::InternalData
{
public:
PlanEditor *m_planEditor;
SituationMap::Map *m_map;
const PlanEditorSession &m_session;
SymbolFavourites *m_symbolFavourites;
QFileDialog *m_fileDialog;
QMenu *m_favouriteStoreMenu;
QMenu *m_favouriteSaveMenu;
QList<LtsWidgets::LtsDragIcon *> m_ltsItems;
QMap<QString, ScopeProps> m_scopeMap;
QMap<QString, FavouriteProps> m_favouriteMap;
AdvancedSymbology::SymbolResultWatcher m_symbolGuard;
explicit InternalData(const PlanEditorSession &session)
: m_planEditor(nullptr)
, m_map(nullptr)
, m_session(session)
, m_symbolFavourites(SymbolFavourites::create())
, m_fileDialog(nullptr)
, m_favouriteStoreMenu(nullptr)
, m_favouriteSaveMenu(nullptr)
, m_ltsItems()
, m_scopeMap()
, m_favouriteMap()
, m_symbolGuard()
{;}
~InternalData()
{
const auto copy = m_favouriteMap;
for (const FavouriteProps &prop : copy)
m_session.removeMenuAction(prop.m_actionWidget);
m_favouriteMap.clear();
m_favouriteStoreMenu = nullptr;
m_favouriteSaveMenu = nullptr;
for (auto item : qAsConst(m_ltsItems))
m_session.removeMenuAction(item);
m_ltsItems.clear();
delete m_symbolFavourites; m_symbolFavourites = nullptr;
delete m_fileDialog; m_fileDialog = nullptr;
}
}; // FavouritesActionManager::InternalData
FavouritesActionManager::FavouritesActionManager(PlanEditor *planEditor, SituationMap::Map *map, const PlanEditorSession &session)
: QObject(planEditor)
, m_internal(new InternalData(session))
{
m_internal -> m_planEditor = planEditor;
m_internal -> m_map = map;
connect(m_internal->m_symbolFavourites, &SymbolFavourites::signalNewScope, this, &FavouritesActionManager::onNewFavouritesScope);
connect(m_internal->m_symbolFavourites, &SymbolFavourites::signalNewSymbol, this, &FavouritesActionManager::onNewFavouritesSymbol);
connect(m_internal->m_symbolFavourites, &SymbolFavourites::signalDeleteScope, this, &FavouritesActionManager::onDeleteFavouritesScope);
connect(m_internal->m_symbolFavourites, &SymbolFavourites::signalDeleteSymbol, this, &FavouritesActionManager::onDeleteFavouritesSymbol);
m_internal->m_fileDialog = new QFileDialog(nullptr);
} // FavouritesActionManager::FavouritesActionManager( SituationMap::Map * map, LtsWidgets::LtsBaseLayoutWidget * ltsbaseWidget, QObject * parent )
void FavouritesActionManager::initMainMenu(bool retranslate)
{
LtsWidgets::PluginData pluginAction;
pluginAction.layoutArea = LtsWidgets::LayoutArea::eMainTab;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Does not work any more! 2018/01/18 JT
*
pluginAction.identifier = QLatin1String("Separator-Favourite-Symbols");
pluginAction.createWidgetFunc = [](QWidget * parent) -> LtsWidgets::LtsDialog *
{
LtsWidgets::LtsDialog *separator = new Dialog(parent);
QHBoxLayout *layout = new QHBoxLayout(separator);
QFrame *line = new QFrame(separator);
line->setLineWidth(2);
line->setFrameStyle(QFrame::HLine);
layout->addSpacing(5);
layout->addWidget(line, 1);
layout->addSpacing(5);
return separator;
}; // separator lambda
m_internal->m_ltsItems += m_internal->m_session.addMenuAction(pluginAction); // make line separator
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
pluginAction.createWidgetFunc = [](QWidget *) -> LtsWidgets::LtsDialog * { return nullptr; }; // Mike's HACK
pluginAction.menuGroup = tr("Favourite Symbols");
if (m_internal->m_session.isLtsSession())
{
pluginAction.identifier = QLatin1String("FMS-Load-Scope");
pluginAction.menuIcon = QIcon(QStringLiteral("icon:library_load_scope.svg"));
pluginAction.menuText = tr("Library Load Scope");
pluginAction.tooltip = tr("Load favourite scope from library");
if (!retranslate)
{
LtsWidgets::LtsDragIcon *btnLoad = m_internal->m_session.addMenuAction(pluginAction);
m_internal->m_ltsItems += btnLoad;
connect(btnLoad, &LtsWidgets::LtsDragIcon::clicked, this, &FavouritesActionManager::onScopeLoadViaSettingService);
}
else m_internal->m_session.addMenuAction(pluginAction);
pluginAction.identifier = QLatin1String("FMS-Store-Scope");
pluginAction.menuIcon = QIcon(QStringLiteral("icon:library_save_scope.svg"));
pluginAction.menuText = tr("Library Store Scope");
pluginAction.tooltip = tr("Store favourite scope into library");
if (!retranslate)
{
LtsWidgets::LtsDragIcon *btnStore = m_internal->m_session.addMenuAction(pluginAction);
m_internal->m_ltsItems += btnStore;
m_internal->m_favouriteStoreMenu = new QMenu(btnStore);
btnStore->setMenu(m_internal->m_favouriteStoreMenu);
connect(btnStore, &LtsWidgets::LtsDragIcon::clicked, this, [this]() { m_internal->m_favouriteStoreMenu -> exec(QCursor::pos()); });
}
else m_internal->m_session.addMenuAction(pluginAction);
}
pluginAction.identifier = QLatin1String("File-Load-Scope");
pluginAction.menuIcon = QIcon(QLatin1String("icon:load.svg"));
pluginAction.menuText = tr("Load from file");
pluginAction.tooltip = tr("Load scope from file");
if (!retranslate)
{
LtsWidgets::LtsDragIcon *btnLoad = m_internal->m_session.addMenuAction(pluginAction);
m_internal->m_ltsItems += btnLoad;
connect(btnLoad, &LtsWidgets::LtsDragIcon::clicked, this, &FavouritesActionManager::onScopeLoadFromFile);
}
else m_internal->m_session.addMenuAction(pluginAction);
pluginAction.identifier = QLatin1String("File-Save");
pluginAction.menuIcon = QIcon(QLatin1String("icon:save.svg"));
pluginAction.menuText = tr("Save to file");
pluginAction.tooltip = tr("Save scope to file");
if (!retranslate)
{
LtsWidgets::LtsDragIcon *btnStore = m_internal->m_session.addMenuAction(pluginAction);
m_internal->m_ltsItems += btnStore;
m_internal->m_favouriteSaveMenu = new QMenu(btnStore);
btnStore->setMenu(m_internal->m_favouriteSaveMenu);
connect(btnStore, &LtsWidgets::LtsDragIcon::clicked, this, [this]() { m_internal->m_favouriteSaveMenu -> exec(QCursor::pos()); });
}
else m_internal->m_session.addMenuAction(pluginAction);
} // void FavouritesActionManager::initMainMenu(bool retranslate)
FavouritesActionManager::~FavouritesActionManager() { delete m_internal; }
void FavouritesActionManager::initFromDefaultSettings()
{
#ifdef USE_QSETTINGS
const QString &settingKey = QLatin1String(SYMBOL_FAVOURITES_SETTING_KEY);
const QString &favouriteXML = QSettings().value(settingKey).toString();
m_internal->m_symbolFavourites->contentFromString(favouriteXML);
#endif
m_internal->m_planEditor->requestFileServiceReadDefaultSymbolFavourites();
} // void FavouritesActionManager::initFromDefaultSettings()
void FavouritesActionManager::removeActionItems()
{
for (auto item : qAsConst(m_internal->m_ltsItems))
m_internal->m_session.removeMenuAction(item);
m_internal->m_ltsItems.clear();
} // void FavouritesActionManager::removeActionItems()
SymbolFavourites *FavouritesActionManager::symbolFavourites() const { return m_internal->m_symbolFavourites; }
void FavouritesActionManager::onNewFavouritesScope(const QString &scope)
{
ScopeProps scopeProps;
if (m_internal->m_favouriteStoreMenu)
{
scopeProps.m_storeMenuAction = m_internal->m_favouriteStoreMenu -> addAction(scope);
connect(scopeProps.m_storeMenuAction, &QAction::triggered, this, [this, scope](bool) { onScopeStoreViaSettingService(scope); }); // lambda
}
scopeProps.m_saveMenuAction = m_internal->m_favouriteSaveMenu -> addAction(scope);
connect(scopeProps.m_saveMenuAction, &QAction::triggered, this, [this, scope](bool) { onScopeSaveToFile(scope); }); // lambda
m_internal -> m_scopeMap[scope] = scopeProps;
emit updateSymbolScopes(m_internal->m_symbolFavourites->scopeList());
} // void FavouritesActionManager::onNewFavouritesScope( const QString & scope )
FavouriteProps &FavouritesActionManager::buildFavouriteAction(const QString &scope, const QString &sidc, const QString &name, const QPixmap &symbolPixmap)
{
LtsWidgets::PluginData pluginAction;
FavouriteProps favourite;
pluginAction.layoutArea = LtsWidgets::LayoutArea::eMainTab;
pluginAction.menuGroup = scope;
pluginAction.identifier = QLatin1String("Sidc ") + sidc;
pluginAction.menuIcon = QIcon(symbolPixmap);
pluginAction.menuText = name;
pluginAction.tooltip = tr("Create '%1' symbol - SIDC %2").arg(name, sidc);
pluginAction.dropHandlerKey = m_internal->m_planEditor->createSymbolDropEvent(sidc);
pluginAction.directFunc = [this, sidc](const LtsWidgets::PluginData &) { m_internal->m_planEditor->onSymbolCreateRubberband(sidc,true); };
favourite.m_actionIcon = symbolPixmap;
favourite.m_actionWidget = m_internal->m_session.addMenuAction(pluginAction);
favourite.m_scope = scope;
favourite.m_sidc = sidc;
if (favourite.m_actionWidget)
{
QMenu *favouriteMenu = new QMenu();
QAction *rmFavouriteAction = favouriteMenu->addAction(tr("Remove from Favourite List"));
connect(rmFavouriteAction, &QAction::triggered, this, [this, sidc](bool) { onSymbolFavouriteDelete(sidc); });
favourite.m_actionWidget->setMenu(favouriteMenu);
rmFavouriteAction->setObjectName(QLatin1String("remove favourite ") + sidc);
}
m_internal->m_favouriteMap[sidc] = favourite;
m_internal->m_scopeMap[scope].m_symbolCount++;
return m_internal->m_favouriteMap[sidc];
} // FavouriteProps & FavouritesActionManager::buildFavouriteAction(const QString & scope, const QString & sidc, const QString & name, const QPixmap & icon )
FavouriteResultWatcher::FavouriteResultWatcher(FavouriteProps &favourite, AdvancedSymbology::SymbolDictionary &symbolDict, QObject *parent)
: QObject(parent)
, m_favourite(favourite)
, m_symbolDict(symbolDict)
, m_symbolGuard()
{
connect(&m_symbolGuard, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, &FavouriteResultWatcher::onSymbolSearchResult);
const QString &baseCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(m_favourite.m_sidc);
const AdvancedSymbology::SymbolProperties &symbolProperties = m_symbolDict.symbolProperties(baseCode);
if (!symbolProperties.key().isEmpty())
{
m_favourite.m_actionWidget->setText(symbolProperties.name());
m_symbolGuard.setSymbolResult(symbolDict.findBaseSymbol(m_favourite.m_sidc));
}
else deleteLater();
} // FavouriteResultWatcher::FavouriteResultWatcher(FavouriteProps & favourite, AdvancedSymbology::SymbolDictionary & symbolDict, QObject * parent)
void FavouriteResultWatcher::onSymbolSearchResult()
{
QSharedPointer<AdvancedSymbology::SymbolResult> symbolResult = m_symbolGuard.symbolResult();
if (nullptr != symbolResult)
{
const QPixmap &symbolPixmap = QPixmap::fromImage(symbolResult->symbolImage().image()).scaled(ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio);
m_favourite.m_actionIcon = symbolPixmap;
m_favourite.m_actionWidget->setIcon(symbolPixmap);
}
deleteLater();
} // void FavouriteResultWatcher::onSymbolSearchResult()
void FavouritesActionManager::onNewFavouritesSymbol(const QString &scope, const QString &sidc)
{
new FavouriteResultWatcher(buildFavouriteAction(scope, sidc, QString(), QPixmap()), m_internal->m_map->symbolDictionary(), this);
} // void FavouritesActionManager::onNewFavouritesSymbol( const QString & scope, const QString & sidc )
void FavouritesActionManager::onDeleteFavouriteSymbol()
{
QObject *signalSender = sender();
if (signalSender)
{
const QString &sidc = signalSender->objectName();
onDeleteFavouritesSymbol(sidc);
}
} // void FavouritesActionManager::onDeleteFavouriteSymbol
void FavouritesActionManager::removeScopeMenus(const QString &scope)
{
if (m_internal -> m_scopeMap.contains(scope))
{
ScopeProps &scopeProps = m_internal->m_scopeMap[scope];
delete scopeProps.m_storeMenuAction; scopeProps.m_storeMenuAction = nullptr;
delete scopeProps.m_saveMenuAction; scopeProps.m_saveMenuAction = nullptr;
m_internal -> m_scopeMap.remove(scope);
}
} // void FavouritesActionManager::removeScopeMenus( const QString & scope )
void FavouritesActionManager::onDeleteFavouritesScope(const QString &scope)
{
removeScopeMenus(scope);
QStringList scopeList = m_internal->m_symbolFavourites->scopeList();
// The scope is about to be deleted, but has not been removed from list
scopeList.removeOne(scope);
emit updateSymbolScopes(scopeList);
} // void FavouritesActionManager::onDeleteFavouritesScope( const QString & scope )
void FavouritesActionManager::onDeleteFavouritesSymbol(const QString &sidc)
{
auto it = m_internal->m_favouriteMap.find(sidc);
if (it != m_internal->m_favouriteMap.end())
{
const FavouriteProps &favouriteProps = it.value();
QString scope = favouriteProps.m_scope;
ScopeProps &scopeProps = m_internal->m_scopeMap[scope];
m_internal->m_session.removeMenuAction(favouriteProps.m_actionWidget);
m_internal->m_favouriteMap.erase(it);
if (scopeProps.m_symbolCount <= 1)
removeScopeMenus(scope);
else
scopeProps.m_symbolCount--;
}
} // void FavouritesActionManager::onDeleteFavouritesSymbol( const QString & sidc )
void FavouritesActionManager::onSymbolFavouriteAdd(const QString &scope, const QString &sidc)
{
const AdvancedSymbology::SymbolDictionary &symbolDict = m_internal->m_map->symbolDictionary();
const AdvancedSymbology::SymbolProperties &symbolProps = symbolDict.symbolProperties(sidc);
m_internal->m_symbolFavourites->addSymbolFavourite(sidc, scope, symbolProps.name());
} // void FavouritesActionManager::onSymbolFavouriteAdd( const QString & scope, const QString & sidc )
void FavouritesActionManager::onSymbolFavouriteDelete(const QString &sidc) { m_internal->m_symbolFavourites->removeSymbolFavourite(sidc); }
void FavouritesActionManager::onSymbolFavouriteDeleteScope(const QString &scope)
{
m_internal->m_symbolFavourites->removeScope(scope);
} // void FavouritesActionManager::onSymbolFavouriteDeleteScope( const QString & scope )
void FavouritesActionManager::onSaveFavouritesToSettings()
{
QSettings().setValue(QLatin1String(SYMBOL_FAVOURITES_SETTING_KEY), m_internal->m_symbolFavourites->toString());
} // void FavouritesActionManager::onSaveFavouritesToSettings()
void FavouritesActionManager::onScopeSaveToFile(const QString &scope)
{
SymbolFavourites *scopeFavourites = SymbolFavourites::create();
if (m_internal->m_symbolFavourites->copyScope(scope, *scopeFavourites))
{
const QString &xmlScope = scopeFavourites->toString();
// Under some conditions QFileDialog calls an processEvents()
// To avoid this, create on demand
// onScopeSaveToFile is only called on LTS_DEBUG
if (!m_internal->m_fileDialog)
m_internal->m_fileDialog = new QFileDialog(nullptr);
m_internal->m_fileDialog->setAcceptMode(QFileDialog::AcceptMode::AcceptSave);
m_internal->m_fileDialog->setDefaultSuffix(QLatin1String(ScopeFileSuffix));
m_internal->m_fileDialog->setNameFilter(QStringLiteral("*.%1").arg(QLatin1String(ScopeFileSuffix)));
m_internal->m_fileDialog->setFileMode(QFileDialog::FileMode::AnyFile);
m_internal->m_fileDialog->selectFile(scope + QStringLiteral(".%1").arg(QLatin1String(ScopeFileSuffix)));
if (QDialog::DialogCode::Accepted == m_internal->m_fileDialog->exec())
{
const QStringList &fileList = m_internal->m_fileDialog->selectedFiles();
if (!fileList.isEmpty())
{
const QString &xmlFileName = fileList.first();
QFile file(xmlFileName, nullptr);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate))
QTextStream(&file) << xmlScope;
else LtsWidgets::LtsMessageDialog::showMessage(m_internal->m_session.topLevelWidget(), tr("Open '%1' favourites xml file failed").arg(xmlFileName)); // Message reading file failed.
}
}
}
else LtsWidgets::LtsMessageDialog::showMessage(m_internal->m_session.topLevelWidget(), tr("Favourite scope '%1' to save doesn't exist").arg(scope));
delete scopeFavourites;
} // void FavouritesActionManager::onScopeSaveToFile( const QString & scope )
QStringList FavouritesActionManager::onScopeLoadFromFile()
{
if (!m_internal->m_fileDialog)
m_internal->m_fileDialog = new QFileDialog(nullptr);
m_internal->m_fileDialog->setAcceptMode(QFileDialog::AcceptMode::AcceptOpen);
m_internal->m_fileDialog->setDefaultSuffix(QLatin1String(ScopeFileSuffix));
m_internal->m_fileDialog->setNameFilter(QStringLiteral("*.%1").arg(QLatin1String(ScopeFileSuffix)));
m_internal->m_fileDialog->setFileMode(QFileDialog::FileMode::ExistingFile);
if (QDialog::DialogCode::Accepted == m_internal->m_fileDialog->exec())
{
const QStringList &fileList = m_internal->m_fileDialog->selectedFiles();
if (!fileList.isEmpty())
{
const QString &xmlFileName = fileList.first();
QFile file(xmlFileName, nullptr);
SymbolFavourites *scopeFavourites = SymbolFavourites::createFromDevice(&file);
if (scopeFavourites)
{
m_internal->m_symbolFavourites->includeSymbolFavourites(*scopeFavourites);
return scopeFavourites->scopeList();
}
else LtsWidgets::LtsMessageDialog::showMessage(m_internal->m_session.topLevelWidget(), tr("Reading or parsing '%1' favourites xml file failed").arg(xmlFileName)); // Message reading file failed.
}
}
return QStringList();
} // QString FavouritesActionManager::onScopeLoadFromFile()
void FavouritesActionManager::onScopeStoreViaSettingService(const QString &scope)
{
SymbolFavourites *scopeFavourites = SymbolFavourites::create();
if (m_internal->m_symbolFavourites->copyScope(scope, *scopeFavourites))
{
const QString &xmlScope = scopeFavourites->toString();
m_internal->m_planEditor->requestFileServiceStoreSymbolFavourites(xmlScope);
}
else LtsWidgets::LtsMessageDialog::showMessage(m_internal->m_session.topLevelWidget(), tr("Favourite scope '%1' to save doesn't exist").arg(scope));
delete scopeFavourites;
} // void FavouritesActionManager::onScopeStoreViaSetttingService( cosnt QString & scope )
QStringList FavouritesActionManager::onScopeLoadViaSettingService()
{
QString favouriteXMLString;
m_internal->m_planEditor->requestFileServiceReadSymbolFavourites(favouriteXMLString);
if (!favouriteXMLString.isEmpty())
{
SymbolFavourites *scopeFavourites = SymbolFavourites::createFromString(favouriteXMLString);
if (scopeFavourites)
{
m_internal->m_symbolFavourites->includeSymbolFavourites(*scopeFavourites);
return scopeFavourites->scopeList();
}
else LtsWidgets::LtsMessageDialog::showMessage(m_internal->m_session.topLevelWidget(), tr("Parsing favourites xml string failed")); // Message reading file failed.
}
return QStringList();
} // QStringList FavouritesActionManager::onScopeLoadViaSetttingService()
} // namespace PlanEditor