Results 1 to 4 of 4

Thread: Cloning a QAction object

  1. #1
    Join Date
    Oct 2008
    Location
    Budapest, Hungary
    Posts
    11
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Cloning a QAction object

    Is it possible to clone a QAction object? I would like to reuse a QAction element named actionTrack_Analysis in my example, but its parent object must be altered, so I should like to make a copy of it. For the time being I use this messy code, the important properties of the object are copied manually:

    Qt Code:
    1. QAction action = contextMenu.addAction(actionTrack_Analysis->text(), this, SLOT(on_actionTrack_Analysis_triggered()), actionTrack_Analysis->shortcut());
    2. action->setEnabled(actionTrack_Analysis->isEnabled());
    3. action->setIcon(actionTrack_Analysis->icon());
    4. contextMenu.addAction(action);
    To copy to clipboard, switch view to plain text mode 

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

    Default Re: Cloning a QAction object

    Why do you need to change the parent? It's not possible to copy the action but you can connect one action to another's triggered() signal. You can even connect to its changed() signal to update one action when the other changes (for instance it gets disabled).

    So you can implement a clone action with more or less this:
    Qt Code:
    1. class CloneAction : public QAction {
    2. Q_OBJECT
    3. public:
    4. CloneAction(QAction *original, QObject *parent = 0) : QAction(parent){
    5. connect(original, SIGNAL(changed()), this, SLOT(updateMe())); // update on change
    6. connect(original, SIGNAL(destroyed()), this, SLOT(deleteLater())); // delete on destroyed
    7. connect(original, SIGNAL(triggered()), this, SLOT(trigger())); // trigger on triggered
    8. // repeat with toggled, etc.
    9. // connect the other way round as well if it makes sense - depends if you want one way or two way relation
    10. m_orig = original;
    11. }
    12. private slots:
    13. void updateMe(){
    14. static QStringList props = QStringList() << "text" << "iconText" << "enabled" << ...;
    15. foreach(const QString prop, props)
    16. setProperty(qPrintable(prop), m_orig->property(qPrintable(prop)));
    17. }
    18. private:
    19. QAction *m_orig;
    20. };
    To copy to clipboard, switch view to plain text mode 

    You can build upon it...

  3. #3
    Join Date
    Oct 2008
    Location
    Budapest, Hungary
    Posts
    11
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Cloning a QAction object

    Thanks for your reply. I'm a beginner in QT, I think it is better to describe my original problem. I have an action which is defined in the main menu (created in QTDesigner), but it can also be used from a toolbar and from a context menu of a control. I wish to know that my action is fired from the context menu (or not) because in this case the slot function connected to the action should be worked slightly differently. In fact I do not wish to create a new action element, I prefer using the existing one, but in this case the sender()->parent() is always the MainWindow object in the connected slot function. Therefore I'm forced to make a duplicate of the original action, it must be created in my context menu. Now I can use sender()->parent()->objectName() to distinguish the source object but it's not an elegant solution, at least copying properties is ugly.

    In the example below, actionTrack_Analysis is the original action. Simple addAction(QAction *) is commented out, I have to duplicate the original action and only its important properties are copied.

    Qt Code:
    1. QMenu contextMenu(this);
    2. contextMenu.setObjectName("contextMenu");
    3.  
    4. // unfortunately original actions cannot be used, because we must know
    5. // that the sender object is from contextMenu or MainWindow
    6.  
    7. //contextMenu.addAction(actionTrack_Analysis);
    8. QAction* action = contextMenu.addAction(actionTrack_Analysis->text(), this, SLOT(on_actionTrack_Analysis_triggered()), actionTrack_Analysis->shortcut());
    9. action->setEnabled(actionTrack_Analysis->isEnabled());
    10. action->setIcon(actionTrack_Analysis->icon());
    11. contextMenu.addAction(action);
    To copy to clipboard, switch view to plain text mode 

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

    Default Re: Cloning a QAction object

    Quote Originally Posted by brazso View Post
    Thanks for your reply. I'm a beginner in QT, I think it is better to describe my original problem. I have an action which is defined in the main menu (created in QTDesigner), but it can also be used from a toolbar and from a context menu of a control. I wish to know that my action is fired from the context menu (or not) because in this case the slot function connected to the action should be worked slightly differently. In fact I do not wish to create a new action element, I prefer using the existing one, but in this case the sender()->parent() is always the MainWindow object in the connected slot function.
    If these "actions" do different things (even if they don't differ much), I'd use separate QAction instances.

    Checking if an action was fired from a context menu is relatively easy - you can set a temporary value on the action while building the menu and remove it after the menu is closed, like in the snippet below, but I'd still use separate actions.

    Qt Code:
    1. QAction *someAction = ...;
    2. connect(someAction, SIGNAL(triggered()), ..., SLOT(doSomething()));
    3. //...
    4. QMenu menu;
    5. menu.addAction(someAction);
    6. someAction->setProperty("calledFromContextMenu", true);
    7. //...
    8. menu.exec();
    9. someAction->setProperty("calledFromContextMenu", false);
    10.  
    11. //...
    12.  
    13. void X::doSomething(){
    14. QAction *a = qobject_cast<QAction*>(sender());
    15. if(!a) return;
    16. if(a->property("calledFromContextMenu").toBool()){
    17. // ...
    18. } else {
    19. // ...
    20. }
    21. }
    To copy to clipboard, switch view to plain text mode 

  5. The following user says thank you to wysota for this useful post:

    brazso (6th January 2009)

Similar Threads

  1. Having some QObject problems
    By Barvik in forum Qt Programming
    Replies: 7
    Last Post: 13th November 2008, 04:29
  2. Problem to recover an object via a QAction
    By Potch in forum Qt Programming
    Replies: 2
    Last Post: 4th July 2008, 11:19
  3. QAction signal: want to send int
    By vonCZ in forum Newbie
    Replies: 10
    Last Post: 2nd July 2007, 18:52

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
  •  
Qt is a trademark of The Qt Company.