File indexing completed on 2025-01-05 03:59:10

0001 /*
0002     SPDX-FileCopyrightText: 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #ifndef MARBLE_GEOPARSER_H
0007 #define MARBLE_GEOPARSER_H
0008 
0009 #include <QString>
0010 #include <QPair>
0011 #include <QStack>
0012 #include <QXmlStreamReader>
0013 
0014 #include "digikam_export.h"
0015 
0016 namespace Marble
0017 {
0018 
0019 using GeoDataGenericSourceType = int;
0020 
0021 class GeoDocument;
0022 class GeoNode;
0023 class GeoStackItem;
0024 
0025 class DIGIKAM_EXPORT GeoParser : public QXmlStreamReader
0026 {
0027  public:
0028     typedef QPair<QString, QString> QualifiedName; // Tag Name & Namespace pair
0029 
0030     explicit GeoParser( GeoDataGenericSourceType sourceType );
0031     virtual ~GeoParser();
0032 
0033     /**
0034      * @brief Main API for reading the XML document.
0035      * This is the only method that is necessary to call to start the GeoParser.
0036      * To retrieve the resulting data see @see releaseDocument() and
0037      * @see releaseModel()
0038      */
0039     bool read( QIODevice* );
0040 
0041     /**
0042      * @brief retrieve the parsed document and reset the parser
0043      * If parsing was successful, retrieve the resulting document
0044      * and set the contained m_document pointer to 0.
0045      */
0046     GeoDocument* releaseDocument();
0047     GeoDocument* activeDocument() { return m_document; }
0048 
0049     // Used by tag handlers, to be overridden by GeoDataParser/GeoSceneParser
0050     virtual bool isValidElement( const QString& tagName ) const;
0051 
0052     // Used by tag handlers, to access a parent element's associated GeoStackItem
0053     GeoStackItem parentElement( unsigned int depth = 0 ) const;
0054 
0055     // Used by tag handlers, to Q_EMIT a warning while parsing
0056     void raiseWarning( const QString& );
0057 
0058     // Used by tag handlers, to retrieve the value for an attribute of the currently parsed element
0059     QString attribute( const char* attributeName ) const;
0060 
0061 protected:
0062     /**
0063      * This method is intended to check if the current element being served by
0064      * the GeoParser is a valid Document Root element. This method is to be
0065      * implemented by GeoDataParser/GeoSceneParser and must check based on the
0066      * current XML Document type, e.g. KML, GPX etc.
0067      * @return @c true if the element is a valid document root.
0068      */
0069     virtual bool isValidRootElement() = 0;
0070 
0071     virtual GeoDocument* createDocument() const = 0;
0072 
0073 protected:
0074     GeoDocument* m_document;
0075     GeoDataGenericSourceType m_source;
0076 
0077 private:
0078     void parseDocument();
0079     QStack<GeoStackItem> m_nodeStack;
0080 };
0081 
0082 class GeoStackItem
0083 {
0084  public:
0085     GeoStackItem()
0086         : m_qualifiedName(),
0087           m_node( nullptr )
0088     {
0089     }
0090 
0091     GeoStackItem( const GeoParser::QualifiedName& qualifiedName, GeoNode* node )
0092         : m_qualifiedName( qualifiedName ),
0093           m_node( node )
0094     {
0095     }
0096 
0097     // Fast path for tag handlers
0098     bool represents( const char* tagName ) const
0099     {
0100         return m_node && (QString::fromUtf8(tagName) == m_qualifiedName.first);
0101     }
0102 
0103     // Helper for tag handlers. Does NOT guard against miscasting. Use with care.
0104     template<class T>
0105     T* nodeAs()
0106     {
0107         Q_ASSERT( dynamic_cast<T*>( m_node ) != nullptr );
0108         return static_cast<T*>(m_node);
0109     }
0110 
0111     template<class T>
0112     bool is() const
0113     {
0114         return nullptr != dynamic_cast<T*>(m_node);
0115     }
0116 
0117     GeoParser::QualifiedName qualifiedName() const { return m_qualifiedName; }
0118     GeoNode* associatedNode() const { return m_node; }
0119 
0120 private:
0121     friend class GeoParser;
0122     void assignNode( GeoNode* node ) { m_node = node; }
0123     GeoParser::QualifiedName m_qualifiedName;
0124     GeoNode* m_node;
0125 };
0126 
0127 }
0128 
0129 #endif