3
votes

I am building a program with a largely sequential flow but also some alternative paths. I thought that a state machine might be the simplest way of implementing this since Qt provides such a class: QStateMachine (also see API).

However, I seem to have quite a number of states (20+). Also, I have a number of different transition events (let's say buttons 1-10). So e.g. pressing button x would cause a transition of state 13 to 14.

Entering or leaving each state should be able to execute specific functions with parameters, and while each state emits such signals, it is not possible to pass parameters, so that it requires a potentially large number of paramter-less functions.

Reimplementing QAbstractState also seems tedious for this matter, unless it would have methods similar to assignProperty() which allows setting QObject properties on "state-entry".

Is QSignalMapper along with several Signal-Slot-Connections for each state's transition signals to handle multiple actions an appropriate approach?

1
As an aside: If you have 20 states in a "fairly linear program" and 10 buttons that each transition to a different state, then you might be doing something wrong on the conceptual level. - Zimano
@Zimano Thanks for your input. But please don't quote something I did not write. Also: you're basically just saying I am doing it wrong, and that might be a good hint, but it's not really helpful. So - how might I do it correctly instead? - handle
No, I am not "basically just saying you are doing it wrong." You might have done it perfectly. I am saying that if the number of states is so large, and quite a big amount of buttons generate unique state transitions while the program in its entirety is "sequential" with some alternative paths, there might be a conceptual error in your design and you might go back to redefining your states and its transitions. I don't know what you are modelling or what your domain is, so I cannot give you any directions. I was just noting this. I am not perscribing anything and had no intent to post an answer - Zimano

1 Answers

2
votes

If you're using C++11, you can connect directly to a lambda that then invokes your function with a specified parameter.

Otherwise, figure out what object is the sender() of your signal, and set a dynamic property on that object. That property can be queried in the slot, and passed on to the function as a parameter.

For example (within a class):

void setup() {
  QState *s2 = new QState();
  s2->assignProperty(myLabel, "text", "state two");
  s2->setProperty("prop", 0);
  connect(s2, SIGNAL(entered()), io, SLOT(testSlot()));
}
Q_SLOT void testSlot() {
  QObject *obj = this->sender();
  QVariant prop = obj->property("prop");
  qDebug() << __FUNCTION__ << prop.toString();
}