Dock windows are windows that can be docked in dock areas. Toolbars are the primary example of dock windows, but there can be other types.
QMainWindow provides four dock areas: one above, one below, one to the left, and one to the right of the window's central widget. When we create QToolBars, they automatically put themselves in their parent's top dock area.
Figure 6.11. Floating dock windows
Every dock window has a handle. This appears as two gray lines at the left or top of each dock window shown in Figure 6.12. Users can move dock windows from one dock area to another by dragging the handle. They can also detach a dock window from an area and let the dock window float as a top-level window by dragging the dock window outside of any dock area. Free floating dock windows have their own caption, and can have a close button. They are always "on top" of their main window.
Figure 6.12. A QMainWindow with five dock windows
To turn on the close button when the dock window is floating, call setCloseMode() as follows:
QDockArea provides a context menu with the list of all dock windows and toolbars. Once a dock window is closed, the user can restore it using the context menu.
Figure 6.13. A QDockArea context menu
Dock windows must be subclasses of QDockWindow. If we just need a toolbar with buttons and some other widgets, we can use QToolBar, which inherits QDockWindow. Here's how to create a QToolBar containing a QComboBox, a QSpinBox, and some toolbar buttons, and how to put it in the bottom dock area:
QToolBar *toolBar = new QToolBar(tr("Font"), this); QComboBox *fontComboBox = new QComboBox(true, toolBar); QSpinBox *fontSize = new QSpinBox(toolBar); boldAct->addTo(toolBar); italicAct->addTo(toolBar); underlineAct->addTo(toolBar); moveDockWindow(toolBar, DockBottom);
This toolbar would look ugly if the user moves it to a QMainWindow's left or right dock areas because the QComboBox and the QSpinBox require too much horizontal space. To prevent this from happening, we can call QMainWindow::setDockEnabled() as follows:
setDockEnabled(toolBar, DockLeft, false); setDockEnabled(toolBar, DockRight, false);
If what we need is something more like a floating widget or tool palette, we can use QDockWindow directly, by calling setWidget() to set the widget to be shown inside the QDockWindow. The widget can be as complicated as we like. If we want the user to be able to resize the dock window even when it's in a dock area, we can call setResizeEnabled() on the dock window. The dock window will then be rendered with a splitter-like handle on the side.
If we want the widget to change itself depending on whether it is put in a horizontal or in a vertical dock area, we can reimplement QDockWindow::setOrientation() and change it there.
If we want to save the position of all the toolbars and other dock windows so that we can restore them the next time the application is run, we can write code that is similar to the code we used to save a QSplitter's state (p. 143), using QMainWindow's << operator to write out the state and QMainWindow's >> operator to read it back in.
Applications like Microsoft Visual Studio and Qt Designer make extensive use of dock windows to provide a very flexible user interface. In Qt, this kind of user interface is usually achieved by using a QMainWindow with many custom QDockWindows and a QWorkspace in the middle to control MDI child windows.