Home · All Classes · Main Classes · Grouped Classes · Modules · Functions

mainwindow.cpp Example File
demos/mainwindow/mainwindow.cpp

 /****************************************************************************
 **
 ** Copyright (C) 2004-2008 Trolltech ASA. All rights reserved.
 **
 ** This file is part of the demonstration applications of the Qt Toolkit.
 **
 ** Licensees holding a valid Qt License Agreement may use this file in
 ** accordance with the rights, responsibilities and obligations
 ** contained therein.  Please consult your licensing agreement or
 ** contact sales@trolltech.com if any conditions of this licensing
 ** agreement are not clear to you.
 **
 ** Further information about Qt licensing is available at:
 ** http://www.trolltech.com/products/qt/licensing.html or by
 ** contacting info@trolltech.com.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/

 #include "mainwindow.h"
 #include "colorswatch.h"
 #include "toolbar.h"

 #include <QAction>
 #include <QLayout>
 #include <QMenu>
 #include <QMenuBar>
 #include <QStatusBar>
 #include <QTextEdit>
 #include <QFile>
 #include <QDataStream>
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QSignalMapper>
 #include <QApplication>
 #include <QPainter>
 #include <QMouseEvent>
 #include <qdebug.h>

 static const char * const message =
     "<p><b>Qt Main Window Demo</b></p>"

     "<p>This is a demonstration of the QMainWindow, QToolBar and "
     "QDockWidget classes.</p>"

     "<p>The tool bar and dock widgets can be dragged around and rearranged "
     "using the mouse or via the menu.</p>"

     "<p>Each dock widget contains a colored frame and a context "
     "(right-click) menu.</p>"

 #ifdef Q_WS_MAC
     "<p>On Mac OS X, the \"Black\" dock widget has been created as a "
     "<em>Drawer</em>, which is a special kind of QDockWidget.</p>"
 #endif
     ;

 MainWindow::MainWindow(const QMap<QString, QSize> &customSizeHints,
                         QWidget *parent, Qt::WindowFlags flags)
     : QMainWindow(parent, flags)
 {
     setObjectName("MainWindow");
     setWindowTitle("Qt Main Window Demo");

     setupToolBar();
     setupMenuBar();
     setupDockWidgets(customSizeHints);

     QTextEdit *center = new QTextEdit(this);
     center->setReadOnly(true);
     center->setHtml(tr(message));
     center->setMinimumSize(400, 205);
     setCentralWidget(center);

     statusBar()->showMessage(tr("Status Bar"));
 }

 void MainWindow::actionTriggered(QAction *action)
 {
     qDebug("action '%s' triggered", action->text().toLocal8Bit().data());
 }

 void MainWindow::setupToolBar()
 {
     for (int i = 0; i < 3; ++i) {
         ToolBar *tb = new ToolBar(QString::fromLatin1("Tool Bar %1").arg(i + 1), this);
         toolBars.append(tb);
         addToolBar(tb);
     }
 }

 void MainWindow::setupMenuBar()
 {
     QMenu *menu = menuBar()->addMenu(tr("&File"));

     QAction *action = menu->addAction(tr("Save layout..."));
     connect(action, SIGNAL(triggered()), this, SLOT(saveLayout()));

     action = menu->addAction(tr("Load layout..."));
     connect(action, SIGNAL(triggered()), this, SLOT(loadLayout()));

     action = menu->addAction(tr("Switch layout direction"));
     connect(action, SIGNAL(triggered()), this, SLOT(switchLayoutDirection()));

     menu->addSeparator();

     menu->addAction(tr("&Quit"), this, SLOT(close()));

     mainWindowMenu = menuBar()->addMenu(tr("Main window"));

     action = mainWindowMenu->addAction(tr("Animated docks"));
     action->setCheckable(true);
     action->setChecked(dockOptions() & AnimatedDocks);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));

     action = mainWindowMenu->addAction(tr("Allow nested docks"));
     action->setCheckable(true);
     action->setChecked(dockOptions() & AllowNestedDocks);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));

     action = mainWindowMenu->addAction(tr("Allow tabbed docks"));
     action->setCheckable(true);
     action->setChecked(dockOptions() & AllowTabbedDocks);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));

     action = mainWindowMenu->addAction(tr("Force tabbed docks"));
     action->setCheckable(true);
     action->setChecked(dockOptions() & ForceTabbedDocks);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));

     action = mainWindowMenu->addAction(tr("Vertical tabs"));
     action->setCheckable(true);
     action->setChecked(dockOptions() & VerticalTabs);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));

     QMenu *toolBarMenu = menuBar()->addMenu(tr("Tool bars"));
     for (int i = 0; i < toolBars.count(); ++i)
         toolBarMenu->addMenu(toolBars.at(i)->menu);

     dockWidgetMenu = menuBar()->addMenu(tr("&Dock Widgets"));
 }

 void MainWindow::setDockOptions()
 {
     DockOptions opts;
     QList<QAction*> actions = mainWindowMenu->actions();

     if (actions.at(0)->isChecked())
         opts |= AnimatedDocks;
     if (actions.at(1)->isChecked())
         opts |= AllowNestedDocks;
     if (actions.at(2)->isChecked())
         opts |= AllowTabbedDocks;
     if (actions.at(3)->isChecked())
         opts |= ForceTabbedDocks;
     if (actions.at(4)->isChecked())
         opts |= VerticalTabs;

     QMainWindow::setDockOptions(opts);
 }

 void MainWindow::saveLayout()
 {
     QString fileName
         = QFileDialog::getSaveFileName(this, tr("Save layout"));
     if (fileName.isEmpty())
         return;
     QFile file(fileName);
     if (!file.open(QFile::WriteOnly)) {
         QString msg = tr("Failed to open %1\n%2")
                         .arg(fileName)
                         .arg(file.errorString());
         QMessageBox::warning(this, tr("Error"), msg);
         return;
     }

     QByteArray geo_data = saveGeometry();
     QByteArray layout_data = saveState();

     bool ok = file.putChar((uchar)geo_data.size());
     if (ok)
         ok = file.write(geo_data) == geo_data.size();
     if (ok)
         ok = file.write(layout_data) == layout_data.size();

     if (!ok) {
         QString msg = tr("Error writing to %1\n%2")
                         .arg(fileName)
                         .arg(file.errorString());
         QMessageBox::warning(this, tr("Error"), msg);
         return;
     }
 }

 void MainWindow::loadLayout()
 {
     QString fileName
         = QFileDialog::getOpenFileName(this, tr("Load layout"));
     if (fileName.isEmpty())
         return;
     QFile file(fileName);
     if (!file.open(QFile::ReadOnly)) {
         QString msg = tr("Failed to open %1\n%2")
                         .arg(fileName)
                         .arg(file.errorString());
         QMessageBox::warning(this, tr("Error"), msg);
         return;
     }

     uchar geo_size;
     QByteArray geo_data;
     QByteArray layout_data;

     bool ok = file.getChar((char*)&geo_size);
     if (ok) {
         geo_data = file.read(geo_size);
         ok = geo_data.size() == geo_size;
     }
     if (ok) {
         layout_data = file.readAll();
         ok = layout_data.size() > 0;
     }

     if (ok)
         ok = restoreGeometry(geo_data);
     if (ok)
         ok = restoreState(layout_data);

     if (!ok) {
         QString msg = tr("Error reading %1")
                         .arg(fileName);
         QMessageBox::warning(this, tr("Error"), msg);
         return;
     }
 }

 QAction *addAction(QMenu *menu, const QString &text, QActionGroup *group, QSignalMapper *mapper,
                     int id)
 {
     bool first = group->actions().isEmpty();
     QAction *result = menu->addAction(text);
     result->setCheckable(true);
     result->setChecked(first);
     group->addAction(result);
     QObject::connect(result, SIGNAL(triggered()), mapper, SLOT(map()));
     mapper->setMapping(result, id);
     return result;
 }

 class BlueTitleBar : public QWidget
 {
     Q_OBJECT
 public:
     BlueTitleBar(QWidget *parent = 0);

     QSize sizeHint() const { return minimumSizeHint(); }
     QSize minimumSizeHint() const;
 protected:
     void paintEvent(QPaintEvent *event);
     void mousePressEvent(QMouseEvent *event);
 private:
     QPixmap leftPm, centerPm, rightPm;
 };

 QSize BlueTitleBar::minimumSizeHint() const
 {
     QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
     Q_ASSERT(dw != 0);
     QSize result(leftPm.width() + rightPm.width(), centerPm.height());
     if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar)
         result.transpose();
     return result;
 }

 BlueTitleBar::BlueTitleBar(QWidget *parent)
     : QWidget(parent)
 {
     leftPm = QPixmap(":/res/titlebarLeft.png");
     centerPm = QPixmap(":/res/titlebarCenter.png");
     rightPm = QPixmap(":/res/titlebarRight.png");
 }

 void BlueTitleBar::paintEvent(QPaintEvent*)
 {
     QPainter painter(this);
     QRect rect = this->rect();

     QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
     Q_ASSERT(dw != 0);

     if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
         QSize s = rect.size();
         s.transpose();
         rect.setSize(s);

         painter.translate(rect.left(), rect.top() + rect.width());
         painter.rotate(-90);
         painter.translate(-rect.left(), -rect.top());
     }

     painter.drawPixmap(rect.topLeft(), leftPm);
     painter.drawPixmap(rect.topRight() - QPoint(rightPm.width() - 1, 0), rightPm);
     QBrush brush(centerPm);
     painter.fillRect(rect.left() + leftPm.width(), rect.top(),
                         rect.width() - leftPm.width() - rightPm.width(),
                         centerPm.height(), centerPm);
 }

 void BlueTitleBar::mousePressEvent(QMouseEvent *event)
 {
     QPoint pos = event->pos();

     QRect rect = this->rect();

     QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
     Q_ASSERT(dw != 0);

     if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
         QPoint p = pos;
         pos.setX(rect.left() + rect.bottom() - p.y());
         pos.setY(rect.top() + p.x() - rect.left());

         QSize s = rect.size();
         s.transpose();
         rect.setSize(s);
     }

     const int buttonRight = 7;
     const int buttonWidth = 20;
     int right = rect.right() - pos.x();
     int button = (right - buttonRight)/buttonWidth;
     switch (button) {
         case 0:
             event->accept();
             dw->close();
             break;
         case 1:
             event->accept();
             dw->setFloating(!dw->isFloating());
             break;
         case 2: {
             event->accept();
             QDockWidget::DockWidgetFeatures features = dw->features();
             if (features & QDockWidget::DockWidgetVerticalTitleBar)
                 features &= ~QDockWidget::DockWidgetVerticalTitleBar;
             else
                 features |= QDockWidget::DockWidgetVerticalTitleBar;
             dw->setFeatures(features);
             break;
         }
         default:
             event->ignore();
             break;
     }
 }

 void MainWindow::setupDockWidgets(const QMap<QString, QSize> &customSizeHints)
 {
     mapper = new QSignalMapper(this);
     connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCorner(int)));

     QMenu *corner_menu = dockWidgetMenu->addMenu(tr("Top left corner"));
     QActionGroup *group = new QActionGroup(this);
     group->setExclusive(true);
     ::addAction(corner_menu, tr("Top dock area"), group, mapper, 0);
     ::addAction(corner_menu, tr("Left dock area"), group, mapper, 1);

     corner_menu = dockWidgetMenu->addMenu(tr("Top right corner"));
     group = new QActionGroup(this);
     group->setExclusive(true);
     ::addAction(corner_menu, tr("Top dock area"), group, mapper, 2);
     ::addAction(corner_menu, tr("Right dock area"), group, mapper, 3);

     corner_menu = dockWidgetMenu->addMenu(tr("Bottom left corner"));
     group = new QActionGroup(this);
     group->setExclusive(true);
     ::addAction(corner_menu, tr("Bottom dock area"), group, mapper, 4);
     ::addAction(corner_menu, tr("Left dock area"), group, mapper, 5);

     corner_menu = dockWidgetMenu->addMenu(tr("Bottom right corner"));
     group = new QActionGroup(this);
     group->setExclusive(true);
     ::addAction(corner_menu, tr("Bottom dock area"), group, mapper, 6);
     ::addAction(corner_menu, tr("Right dock area"), group, mapper, 7);

     dockWidgetMenu->addSeparator();

     static const struct Set {
         const char * name;
         uint flags;
         Qt::DockWidgetArea area;
     } sets [] = {
 #ifndef Q_WS_MAC
         { "Black", 0, Qt::LeftDockWidgetArea },
 #else
         { "Black", Qt::Drawer, Qt::LeftDockWidgetArea },
 #endif
         { "White", 0, Qt::RightDockWidgetArea },
         { "Red", 0, Qt::TopDockWidgetArea },
         { "Green", 0, Qt::TopDockWidgetArea },
         { "Blue", 0, Qt::BottomDockWidgetArea },
         { "Yellow", 0, Qt::BottomDockWidgetArea }
     };
     const int setCount = sizeof(sets) / sizeof(Set);

     for (int i = 0; i < setCount; ++i) {
         ColorSwatch *swatch = new ColorSwatch(tr(sets[i].name), this, Qt::WindowFlags(sets[i].flags));
         if (i%2)
             swatch->setWindowIcon(QIcon(QPixmap(":/res/qt.png")));
         if (qstrcmp(sets[i].name, "Blue") == 0) {
             swatch->setTitleBarWidget(new BlueTitleBar(swatch));
 #ifdef Q_WS_QWS
             QPalette pal = palette();
             pal.setBrush(backgroundRole(), QColor(0,0,0,0));
             swatch->setPalette(pal);
 #endif
         }

         QString name = QString::fromLatin1(sets[i].name);
         if (customSizeHints.contains(name))
             swatch->setCustomSizeHint(customSizeHints.value(name));

         addDockWidget(sets[i].area, swatch);
         dockWidgetMenu->addMenu(swatch->menu);
     }
 }

 void MainWindow::setCorner(int id)
 {
     switch (id) {
         case 0:
             QMainWindow::setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
             break;
         case 1:
             QMainWindow::setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
             break;
         case 2:
             QMainWindow::setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
             break;
         case 3:
             QMainWindow::setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
             break;
         case 4:
             QMainWindow::setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
             break;
         case 5:
             QMainWindow::setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
             break;
         case 6:
             QMainWindow::setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
             break;
         case 7:
             QMainWindow::setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
             break;
     }
 }

 void MainWindow::switchLayoutDirection()
 {
     if (layoutDirection() == Qt::LeftToRight)
         qApp->setLayoutDirection(Qt::RightToLeft);
     else
         qApp->setLayoutDirection(Qt::LeftToRight);
 }

 #include "mainwindow.moc"


Copyright © 2008 Trolltech Trademarks
Qt 4.3.5