/************************************************************************ ** ** @file vdomdocument.cpp ** @author Roman Telezhynskyi ** @date November 15, 2013 ** ** @brief ** @copyright ** This source code is part of the Valentine project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2013 Valentina project ** All Rights Reserved. ** ** Valentina is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** Valentina is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Valentina. If not, see . ** *************************************************************************/ #include "vdomdocument.h" #include "../exception/vexceptionconversionerror.h" #include "../exception/vexceptionemptyparameter.h" #include "../exception/vexceptionbadid.h" #include "../options.h" #include "../core/vapplication.h" #include #include #include #include #include #include //This class need for validation pattern file using XSD shema class MessageHandler : public QAbstractMessageHandler { public: MessageHandler() : QAbstractMessageHandler(), m_messageType(QtMsgType()), m_description(QString()), m_sourceLocation(QSourceLocation()){} QString statusMessage() const; qint64 line() const; qint64 column() const; protected: // cppcheck-suppress unusedFunction virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation); private: QtMsgType m_messageType; QString m_description; QSourceLocation m_sourceLocation; }; //--------------------------------------------------------------------------------------------------------------------- inline QString MessageHandler::statusMessage() const { return m_description; } //--------------------------------------------------------------------------------------------------------------------- inline qint64 MessageHandler::line() const { return m_sourceLocation.line(); } //--------------------------------------------------------------------------------------------------------------------- inline qint64 MessageHandler::column() const { return m_sourceLocation.column(); } //--------------------------------------------------------------------------------------------------------------------- // cppcheck-suppress unusedFunction void MessageHandler::handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) { Q_UNUSED(type); Q_UNUSED(identifier); m_messageType = type; m_description = description; m_sourceLocation = sourceLocation; } Q_LOGGING_CATEGORY(vXML, "v.xml") const QString VDomDocument::AttrId = QStringLiteral("id"); const QString VDomDocument::AttrUnit = QStringLiteral("unit"); const QString VDomDocument::UnitMM = QStringLiteral("mm"); const QString VDomDocument::UnitCM = QStringLiteral("cm"); const QString VDomDocument::UnitINCH = QStringLiteral("inch"); const QString VDomDocument::TagVersion = QStringLiteral("version"); //--------------------------------------------------------------------------------------------------------------------- VDomDocument::VDomDocument(VContainer *data) : QDomDocument(), data(data), map(QHash()) {} //--------------------------------------------------------------------------------------------------------------------- VDomDocument::~VDomDocument() {} //--------------------------------------------------------------------------------------------------------------------- /** * @brief Finds an element by id. * @param id value id attribute. * @return dom element. */ QDomElement VDomDocument::elementById(const QString& id) { if (map.contains(id)) { QDomElement e = map[id]; if (e.parentNode().nodeType() != QDomNode::BaseNode) { return e; } map.remove(id); } if (this->find(this->documentElement(), id)) { return map[id]; } return QDomElement(); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Removes all children of a given element tag. RENAME: removeAllChildren * @param element tag */ void VDomDocument::removeAllChilds(QDomElement &element) { QDomNode domNode = element.firstChild(); while (domNode.isNull() == false) { if (domNode.isElement()) { QDomElement domElement = domNode.toElement(); if (domElement.isNull() == false) { element.removeChild(domElement); } } domNode = element.firstChild(); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Find element by id. * @param node node * @param id id value * @return true if found */ bool VDomDocument::find(const QDomElement &node, const QString& id) { if (node.hasAttribute(AttrId)) { const QString value = node.attribute(AttrId); this->map[value] = node; if (value == id) { return true; } } for (qint32 i=0; ifind(n.toElement(), id)) { return true; } } } return false; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Returns the long long value of the given attribute. RENAME: GetParameterLongLong? * @param domElement tag in xml tree * @param name attribute name * @return long long value */ quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); bool ok = false; QString parametr; quint32 id = 0; QString message = tr("Can't convert toUInt parameter"); try { parametr = GetParametrString(domElement, name, defValue); id = parametr.toUInt(&ok); if (ok == false) { throw VExceptionConversionError(message, name); } } catch (const VExceptionEmptyParameter &e) { VExceptionConversionError excep(message, name); excep.AddMoreInformation(e.ErrorMessage()); throw excep; } return id; } //--------------------------------------------------------------------------------------------------------------------- bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); QString parametr; bool val = true; QString message = tr("Can't convert toBool parameter"); try { parametr = GetParametrString(domElement, name, defValue); QStringList bools = QStringList() << QLatin1String("true") << QLatin1String("false"); switch (bools.indexOf(parametr)) { case 0: // true val = true; break; case 1: // false val = false; break; default:// others throw VExceptionConversionError(message, name); break; } } catch (const VExceptionEmptyParameter &e) { VExceptionConversionError excep(message, name); excep.AddMoreInformation(e.ErrorMessage()); throw excep; } return val; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Returns the string value of the given attribute. RENAME: see above * * if attribute empty return default value. If default value empty too throw exception. * @return attribute value * @throw VExceptionEmptyParameter when attribute is empty */ QString VDomDocument::GetParametrString(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); const QString parameter = domElement.attribute(name, defValue); if (parameter.isEmpty()) { if (defValue.isEmpty()) { throw VExceptionEmptyParameter(tr("Got empty parameter"), name, domElement); } else { return defValue; } } return parameter; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Returns the double value of the given attribute. * @param domElement tag in xml tree * @param name attribute name * @return double value */ qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); bool ok = false; qreal param = 0; QString message = tr("Can't convert toDouble parameter"); try { QString parametr = GetParametrString(domElement, name, defValue); param = parametr.replace(",", ".").toDouble(&ok); if (ok == false) { throw VExceptionConversionError(message, name); } } catch (const VExceptionEmptyParameter &e) { VExceptionConversionError excep(message, name); excep.AddMoreInformation(e.ErrorMessage()); throw excep; } return param; } //--------------------------------------------------------------------------------------------------------------------- QString VDomDocument::UniqueTagText(const QString &tagName, const QString &defVal) const { const QDomNodeList nodeList = this->elementsByTagName(tagName); if (nodeList.isEmpty()) { return defVal; } else { const QDomNode domNode = nodeList.at(0); if (domNode.isNull() == false && domNode.isElement()) { const QDomElement domElement = domNode.toElement(); if (domElement.isNull() == false) { return domElement.text(); } } } return defVal; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ValidateXML validate xml file by xsd schema. * @param schema path to schema file. * @param fileName name of xml file. */ void VDomDocument::ValidateXML(const QString &schema, const QString &fileName) { qCDebug(vXML)<<"Validation xml file"<elementsByTagName(tag); if (nodeList.isEmpty()) { qDebug()<<"Can't save tag "<= 1 ) { domElement.removeChild( domElement.firstChild() ); } } } //--------------------------------------------------------------------------------------------------------------------- QDomNode VDomDocument::ParentNodeById(const quint32 &nodeId) { QDomElement domElement = NodeById(nodeId); return domElement.parentNode(); } //--------------------------------------------------------------------------------------------------------------------- QDomElement VDomDocument::CloneNodeById(const quint32 &nodeId) { QDomElement domElement = NodeById(nodeId); return domElement.cloneNode().toElement(); } //--------------------------------------------------------------------------------------------------------------------- QDomElement VDomDocument::NodeById(const quint32 &nodeId) { QDomElement domElement = elementById(QString().setNum(nodeId)); if (domElement.isNull() || domElement.isElement() == false) { throw VExceptionBadId(tr("Couldn't get node"), nodeId); } return domElement; }