summaryrefslogtreecommitdiffstats
path: root/amarok/src/xmlloader.h
blob: bbbf681c68a2412fac14b971e485d236a6f9432a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
  Copyright (c) 2006 Gábor Lehel <illissius@gmail.com>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/


#ifndef AMAROK_XML_LOADER_H
#define AMAROK_XML_LOADER_H

#include <tqevent.h>
#include <tqobject.h>
#include <tqxml.h>
#include "metabundle.h"

/**
 * Used for loading XML of the format outputted by MetaBundle::save(),
 * back into MetaBundle form.
 * There are four ways of using it:
 * - the simplest is to use MetaBundle::XmlLoader::loadBundles(), which just
 *   returns a BundleList of the loaded MetaBundles, to load all the bundles
 *   synchronously in a single shot
 * - you can create a MetaBundle::XmlLoader object and ask it to load(), and
 *   connect to the newBundle() signal to receive the loaded bundles, to load
 *   the bundles synchronously, but one-by-one
 * - you can use MetaBundle::XmlLoader::loadInThread(), and the loaded bundles
 *   will get posted as BundleLoadedEvents to the object you specify; this way
 *   you can load asynchronously
 * - or you can derive from MetaBundle::XmlLoader, reimplement the relevant
 *   functions, and do whatever you want
 */

/** The type used for extra XML attributes not recognized. */
typedef TQValueList< TQPair<TQString, TQString> > XmlAttributeList;


class MetaBundle::XmlLoader: public TQObject, public TQXmlDefaultHandler
{
    Q_OBJECT
  
    public:
        /** Posted when a MetaBundle has been loaded. */
        class BundleLoadedEvent: public TQCustomEvent
        {
            public:
                /** The type() of BundleLoadedEvents. */
                static const int Type = TQEvent::User + 127;

                /** Whether an error occurred. If yes, both bundle and extraAttributes are empty. */
                bool error;

                /** A description of the error, if there was one. */
                TQString errorMessage;

                /** The loaded bundle. */
                MetaBundle bundle;

                /** Any extra attributes not recognized. */
                TQValueList< TQPair<TQString, TQString> > extraAttributes;

            public:
                BundleLoadedEvent( const MetaBundle &b, const XmlAttributeList &a )
                    : TQCustomEvent( Type ), error( false ), bundle( b ), extraAttributes( a ) { }
                BundleLoadedEvent( const TQString &error )
                    : TQCustomEvent( Type ), error( true ), errorMessage( error ) { }
        };

    public:
        /** Construct a MetaBundle::XmlLoader. */
        XmlLoader();

        /** Destruct. */
        virtual ~XmlLoader();

        /**
         * Load bundles from \p source. The loaded bundles will be emitted as
         * newBundle() signals, and if you provide a \p target, also sent as
         * BundleLoadedEvents to \p target. In case of a fatal error,
         * processing will stop and false will be returned, and an empty
         * BundleLoadedEvent with the error flag set will be sent to \p target,
         * if one is provided.
         * @param source the source to load from
         * @param target the target to send events to; if none is provided,
         *               none will be sent
         * @return whether a fatal error occurred
         * @see newBundle
         * @see BundleLoadedEvent
         */
        bool load( TQXmlInputSource *source, TQObject *target = 0 );

        /** Aborts loading. */
        void abort();

        /** Returns the last error encountered; empty if there hasn't been an error. */
        TQString lastError() const;

        /**
         * Load bundles from \p source. If a fatal error occurs, processing
         * will stop and the list of complete bundles at that point will be
         * returned, and \p ok will be set to true, if provided.
         * @param source the source to load from
         * @param ok if provided, will be set to false if a fatal error occurs,
                     and to true otherwise
         * @return the list of loaded bundles
         */
        static BundleList loadBundles( TQXmlInputSource *source, bool *ok = 0 );

        /**
         * Load bundles from \p source in a separate thread. The loaded bundles
         * will be posted as BundleLoadedEvents to \p target. If an error
         * occurs, processing will stop and an empty BundleLoadedEvent will be
         * posted with the error flag set to true.
         * This function returns immediately after being called.
         * @param source the source to load from
         * @param target the object to post BundleLoadedEvents to
         * @see BundleLoadedEvent
         */
        static void loadInThread( TQXmlInputSource *source, TQObject *target );

    signals:
        /**
         * Emitted by load() whenever a MetaBundle has been loaded.
         * @param bundle the loaded MetaBundle
         * @param extraAttributes any extra attributes in the XML not recognized
         */
        void newBundle( const MetaBundle &bundle, const XmlAttributeList &extraAttributes );

        /** Emitted when an error occurs. */
        void error( const TQString &errorMessage );

    protected:
        virtual void newAttribute( const TQString &key, const TQString &value );
        virtual void newTag( const TQString &name, const TQString &value );
        virtual void bundleLoaded();
        virtual void errorEncountered( const TQString &message, int line, int column );

    protected:
        /** The bundle currently being loaded. */
        MetaBundle m_bundle;

        /** Unrecognized attributes in the XML for the currently loading bundle. */
        XmlAttributeList m_attributes;

        /** The message from the last error encountered, empty if there hasn't been an error. */
        TQString m_lastError;

        /** Whether we have been abort()ed. */
        bool m_aborted;

    private:
        TQXmlSimpleReader m_reader;
        TQString m_currentElement;
        TQObject *m_target;

    protected:
        virtual bool startElement( const TQString&, const TQString&, const TQString &, const TQXmlAttributes& );
        virtual bool endElement( const TQString &namespaceURI, const TQString &localName, const TQString &qName );
        virtual bool characters( const TQString &ch );
        virtual bool endDocument();
        virtual bool fatalError( const TQXmlParseException &exception );

    public: //these should be private
        class ThreadedLoader;
        class SimpleLoader;
};


#endif