File indexing completed on 2024-04-21 04:32:14

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 }