1

I've a menu screen which must be updated before the login screen closed. The code is something similar to below one;

emit updateMainMenuAccordingToUserRights;

QCoreApplication::processEvents();

emit jumpMainMenu();

The problem is 'how can I be sure that all events have been processed?'. Because some of the slots triggered by updateMainMenuAccordingToUserRights signal adds new events to the event loop to update view components. Before jumping main menu I must be sure that it's already updated. I've searched a little and seen that QCoreApplication::processEvent process the loop for just once. Okay, that's the reason why the above code does not work. Even I tried some QEventLoop methods but couldn't manage to solve this problem.

Thanks for any advice.

cumbaba
  • 11
  • 3
  • You need to add a signal to main menu which triggers a slot once the update is completed. In this slot you emit the function call `jumpMainMenu`. – user3606329 Mar 27 '18 at 20:55
  • Did you give a try to `QEventLoop::WaitForMoreEvents` flag. – Mohammad Kanan Mar 27 '18 at 21:06
  • But for my case the main menu is a consist of small plugins. The main menu is not just one object. It's being changed by small parts of application (where there is a slot for updateMainMenuAccordingToUserRights in each plugin). So, all these slots should be executed. Even these slots could add new events/ emit signals in themselves. – cumbaba Mar 27 '18 at 21:13
  • @MohammadKanan yes, I've already tried that. – cumbaba Mar 27 '18 at 21:25
  • What is your login screen class? QDialog? – Mohammad Kanan Mar 27 '18 at 21:31
  • @MohammadKanan It's a QObject which displays all the enabled plugins(QObjects). Every plugin is a singleton. – cumbaba Mar 27 '18 at 21:45
  • That sounds to be your main menu screen not login screen? – Mohammad Kanan Mar 27 '18 at 21:47
  • 3
    Having to force the event loop means you are probably doing something that is not recommended and can be done in a better way. I've been using Qt for 10 years extensively, and I've done some crazy complex stuff with it, and I've never had to force event processing, not once. – dtech Mar 27 '18 at 23:27

1 Answers1

1

I've a menu screen which must be updated before the login screen closed

Not at all - it's an XY problem. In other words: your design is wrong. You need to lightly couple the login screen somehow to the menu screen, so that the menu screen gets the information it needs to update itself, before the login screen is closed. At any point after that, the login screen can indeed close.

Most likely you're tightly coupling the login screen with login controller, and thus the LoginScreen class should emit the event that the MenuScreen will process.

Your current signal names suggest very tight coupling between the screens. There is just one signal that you need: loginDone(const LoginData &), where LoginData is a structure/class that carries the information about the logged in user etc.

Then, the three lines of code from the question simply become:

auto d = this->getLoginData();
emit loginDone(d);
close();

and

LoginData LoginScreen::getLoginData() const {
  LoginData d;
  d.foo = this->foo();
  d.bar = this->bar();
  ...
  return d;
}

A function (ideally in a controller class) would then couple the LoginScreen to MenuScreen loosely via the LoginData object:

void setLoginDataOnMenu(const LoginData &data, MenuScreen *menu) {
  ...
  menu->show();
};

int main(int argc, char **argv) {
  QApplication app{argc, argv};
  LoginScreen login;
  MenuScreen menu;
  QObject::connect(&login, &LoginScreen::loginDone, &menu, [&](const LoginData &){
    setLoginDataOnMenu(data, &menu);
  });
  login.show();
  return app.exec();
};

Ideally, you'd want to have a separate controller class to implement the logic, instead of having it in screens. The LoginScreen and MenuScreen could then be views for the data exposed by the controller.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313