Sans Pareil Technologies, Inc.

Key To Your Business

Stack QMainWindow Instances



Qt by default defers to the native window manager when placing new QMainWindow instances (or other widgets like dialogs, frames, etc.). This in general means that multiple window instances spawned by the application are stacked over each other (the top-left corner of each application will usually occupy the same point on screen). The simple code illustrated here may be adapted to vary the placement of new window instances in your applications.

The approach we took was to develop a base Window class, from which all top-level window classes of our application derive. Note that, the code in the method may easily be made a function (eg. mongoviewer::view::placeWindow( QMainWindow* win ))and thus avoid any inheritance requirement.

Window.h

    1: #ifndef MONGOVIEWER_VIEW_WINDOW_H
    2: #define MONGOVIEWER_VIEW_WINDOW_H
    3:
    4: #include <QtGui/QMainWindow>
    5:
    6: namespace mongoviewer
    7: {
    8:   namespace view
    9:   {
   10:     class Window : public QMainWindow
   11:     {
   12:       Q_OBJECT
   13:     public:
   14:       explicit Window( QWidget* parent = 0 );
   15:
   16:     protected:
   17:       /**
   18:        * Invoke (usually from constructor) to modify the default window
   19:        * manager controlled placement of new window instances.
   20:        *
   21:        * \param increment The increment factor to be applied to the
   22:        *   top-left corner of the new window from the previous window.
   23:        * \param point The default location for the top-left corner of
   24:        *   the new window, if applying the increment would make the
   25:        *   window edges go beyond the desktop bounds.
   26:        */
   27:       void placeWindow( int increment = 50, int point = 25 );
   28:     };
   29:
   30:   } // namespace view
   31: } // namespace mongoviewer
   32:
   33: #endif // MONGOVIEWER_VIEW_WINDOW_H

Window.cpp

    1: #include <view/Window.h>
    2:
    3: #include <QtGui/QApplication>
    4: #include <QtGui/QDesktopWidget>
    5:
    6: #include <algorithm>
    7:
    8: using namespace mongoviewer::view;
    9:
   10: Window::Window( QWidget* parent ) : QMainWindow( parent ) {}
   11:
   12: void Window::placeWindow( int increment, int point )
   13: {
   14:   using std::max;
   15:   const QDesktopWidget* desktop = qApp->desktop();
   16:   const QRect& dg = desktop->availableGeometry();
   17:
   18:   int x = 0;
   19:   int y = 0;
   20:
   21:   foreach ( QWidget* widget, qApp->allWidgets() )
   22:   {
   23:     if ( QMainWindow* mw = qobject_cast<QMainWindow*>( widget ) )
   24:     {
   25:       if ( this == mw ) continue;
   26:       const QRect& wg = widget->geometry();
   27:       x = max<int>( x, wg.left() );
   28:       y = max<int>( y, wg.top() );
   29:     }
   30:   }
   31:
   32:   QRect wg = geometry();
   33:   wg.moveLeft( ( ( x + increment ) > dg.bottomRight().x() ) ? point : x + increment );
   34:   wg.moveTop( ( ( y + increment ) > dg.bottom() ) ? point : y + increment );
   35:   setGeometry( wg );
   36: }

See the effect of using the above code to perform window placement in this screencapture.