File indexing completed on 2024-05-05 08:41:22
0001 /* 0002 * Copyright (C) 2010-2015 by Stephen Allewell 0003 * steve.allewell@gmail.com 0004 * 0005 * This program is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation; either version 2 of the License, or 0008 * (at your option) any later version. 0009 */ 0010 0011 /** 0012 @file 0013 Implements the scheme parser to read an XML formatted scheme file. 0014 */ 0015 0016 #include "SchemeParser.h" 0017 0018 #include <KLocalizedString> 0019 0020 #include "Floss.h" 0021 #include "FlossScheme.h" 0022 0023 /** 0024 Valid tags that can exist in the file. 0025 */ 0026 const QStringList validTags = { 0027 QStringLiteral("flossScheme"), /**< The enclosing tags for the file */ 0028 QStringLiteral("title"), /**< The title of the scheme */ 0029 QStringLiteral("floss"), /**< Enclosing tags for a floss definition */ 0030 QStringLiteral("name"), /**< The name of the floss */ 0031 QStringLiteral("description"), /**< The descriptive text for the floss */ 0032 QStringLiteral("color"), /**< Enclosing tags for a color definition */ 0033 QStringLiteral("red"), /**< Red color value */ 0034 QStringLiteral("green"), /**< Green color value */ 0035 QStringLiteral("blue") /**< Blue color value */ 0036 }; 0037 0038 /** 0039 Error messages. 0040 */ 0041 const char *errorMessages[] = {I18N_NOOP("No error"), 0042 I18N_NOOP("Floss not completely defined"), 0043 I18N_NOOP("Unmatched element tags"), 0044 I18N_NOOP("Unknown element tag"), 0045 I18N_NOOP("Color value is invalid"), 0046 I18N_NOOP("Unknown error code")}; 0047 0048 /** 0049 Constructor. Initialises pointers to 0 and set the m_errorCode value to 0. 0050 */ 0051 SchemeParser::SchemeParser() 0052 : m_errorCode(0) 0053 , m_scheme(nullptr) 0054 { 0055 } 0056 0057 /** 0058 Get a pointer to the read FlossScheme. 0059 @return pointer to FlossScheme class. 0060 */ 0061 FlossScheme *SchemeParser::flossScheme() 0062 { 0063 return m_scheme; 0064 } 0065 0066 /** 0067 Start a new XML document, creating an instance of a FlossScheme. 0068 @return true if the scheme is created, false otherwise. 0069 */ 0070 bool SchemeParser::startDocument() 0071 { 0072 m_scheme = new FlossScheme; 0073 return (m_scheme) ? true : false; 0074 } 0075 0076 /** 0077 Start a new element. Reimplemented from QXmlDefaultHandler. 0078 @param namespaceURI not used 0079 @param localName not used 0080 @param qName name of the tag. 0081 @param qxmlAttributes not used 0082 @return true if the tag is valid, false otherwise. 0083 */ 0084 bool SchemeParser::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &qxmlAttributes) 0085 { 0086 Q_UNUSED(namespaceURI); 0087 Q_UNUSED(localName); 0088 Q_UNUSED(qxmlAttributes); 0089 0090 QString name = qName.simplified(); 0091 0092 if (validTags.contains(name)) { 0093 m_elements.push(name); 0094 return true; 0095 } 0096 0097 // invalid tag found 0098 m_errorCode = 3; 0099 return false; 0100 } 0101 0102 /** 0103 Process a string of characters. Reimplemented from QXmlDefaultHandler. 0104 @param d QString reference of the characters read from the file. 0105 @return true if the data is acceptable, false otherwise. 0106 */ 0107 bool SchemeParser::characters(const QString &d) 0108 { 0109 QString data = d.simplified(); 0110 0111 if (data.isEmpty()) { 0112 return true; 0113 } 0114 0115 if (m_elements.top() == QLatin1String("title")) { 0116 m_scheme->setSchemeName(data); 0117 } else { 0118 m_flossMap.insert(m_elements.top(), data); 0119 } 0120 0121 if (m_elements.top() == QLatin1String("red") || m_elements.top() == QLatin1String("green") || m_elements.top() == QLatin1String("blue")) { 0122 if (data.toInt() > 255) { 0123 // color value is not valid 0124 m_errorCode = 4; 0125 return false; 0126 } 0127 } 0128 0129 return true; 0130 } 0131 0132 /** 0133 End an element. Reimplemented from QXmlDefaultHandler. 0134 @param namespaceURI not used 0135 @param localName not used 0136 @param qName name of the tag. 0137 @return true if the tag is valid, false otherwise. 0138 */ 0139 bool SchemeParser::endElement(const QString &namespaceURI, const QString &localName, const QString &qName) 0140 { 0141 Q_UNUSED(namespaceURI); 0142 Q_UNUSED(localName); 0143 0144 QString name = qName.simplified(); 0145 QString s = m_elements.pop(); 0146 0147 if (s == name) { 0148 if (name == QLatin1String("floss")) { 0149 if (m_flossMap.contains(QLatin1String("name")) && m_flossMap.contains(QLatin1String("description")) && m_flossMap.contains(QLatin1String("red")) 0150 && m_flossMap.contains(QLatin1String("green")) && m_flossMap.contains(QLatin1String("blue"))) { 0151 m_scheme->addFloss(new Floss( 0152 m_flossMap[QLatin1String("name")], 0153 m_flossMap[QLatin1String("description")], 0154 QColor(m_flossMap[QLatin1String("red")].toInt(), m_flossMap[QLatin1String("green")].toInt(), m_flossMap[QLatin1String("blue")].toInt()))); 0155 m_flossMap.clear(); 0156 } else { 0157 // not all elements defined for a floss 0158 m_errorCode = 1; 0159 } 0160 } 0161 } else 0162 // mismatched tags 0163 { 0164 m_errorCode = 2; 0165 } 0166 0167 if (m_errorCode) { 0168 return false; 0169 } else { 0170 return true; 0171 } 0172 } 0173 0174 /** 0175 Return an error string related to the last error code encountered which is stored in m_errorCode. 0176 @return QString containing the error message. 0177 */ 0178 QString SchemeParser::errorString() const 0179 { 0180 return i18n(errorMessages[m_errorCode]); 0181 }