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 
#ifndef MONGOVIEWER_VIEW_WINDOW_H
#define MONGOVIEWER_VIEW_WINDOW_H

#include <QtGui/QMainWindow>

namespace mongoviewer
{
  namespace view
  {
    class Window : public QMainWindow
    {
      Q_OBJECT
    public:
      explicit Window( QWidget* parent = 0 );

    protected:
      /**
       * Invoke (usually from constructor) to modify the default window
       * manager controlled placement of new window instances.
       *
       * \param increment The increment factor to be applied to the
       *   top-left corner of the new window from the previous window.
       * \param point The default location for the top-left corner of
       *   the new window, if applying the increment would make the
       *   window edges go beyond the desktop bounds.
       */
      void placeWindow( int increment = 50, int point = 25 );
    };

  } // namespace view
} // namespace mongoviewer

#endif // MONGOVIEWER_VIEW_WINDOW_H
Window.cpp 
#include <view/Window.h>

#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>

#include <algorithm>

using namespace mongoviewer::view;

Window::Window( QWidget* parent ) : QMainWindow( parent ) {}

void Window::placeWindow( int increment, int point )
{
  using std::max;
  const QDesktopWidget* desktop = qApp->desktop();
  const QRect& dg = desktop->availableGeometry();

  int x = 0;
  int y = 0;

  foreach ( QWidget* widget, qApp->allWidgets() )
  {
    if ( QMainWindow* mw = qobject_cast<QMainWindow*>( widget ) )
    {
      if ( this == mw ) continue;
      const QRect& wg = widget->geometry();
      x = max<int>( x, wg.left() );
      y = max<int>( y, wg.top() );
    }
  }

  QRect wg = geometry();
  wg.moveLeft( ( ( x + increment ) > dg.bottomRight().x() ) ? point : x + increment );
  wg.moveTop( ( ( y + increment ) > dg.bottom() ) ? point : y + increment );
  setGeometry( wg );
}
See the effect of using the above code to perform window placement in this screencapture.