/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the demonstration applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "colorswatch.h" #include "toolbar.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char * const message = "

Qt Main Window Demo

" "

This is a demonstration of the QMainWindow, QToolBar and " "QDockWidget classes.

" "

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

" "

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

" #ifdef Q_WS_MAC "

On Mac OS X, the \"Black\" dock widget has been created as a " "Drawer, which is a special kind of QDockWidget.

" #endif ; Q_DECLARE_METATYPE(QDockWidget::DockWidgetFeatures) MainWindow::MainWindow(const QMap &customSizeHints, QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { setObjectName("MainWindow"); setWindowTitle("Qt Main Window Demo"); center = new QTextEdit(this); center->setReadOnly(true); center->setMinimumSize(400, 205); setCentralWidget(center); setupToolBar(); setupMenuBar(); setupDockWidgets(customSizeHints); 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 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; } void MainWindow::setupDockWidgets(const QMap &customSizeHints) { qRegisterMetaType(); 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) { BlueTitleBar *titlebar = new BlueTitleBar(swatch); swatch->setTitleBarWidget(titlebar); connect(swatch, SIGNAL(topLevelChanged(bool)), titlebar, SLOT(updateMask())); connect(swatch, SIGNAL(featuresChanged(QDockWidget::DockWidgetFeatures)), titlebar, SLOT(updateMask()), Qt::QueuedConnection); #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); } createDockWidgetAction = new QAction(tr("Add dock widget..."), this); connect(createDockWidgetAction, SIGNAL(triggered()), this, SLOT(createDockWidget())); destroyDockWidgetMenu = new QMenu(tr("Destroy dock widget"), this); destroyDockWidgetMenu->setEnabled(false); connect(destroyDockWidgetMenu, SIGNAL(triggered(QAction*)), this, SLOT(destroyDockWidget(QAction*))); dockWidgetMenu->addSeparator(); dockWidgetMenu->addAction(createDockWidgetAction); dockWidgetMenu->addMenu(destroyDockWidgetMenu); } 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::showEvent(QShowEvent *event) { QMainWindow::showEvent(event); } void MainWindow::switchLayoutDirection() { if (layoutDirection() == Qt::LeftToRight) qApp->setLayoutDirection(Qt::RightToLeft); else qApp->setLayoutDirection(Qt::LeftToRight); } class CreateDockWidgetDialog : public QDialog { public: CreateDockWidgetDialog(QWidget *parent = 0); QString objectName() const; Qt::DockWidgetArea location() const; private: QLineEdit *m_objectName; QComboBox *m_location; }; CreateDockWidgetDialog::CreateDockWidgetDialog(QWidget *parent) : QDialog(parent) { QGridLayout *layout = new QGridLayout(this); layout->addWidget(new QLabel(tr("Object name:")), 0, 0); m_objectName = new QLineEdit; layout->addWidget(m_objectName, 0, 1); layout->addWidget(new QLabel(tr("Location:")), 1, 0); m_location = new QComboBox; m_location->setEditable(false); m_location->addItem(tr("Top")); m_location->addItem(tr("Left")); m_location->addItem(tr("Right")); m_location->addItem(tr("Bottom")); m_location->addItem(tr("Restore")); layout->addWidget(m_location, 1, 1); QHBoxLayout *buttonLayout = new QHBoxLayout; layout->addLayout(buttonLayout, 2, 0, 1, 2); buttonLayout->addStretch(); QPushButton *cancelButton = new QPushButton(tr("Cancel")); connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); buttonLayout->addWidget(cancelButton); QPushButton *okButton = new QPushButton(tr("Ok")); connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); buttonLayout->addWidget(okButton); okButton->setDefault(true); } QString CreateDockWidgetDialog::objectName() const { return m_objectName->text(); } Qt::DockWidgetArea CreateDockWidgetDialog::location() const { switch (m_location->currentIndex()) { case 0: return Qt::TopDockWidgetArea; case 1: return Qt::LeftDockWidgetArea; case 2: return Qt::RightDockWidgetArea; case 3: return Qt::BottomDockWidgetArea; default: break; } return Qt::NoDockWidgetArea; } void MainWindow::createDockWidget() { CreateDockWidgetDialog dialog(this); int ret = dialog.exec(); if (ret == QDialog::Rejected) return; QDockWidget *dw = new QDockWidget; dw->setObjectName(dialog.objectName()); dw->setWindowTitle(dialog.objectName()); dw->setWidget(new QTextEdit); Qt::DockWidgetArea area = dialog.location(); switch (area) { case Qt::LeftDockWidgetArea: case Qt::RightDockWidgetArea: case Qt::TopDockWidgetArea: case Qt::BottomDockWidgetArea: addDockWidget(area, dw); break; default: if (!restoreDockWidget(dw)) { QMessageBox::warning(this, QString(), tr("Failed to restore dock widget")); delete dw; return; } break; } extraDockWidgets.append(dw); destroyDockWidgetMenu->setEnabled(true); destroyDockWidgetMenu->addAction(new QAction(dialog.objectName(), this)); } void MainWindow::destroyDockWidget(QAction *action) { int index = destroyDockWidgetMenu->actions().indexOf(action); delete extraDockWidgets.takeAt(index); destroyDockWidgetMenu->removeAction(action); action->deleteLater(); if (destroyDockWidgetMenu->isEmpty()) destroyDockWidgetMenu->setEnabled(false); }