PDA

View Full Version : How does qdesigner save non-QObject, such as QRect?



lni
15th January 2009, 16:33
Hi,

I are trying to understand how QRect is saved by qdesigner. It is not a QObject, how does it know the properties of the QRect? and how it can restore those properties?

Thanks

aamer4yu
15th January 2009, 17:46
Have a look at the .ui file . Open in some editor, or notepad.
You will get the idea (hint :xml )

lni
15th January 2009, 18:21
Have a look at the .ui file . Open in some editor, or notepad.
You will get the idea (hint :xml )

I have read those files...

My questions is when designer saves a QRect object, how does it know that QRect has x, y, width and height properties? It is not an QObject, it has no Q_PROPERTY. Nothing in QRect class tell outside about its properties...

I could have a MyRect that has x1, x2, y1, y2, will qdesigner save it if I create MyRect class the same way as QRect?

Somewhere and somehow, x/y/width/height in QRect must be hard-coded in qdesigner for QRect to be saved and restored, I look at QVariant source and didn't find useful hint either.

lni
15th January 2009, 20:49
Ok, I found a DomRect at tools/designer/src/lib/uilib/ui4_p.h

But why clone the member field of QRect in DomRect?

Why not do like



class DomRect {

...
inline int elementX() const { return rect.x();}
void setElementX(int a) {
m_children |= X;
rect.setX( a );
}
...

private:

QRect rect;
};



More over, from what I see, for every data object class, I have to have a Dom class to come with it? That is like double work load...

I have been looking for a generic Dom that works for all data object, which does not have to derive from QObject...

Well, I think Qt could provide a template schema class in this case, such as
schema.addSchemaItem<T>( tag, obj, readMemberFunction, writeMemberFunction...)

Can this be achived?

Brandybuck
15th January 2009, 22:26
Designer doesn't save QRect objects, it only works on QWidgets and some closely related classes.

wysota
16th January 2009, 09:22
Designer might have used QDataStream to serialize all the objects, but its creators wanted the file format (ui) to be based on XML and not an internal format thus they had to provide operators for storing properties of those data objects in XML, hence the doubled work.

lni
16th January 2009, 16:39
Designer might have used QDataStream to serialize all the objects, but its creators wanted the file format (ui) to be based on XML and not an internal format thus they had to provide operators for storing properties of those data objects in XML, hence the doubled work.

Sure, but I think if Qt provide some light-weighted base class for savable object and some Xml schemas, then we could reuse some of designer's codes. And designer itself could have a better looking parser. This would reduce a lot of code redundancy.

For instance



class QSavableClass {
public:

virtual ~QSavableClass();
};

class QXmlSchemaBase {

}

template <class Type>
class QXmlSchemaItem : public QXmlSchemaBase {
public:
typedef const Type& (QSavableClass::*Getter)() const;
typedef void (QSavableClass::*Setter)( const Type& );

QXmlSchemaItem( const QString& tag, QSavableClass& obj, Getter, Setter );

};

class QXmlSchema : public QXmlSchemaBase {

template <typename T>
void addSchemeItem( const QXmlSchemaItem& );

void addScheme( const QXmlSchema& );

};

Now it becomes easier for me:

class MyClass : public QSavableClass {
public:

const QString& str() const {
return _str;
}

void setString( const QString& str ) {
_str = str;
}

private:

QString _str;
}

I can now create a schema for MyClass by deriving from QXmlSchema and add the schema items accordingly, and much of the designer codes can be re-used and simplified...Any comments?

Also, looking at DomUI, I wonder why it has to parse the entire content first and then create the objects. Can we populate the objects while parsing the file? Is there a particular reason for what has been done in qdesigner's parser?

wysota
16th January 2009, 18:15
Sure, but I think if Qt provide some light-weighted base class for savable object and some Xml schemas, then we could reuse some of designer's codes. And designer itself could have a better looking parser. This would reduce a lot of code redundancy.
You can't expect to snap your fingers and classes to emerge magically from the vastness of the Universe. There is a class developed for serializing QObject properties as XML but it's not part of Qt. There is nothing that should prevent you from developing your own set of classes and share it with others but it seems that Qt developers have different goals right now.

Now it becomes easier for me:


class MyClass : public QSavableClass {
public:

const QString& str() const {
return _str;
}

void setString( const QString& str ) {
_str = str;
}

private:

QString _str;
}

Yeah, but then every class would have to be derived from QSavableClass which immediately loses the point of having such class.


Also, looking at DomUI, I wonder why it has to parse the entire content first and then create the objects.
That's how DOM works.


Can we populate the objects while parsing the file? Is there a particular reason for what has been done in qdesigner's parser?
Yes, but not using DOM. What's wrong with creating objects when the whole tree is ready anyway? UI files are quite short, so performance is not an issue here.

lni
16th January 2009, 22:40
share it with others

I am in no way to be good at XML things, that is why I need help...

But I think perhaps we can make it better by having some base classes. I am trying to develop a shared object system, each object will have a unique object name to identify it. So a base class containing name is reasonable.

In the example attached, I am having trouble to handle Tool within Modeling object. Can someone find a better solution by telling Modeling::tool and Modeling::setTool methods to the schema?

Thanks

wysota
17th January 2009, 00:43
But I think perhaps we can make it better by having some base classes.
Base classes are bad. They are opposite of "fast" :)


I am trying to develop a shared object system, each object will have a unique object name to identify it. So a base class containing name is reasonable.
Just don't reinvent the wheel.


In the example attached, I am having trouble to handle Tool within Modeling object. Can someone find a better solution by telling Modeling::tool and Modeling::setTool methods to the schema?

How about writing a proper serialization mechanism using QXmlStreamReader and QXmlStreamWriter?

There are some design patterns you might use to get a neat solution.

lni
17th January 2009, 01:21
How about writing a proper serialization mechanism using QXmlStreamReader and QXmlStreamWriter?

There are some design patterns you might use to get a neat solution.

I would very much appreciate If you can point me to some better solution, I am really struggling with XML things.

Basically, I have a list of classes that contain QExplicitlySharedDataPointer. Some of the objects may be shared by several other objects. Objects are identified by name, so the requirements are that each object will have a unique name. Those objects are stored in a dictionary (a singleton dictionary global to the application), with its name as lookup key.

I need to save the objects in the dictionary, keep the object sharing information, and I need to restore them at a later time.

The requirements are almost the same as qdesigner, except I need shareable objects.

Are you saying that the current method in qdesigner to save/restore ui file is the right way, that each class needs to have a corresponding Dom class, and the Dom class needs to have all the properties that the class has? It seems too much work in there. The example I have only requires a very light-weight base class, and there won't be more than a few hundreds of such objects in an application...

wysota
17th January 2009, 09:06
I didn't say what is the right or the wrong way of doing things. I said there is nothing wrong in the way Designer saves forms to a file. As I said, there are some design patterns you might use to delegate serialization from some external object to some other object (like the serialized class itself). If you want things to be fast, I'd advise against using XML. I'd use QDataStream instead. All you need to do then is to implement operator<< and operator>> between your class and QDataStream. See docs for details.