File indexing completed on 2024-05-12 03:47:46
0001 /* 0002 File : XmlStreamReader.cpp 0003 Project : LabPlot 0004 Description : XML stream parser that supports errors and warnings 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2009 Tilman Benkert <thzs@gmx.net> 0007 SPDX-FileCopyrightText: 2015-2016 Alexander Semke <alexander.semke@web.de> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "backend/lib/XmlStreamReader.h" 0013 #include <KLocalizedString> 0014 0015 /** 0016 * \class XmlStreamReader 0017 * \brief XML stream parser that supports errors as well as warnings. 0018 * This class also adds line and column numbers to the error message. 0019 */ 0020 XmlStreamReader::XmlStreamReader() = default; 0021 0022 XmlStreamReader::XmlStreamReader(QIODevice* device) 0023 : QXmlStreamReader(device) { 0024 } 0025 0026 XmlStreamReader::XmlStreamReader(const QByteArray& data) 0027 : QXmlStreamReader(data) { 0028 } 0029 0030 XmlStreamReader::XmlStreamReader(const QString& data) 0031 : QXmlStreamReader(data) { 0032 } 0033 0034 XmlStreamReader::XmlStreamReader(const char* data) 0035 : QXmlStreamReader(data) { 0036 } 0037 0038 const QStringList& XmlStreamReader::warningStrings() const { 0039 return m_warnings; 0040 } 0041 0042 /* 0043 * returns the human readable string for the missing CAS plugins in case 0044 * the project has some CAS content but the application was either not compiled with 0045 * CAS/Cantor support or the correspongind plugins for the required backends are missing. 0046 * 0047 * The returned text is in the form "Octave" or "Octave and Maxima" or "Octave, Maxima and Python", etc. 0048 */ 0049 QString XmlStreamReader::missingCASWarning() const { 0050 const int count = m_missingCASPlugins.count(); 0051 if (count == 1) 0052 return m_missingCASPlugins.constFirst(); 0053 else { 0054 QString msg; 0055 for (int i = 0; i < count; ++i) { 0056 if (!msg.isEmpty()) { 0057 if (i == count - 1) 0058 msg += QLatin1Char(' ') + i18n("and") + QLatin1Char(' '); 0059 else 0060 msg += QLatin1String(", "); 0061 } 0062 msg += m_missingCASPlugins.at(i); 0063 } 0064 return msg; 0065 } 0066 } 0067 0068 bool XmlStreamReader::hasWarnings() const { 0069 return !m_warnings.isEmpty(); 0070 } 0071 0072 bool XmlStreamReader::hasMissingCASWarnings() const { 0073 return !m_missingCASPlugins.isEmpty(); 0074 } 0075 0076 void XmlStreamReader::setFailedCASMissing(bool value) { 0077 m_failedCASMissing = value; 0078 } 0079 0080 /*! 0081 * returns \c true if the loading of an project object failed because 0082 * of the missing CAS functionality (no CAS support or missing CAS plugin). 0083 * returns \c false if the loadign failed because of other reasons 0084 * like broken XML or missing important and required attributes. 0085 */ 0086 bool XmlStreamReader::failedCASMissing() const { 0087 return m_failedCASMissing; 0088 } 0089 0090 void XmlStreamReader::raiseError(const QString& message) { 0091 QXmlStreamReader::raiseError(i18n("line %1, column %2: %3", lineNumber(), columnNumber(), message)); 0092 } 0093 0094 void XmlStreamReader::raiseWarning(const QString& message) { 0095 m_warnings.append(i18n("line %1, column %2: %3", lineNumber(), columnNumber(), message)); 0096 } 0097 0098 void XmlStreamReader::raiseMissingAttributeWarning(const QString& attribute) { 0099 static auto warning = i18n("Attribute '%1' missing or empty, default value is used"); 0100 m_warnings.append(i18n("line %1, column %2: %3", lineNumber(), columnNumber(), warning.arg(attribute))); 0101 } 0102 0103 void XmlStreamReader::raiseUnknownElementWarning() { 0104 static auto warning = i18n("unknown element '%1'"); 0105 m_warnings.append(i18n("line %1, column %2: %3", lineNumber(), columnNumber(), warning.arg(name()))); 0106 } 0107 0108 void XmlStreamReader::raiseMissingCASWarning(const QString& name) { 0109 m_missingCASPlugins.append(name); 0110 } 0111 0112 /*! 0113 * Go to the next start or end element tag 0114 * If the end of the document is reached, an error is raised. 0115 * \return false if end of document reached, otherwise true 0116 */ 0117 bool XmlStreamReader::skipToNextTag() { 0118 if (atEnd()) { 0119 raiseError(i18n("unexpected end of document")); 0120 return false; 0121 } 0122 0123 do { 0124 readNext(); 0125 } while (!(isStartElement() || isEndElement() || atEnd())); 0126 0127 if (atEnd()) { 0128 raiseError(i18n("unexpected end of document")); 0129 return false; 0130 } 0131 0132 return true; 0133 } 0134 0135 /*! 0136 * Go to the end element tag of the current element 0137 * If the end of the document is reached, an error is raised. 0138 * \return false if end of document reached, otherwise true 0139 */ 0140 bool XmlStreamReader::skipToEndElement() { 0141 int depth = 1; 0142 if (atEnd()) { 0143 raiseError(i18n("unexpected end of document")); 0144 return false; 0145 } 0146 0147 do { 0148 readNext(); 0149 if (isEndElement()) 0150 depth--; 0151 if (isStartElement()) 0152 depth++; 0153 } while (!((isEndElement() && depth == 0) || atEnd())); 0154 0155 if (atEnd()) { 0156 raiseError(i18n("unexpected end of document")); 0157 return false; 0158 } 0159 0160 return true; 0161 } 0162 0163 /*! 0164 * Read an XML attribute and convert it to int 0165 * \param name attribute name 0166 * \param ok pointer to report back whether the attribute value could be determined (may be NULL) 0167 * \return the attribute value if found and converted, otherwise zero (in this case *ok is false) 0168 */ 0169 int XmlStreamReader::readAttributeInt(const QString& name, bool* ok) { 0170 QString str = attributes().value(namespaceUri().toString(), name).toString(); 0171 if (str.isEmpty()) { 0172 if (ok) 0173 *ok = false; 0174 return 0; 0175 } 0176 0177 return str.toInt(ok); 0178 }