16.2.2. Importing Objects with an Abstract Factory

[ fromfile: memento.xml id: importing ]

[Caution]Prerequisites

Example 16.12. src/libs/dataobjects/qobjectreader.h

[ . . . . ]
#include "dobjs_export.h"
#include <QString>
#include <QStack>
#include <QQueue>
#include <QXmlDefaultHandler>

class AbstractFactory;
class DOBJS_EXPORT  QObjectReader : public QXmlDefaultHandler {
  public:
    explicit QObjectReader (AbstractFactory* factory=0) : 
                         m_Factory(factory), m_Current(0) { }
    explicit QObjectReader (QString filename, AbstractFactory* factory=0);
    void parse(QString text);
    void parseFile(QString filename);
    QObject* getRoot();
    ~QObjectReader();

    // callback methods from QXmlDefaultHandler
    bool startElement( const QString& namespaceURI,
                       const QString& name,
                       const QString& qualifiedName,
                       const QXmlAttributes& attributes );
    bool endElement(  const QString& namespaceURI,
                      const QString& localName,
                      const QString& qualifiedName);
    bool endDocument();
  private:
    void addCurrentToQueue();
    AbstractFactory* m_Factory;
    QObject* m_Current;
    QQueue<QObject*> m_ObjectList;
    QStack<QObject*> m_ParentStack;
};
[ . . . . ]

Figure 16.3. QObjectReader and Its Related Classes

QObjectReader and Its Related Classes

Example 16.13. src/xml/propchildren/customerlist.xml

<object class="CustomerList" name="Customers" >

   <object class="Customer" name="Simon" >
     <property name="Name" type="QString" value="Simon" />
     <property name="Date" type="QDate" value="1963-11-22" />
     <property name="LuckyNumber" type="int" value="834" />
     <property name="State" type="QString" value="WA" />
     <property name="Zip" type="QString" value="12345" />
     <property name="FavoriteFood" type="QString" value="Donuts" />
     <property name="FavoriteDrink" type="QString" value="YooHoo"/>
   </object>


   <object class="Customer" name="Raja" >
     <property name="Name" type="QString" value="Raja" />
     <property name="Date" type="QDate" value="1969-06-15" />
     <property name="LuckyNumber" type="int" value="62" />
     <property name="State" type="QString" value="AZ" />
     <property name="Zip" type="QString" value="54321" />
     <property name="FavoriteFood" type="QString" value="Mushrooms" />
     <property name="FavoriteDrink" type="QString" value="Jolt" />
   </object>

</object>

Example 16.14. src/libs/dataobjects/qobjectreader.cpp

[ . . . . ]

bool QObjectReader::startElement( const QString&,
     const QString& elementName, const QString&,
     const QXmlAttributes& atts) {              1
    if (elementName == "object") {
        if (m_Current != 0)                     2
            m_ParentStack.push(m_Current);      3
        QString classname = atts.value("class");
        QString instancename = atts.value("name");
        m_Current = m_Factory->newObject(classname);
        m_Current->setObjectName(instancename);
        if (!m_ParentStack.empty()) {           4           
            m_Current->setParent(m_ParentStack.top());
        }
        return true;
    }
    if (elementName == "property") {
        QString fieldType = atts.value("type");
        QString fieldName = atts.value("name");
        QString fieldValue = atts.value("value");
        QVariant qv = QVariant(fieldValue);
        m_Current->setProperty(fieldName.toAscii(), qv);

    }
    return true;
}

1

No need to name unused parameters.

2

If already inside a <object>,

3

push previous current onto stack.

4

Top of parentstack, or previous current, should be my parent.


Example 16.15. src/libs/dataobjects/qobjectreader.cpp

[ . . . . ]

bool QObjectReader::endElement( const QString& ,
                            const QString& elementName,
                            const QString& ) {
    if (elementName == "object") {
        if (!m_ParentStack.empty())
            m_Current = m_ParentStack.pop();
        else {
            addCurrentToQueue();
        }
    }
    return true;
}