Results 1 to 11 of 11

Thread: add signal/slots at runtime?

  1. #1
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default add signal/slots at runtime?

    In Lumina http://lumina.sourceforge.net I have a QObject based tree that represents the (virtual) world.
    The main design problem is that subobject require always simple generator function/slots like addChildFoo(....) that are used by the contextmenu and scripting.

    It would be much better if the child object could be registerd without these additional functions. That won't be a problem with some abused c++ code like that:

    Qt Code:
    1. class A{
    2. static bool v;
    3. public:
    4. A(){
    5. std::cout << "Constructor" << v << std::endl;
    6. }
    7. static bool init(){
    8. std::cout << "init class A" << std::endl;
    9. return true;
    10. }
    11. };
    12.  
    13. bool A::v = A::init();
    14.  
    15. int main(int argc, char **argv){
    16. return 0; // do nothing, not really
    17. }
    To copy to clipboard, switch view to plain text mode 

    A::init() is called before any regular code will be executed. It won't be a problem to use that mechanism, to register that class on a parent class (really class because no object exist at that time).

    Now it would be possible that the parent class has a registered QAction (for a context menu entry) But there is a small issue left:
    Either the QAction will be connected with a childclasses create function: Any information about the activating objects get lost.
    Or the QAction have to be connected to the activating objects slot: Unfortunately it's also impossible to determine the right QAction, but with QAction derivated class (which knows the activating and child object) it should be solvable.

    Without scripting the dynamic glueing at startup is possible, but now theres the scripting problem: It isn't possible to call the non existend slots anymore....
    on e solution could be a generic create()....) slot that takes a class name as first argument, but that won't be ideal.
    Another problem are objects extended by scripts, there isn't a interfact to a scripted member function....

    The ideal solution would be a proxy slot / signal system, where a proxy could be created by with a signature like "slotname(argumenttype,.....)" and always it's activated a matching signal with the signature "slotname_sig(QObject*, argumenttype,.....)" will be emit.

    In that case the setup would look like:

    * child class registers its QAction contextmenu entry at parent class
    * child class registers also a proxy slot+signal at parent class
    * main() will be executed
    * a new parent class will be created:
    * a own instance of the registered QAction will be created (copy) and connected to that proxy slot.

    if the context menu is triggered it will call the proxy slot that add the objects pointer to the arguments, so that the createChild slot can be called without problems.
    A script function would also be able to call that proxy slot. that acts like a true memberfunction. Although it may handled by something unknown :P

    The only problem is the implementation, because the moc has to modified to add that functionality.....

  2. #2
    Join Date
    May 2006
    Posts
    788
    Thanks
    49
    Thanked 48 Times in 46 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: add signal/slots at runtime?

    To store QAction as static .. to use alround on code i use this piece of code....
    but you must register on Q_OBJECT class to tell moc

    Qt Code:
    1. typedef enum {
    2. ID_NONE = 0,
    3. WEB_PAGE_ACTUAL = 1000,
    4. ID_ABOUT_QT = 1403
    5. } CommandID;
    6.  
    7.  
    8. struct Command {
    9. Command() {
    10. id = ID_NONE;
    11. }
    12. Command(CommandID Id, QString Name, QIcon Icon, QKeySequence Seq, QObject* Reciever, const QString& Slot) {
    13. id = Id;
    14. name = Name;
    15. icon = Icon;
    16. shortcut = Seq;
    17. reciever = Reciever;
    18. slot = Slot;
    19. }
    20.  
    21. CommandID id;
    22. QString name;
    23. QIcon icon;
    24. QKeySequence shortcut;
    25. QObject* reciever;
    26. QString slot;
    27. };
    28.  
    29. class CommandStorage {
    30. public:
    31. static CommandStorage* instance();
    32.  
    33. void registerCommand(const Command&);
    34. QAction* action(CommandID);
    35. inline void clear() { cmds_.clear(); }
    36.  
    37. private:
    38. CommandStorage() { }
    39. static CommandStorage* st_;
    40. QMap<CommandID, QAction*> cmds_;
    41. };
    42.  
    43.  
    44.  
    45.  
    46. #include <QtGui/QAction>
    47.  
    48. CommandStorage* CommandStorage::instance() {
    49. if (st_ == 0)
    50. st_ = new CommandStorage();
    51.  
    52. return st_;
    53. }
    54.  
    55. void CommandStorage::registerCommand(const Command& cmd) {
    56. CommandID id = cmd.id;
    57.  
    58. if (cmds_.contains(id))
    59. delete cmds_[id];
    60.  
    61. QString keya = QString(); /* not Shortcut */
    62. if (!cmd.shortcut.isEmpty()) {
    63. keya = QString(" ") + cmd.shortcut.toString(QKeySequence::NativeText);
    64. }
    65. QAction* action = new QAction(cmd.icon, cmd.name + keya, 0);
    66. action->setShortcut(cmd.shortcut);
    67. action->setData(id);
    68. action->setIcon(cmd.icon);
    69. QObject::connect(action, SIGNAL(triggered()), cmd.reciever, qPrintable(cmd.slot));
    70. cmds_[id] = action;
    71. }
    72.  
    73. QAction* CommandStorage::action(CommandID id) {
    74. return cmds_[id];
    75. }
    76.  
    77. CommandStorage* CommandStorage::st_ = 0;
    To copy to clipboard, switch view to plain text mode 

    register:

    Qt Code:
    1. void PageEdit::createCommands()
    2. {
    3. CommandStorage* st = CommandStorage::instance(); /* new or exist? */
    4. st->clear(); /* clear old command !!! or replace reciver....
    5.   CommandID id is on data from qaction ... to distinct its
    6.   */
    7. Command cmds[] = {
    8. Command(NEW_LAYER_AUTO,tr("New flow text Layer"),QIcon(":/img/view_remove.png"),QKeySequence("F9"),ViewPanel, SLOT(NewLayer())),
    9. Command(NEW_LAYER_ABS,tr("New absolute Layer"),QIcon(":/img/view_sidetree.png"),QKeySequence("F10"),ViewPanel, SLOT(NewLayer())),
    10. Command()
    11. };
    12. for (unsigned i = 0; cmds[i].id != 0; i++) {
    13. Command& cmd = cmds[i];
    14. if (st->action(cmd.id) == 0) {
    15. st->registerCommand(cmds[i]);
    16. }
    17. else {
    18. st->action(cmd.id)->setIcon(cmd.icon);
    19. }
    20. }
    21. }
    To copy to clipboard, switch view to plain text mode 


    append on a toolbar after toolbar-clear() or compose qmenu at live time....

    Qt Code:
    1. CommandID viewMenu[] = { NEW_LAYER_AUTO , NEW_LAYER_ABS, NEW_LAYER_OOO , PRINT_CURRENT , SAVE_PAGE, OPEN_PAGE , CLEAR_PAGE , PASTE_LAYER , ID_NONE };
    2.  
    3.  
    4. for (int j = 0; viewMenu[j] != ID_NONE; j++) {
    5. CommandID id = viewMenu[j];
    6. QAction* a_1 = CommandStorage::instance()->action(id);
    7. if (a_1) {
    8. toolBar_save->addAction ( a_1 );
    9. }
    10. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: add signal/slots at runtime?

    I haven't read your whole post (sorry, I currently can't focus myself to read a larger chunk of text), but based on what I understand I'd like to suggest using one of two solutions:

    1. a dirty hack to monitor widgets that currently have focus (you do that through the application object) and remember which of the wanted widgets had focus last time and assume the action came from the last widget

    2. subclass QAction and equip it with a custom signal emitting a pointer or identifier with the triggered signal. Then allow registration of objects within it and write a modified handler for the context menu so that it sets an "active" object with those actions and when the action is chosen, it emits the triggered signal with the proper pointer/identifier. A mockup could be:
    Qt Code:
    1. void ...::customContextMenuHandler(){
    2. QList<QAction*> actList = actions();
    3. QMenu menu;
    4. foreach(QAction *act, actList){
    5. MyAction *myact = qobject_cast<MyAction*>(act);
    6. if(myact==0) continue;
    7. myact->setActiveObject("xyz"/this/7/whatever);
    8. menu.addAction(myact);
    9. }
    10. if(menu.actions().count()>0) menu.exec(QCursor::pos());
    11. // reset the current object
    12. foreach(QAction *act, menu.actions()){
    13. MyAction *myact = qobject_cast<MyAction*>(act);
    14. if(myact==0) continue;
    15. myact->setActiveObject(0/whatever);
    16. }
    17. }
    To copy to clipboard, switch view to plain text mode 

    The action class should emit the custom signal upon its own triggered() signal.
    Last edited by wysota; 25th June 2008 at 15:11. Reason: Missing tag

  4. #4
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: add signal/slots at runtime?

    There are several QAction based versions possible, but it won't fix the non existent slots, that are required for the scripting. And using a generic call function that takes the function name as first and the arguments as second argument is ugly. I'm using something like this for calling functions in other scripts, but there are many problems with the return values....

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: add signal/slots at runtime?

    Creating slots and signals on the fly is possible, but they won't allow scripting, so I don't think it would fix your problem.

  6. #6
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: add signal/slots at runtime?

    Why not? Where can i find information about creating signal slots on the fly (at runtime) ?

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: add signal/slots at runtime?


  8. #8
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: add signal/slots at runtime?

    That looks interresting. But it think the optimal solution would be a templateclass, that creates a dynamic qobject from a qobject.

  9. #9
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: add signal/slots at runtime?

    It looks like my template based class is working

    It uses a dynamic meta object class that is derived from QMetaObject and has some functions to manipulate the internal data, so that the new slots are visible for QtScript

    With some more code it should be possible to patch/extend a class with scripts. Unfortunately it's no possible to clone a class to use it with different extensions.... but maybe the static metaobject could be replaced by a own for each object.

  10. #10
    Join Date
    May 2007
    Posts
    15
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: add signal/slots at runtime?

    The DQObject system is working In the next days I 'll release a new version of Lumina that will used that technique as core feature.

    The current implementation is able to create dynamic slots combined with a callback function to handle the slot call. (Using the Qt Signal Slot system wouldn't work with static slots, because it uses a virtual function for processing the meta calls)

    For scripting the new dynamic slots are like the usual ones, the can use any metatypes as argument and return value.

    Maybee I'll will release the framework as a own project too.... ( If anyone is interrested )

  11. #11
    Join Date
    Jun 2009
    Posts
    5
    Thanks
    1
    Thanked 2 Times in 1 Post
    Platforms
    Unix/X11 Windows

    Default Re: add signal/slots at runtime?

    I'd be very interested in seeing any code!

Similar Threads

  1. Which runtime libs are allowed by Qt? (vc++7.1)
    By gri in forum Installation and Deployment
    Replies: 5
    Last Post: 2nd October 2007, 10:51
  2. Replies: 5
    Last Post: 21st February 2007, 22:11
  3. Replies: 3
    Last Post: 16th November 2006, 12:24
  4. QSA: loading scripts at runtime
    By seneca in forum Qt Programming
    Replies: 0
    Last Post: 15th February 2006, 15:19
  5. runtime libraries?
    By fwohlfert in forum Newbie
    Replies: 1
    Last Post: 5th January 2006, 18:12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.