Tuesday 7 August 2012

Ping again...

Still going through design, and plenty of PoCs (Proof-of-Concept).

And one - minor - rant...

An app creates a window. Call it a MainWindow, e.g., à-la-Qt. When the user works in that window, he may create other windows. If these windows are created as children of the main window, we have some tasks conveniently taken care of, such as minimizing/restoring those windows when the main window is minimized/restored.

However, in this arrangement, a child window can never be placed below (on the Z-order) its parent window; i.e., assuming no modal windows, when you click the parent window, it won't come to the top, it'll remain obscured by whatever child windows (children windows?) are on top of it. I realize this may be correct default behaviour. What I fail to understand is why is this dogma, why there's no property/setting to turn this off.

Why would I need to turn this off? My main window is what we might conceptually call a toolbox. On the course of executing a task, several tools may be needed, each tool corresponding to a window. So, the user may open a window (call it WinA), do some work and then need to go to the main window and open another window. It won't do to force him to move WinA out of the way to have uncluttered access to the main window.

I had this issue in C#, with WinForms. In the end, I had to create the windows as non-children and manage their behaviour myself. Now, with Qt's MainWindow/Dialog, I'm faced with the same problem. In C#, I created a separate class to track the main window and its "children". In C++, I wanted to try a different approach.

On my first attempt, I've created two static members in my fake-child (FC) window class:
  • A counter. It's increased every time an FC window is created or activated. This counter corresponds to the FC window's Z-order index. This allows me to restore the FC windows in the correct Z-order.
  • A container, to keep track of the FC windows.

With this setup, it was just a matter of implementing the ChangeEvent and CloseEvent on the FC window's class and on the MainWindow. Of course, I'd have to duplicate all this work the next time I needed it. So, I started looking for ways to avoid this duplication.

My first thought was a template class. After some experimentation, I've got a working solution for the Z-order that's mildly intrusive - requires implementation of a member function and a callback. I believe I can get rid of the member function, but not the callback - the event entry point is the parameter class, but the management occurs in the template class, which must be notified; hence, the callback. However, the template may not be the best solution, since I still need to implement the event handlers - this means we'd have more situations where the flow is from the parameter class to the template class. I'm still working on it, but I'm already considering other alternatives: 
  • Inheritance. Instead of inheriting from QDialog, I could inherit from MyQDialog class, which would implement my solution. The same for MainWindow.
  • An unorthodox idea that has popped up in my head - when the main window is minimized, set all the FC windows as its children, and when it's restored, set them as non-children again. I'd also have to set them as children when the main window is closed. If this works (i.e., if it has no side-effects), it might be the simplest solution, even though the "smell factor" is somewhat high.

No comments:

Post a Comment