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

832 lines
23 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 "symbol_favourites.h"
#include "plan_editor.h"
#include <QtCore/QIODevice>
#include <QtCore/QMetaMethod>
#include <QtXml/QDomDocument>
#include <QtXml/QDomNode>
#include <QtXml/QDomNodeList>
#include <QtXml/QDomElement>
namespace PlanEditor
{
static const char *const attributeKeyName = "name";
static const char *const attributeKeySymbolCode = "sidc";
class DomNodeVisitor
{
public:
DomNodeVisitor() = default;
virtual ~DomNodeVisitor() = default;
DomNodeVisitor(const DomNodeVisitor &) = delete;
DomNodeVisitor &operator = (const DomNodeVisitor &) = delete;
bool traverse(const QDomNode &node)
{
if (node.isNull()) return true;
if (!apply(node)) return false;
const QDomNodeList &childList = node.childNodes();
for (int i = 0; i < childList.size(); ++i)
{
if (!traverse(childList.at(i))) return false;
}
return postApply(node);
} // void traverse( const QDomNode & node )
bool traverse(const QDomDocument &domDoc) { return traverse(static_cast<const QDomNode &>(domDoc)); }
private:
virtual bool apply(const QDomNode &) = 0;
virtual bool postApply(const QDomNode &) { return true; }
}; // DomVisitor
class ListNodes : public DomNodeVisitor
{
QList<QDomNode> m_sidcNodes;
QStringList m_sidcList;
QList<QDomNode> m_scopeNodes;
QStringList m_scopeList;
bool apply(const QDomNode &node) override;
public:
explicit ListNodes(const QDomDocument &domDoc)
: DomNodeVisitor()
, m_sidcNodes()
, m_sidcList()
, m_scopeNodes()
, m_scopeList()
{
traverse(domDoc);
}
virtual ~ListNodes() = default;
const QList<QDomNode> &nodeScopeList() const { return m_scopeNodes; }
const QList<QDomNode> &nodeSidcList() const { return m_sidcNodes; }
const QStringList &scopeList() const { return m_scopeList; }
const QStringList &sidcList() const { return m_sidcList; }
}; // ListNodes
class FindSidc : public DomNodeVisitor
{
QDomNode m_sidcNode;
QString m_sidc;
bool apply(const QDomNode &node) override;
public:
FindSidc(const QDomDocument &domDoc, const QString &sidc) : DomNodeVisitor(), m_sidcNode(), m_sidc(sidc) { traverse(domDoc); }
virtual ~FindSidc() = default;
bool found() const { return !m_sidcNode.isNull(); }
QDomNode sidcNode() const { return m_sidcNode; }
}; // FindSidc
class FindScope : public DomNodeVisitor
{
QDomNode m_scopeNode;
QString m_scope;
bool apply(const QDomNode &node) override;
public:
FindScope(const QDomDocument &domDoc, const QString &scope) : DomNodeVisitor(), m_scopeNode(), m_scope(scope) { traverse(domDoc); }
virtual ~FindScope() = default;
bool found() const { return !m_scopeNode.isNull(); }
QDomNode scopeNode() const { return m_scopeNode; }
}; // FindScope
class SymbolFavouritesDom;
class IncludeOperator : public DomNodeVisitor
{
SymbolFavouritesDom &m_mainFavourites;
QString m_currentScope;
bool apply(const QDomNode &node) override;
bool postApply(const QDomNode &node) override;
public:
IncludeOperator(SymbolFavouritesDom &mainFavourites, const SymbolFavourites &toInclude);
virtual ~IncludeOperator() = default;
}; // IncludeOperator
class CopyScopeOperator : public DomNodeVisitor
{
SymbolFavourites &m_scopeFavourites;
QString m_scope;
bool m_doCut;
unsigned int m_symbolCount;
bool apply(const QDomNode &node) override;
bool postApply(const QDomNode &node) override;
public:
CopyScopeOperator(const SymbolFavouritesDom &mainFavourites, const QString &scope, SymbolFavourites &scopeFavourites);
virtual ~CopyScopeOperator() = default;
bool scopeIsNotEmpty() const { return m_symbolCount; }
}; // CopyScopeOperator
class VisitorVisitor : public DomNodeVisitor
{
const SymbolFavourites::SymbolVisitor &m_symbolVisitor;
QString m_currentScope;
bool apply(const QDomNode &node) override;
bool postApply(const QDomNode &node) override;
public:
VisitorVisitor(const QDomDocument &domDoc, const SymbolFavourites::SymbolVisitor &symbolVisitor)
: DomNodeVisitor()
, m_symbolVisitor(symbolVisitor)
, m_currentScope()
{
traverse(domDoc);
} // VisitorVisitor( const QDomDocument & domDoc, const SymbolFavourites::SymbolVisitor & symbolVisitor )
virtual ~VisitorVisitor() = default;
};
SymbolFavourites::SymbolFavourites() : QObject(nullptr) {;}
class SymbolFavouritesDom : public SymbolFavourites, virtual protected QDomDocument
{
Q_OBJECT
friend FindScope;
friend FindSidc;
friend ListNodes;
friend IncludeOperator;
friend CopyScopeOperator;
friend VisitorVisitor;
public:
enum class NodeType
{
Anything,
Scope,
Symbol
}; // NodeType
SymbolFavouritesDom() : QDomDocument(QLatin1String(m_rootNodeName) + QLatin1String("Document")), m_logger(getLogger("SymbolFavourites"))
{
if (!m_initStaticDone) initStatic();
QDomElement root = createElement(QLatin1String(m_rootNodeName));
appendChild(root);
}
virtual ~SymbolFavouritesDom() = default;
QStringList sidcList() const override
{
ListNodes listSidc(*this);
return listSidc.sidcList();
} // QStringList sidcList() const
QStringList scopeList() const override
{
ListNodes listScope(*this);
return listScope.scopeList();
} // QStringList scopeList() const
void addScope(const QString &scope) override
{
if (scope.isEmpty()) return;
FindScope findScope(*this, scope);
if (!findScope.found())
addScopeNode(scope);
} // void addScope( const QString & scope )
void addSymbolFavourite(const QString &sidc, const QString &scope, const QString &name) override
{
FindSidc findSidc(*this, sidc);
if (findSidc.found())
{
// remove sidc node when already exists
removeSymbolNode(QDomNode(), findSidc.sidcNode());
}
QDomNode scopeNode = firstChildElement(QLatin1String(m_rootNodeName));
if (!scope.isEmpty())
{
FindScope findScope(*this, scope);
if (!findScope.found()) scopeNode = addScopeNode(scope);
else scopeNode = findScope.scopeNode();
}
addSymbolNode(scopeNode, scope, name, sidc);
} // void addSymbolFavourite( const QString & sidc, const QString & scope, const QString & name ) override
bool isFavourite(const QString &sidc) const override
{
FindSidc findSidc(*this, sidc);
return findSidc.found();
} // bool isFavourite( const QString & sidc ) const
QString scope(const QString &sidc) const override
{
FindSidc findSidc(*this, sidc);
if (findSidc.found())
{
QDomElement symbolNode = findSidc.sidcNode().toElement();
if (!symbolNode.isNull())
{
QDomElement scopeNode = symbolNode.parentNode().toElement();
if (!scopeNode.isNull())
{
// In case of symbol node has any scope it is parent of root node
// and scope is then an empty string.
return scopeNode.attribute(QLatin1String(attributeKeyName), QString());
}
}
}
return QString();
} // QString scope( const QString & sidc ) const
QString name(const QString &sidc) const override
{
FindSidc findSidc(*this, sidc);
if (findSidc.found())
{
QDomElement symbolNode = findSidc.sidcNode().toElement();
if (!symbolNode.isNull())
return symbolNode.attribute(QLatin1String(attributeKeyName));
}
return QString();
} // QString name( const QString & sidc ) const
void removeSymbolFavourite(const QString &sidc) override
{
FindSidc findSidc(*this, sidc);
if (findSidc.found())
{
// remove sidc node when already exists
removeSymbolNode(QDomNode(), findSidc.sidcNode());
}
} // void removeSymbolFavourite( const QString & sidc )
void removeScope(const QString &scope) override
{
FindScope findScope(*this, scope);
if (findScope.found())
removeScopeNode(findScope.scopeNode());
} // void removeScope( const QString & scope )
void includeSymbolFavourites(const SymbolFavourites &toInclude) override
{
IncludeOperator incOp(*this, toInclude);
} // void includeSymbolFavourites( const SymbolFavourites & toInclude )
bool copyScope(const QString &scope, SymbolFavourites &scopeSymbols) override
{
CopyScopeOperator copyOp(*this, scope, scopeSymbols);
return copyOp.scopeIsNotEmpty();
} // bool copyScope( const QString & scope, SymbolFavourites & scopeSymbols )
QString toString() override { return QDomDocument::toString(3); }
class UpdateVisitor : public SymbolFavourites::SymbolVisitor
{
public:
UpdateVisitor(SymbolFavouritesDom *fav, bool construction) : m_favourites(fav), m_construction(construction) {;}
private:
SymbolFavouritesDom *m_favourites;
bool m_construction;
bool apply(const QString &scope) const override
{
if (m_construction) m_favourites -> emitSignalNewScope(scope);
else m_favourites -> emitSignalDeleteScope(scope);
return true;
}
bool apply(const QString &scope, const QString &name, const QString &sidc) const override
{
Q_UNUSED(name);
if (m_construction) m_favourites -> emitSignalNewSymbol(scope, sidc);
else m_favourites -> emitSignalDeleteSymbol(sidc);
return true;
}
}; // UpdateVisitor
bool contentFromString(const QString &xml) override
{
if (xml.isEmpty()) return true;
const QString &backup = toString();
QString errorMsg;
int errorLine;
int errorColumn;
if (!setContent(xml, &errorMsg, &errorLine, &errorColumn))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " parsing xml input failed: " << errorMsg << " at line " << errorLine << " , column " << errorColumn;
setContent(backup);
return false;
}
VisitorVisitor update(*this, UpdateVisitor(this, true));
return true;
} // bool contentFromString(const QString & xml) override
bool contentFromDevice(QIODevice *device) override
{
if (nullptr == device) return false;
const QString &backup = toString();
QString errorMsg;
int errorLine;
int errorColumn;
if (!setContent(device, &errorMsg, &errorLine, &errorColumn))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " parsing xml input failed: " << errorMsg << " at line " << errorLine << " , column " << errorColumn;
setContent(backup);
return false;
}
VisitorVisitor update(*this, UpdateVisitor(this, true));
return true;
} // bool contentFromDevice( const QIODevice * device ) override
void traverse(const SymbolVisitor &symbolVisitor) override { VisitorVisitor visitorVisitor(*this, symbolVisitor); }
void emitSignalNewScope(const QString &scope) { emit signalNewScope(scope); }
void emitSignalNewSymbol(const QString &scope, const QString &sidc) { emit signalNewSymbol(scope, sidc); }
void emitSignalDeleteScope(const QString &scope) { emit signalDeleteScope(scope); }
void emitSignalDeleteSymbol(const QString &sidc) { emit signalDeleteSymbol(sidc); }
private:
QDomElement addScopeNode(const QString &scope)
{
QDomElement root = firstChildElement(QLatin1String(m_rootNodeName));
QDomElement scopeNode = createElement(m_nodeTagStrings[NodeType::Scope]);
scopeNode.setAttribute(QLatin1String(attributeKeyName), scope);
root.appendChild(scopeNode);
emitSignalNewScope(scope);
return scopeNode;
} // QDomElement addScopeNode( const QString & scope )
QDomElement addSymbolNode(QDomNode &scopeNode, const QString &scope, const QString &name, const QString &sidc)
{
QDomElement symbolNode = createElement(m_nodeTagStrings[NodeType::Symbol]);
symbolNode.setAttribute(QLatin1String(attributeKeyName), name);
symbolNode.setAttribute(QLatin1String(attributeKeySymbolCode), sidc);
scopeNode.appendChild(symbolNode);
emit signalNewSymbol(scope, sidc);
return symbolNode;
} // QDomElement addSymbolNode( QDomNode & scopeNode, const QString & name, const QString & sidc )
void removeScopeNode(const QDomNode &scopeNode)
{
QDomNode parent = scopeNode.parentNode();
if (!parent.isNull())
{
const QDomNodeList &childList = scopeNode.childNodes();
for (int i = 0; i < childList.size(); ++i)
removeSymbolNode(scopeNode, childList.at(i));
if (isSignalConnected(QMetaMethod::fromSignal(&SymbolFavourites::signalDeleteScope)))
{
const QDomElement &scopeElem = scopeNode.toElement();
const QString &scope = scopeElem.attribute(QLatin1String(attributeKeyName), QString());;
emit signalDeleteScope(scope);
}
parent.removeChild(scopeNode);
}
} // void removeScopeNode( QDomNode & scopeNode )
void removeSymbolNode(const QDomNode &scopeNode, const QDomNode &symbolNode)
{
if (symbolNode.isNull()) return;
QDomNode parent = scopeNode;
if (parent.isNull()) parent = symbolNode.parentNode();
if (!parent.isNull())
{
if (isSignalConnected(QMetaMethod::fromSignal(&SymbolFavourites::signalDeleteSymbol)))
{
const QDomElement &symbolElem = symbolNode.toElement();
const QString &sidc = symbolElem.attribute(QLatin1String(attributeKeySymbolCode), QString());;
emit signalDeleteSymbol(sidc);
}
parent.removeChild(symbolNode);
}
} // void removeSymbolNode( const QDomNode & symbolNode )
Logger &m_logger;
static bool m_initStaticDone;
static const char *const m_rootNodeName;
static QMap<QString, NodeType> m_nodeTags;
static QMap<NodeType, QString> m_nodeTagStrings;
static NodeType nodeType(const QDomNode &node)
{
const QString &tag = node.nodeName();
return (m_nodeTags.contains(tag)) ? m_nodeTags[tag] : NodeType::Anything;
} // NodeType nodeType( const QDomNode & node )
static void initStatic();
}; // SymbolFavouritesDom
SymbolFavourites *SymbolFavourites::create() { return new SymbolFavouritesDom(); }
SymbolFavourites *SymbolFavourites::createFromString(const QString &xml)
{
SymbolFavouritesDom *domDoc = new SymbolFavouritesDom();
if (domDoc->contentFromString(xml)) return domDoc;
delete domDoc;
return nullptr;
} // SymbolFavourites * SymbolFavourites::createFromString( const QString & xml )
SymbolFavourites *SymbolFavourites::createFromDevice(QIODevice *device)
{
SymbolFavouritesDom *domDoc = new SymbolFavouritesDom();
if (domDoc->contentFromDevice(device)) return domDoc;
delete domDoc;
return nullptr;
} // SymbolFavourites * SymbolFavourites::createFromDevice( QIODevice * device )
const char *const SymbolFavouritesDom::m_rootNodeName = "SymbolFavourites";
bool SymbolFavouritesDom::m_initStaticDone = false;
QMap<QString, SymbolFavouritesDom::NodeType> SymbolFavouritesDom::m_nodeTags;
QMap<SymbolFavouritesDom::NodeType, QString> SymbolFavouritesDom::m_nodeTagStrings;
void SymbolFavouritesDom::initStatic()
{
m_nodeTags[QLatin1String("Scope")] = NodeType::Scope;
m_nodeTags[QLatin1String("Symbol")] = NodeType::Symbol;
m_nodeTagStrings[NodeType::Scope ] = QLatin1String("Scope");
m_nodeTagStrings[NodeType::Symbol] = QLatin1String("Symbol");
m_initStaticDone = true;
} // void SymbolFavouritesDom::initStatic()
bool ListNodes::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::m_nodeTags.contains(tag))
{
switch (SymbolFavouritesDom::m_nodeTags[tag])
{
case SymbolFavouritesDom::NodeType::Symbol:
{
QDomElement e = node.toElement();
if (e.hasAttribute(QLatin1String(attributeKeySymbolCode)))
{
m_sidcNodes += node;
m_sidcList += e.attribute(QLatin1String(attributeKeySymbolCode));
}
} break;
case SymbolFavouritesDom::NodeType::Scope:
{
QDomElement e = node.toElement();
if (e.hasAttribute(QLatin1String(attributeKeyName)))
{
m_scopeNodes += node;
m_scopeList += e.attribute(QLatin1String(attributeKeyName));
}
} break;
default : break;
}
}
return true;
} // bool ListNodes::apply( const QDomNode & node )
bool FindSidc::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::m_nodeTags.contains(tag))
{
if (SymbolFavouritesDom::NodeType::Symbol == SymbolFavouritesDom::m_nodeTags[tag])
{
QDomElement e = node.toElement();
if (e.attribute(QLatin1String(attributeKeySymbolCode)) == m_sidc)
{
m_sidcNode = node;
return false;
}
}
}
return true;
} // bool FindSidc::apply( const QDomNode & node )
bool FindScope::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::m_nodeTags.contains(tag))
{
if (SymbolFavouritesDom::NodeType::Scope == SymbolFavouritesDom::m_nodeTags[tag])
{
QDomElement e = node.toElement();
if (e.attribute(QLatin1String(attributeKeyName)) == m_scope)
{
m_scopeNode = node;
return false;
}
}
}
return true;
} // bool FindScope::apply( const QDomNode & node )
IncludeOperator::IncludeOperator(SymbolFavouritesDom &mainFavourites, const SymbolFavourites &toInclude)
: DomNodeVisitor()
, m_mainFavourites(mainFavourites)
, m_currentScope()
{
const SymbolFavouritesDom *toIncludeDom = dynamic_cast<const SymbolFavouritesDom *>(&toInclude);
if (toIncludeDom)
traverse(*toIncludeDom);
else ERROR_LOG(mainFavourites.m_logger) << LOGFUNCTION << " Type mismatch: SymbolFavourites toInclude have wrong type.";
} // IncludeOperator::IncludeOperator( SymbolFavouritesDom & mainFavourites, SymbolFavouritesDom & toInclude )
bool IncludeOperator::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
switch (SymbolFavouritesDom::m_nodeTags[tag])
{
case SymbolFavouritesDom::NodeType::Scope:
{
QDomElement elmt = node.toElement();
const QString &scope = elmt.attribute(QLatin1String(attributeKeyName));
m_mainFavourites.addScope(scope);
m_currentScope = scope;
} break;
case SymbolFavouritesDom::NodeType::Symbol:
{
QDomElement elmt = node.toElement();
const QString &name = elmt.attribute(QLatin1String(attributeKeyName));
const QString &sidc = elmt.attribute(QLatin1String(attributeKeySymbolCode));
m_mainFavourites.addSymbolFavourite(sidc, m_currentScope, name);
} break;
default : break;
}
return true;
} // bool IncludeOperator::apply( const QDomNode & node )
bool IncludeOperator::postApply(const QDomNode &node)
{
// if scope node has been processed reset m_currentScope
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::NodeType::Scope == SymbolFavouritesDom::m_nodeTags[tag])
m_currentScope.clear();
return true;
} // bool IncludeOperator::postApply( const QDomNode & node )
CopyScopeOperator::CopyScopeOperator(const SymbolFavouritesDom &mainFavourites, const QString &scope, SymbolFavourites &scopeFavourites)
: DomNodeVisitor()
, m_scopeFavourites(scopeFavourites)
, m_scope(scope)
, m_doCut(false)
, m_symbolCount(0)
{
traverse(mainFavourites);
} // CopyScopeOperator::CopyScopeOperator( SymbolFavouritesDom & mainFavourites, const QString & scope, SymbolFavouritesDom & scopeFavourites )
bool CopyScopeOperator::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
switch (SymbolFavouritesDom::m_nodeTags[tag])
{
case SymbolFavouritesDom::NodeType::Scope:
{
QDomElement elmt = node.toElement();
const QString &scope = elmt.attribute(QLatin1String(attributeKeyName));
if (scope == m_scope)
{
m_scopeFavourites.addScope(scope);
m_doCut = true;
}
} break;
case SymbolFavouritesDom::NodeType::Symbol:
{
if (m_doCut)
{
QDomElement elmt = node.toElement();
const QString &name = elmt.attribute(QLatin1String(attributeKeyName));
const QString &sidc = elmt.attribute(QLatin1String(attributeKeySymbolCode));
m_scopeFavourites.addSymbolFavourite(sidc, m_scope, name);
m_symbolCount++;
}
} break;
default: break;
}
return true;
} // bool CopyScopeOperator::apply( const QDomNode & node )
bool CopyScopeOperator::postApply(const QDomNode &node)
{
if (m_doCut)
{
// if scope node has been processed reset m_currentScope
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::NodeType::Scope == SymbolFavouritesDom::m_nodeTags[tag])
{
m_doCut = false;
return false;
}
}
return true;
} // bool CopyScopeOperator::postApply( const QDomNode & node )
bool VisitorVisitor::apply(const QDomNode &node)
{
const QString &tag = node.nodeName();
switch (SymbolFavouritesDom::m_nodeTags[tag])
{
case SymbolFavouritesDom::NodeType::Scope:
{
QDomElement elmt = node.toElement();
m_currentScope = elmt.attribute(QLatin1String(attributeKeyName));
return m_symbolVisitor.apply(m_currentScope);
} break;
case SymbolFavouritesDom::NodeType::Symbol:
{
QDomElement elmt = node.toElement();
const QString &name = elmt.attribute(QLatin1String(attributeKeyName));
const QString &sidc = elmt.attribute(QLatin1String(attributeKeySymbolCode));
return m_symbolVisitor.apply(m_currentScope, name, sidc);
} break;
default: break;
}
return true;
} // bool VisitorVisitor::apply( const QDomNode & node )
bool VisitorVisitor::postApply(const QDomNode &node)
{
const QString &tag = node.nodeName();
if (SymbolFavouritesDom::NodeType::Scope == SymbolFavouritesDom::m_nodeTags[tag])
m_currentScope.clear();
return true;
} // bool VisitorVisitor::postApply( const QDomNode & node )
bool SymbolFavourites::SymbolVisitor::apply(const QString &) const { return true; }
bool SymbolFavourites::SymbolVisitor::apply(const QString &, const QString &, const QString &) const { return true; }
} // namespace PlanEditor
#include "symbol_favourites.moc"