QDockWidget visibility sync problem
-
Hi, new poster here.
I'm one of the contributors to an open source audio programming environment, SuperCollider (aka SC), that uses Qt for its interfaces. I haven't done much interface development, but I've gotten interested in a particular interface problem.
The main SC interface is a Qt-based Integrated Development Environment, whose main components (relevant to this issue) are a tabbed code editor (always visible) and a handful of docklets (QDockWidgets), one of which is a documentation browser (currently using QtWebKit, though we will go to QtWebEngine sometime in the future).
Problem: If the help docklet's saved state (from the last session) is detached and closed, then, when I launch the IDE again later, about 75% of the time, the help window is visible, but inactive. It should be hidden.
It looks to me like some of the GUI init actions are being forked onto separate threads, and completing out of sync. The SC-IDE code expects that the help docklet window will be fully created, and then updated to the saved state (including visibility), but a majority of the time, it seems that the visibility status is being set before the window is drawn, and then I'm left with garbage on screen.
I didn't write this code, but tracing it through, I think it's going like this.
-
main()
creates an instance ofMainWindow
. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/core/main.cpp#L92 -
MainWindow
's constructor creates an instance ofHelpBrowserDocklet
. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/widgets/main_window.cpp#L146 -
HelpBrowserDocklet
's constructor makes aQDockWidget
: https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/widgets/util/docklet.cpp#L138 -
main()
shows the main window. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/core/main.cpp#L101 -
main()
gets geometry and dock state variables from a session, or last-saved defaults, and does eithersessions->openSession()
orwin->restoreWindowState()
. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/core/main.cpp#L103-L117 -
AFAICS both of these paths eventually get around to
template <class T> void MainWindow::restoreWindowState( T * settings )
, which includesrestoreDetachedState( mHelpBrowserDocklet, detachedData );
. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/widgets/main_window.cpp#L739 -
Docklet::restoreDetachedState()
sets the help window's visible state. https://github.com/supercollider/supercollider/blob/develop/editors/sc-ide/widgets/util/docklet.cpp#L290
If we assume all of these calls are synchronous, then the problem I'm observing should be impossible: the docklet's visibility is set after the main window is prepared. But I'm not seeing that behavior. Therefore, the calls must not be synchronous. However, I can't see in this init process where SC-IDE is explicitly asking for asynchronous behavior -- so I have to assume that the asynchronicity is buried within Qt internals.
BTW, I'm 100% certain that the problem is not because the help docklet's state is saved as "visible." I tested -- there are other differences in behavior if the help browser is open the last time I quit the IDE.
So, the question: What is the right way to initialize this docklet? Some sync magic that needs to be added? Or is the whole approach (create, and then hide, the docklet) incorrect and there's a better way?
Thanks,
hjh -
-
Hi and welcome to devnet,
From a very quick look, I'd say that you should try delaying the settings loading to just after the event loop started. For that use a QTimer::singleShot (the overload that fits best) with 0 as delay.
Hope it helps
-
Hi and welcome to devnet,
From a very quick look, I'd say that you should try delaying the settings loading to just after the event loop started. For that use a QTimer::singleShot (the overload that fits best) with 0 as delay.
Hope it helps
Thanks!
I attempted that[1], and it did improve the behavior somewhat. There's some confusion about applying the persisted settings (it looks to me like delaying the window restore into the app loop changes the settings object so that the help docklet is now considered to be always visible), but that may be a logic problem rather than a Qt problem.
In any case, the timer did change the behavior. Much appreciated!
hjh[1] https://github.com/jamshark70/supercollider/commit/1cd6643aa2938d2eff5f0cf6d0adbf79689d8af6 -- a bit messy, I haven't deleted the commented-out bits yet
-
What about having a known default state at construction (e.g. help is hidden) ? i.e. you ensure that your application has sensible defaults before loading the settings.