Getting QMetaMethod of slot member function to connect "later"



  • Hi. I have a class that I want to use as a container to hold the receiver and the slot method of a class. So that later the first class instance will pass as a parameter to a function that will make the final connect, using whatever sender and signal to the stored receiver and slot. I am not sure how could I store the address of a member method (a slot) from a class to a QMetaMethod object to later use the overload connect method.

    At the moment I am managing to do so by making the class to be a templated class, but then the signature gets a little weird to pass the parameters, and I would simplify it as the connect method from QObject.

    Thanks a lot!

    Regards,

    David.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Can you show some pseudo code to explain what you would like to achieve ?



  • I want to refactor from THIS:

    
    class ManageUserWorkflow : public QObject
    {
        Q_OBJECT;
    	enum WorkflowStep {
    		WS_STEP_1,
    		WS_STEP_2,
    		WS_STEP_3
    	}
    	enum Action {
    		A_OK,
    		A_CANCEL,
    		A_RETRY
    	}
    public:
        ManageUserWorkflow(){};
    public slot:
        void ActionHandler(){ // do Handle code }
    	FooterController* createFooter(const QList<Action>& actions)
    	{
    		FooterController* fc = new FooterController();
    		for( int i = 0; i < actionList.size(); ++i)
    		{
    			Button* b = new Button(actions.at(i));
    			connect(button, &Button::clicked, this, &ManageUserWorkflow::ActionHandler);
    			fc->addButton(b);
    		}
    	}
        DialogController* createDialog(WorkflowStep step) {
    		
    		QList<Action> actions;
            switch( step ) {
                case WS_STEP_1:
    			{
    				dialog = new DialogController("A");
    				actions << A_OK;
    				break;
    			}
                case WS_STEP_2:
    			{
    				dialog = new DialogController("B");
    				actions << A_OK;
    				actions << A_CANCEL;
    				break;
    			}
                case WS_STEP_2:
    			{
    				dialog = new DialogController("C");
    				actions << A_RETRY;
    				actions << A_CANCEL;
    				break;
    			}
            }
    		
    		FooterController footer = new FooterController(actions);
    		dialog->setFooter( footer );
        }
    }
    
    

    to THIS:

    class WorkflowDialogCreator : public QObject
    {
        Q_OBJECT;
    public:
        WorkflowDialogCreator(){};
    
    	FooterController* createFooter(const QList<Action>& actions, const QList<QPair<QObject*, QMetaMethod*>> actionHandlers)
    	{
    		FooterController* fc = new FooterController();
    		for( int i = 0; i < actionList.size(); ++i)
    		{
    			Button* b = new Button(actions.at(i));
    			connect(button, &Button::clicked, actionHandlers.at(i).first, actionHandlers.at(i).first.second);
    			fc->addButton(b);
    		}
    	}
    }
    
    class ManageUserWorkflow : public QObject
        Q_OBJECT;
    	enum WorkflowStep {
    		WS_STEP_1,
    		WS_STEP_2,
    		WS_STEP_3
    	}
    	enum Action {
    		A_OK,
    		A_CANCEL,
    		A_RETRY
    	}
    public:
        ManageUserWorkflow(WorkflowDialogCreator* dc) :
    	dc_(dc){};
    public slot:
        void ActionHandler(){ // do Handle code }
    	FooterController* createFooter(const QList<Action>& actions)
    	{
    		FooterController* fc = new FooterController();
    		for( int i = 0; i < actionList.size(); ++i)
    		{
    			Button* b = new Button(actions.at(i));
    			connect(button, &Button::clicked, this, &ManageUserWorkflow::ActionHandler);
    			fc->addButton(b);
    		}
    	}
        DialogController* createDialog(WorkflowStep step) {
    		
    		QList<Action> actions;
    		QList<QPair<QObject*, QMetaMethod*>> actionHandlers
            switch( step ) {
                case WS_STEP_1:
    			{
    				dialog = new DialogController("A");
    				actions << A_OK;
    				actionHandlers << QPair(this, &ManageUserWorkflow::ActionHandler);
    				break;
    			}
                case WS_STEP_2:
    			{
    				dialog = new DialogController("B");
    				actions << A_OK;
    				actions << A_CANCEL;
    				actionHandlers << QPair(this, &ManageUserWorkflow::ActionHandler);
    				actionHandlers << QPair(this, &ManageUserWorkflow::ActionHandler);
    				break;
    			}
                case WS_STEP_2:
    			{
    				dialog = new DialogController("C");
    				actions << A_RETRY;
    				actions << A_CANCEL;
    				actionHandlers << QPair(this, &ManageUserWorkflow::ActionHandler);
    				actionHandlers << QPair(this, &ManageUserWorkflow::ActionHandler);
    				break;
    			}
            }
    		
    		FooterController footer = dc_.createFooter(actions, actionHandlers);
    		dialog->setFooter( footer );
        }
    	
    	WorkflowDialogCreator* dc_;
    }
    

    Please forget constant correctness and other things. I made it fast in purpose. Also take into account this is a simplification of what the real code is.



  • The most similar solution of what I think I need found it here:
    https://stackoverflow.com/questions/31836199/how-to-store-qt-signal-slot-names-to-a-data-structure


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.