diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp index a156cb93a..6aced9eaa 100644 --- a/src/libs/ifc/xml/vabstractpattern.cpp +++ b/src/libs/ifc/xml/vabstractpattern.cpp @@ -239,13 +239,12 @@ void GatherTokens(QSet &tokens, const QList &tokenList) //--------------------------------------------------------------------------------------------------------------------- VAbstractPattern::VAbstractPattern(QObject *parent) - : QObject(parent), - VDomDocument(), - nameActivPP(QString()), + : VDomDocument(parent), + nameActivPP(), cursor(0), toolsOnRemove(QVector()), history(QVector()), - patternPieces(QStringList()), + patternPieces(), modified(false) {} diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h index 694ff21b6..1bfcd63e3 100644 --- a/src/libs/ifc/xml/vabstractpattern.h +++ b/src/libs/ifc/xml/vabstractpattern.h @@ -79,7 +79,7 @@ struct VFinalMeasurement QT_WARNING_POP -class VAbstractPattern : public QObject, public VDomDocument +class VAbstractPattern : public VDomDocument { Q_OBJECT public: diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp index d0763f14c..ed488071d 100644 --- a/src/libs/ifc/xml/vdomdocument.cpp +++ b/src/libs/ifc/xml/vdomdocument.cpp @@ -59,6 +59,9 @@ #include #include #include +#include +#include +#include namespace { @@ -190,10 +193,20 @@ const QString VDomDocument::TagUnit = QStringLiteral("unit"); const QString VDomDocument::TagLine = QStringLiteral("line"); //--------------------------------------------------------------------------------------------------------------------- -VDomDocument::VDomDocument() - : QDomDocument(), - map() -{} +VDomDocument::VDomDocument(QObject *parent) + : QObject(parent), + QDomDocument(), + m_elementIdCache(), + m_refreshCacheTimer(new QTimer(this)), + m_watcher(new QFutureWatcher>(this)) +{ + m_refreshCacheTimer->setTimerType(Qt::VeryCoarseTimer); + m_refreshCacheTimer->setInterval(10000); + m_refreshCacheTimer->setSingleShot(true); + connect(m_refreshCacheTimer, &QTimer::timeout, this, &VDomDocument::RefreshElementIdCache); + connect(m_watcher, &QFutureWatcher>::finished, this, &VDomDocument::CacheRefreshed); + m_refreshCacheTimer->start(); +} //--------------------------------------------------------------------------------------------------------------------- QDomElement VDomDocument::elementById(quint32 id, const QString &tagName) @@ -203,21 +216,21 @@ QDomElement VDomDocument::elementById(quint32 id, const QString &tagName) return QDomElement(); } - if (map.contains(id)) + if (m_elementIdCache.contains(id)) { - const QDomElement e = map[id]; + const QDomElement e = m_elementIdCache.value(id); if (e.parentNode().nodeType() != QDomNode::BaseNode) { return e; } - map.remove(id); + m_elementIdCache.remove(id); } if (tagName.isEmpty()) { - if (this->find(this->documentElement(), id)) + if (VDomDocument::find(m_elementIdCache, this->documentElement(), id)) { - return map[id]; + return m_elementIdCache.value(id); } } else @@ -228,19 +241,12 @@ QDomElement VDomDocument::elementById(quint32 id, const QString &tagName) const QDomElement domElement = list.at(i).toElement(); if (not domElement.isNull() && domElement.hasAttribute(AttrId)) { - try - { - const quint32 elementId = GetParametrUInt(domElement, AttrId, NULL_ID_STR); + const quint32 elementId = GetParametrUInt(domElement, AttrId, NULL_ID_STR); - this->map[elementId] = domElement; - if (elementId == id) - { - return domElement; - } - } - catch (const VExceptionConversionError &) + m_elementIdCache.insert(elementId, domElement); + if (elementId == id) { - // do nothing + return domElement; } } } @@ -252,27 +258,21 @@ QDomElement VDomDocument::elementById(quint32 id, const QString &tagName) //--------------------------------------------------------------------------------------------------------------------- /** * @brief Find element by id. + * @param cache cache with element ids * @param node node * @param id id value * @return true if found */ -bool VDomDocument::find(const QDomElement &node, quint32 id) +bool VDomDocument::find(QHash &cache, const QDomElement &node, quint32 id) { if (node.hasAttribute(AttrId)) { - try - { - const quint32 elementId = GetParametrUInt(node, AttrId, NULL_ID_STR); + const quint32 elementId = GetParametrUInt(node, AttrId, NULL_ID_STR); - this->map[elementId] = node; - if (elementId == id) - { - return true; - } - } - catch (const VExceptionConversionError &) + cache.insert(elementId, node); + if (elementId == id) { - // do nothing + return true; } } @@ -281,7 +281,7 @@ bool VDomDocument::find(const QDomElement &node, quint32 id) const QDomNode n = node.childNodes().at(i); if (n.isElement()) { - if (this->find(n.toElement(), id)) + if (VDomDocument::find(cache, n.toElement(), id)) { return true; } @@ -290,6 +290,15 @@ bool VDomDocument::find(const QDomElement &node, quint32 id) return false; } + +//--------------------------------------------------------------------------------------------------------------------- +QHash VDomDocument::RefreshCache(const QDomElement &root) const +{ + QHash cache; + VDomDocument::find(cache, root, NULL_ID); + return cache; +} + //--------------------------------------------------------------------------------------------------------------------- bool VDomDocument::SaveCanonicalXML(QIODevice *file, int indent, QString &error) const { @@ -602,6 +611,19 @@ void VDomDocument::CollectId(const QDomElement &node, QVector &vector) } } +//--------------------------------------------------------------------------------------------------------------------- +void VDomDocument::RefreshElementIdCache() +{ + m_watcher->setFuture(QtConcurrent::run(this, &VDomDocument::RefreshCache, documentElement())); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VDomDocument::CacheRefreshed() +{ + m_elementIdCache = m_watcher->future().result(); + m_refreshCacheTimer->start(); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief ValidateXML validate xml file by xsd schema. @@ -690,6 +712,8 @@ void VDomDocument::setXMLContent(const QString &fileName) .arg(fileName)); throw e; } + + RefreshElementIdCache(); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/ifc/xml/vdomdocument.h b/src/libs/ifc/xml/vdomdocument.h index b2a401e4a..c27fe5258 100644 --- a/src/libs/ifc/xml/vdomdocument.h +++ b/src/libs/ifc/xml/vdomdocument.h @@ -50,6 +50,7 @@ class QDomElement; class QDomNode; template class QVector; +template class QFutureWatcher; Q_DECLARE_LOGGING_CATEGORY(vXML) @@ -78,9 +79,9 @@ QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor") * Of these, 2) and 3) are visible in the final pattern (draw mode 'Modeling'), * 1) is only displayed when editing (draw mode 'Calculation') the pattern. */ -class VDomDocument : public QDomDocument +class VDomDocument : public QObject, public QDomDocument { - Q_DECLARE_TR_FUNCTIONS(VDomDocument) + Q_OBJECT public: static const QString AttrId; static const QString AttrText; @@ -93,7 +94,7 @@ public: static const QString TagUnit; static const QString TagLine; - VDomDocument(); + VDomDocument(QObject *parent = nullptr); virtual ~VDomDocument() Q_DECL_EQ_DEFAULT; QDomElement elementById(quint32 id, const QString &tagName = QString()); @@ -141,12 +142,19 @@ protected: void TestUniqueId() const; void CollectId(const QDomElement &node, QVector &vector)const; +private slots: + void RefreshElementIdCache(); + void CacheRefreshed(); + private: Q_DISABLE_COPY(VDomDocument) /** @brief Map used for finding element by id. */ - QHash map; + QHash m_elementIdCache; + QTimer *m_refreshCacheTimer; + QFutureWatcher> *m_watcher; - bool find(const QDomElement &node, quint32 id); + static bool find(QHash &cache, const QDomElement &node, quint32 id); + QHash RefreshCache(const QDomElement &root) const; bool SaveCanonicalXML(QIODevice *file, int indent, QString &error) const; };