8

In our application, we have a variable number of dockwidgets because some of them are added by plugins that are loaded at runtime. Not all dockwidgets need to be visible at the same time necessarily. This depends strongly on what the user is working on and what plugins are active.

However, if too many dockwidgets are added programmatically with addDockWidget(...), they start to overlap each other (not in terms of tabs, but in terms of content of one being painted on the area of a different one, which obviously looks broken).

Overlapping dockwidgets

The user can move the dockwidgets to dockareas that still have space left, but the layout/main window successfully prevents (untabbed) re-addition to the "crowded" dockarea.

We do allow tabbed docks to allow the user to arrange the dockwidgets a required, but we don't want to enable QMainWindow::ForceTabbedDocks since this would constrain the number of simultaneously visible dockwidgets too much (one per dock area).

How can I prevent this or better control how dockwidgets are added?

Johannes S.
  • 4,566
  • 26
  • 41

3 Answers3

6

Not answering your question directly but it might be worthwhile to actually forget about Qt and actually think of how the whole interaction should work. What are the user expectations? What should actually happen if 10 different plugins become active? Should they be docked or should they be floating or should they become pin-able docking windows with initial state as a small button on the MainWindow edges? I think once you do that ground work and come up with user interface mock-ups, you can then start looking at Qt and figure out if Qt provides a direct way to develop that interface and if not what additional components you will need to develop to get that interface working.

From my own experience, I had developed a similar interface long back but in MFC. The way we did it was that some of the docked windows were deemed to be must have and they would come up as docked. Then there were a set of windows that didnt need to be visible always but should be quickly available and their initial state was as hidden pin-able dock window which meant they came up as buttons on the MainWindow edge. Finally there was a third set that was not required by the user always and could be called in from File->View Menu. Once the user made it visible, the user typically would assign it to one of the first two groups or keep it afloat. This whole configuration was saved in a config file and from there onwards whenever the plugin was loaded/became active the last used state of the associated docking window was used. It though involved quite a bit of extra work but the end result was to the satisfaction of all users.

Pankaj
  • 599
  • 3
  • 10
  • 1
    Thank you. I guess this is sound advice. This might be a good example that it is always a good idea to take a step back and rethink the overall design and big picture when getting lost in technical details. – Johannes S. Aug 06 '12 at 06:40
2

Have you tryed setDockOptions(QMainWindow::AllowNestedDocks)? I can't test it now but it may help. By default, QMainWindow::dockOptions is set to AnimatedDocks | AllowTabbedDocks so you would want something like

setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)

EDIT: If you are having too many problems, you may be going about this the wrong way. Instead of using docks, you may want to try using QMdiArea with QMdiWindow. This may not work for your program, but its something to think about.

Ben Gates
  • 762
  • 5
  • 14
  • I will try this, although I am not sure whether I like `AllowNestedDocks`. As it is now, it can already be quite annoying at times that dockwidgets start to *snap* to the different areas, when you just want to move a floating widget. Enabling nesting will even increase the number of possible dock areas, doesn't it? – Johannes S. Aug 02 '12 at 14:48
  • Yes it will. The qt documentation states that it is good for many docks but that it can be annoying. – Ben Gates Aug 02 '12 at 15:26
  • It is even worse. First of all, it does not work. With a single "level" of dockwidgets, it's just the same as before. But if I nest to dockwidgets next to each other and then programmatically add another dockwidget to that area, it just overlaps **both** nested dockwidgets :/ – Johannes S. Aug 02 '12 at 15:34
1

This is the solution I tried:

  1. I created in QTCreator an empty project with a window, a minimalistic menu labelled "New Dock" and a DockWidget named dockWidget

  2. This is the triggered() handler for my menu item:

      void MainWindow::on_actionNew_Dock_triggered()
     {    
         QDockWidget* w = new QDockWidget("Demo", ui->dockWidget);
         this->addDockWidget(Qt::LeftDockWidgetArea,w);
         this->tabifyDockWidget(ui->dockWidget,w);
     }
    

tabifyDockWidget(QDockWidget* first, QDockWidget* second) is a QMainWindow method that stacks the second dockwidget upon the first one. Hope it helps...

Max Lambertini
  • 3,583
  • 1
  • 19
  • 24
  • However, then I would need to first check if there already is a dock widget on that side andmm, if there are multiple, decide which one to tabify. But even that would not solve the problem I guess: Assume there are two dockwidgets in `LeftDockWidgetArea`. W.r.t their minimumSize, they occupy all available space. One is small, one is large. I add a rather large dockwidget. If I now choose the small one to be tabbed with my new dockwidget, I'm afraid to run into exactly the same issues (two dockwidgets side by side, both too large so Qt overrides the minimumSize and causes the ugly overlap. – Johannes S. Aug 02 '12 at 14:46
  • Or am I missing something? Maybe we have to redefine the whole "process" of when, how and where which dockwidgets can be added.... – Johannes S. Aug 02 '12 at 14:47
  • You could implement tabbing/docking policies at plugin level. I assume, though, that your plugins derive from `QWidget` and get set as `QDockWindow`'s main widget. If this is the case, the common plugin ancestor could devise a basic docking/positioning policy, that can be modified by their descendants. – Max Lambertini Aug 03 '12 at 06:31
  • More about this: every pane of Visual Studio 2010 (watches, compiler messages, search/replace, etc.) can be docked pretty much everywhere, but depending on their layout these have a preferred default: watches usually appear at the bottom, class hierarchies at the left or right, search/replace as an independent window... but then, you can dock them everywhere else. I think your plugins should follow a similar path. – Max Lambertini Aug 03 '12 at 06:51