PDA

View Full Version : How to cast QObject to custom QWidget in abstract factory pattern?



remizero
19th February 2015, 17:25
Hi all, Have a nice day.

I am new to the forum and is my first post, I reviewed most of this forum and the web and not get anything definitive to help me understand the problem I am waiting here can help me as I often they have done in other post for other people.

I am trying to apply the abstract factory pattern to create a series of modules that require to an application I'm developing.

I have taken an example from the book An Introduction to Design Patterns in C ++ With Qt (Prentice Hall-2011-2nd Edition) page 483, paragraph 16.1.1 Abstract Factory
Chapter 16, as well as, I read on the website of some other examples and
I have the following code to do what I need.



typedef QHash<QString, QMetaObject> T_Modules;

T_Modules modulesTypesList () {

T_Modules hash;

hash [ "LibraryGui" ] = LibraryGui::staticMetaObject;
hash [ "ConvertGui" ] = ConvertGui::staticMetaObject;
hash [ "BurnGui" ] = BurnGui::staticMetaObject;
hash [ "PlaylistGui" ] = PlaylistGui::staticMetaObject;
hash [ "PlayingGui" ] = PlayingGui::staticMetaObject;

return hash;
}

Module *ModulesFactory::createModule ( QString className, QWidget *parent ) {

T_Modules modulesType = modulesTypesList ();

Module *moduleCreated = 0;

if ( modulesType.contains ( className ) ) {

const QMetaObject& metaObjectClass = modulesType [ className ];
moduleCreated = qobject_cast<Module *> ( metaObjectClass.newInstance () );

if ( moduleCreated == 0 ) {

qDebug () << "Error creating " << className;
abort ();

} else if ( parent != 0 ) {

moduleCreated->setParent ( parent );
}
} else {

qDebug () << "Error creating " << className;
abort ();
}
return moduleCreated;
}


In theory everything is fine (compiles complete), but when running, it generates the
following error:



Starting /home/remizero/Proyectos/Qt/rockola/build-rockola-Desktop-Debug/rockola...
Error creating "LibraryGui"
The program has unexpectedly finished.
/home/remizero/Proyectos/Qt/rockola/build-rockola-Desktop-Debug/rockola crashed


Of course, not a bug properly, the detail is that I did not create the object (send to abort to avoid having to close the application and to debug faster; p)

My question is, What am I doing wrong trying to create object of type Module? on line 25


moduleCreated = qobject_cast<Module *> ( metaObjectClass.newInstance () );

I'm working with QtCreator 3.2.1, Qt 5.3.2, gcc 4.9.1 32bit

If you need a compilable example, I'll have to pass on the project with a minimum of 20 files and tell the file in question to go directly.

Sorry for my bad English.

Thanks in advance.

wysota
19th February 2015, 17:49
Does your class inherit Module? Does Module have a Q_OBJECT macro? Does newInstance() return a valid pointer?

remizero
21st February 2015, 03:16
Goodnight wysota. Thanks for responding so quickly.

Yes, my class inherits from Module and also has the Q_OBJECT macro. newInstance() returned a pointer to 0, which was driving me crazy lol.

Reviewing some structure in my class LibraryGui, the error had it in the constructor of the class, because I was missing the macro Q_INVOKABLE, which did not recognize the constructor, but still was still presenting another error is that the constructor required parameters and that I solved using the macro Q_ARG (MyObject * myArg), leaving my code section as follows:



typedef QHash<QString, QMetaObject> T_Modules;

T_Modules modulesTypesList () {

T_Modules hash;

hash [ "LibraryGui" ] = LibraryGui::staticMetaObject;
hash [ "ConvertGui" ] = ConvertGui::staticMetaObject;
hash [ "BurnGui" ] = BurnGui::staticMetaObject;
hash [ "PlaylistGui" ] = PlaylistGui::staticMetaObject;
hash [ "PlayingGui" ] = PlayingGui::staticMetaObject;

return hash;
}

Module *ModulesFactory::createModule ( QString className, QWidget *parent ) {

T_Modules modulesType = modulesTypesList ();

Module *moduleCreated = 0;

if ( modulesType.contains ( className ) ) {

const QMetaObject& metaObjectClass = modulesType [ className ];
moduleCreated = qobject_cast<QAction *> ( metaObjectClass.newInstance ( Q_ARG ( QWidget*, parent ) ) );

if ( moduleCreated == 0 ) {

qDebug () << "Error creating " << className;
abort ();

} else if ( parent != 0 ) {

moduleCreated->setParent ( parent );
}
} else {

qDebug () << "Error creating " << className;
abort ();
}
return moduleCreated;
}


And in my class LibraryGui, which inherits from Module, is as follows:



class LibraryGui : public Module {

Q_OBJECT

public:
Q_INVOKABLE explicit LibraryGui ( QWidget *parent = 0 );
...
}


Thank you very much for your questions because I did check with my code more carefully.

So I close this thread.

Thank you very much again and hope that this error is a reminder to other programmers colleagues.

PS: I do not get as placing "solved" in the title of the post :(