summaryrefslogtreecommitdiffstats
path: root/demos/mainwindow
diff options
context:
space:
mode:
Diffstat (limited to 'demos/mainwindow')
-rw-r--r--demos/mainwindow/colorswatch.cpp746
-rw-r--r--demos/mainwindow/colorswatch.h136
-rw-r--r--demos/mainwindow/main.cpp164
-rw-r--r--demos/mainwindow/mainwindow.cpp510
-rw-r--r--demos/mainwindow/mainwindow.h90
-rw-r--r--demos/mainwindow/mainwindow.pro18
-rw-r--r--demos/mainwindow/mainwindow.qrc8
-rw-r--r--demos/mainwindow/qt.pngbin0 -> 2037 bytes
-rw-r--r--demos/mainwindow/titlebarCenter.pngbin0 -> 146 bytes
-rw-r--r--demos/mainwindow/titlebarLeft.pngbin0 -> 5148 bytes
-rw-r--r--demos/mainwindow/titlebarRight.pngbin0 -> 2704 bytes
-rw-r--r--demos/mainwindow/toolbar.cpp383
-rw-r--r--demos/mainwindow/toolbar.h118
13 files changed, 2173 insertions, 0 deletions
diff --git a/demos/mainwindow/colorswatch.cpp b/demos/mainwindow/colorswatch.cpp
new file mode 100644
index 0000000..ba6a076
--- /dev/null
+++ b/demos/mainwindow/colorswatch.cpp
@@ -0,0 +1,746 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "colorswatch.h"
+
+#include <QAction>
+#include <QtEvents>
+#include <QFrame>
+#include <QMainWindow>
+#include <QMenu>
+#include <QPainter>
+#include <QImage>
+#include <QColor>
+#include <QDialog>
+#include <QGridLayout>
+#include <QSpinBox>
+#include <QLabel>
+#include <QPainterPath>
+#include <QPushButton>
+#include <QHBoxLayout>
+#include <QBitmap>
+#include <QtDebug>
+
+#undef DEBUG_SIZEHINTS
+
+QColor bgColorForName(const QString &name)
+{
+ if (name == "Black")
+ return QColor("#D8D8D8");
+ else if (name == "White")
+ return QColor("#F1F1F1");
+ else if (name == "Red")
+ return QColor("#F1D8D8");
+ else if (name == "Green")
+ return QColor("#D8E4D8");
+ else if (name == "Blue")
+ return QColor("#D8D8F1");
+ else if (name == "Yellow")
+ return QColor("#F1F0D8");
+ return QColor(name).light(110);
+}
+
+QColor fgColorForName(const QString &name)
+{
+ if (name == "Black")
+ return QColor("#6C6C6C");
+ else if (name == "White")
+ return QColor("#F8F8F8");
+ else if (name == "Red")
+ return QColor("#F86C6C");
+ else if (name == "Green")
+ return QColor("#6CB26C");
+ else if (name == "Blue")
+ return QColor("#6C6CF8");
+ else if (name == "Yellow")
+ return QColor("#F8F76C");
+ return QColor(name);
+}
+
+class ColorDock : public QFrame
+{
+ Q_OBJECT
+public:
+ ColorDock(const QString &c, QWidget *parent);
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+ void setCustomSizeHint(const QSize &size);
+
+public slots:
+ void changeSizeHints();
+
+protected:
+ void paintEvent(QPaintEvent *);
+ QString color;
+ QSize szHint, minSzHint;
+};
+
+ColorDock::ColorDock(const QString &c, QWidget *parent)
+ : QFrame(parent) , color(c)
+{
+ QFont font = this->font();
+ font.setPointSize(8);
+ setFont(font);
+ szHint = QSize(-1, -1);
+ minSzHint = QSize(125, 75);
+}
+
+QSize ColorDock::sizeHint() const
+{
+ return szHint;
+}
+
+QSize ColorDock::minimumSizeHint() const
+{
+ return minSzHint;
+}
+
+void ColorDock::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.fillRect(rect(), bgColorForName(color));
+
+ p.save();
+
+ extern void render_qt_text(QPainter *, int, int, const QColor &);
+ render_qt_text(&p, width(), height(), fgColorForName(color));
+
+ p.restore();
+
+#ifdef DEBUG_SIZEHINTS
+ p.setRenderHint(QPainter::Antialiasing, false);
+
+ QSize sz = size();
+ QSize szHint = sizeHint();
+ QSize minSzHint = minimumSizeHint();
+ QSize maxSz = maximumSize();
+ QString text = QString::fromLatin1("sz: %1x%2\nszHint: %3x%4\nminSzHint: %5x%6\n"
+ "maxSz: %8x%9")
+ .arg(sz.width()).arg(sz.height())
+ .arg(szHint.width()).arg(szHint.height())
+ .arg(minSzHint.width()).arg(minSzHint.height())
+ .arg(maxSz.width()).arg(maxSz.height());
+
+ QRect r = fontMetrics().boundingRect(rect(), Qt::AlignLeft|Qt::AlignTop, text);
+ r.adjust(-2, -2, 1, 1);
+ p.translate(4, 4);
+ QColor bg = Qt::yellow;
+ bg.setAlpha(120);
+ p.setBrush(bg);
+ p.setPen(Qt::black);
+ p.drawRect(r);
+ p.drawText(rect(), Qt::AlignLeft|Qt::AlignTop, text);
+#endif // DEBUG_SIZEHINTS
+}
+
+static QSpinBox *createSpinBox(int value, QWidget *parent, int max = 1000)
+{
+ QSpinBox *result = new QSpinBox(parent);
+ result->setMinimum(-1);
+ result->setMaximum(max);
+ result->setValue(value);
+ return result;
+}
+
+void ColorDock::changeSizeHints()
+{
+ QDialog dialog(this);
+ dialog.setWindowTitle(color);
+
+ QVBoxLayout *topLayout = new QVBoxLayout(&dialog);
+
+ QGridLayout *inputLayout = new QGridLayout();
+ topLayout->addLayout(inputLayout);
+
+ inputLayout->addWidget(new QLabel(tr("Size Hint:"), &dialog), 0, 0);
+ inputLayout->addWidget(new QLabel(tr("Min Size Hint:"), &dialog), 1, 0);
+ inputLayout->addWidget(new QLabel(tr("Max Size:"), &dialog), 2, 0);
+ inputLayout->addWidget(new QLabel(tr("Dockwgt Max Size:"), &dialog), 3, 0);
+
+ QSpinBox *szHintW = createSpinBox(szHint.width(), &dialog);
+ inputLayout->addWidget(szHintW, 0, 1);
+ QSpinBox *szHintH = createSpinBox(szHint.height(), &dialog);
+ inputLayout->addWidget(szHintH, 0, 2);
+
+ QSpinBox *minSzHintW = createSpinBox(minSzHint.width(), &dialog);
+ inputLayout->addWidget(minSzHintW, 1, 1);
+ QSpinBox *minSzHintH = createSpinBox(minSzHint.height(), &dialog);
+ inputLayout->addWidget(minSzHintH, 1, 2);
+
+ QSize maxSz = maximumSize();
+ QSpinBox *maxSzW = createSpinBox(maxSz.width(), &dialog, QWIDGETSIZE_MAX);
+ inputLayout->addWidget(maxSzW, 2, 1);
+ QSpinBox *maxSzH = createSpinBox(maxSz.height(), &dialog, QWIDGETSIZE_MAX);
+ inputLayout->addWidget(maxSzH, 2, 2);
+
+ QSize dwMaxSz = parentWidget()->maximumSize();
+ QSpinBox *dwMaxSzW = createSpinBox(dwMaxSz.width(), &dialog, QWIDGETSIZE_MAX);
+ inputLayout->addWidget(dwMaxSzW, 3, 1);
+ QSpinBox *dwMaxSzH = createSpinBox(dwMaxSz.height(), &dialog, QWIDGETSIZE_MAX);
+ inputLayout->addWidget(dwMaxSzH, 3, 2);
+
+ inputLayout->setColumnStretch(1, 1);
+ inputLayout->setColumnStretch(2, 1);
+
+ topLayout->addStretch();
+
+ QHBoxLayout *buttonBox = new QHBoxLayout();
+ topLayout->addLayout(buttonBox);
+
+ QPushButton *okButton = new QPushButton(tr("Ok"), &dialog);
+ QPushButton *cancelButton = new QPushButton(tr("Cancel"), &dialog);
+ connect(okButton, SIGNAL(clicked()), &dialog, SLOT(accept()));
+ connect(cancelButton, SIGNAL(clicked()), &dialog, SLOT(reject()));
+ buttonBox->addStretch();
+ buttonBox->addWidget(cancelButton);
+ buttonBox->addWidget(okButton);
+
+
+ if (!dialog.exec())
+ return;
+
+ szHint = QSize(szHintW->value(), szHintH->value());
+ minSzHint = QSize(minSzHintW->value(), minSzHintH->value());
+ maxSz = QSize(maxSzW->value(), maxSzH->value());
+ setMaximumSize(maxSz);
+ dwMaxSz = QSize(dwMaxSzW->value(), dwMaxSzH->value());
+ parentWidget()->setMaximumSize(dwMaxSz);
+ updateGeometry();
+ update();
+}
+
+void ColorDock::setCustomSizeHint(const QSize &size)
+{
+ szHint = size;
+ updateGeometry();
+}
+
+ColorSwatch::ColorSwatch(const QString &colorName, QWidget *parent, Qt::WindowFlags flags)
+ : QDockWidget(parent, flags)
+{
+ setObjectName(colorName + QLatin1String(" Dock Widget"));
+ setWindowTitle(objectName() + QLatin1String(" [*]"));
+
+ QFrame *swatch = new ColorDock(colorName, this);
+ swatch->setFrameStyle(QFrame::Box | QFrame::Sunken);
+
+ setWidget(swatch);
+
+ changeSizeHintsAction = new QAction(tr("Change Size Hints"), this);
+ connect(changeSizeHintsAction, SIGNAL(triggered()), swatch, SLOT(changeSizeHints()));
+
+ closableAction = new QAction(tr("Closable"), this);
+ closableAction->setCheckable(true);
+ connect(closableAction, SIGNAL(triggered(bool)), SLOT(changeClosable(bool)));
+
+ movableAction = new QAction(tr("Movable"), this);
+ movableAction->setCheckable(true);
+ connect(movableAction, SIGNAL(triggered(bool)), SLOT(changeMovable(bool)));
+
+ floatableAction = new QAction(tr("Floatable"), this);
+ floatableAction->setCheckable(true);
+ connect(floatableAction, SIGNAL(triggered(bool)), SLOT(changeFloatable(bool)));
+
+ verticalTitleBarAction = new QAction(tr("Vertical title bar"), this);
+ verticalTitleBarAction->setCheckable(true);
+ connect(verticalTitleBarAction, SIGNAL(triggered(bool)),
+ SLOT(changeVerticalTitleBar(bool)));
+
+ floatingAction = new QAction(tr("Floating"), this);
+ floatingAction->setCheckable(true);
+ connect(floatingAction, SIGNAL(triggered(bool)), SLOT(changeFloating(bool)));
+
+ allowedAreasActions = new QActionGroup(this);
+ allowedAreasActions->setExclusive(false);
+
+ allowLeftAction = new QAction(tr("Allow on Left"), this);
+ allowLeftAction->setCheckable(true);
+ connect(allowLeftAction, SIGNAL(triggered(bool)), SLOT(allowLeft(bool)));
+
+ allowRightAction = new QAction(tr("Allow on Right"), this);
+ allowRightAction->setCheckable(true);
+ connect(allowRightAction, SIGNAL(triggered(bool)), SLOT(allowRight(bool)));
+
+ allowTopAction = new QAction(tr("Allow on Top"), this);
+ allowTopAction->setCheckable(true);
+ connect(allowTopAction, SIGNAL(triggered(bool)), SLOT(allowTop(bool)));
+
+ allowBottomAction = new QAction(tr("Allow on Bottom"), this);
+ allowBottomAction->setCheckable(true);
+ connect(allowBottomAction, SIGNAL(triggered(bool)), SLOT(allowBottom(bool)));
+
+ allowedAreasActions->addAction(allowLeftAction);
+ allowedAreasActions->addAction(allowRightAction);
+ allowedAreasActions->addAction(allowTopAction);
+ allowedAreasActions->addAction(allowBottomAction);
+
+ areaActions = new QActionGroup(this);
+ areaActions->setExclusive(true);
+
+ leftAction = new QAction(tr("Place on Left") , this);
+ leftAction->setCheckable(true);
+ connect(leftAction, SIGNAL(triggered(bool)), SLOT(placeLeft(bool)));
+
+ rightAction = new QAction(tr("Place on Right") , this);
+ rightAction->setCheckable(true);
+ connect(rightAction, SIGNAL(triggered(bool)), SLOT(placeRight(bool)));
+
+ topAction = new QAction(tr("Place on Top") , this);
+ topAction->setCheckable(true);
+ connect(topAction, SIGNAL(triggered(bool)), SLOT(placeTop(bool)));
+
+ bottomAction = new QAction(tr("Place on Bottom") , this);
+ bottomAction->setCheckable(true);
+ connect(bottomAction, SIGNAL(triggered(bool)), SLOT(placeBottom(bool)));
+
+ areaActions->addAction(leftAction);
+ areaActions->addAction(rightAction);
+ areaActions->addAction(topAction);
+ areaActions->addAction(bottomAction);
+
+ connect(movableAction, SIGNAL(triggered(bool)), areaActions, SLOT(setEnabled(bool)));
+
+ connect(movableAction, SIGNAL(triggered(bool)), allowedAreasActions, SLOT(setEnabled(bool)));
+
+ connect(floatableAction, SIGNAL(triggered(bool)), floatingAction, SLOT(setEnabled(bool)));
+
+ connect(floatingAction, SIGNAL(triggered(bool)), floatableAction, SLOT(setDisabled(bool)));
+ connect(movableAction, SIGNAL(triggered(bool)), floatableAction, SLOT(setEnabled(bool)));
+
+ tabMenu = new QMenu(this);
+ tabMenu->setTitle(tr("Tab into"));
+ connect(tabMenu, SIGNAL(triggered(QAction*)), this, SLOT(tabInto(QAction*)));
+
+ splitHMenu = new QMenu(this);
+ splitHMenu->setTitle(tr("Split horizontally into"));
+ connect(splitHMenu, SIGNAL(triggered(QAction*)), this, SLOT(splitInto(QAction*)));
+
+ splitVMenu = new QMenu(this);
+ splitVMenu->setTitle(tr("Split vertically into"));
+ connect(splitVMenu, SIGNAL(triggered(QAction*)), this, SLOT(splitInto(QAction*)));
+
+ windowModifiedAction = new QAction(tr("Modified"), this);
+ windowModifiedAction->setCheckable(true);
+ windowModifiedAction->setChecked(false);
+ connect(windowModifiedAction, SIGNAL(toggled(bool)), this, SLOT(setWindowModified(bool)));
+
+ menu = new QMenu(colorName, this);
+ menu->addAction(toggleViewAction());
+ QAction *action = menu->addAction(tr("Raise"));
+ connect(action, SIGNAL(triggered()), this, SLOT(raise()));
+ menu->addAction(changeSizeHintsAction);
+ menu->addSeparator();
+ menu->addAction(closableAction);
+ menu->addAction(movableAction);
+ menu->addAction(floatableAction);
+ menu->addAction(floatingAction);
+ menu->addAction(verticalTitleBarAction);
+ menu->addSeparator();
+ menu->addActions(allowedAreasActions->actions());
+ menu->addSeparator();
+ menu->addActions(areaActions->actions());
+ menu->addSeparator();
+ menu->addMenu(splitHMenu);
+ menu->addMenu(splitVMenu);
+ menu->addMenu(tabMenu);
+ menu->addSeparator();
+ menu->addAction(windowModifiedAction);
+
+ connect(menu, SIGNAL(aboutToShow()), this, SLOT(updateContextMenu()));
+
+ if(colorName == "Black") {
+ leftAction->setShortcut(Qt::CTRL|Qt::Key_W);
+ rightAction->setShortcut(Qt::CTRL|Qt::Key_E);
+ toggleViewAction()->setShortcut(Qt::CTRL|Qt::Key_R);
+ }
+}
+
+void ColorSwatch::updateContextMenu()
+{
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(this);
+ const Qt::DockWidgetAreas areas = allowedAreas();
+
+ closableAction->setChecked(features() & QDockWidget::DockWidgetClosable);
+ if (windowType() == Qt::Drawer) {
+ floatableAction->setEnabled(false);
+ floatingAction->setEnabled(false);
+ movableAction->setEnabled(false);
+ verticalTitleBarAction->setChecked(false);
+ } else {
+ floatableAction->setChecked(features() & QDockWidget::DockWidgetFloatable);
+ floatingAction->setChecked(isWindow());
+ // done after floating, to get 'floatable' correctly initialized
+ movableAction->setChecked(features() & QDockWidget::DockWidgetMovable);
+ verticalTitleBarAction
+ ->setChecked(features() & QDockWidget::DockWidgetVerticalTitleBar);
+ }
+
+ allowLeftAction->setChecked(isAreaAllowed(Qt::LeftDockWidgetArea));
+ allowRightAction->setChecked(isAreaAllowed(Qt::RightDockWidgetArea));
+ allowTopAction->setChecked(isAreaAllowed(Qt::TopDockWidgetArea));
+ allowBottomAction->setChecked(isAreaAllowed(Qt::BottomDockWidgetArea));
+
+ if (allowedAreasActions->isEnabled()) {
+ allowLeftAction->setEnabled(area != Qt::LeftDockWidgetArea);
+ allowRightAction->setEnabled(area != Qt::RightDockWidgetArea);
+ allowTopAction->setEnabled(area != Qt::TopDockWidgetArea);
+ allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
+ }
+
+ leftAction->blockSignals(true);
+ rightAction->blockSignals(true);
+ topAction->blockSignals(true);
+ bottomAction->blockSignals(true);
+
+ leftAction->setChecked(area == Qt::LeftDockWidgetArea);
+ rightAction->setChecked(area == Qt::RightDockWidgetArea);
+ topAction->setChecked(area == Qt::TopDockWidgetArea);
+ bottomAction->setChecked(area == Qt::BottomDockWidgetArea);
+
+ leftAction->blockSignals(false);
+ rightAction->blockSignals(false);
+ topAction->blockSignals(false);
+ bottomAction->blockSignals(false);
+
+ if (areaActions->isEnabled()) {
+ leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);
+ rightAction->setEnabled(areas & Qt::RightDockWidgetArea);
+ topAction->setEnabled(areas & Qt::TopDockWidgetArea);
+ bottomAction->setEnabled(areas & Qt::BottomDockWidgetArea);
+ }
+
+ tabMenu->clear();
+ splitHMenu->clear();
+ splitVMenu->clear();
+ QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow);
+ foreach (ColorSwatch *dock, dock_list) {
+// if (!dock->isVisible() || dock->isFloating())
+// continue;
+ tabMenu->addAction(dock->objectName());
+ splitHMenu->addAction(dock->objectName());
+ splitVMenu->addAction(dock->objectName());
+ }
+}
+
+void ColorSwatch::splitInto(QAction *action)
+{
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow);
+ ColorSwatch *target = 0;
+ foreach (ColorSwatch *dock, dock_list) {
+ if (action->text() == dock->objectName()) {
+ target = dock;
+ break;
+ }
+ }
+ if (target == 0)
+ return;
+
+ Qt::Orientation o = action->parent() == splitHMenu
+ ? Qt::Horizontal : Qt::Vertical;
+ mainWindow->splitDockWidget(target, this, o);
+}
+
+void ColorSwatch::tabInto(QAction *action)
+{
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ QList<ColorSwatch*> dock_list = qFindChildren<ColorSwatch*>(mainWindow);
+ ColorSwatch *target = 0;
+ foreach (ColorSwatch *dock, dock_list) {
+ if (action->text() == dock->objectName()) {
+ target = dock;
+ break;
+ }
+ }
+ if (target == 0)
+ return;
+
+ mainWindow->tabifyDockWidget(target, this);
+}
+
+void ColorSwatch::contextMenuEvent(QContextMenuEvent *event)
+{
+ event->accept();
+ menu->exec(event->globalPos());
+}
+
+void ColorSwatch::resizeEvent(QResizeEvent *e)
+{
+ if (BlueTitleBar *btb = qobject_cast<BlueTitleBar*>(titleBarWidget()))
+ btb->updateMask();
+
+ QDockWidget::resizeEvent(e);
+}
+
+
+void ColorSwatch::allow(Qt::DockWidgetArea area, bool a)
+{
+ Qt::DockWidgetAreas areas = allowedAreas();
+ areas = a ? areas | area : areas & ~area;
+ setAllowedAreas(areas);
+
+ if (areaActions->isEnabled()) {
+ leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);
+ rightAction->setEnabled(areas & Qt::RightDockWidgetArea);
+ topAction->setEnabled(areas & Qt::TopDockWidgetArea);
+ bottomAction->setEnabled(areas & Qt::BottomDockWidgetArea);
+ }
+}
+
+void ColorSwatch::place(Qt::DockWidgetArea area, bool p)
+{
+ if (!p) return;
+
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ mainWindow->addDockWidget(area, this);
+
+ if (allowedAreasActions->isEnabled()) {
+ allowLeftAction->setEnabled(area != Qt::LeftDockWidgetArea);
+ allowRightAction->setEnabled(area != Qt::RightDockWidgetArea);
+ allowTopAction->setEnabled(area != Qt::TopDockWidgetArea);
+ allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
+ }
+}
+
+void ColorSwatch::setCustomSizeHint(const QSize &size)
+{
+ if (ColorDock *dock = qobject_cast<ColorDock*>(widget()))
+ dock->setCustomSizeHint(size);
+}
+
+void ColorSwatch::changeClosable(bool on)
+{ setFeatures(on ? features() | DockWidgetClosable : features() & ~DockWidgetClosable); }
+
+void ColorSwatch::changeMovable(bool on)
+{ setFeatures(on ? features() | DockWidgetMovable : features() & ~DockWidgetMovable); }
+
+void ColorSwatch::changeFloatable(bool on)
+{ setFeatures(on ? features() | DockWidgetFloatable : features() & ~DockWidgetFloatable); }
+
+void ColorSwatch::changeFloating(bool floating)
+{ setFloating(floating); }
+
+void ColorSwatch::allowLeft(bool a)
+{ allow(Qt::LeftDockWidgetArea, a); }
+
+void ColorSwatch::allowRight(bool a)
+{ allow(Qt::RightDockWidgetArea, a); }
+
+void ColorSwatch::allowTop(bool a)
+{ allow(Qt::TopDockWidgetArea, a); }
+
+void ColorSwatch::allowBottom(bool a)
+{ allow(Qt::BottomDockWidgetArea, a); }
+
+void ColorSwatch::placeLeft(bool p)
+{ place(Qt::LeftDockWidgetArea, p); }
+
+void ColorSwatch::placeRight(bool p)
+{ place(Qt::RightDockWidgetArea, p); }
+
+void ColorSwatch::placeTop(bool p)
+{ place(Qt::TopDockWidgetArea, p); }
+
+void ColorSwatch::placeBottom(bool p)
+{ place(Qt::BottomDockWidgetArea, p); }
+
+void ColorSwatch::changeVerticalTitleBar(bool on)
+{
+ setFeatures(on ? features() | DockWidgetVerticalTitleBar
+ : features() & ~DockWidgetVerticalTitleBar);
+}
+
+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 BlueTitleBar::updateMask()
+{
+ QDockWidget *dw = qobject_cast<QDockWidget*>(parent());
+ Q_ASSERT(dw != 0);
+
+ QRect rect = dw->rect();
+ QPixmap bitmap(dw->size());
+
+ {
+ QPainter painter(&bitmap);
+
+ ///initialize to transparent
+ painter.fillRect(rect, Qt::color0);
+
+ QRect contents = rect;
+ contents.setTopLeft(geometry().bottomLeft());
+ contents.setRight(geometry().right());
+ contents.setBottom(contents.bottom()-y());
+ painter.fillRect(contents, Qt::color1);
+
+
+
+ //let's pait the titlebar
+
+ QRect titleRect = this->geometry();
+
+ if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
+ QSize s = rect.size();
+ s.transpose();
+ rect.setSize(s);
+
+ QSize s2 = size();
+ s2.transpose();
+ titleRect.setSize(s2);
+
+ painter.translate(rect.left(), rect.top() + rect.width());
+ painter.rotate(-90);
+ painter.translate(-rect.left(), -rect.top());
+ }
+
+ contents.setTopLeft(titleRect.bottomLeft());
+ contents.setRight(titleRect.right());
+ contents.setBottom(rect.bottom()-y());
+
+ QRect rect = titleRect;
+
+
+ painter.drawPixmap(rect.topLeft(), leftPm.mask());
+ painter.fillRect(rect.left() + leftPm.width(), rect.top(),
+ rect.width() - leftPm.width() - rightPm.width(),
+ centerPm.height(), Qt::color1);
+ painter.drawPixmap(rect.topRight() - QPoint(rightPm.width() - 1, 0), rightPm.mask());
+
+ painter.fillRect(contents, Qt::color1);
+ }
+
+ dw->setMask(bitmap);
+}
+
+#include "colorswatch.moc"
diff --git a/demos/mainwindow/colorswatch.h b/demos/mainwindow/colorswatch.h
new file mode 100644
index 0000000..57c5ac6
--- /dev/null
+++ b/demos/mainwindow/colorswatch.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COLORSWATCH_H
+#define COLORSWATCH_H
+
+#include <QDockWidget>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QActionGroup)
+QT_FORWARD_DECLARE_CLASS(QMenu)
+
+class ColorSwatch : public QDockWidget
+{
+ Q_OBJECT
+
+ QAction *closableAction;
+ QAction *movableAction;
+ QAction *floatableAction;
+ QAction *floatingAction;
+ QAction *verticalTitleBarAction;
+
+ QActionGroup *allowedAreasActions;
+ QAction *allowLeftAction;
+ QAction *allowRightAction;
+ QAction *allowTopAction;
+ QAction *allowBottomAction;
+
+ QActionGroup *areaActions;
+ QAction *leftAction;
+ QAction *rightAction;
+ QAction *topAction;
+ QAction *bottomAction;
+
+ QAction *changeSizeHintsAction;
+
+ QMenu *tabMenu;
+ QMenu *splitHMenu;
+ QMenu *splitVMenu;
+
+ QAction *windowModifiedAction;
+
+public:
+ ColorSwatch(const QString &colorName, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+ QMenu *menu;
+ void setCustomSizeHint(const QSize &size);
+
+protected:
+ virtual void contextMenuEvent(QContextMenuEvent *event);
+ virtual void resizeEvent(QResizeEvent *e);
+
+private:
+ void allow(Qt::DockWidgetArea area, bool allow);
+ void place(Qt::DockWidgetArea area, bool place);
+
+private slots:
+ void changeClosable(bool on);
+ void changeMovable(bool on);
+ void changeFloatable(bool on);
+ void changeFloating(bool on);
+ void changeVerticalTitleBar(bool on);
+ void updateContextMenu();
+
+ void allowLeft(bool a);
+ void allowRight(bool a);
+ void allowTop(bool a);
+ void allowBottom(bool a);
+
+ void placeLeft(bool p);
+ void placeRight(bool p);
+ void placeTop(bool p);
+ void placeBottom(bool p);
+
+ void splitInto(QAction *action);
+ void tabInto(QAction *action);
+};
+
+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);
+public slots:
+ void updateMask();
+
+private:
+ QPixmap leftPm, centerPm, rightPm;
+};
+
+
+#endif
diff --git a/demos/mainwindow/main.cpp b/demos/mainwindow/main.cpp
new file mode 100644
index 0000000..46268b5
--- /dev/null
+++ b/demos/mainwindow/main.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QPainterPath>
+#include <QPainter>
+#include <QMap>
+#include <qdebug.h>
+
+void render_qt_text(QPainter *painter, int w, int h, const QColor &color) {
+ QPainterPath path;
+ path.moveTo(-0.083695, 0.283849);
+ path.cubicTo(-0.049581, 0.349613, -0.012720, 0.397969, 0.026886, 0.428917);
+ path.cubicTo(0.066493, 0.459865, 0.111593, 0.477595, 0.162186, 0.482108);
+ path.lineTo(0.162186, 0.500000);
+ path.cubicTo(0.115929, 0.498066, 0.066565, 0.487669, 0.014094, 0.468810);
+ path.cubicTo(-0.038378, 0.449952, -0.088103, 0.423839, -0.135082, 0.390474);
+ path.cubicTo(-0.182061, 0.357108, -0.222608, 0.321567, -0.256722, 0.283849);
+ path.cubicTo(-0.304712, 0.262250, -0.342874, 0.239362, -0.371206, 0.215184);
+ path.cubicTo(-0.411969, 0.179078, -0.443625, 0.134671, -0.466175, 0.081963);
+ path.cubicTo(-0.488725, 0.029255, -0.500000, -0.033043, -0.500000, -0.104932);
+ path.cubicTo(-0.500000, -0.218407, -0.467042, -0.312621, -0.401127, -0.387573);
+ path.cubicTo(-0.335212, -0.462524, -0.255421, -0.500000, -0.161752, -0.500000);
+ path.cubicTo(-0.072998, -0.500000, 0.003903, -0.462444, 0.068951, -0.387331);
+ path.cubicTo(0.133998, -0.312218, 0.166522, -0.217440, 0.166522, -0.102998);
+ path.cubicTo(0.166522, -0.010155, 0.143394, 0.071325, 0.097138, 0.141441);
+ path.cubicTo(0.050882, 0.211557, -0.009396, 0.259026, -0.083695, 0.283849);
+ path.moveTo(-0.167823, -0.456963);
+ path.cubicTo(-0.228823, -0.456963, -0.277826, -0.432624, -0.314831, -0.383946);
+ path.cubicTo(-0.361665, -0.323340, -0.385082, -0.230335, -0.385082, -0.104932);
+ path.cubicTo(-0.385082, 0.017569, -0.361376, 0.112025, -0.313964, 0.178433);
+ path.cubicTo(-0.277248, 0.229368, -0.228534, 0.254836, -0.167823, 0.254836);
+ path.cubicTo(-0.105088, 0.254836, -0.054496, 0.229368, -0.016045, 0.178433);
+ path.cubicTo(0.029055, 0.117827, 0.051605, 0.028691, 0.051605, -0.088975);
+ path.cubicTo(0.051605, -0.179562, 0.039318, -0.255803, 0.014744, -0.317698);
+ path.cubicTo(-0.004337, -0.365409, -0.029705, -0.400548, -0.061362, -0.423114);
+ path.cubicTo(-0.093018, -0.445680, -0.128505, -0.456963, -0.167823, -0.456963);
+ path.moveTo(0.379011, -0.404739);
+ path.lineTo(0.379011, -0.236460);
+ path.lineTo(0.486123, -0.236460);
+ path.lineTo(0.486123, -0.197292);
+ path.lineTo(0.379011, -0.197292);
+ path.lineTo(0.379011, 0.134913);
+ path.cubicTo(0.379011, 0.168117, 0.383276, 0.190442, 0.391804, 0.201886);
+ path.cubicTo(0.400332, 0.213330, 0.411246, 0.219052, 0.424545, 0.219052);
+ path.cubicTo(0.435531, 0.219052, 0.446227, 0.215264, 0.456635, 0.207689);
+ path.cubicTo(0.467042, 0.200113, 0.474993, 0.188910, 0.480486, 0.174081);
+ path.lineTo(0.500000, 0.174081);
+ path.cubicTo(0.488436, 0.210509, 0.471957, 0.237911, 0.450564, 0.256286);
+ path.cubicTo(0.429170, 0.274662, 0.407054, 0.283849, 0.384215, 0.283849);
+ path.cubicTo(0.368893, 0.283849, 0.353859, 0.279094, 0.339115, 0.269584);
+ path.cubicTo(0.324371, 0.260074, 0.313530, 0.246534, 0.306592, 0.228965);
+ path.cubicTo(0.299653, 0.211396, 0.296184, 0.184075, 0.296184, 0.147002);
+ path.lineTo(0.296184, -0.197292);
+ path.lineTo(0.223330, -0.197292);
+ path.lineTo(0.223330, -0.215667);
+ path.cubicTo(0.241833, -0.224049, 0.260697, -0.237992, 0.279922, -0.257495);
+ path.cubicTo(0.299147, -0.276999, 0.316276, -0.300129, 0.331310, -0.326886);
+ path.cubicTo(0.338826, -0.341070, 0.349523, -0.367021, 0.363400, -0.404739);
+ path.lineTo(0.379011, -0.404739);
+ path.moveTo(-0.535993, 0.275629);
+
+ painter->translate(w / 2, h / 2);
+ double scale = qMin(w, h) * 8 / 10.0;
+ painter->scale(scale, scale);
+
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ painter->save();
+ painter->translate(.1, .1);
+ painter->fillPath(path, QColor(0, 0, 0, 63));
+ painter->restore();
+
+ painter->setBrush(color);
+ painter->setPen(QPen(Qt::black, 0.02, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
+ painter->drawPath(path);
+}
+
+void usage()
+{
+ qWarning() << "Usage: mainwindow [-SizeHint<color> <width>x<height>] ...";
+ exit(1);
+}
+
+QMap<QString, QSize> parseCustomSizeHints(int argc, char **argv)
+{
+ QMap<QString, QSize> result;
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = QString::fromLocal8Bit(argv[i]);
+
+ if (arg.startsWith(QLatin1String("-SizeHint"))) {
+ QString name = arg.mid(9);
+ if (name.isEmpty())
+ usage();
+ if (++i == argc)
+ usage();
+ QString sizeStr = QString::fromLocal8Bit(argv[i]);
+ int idx = sizeStr.indexOf(QLatin1Char('x'));
+ if (idx == -1)
+ usage();
+ bool ok;
+ int w = sizeStr.left(idx).toInt(&ok);
+ if (!ok)
+ usage();
+ int h = sizeStr.mid(idx + 1).toInt(&ok);
+ if (!ok)
+ usage();
+ result[name] = QSize(w, h);
+ }
+ }
+
+ return result;
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QMap<QString, QSize> customSizeHints = parseCustomSizeHints(argc, argv);
+ MainWindow mainWin(customSizeHints);
+ mainWin.resize(800, 600);
+ mainWin.show();
+ return app.exec();
+}
diff --git a/demos/mainwindow/mainwindow.cpp b/demos/mainwindow/mainwindow.cpp
new file mode 100644
index 0000000..7edaf52
--- /dev/null
+++ b/demos/mainwindow/mainwindow.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#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 <QLineEdit>
+#include <QComboBox>
+#include <QLabel>
+#include <QPushButton>
+#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");
+
+ 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<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;
+}
+
+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) {
+ 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()));
+
+#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);
+}
diff --git a/demos/mainwindow/mainwindow.h b/demos/mainwindow/mainwindow.h
new file mode 100644
index 0000000..9c7f620
--- /dev/null
+++ b/demos/mainwindow/mainwindow.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QTextEdit>
+
+class ToolBar;
+QT_FORWARD_DECLARE_CLASS(QMenu)
+QT_FORWARD_DECLARE_CLASS(QSignalMapper)
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+ QTextEdit *center;
+ QList<ToolBar*> toolBars;
+ QMenu *dockWidgetMenu;
+ QMenu *mainWindowMenu;
+ QSignalMapper *mapper;
+ QList<QDockWidget*> extraDockWidgets;
+ QAction *createDockWidgetAction;
+ QMenu *destroyDockWidgetMenu;
+
+public:
+ MainWindow(const QMap<QString, QSize> &customSizeHints,
+ QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+protected:
+ void showEvent(QShowEvent *event);
+
+public slots:
+ void actionTriggered(QAction *action);
+ void saveLayout();
+ void loadLayout();
+ void setCorner(int id);
+ void switchLayoutDirection();
+ void setDockOptions();
+
+ void createDockWidget();
+ void destroyDockWidget(QAction *action);
+
+private:
+ void setupToolBar();
+ void setupMenuBar();
+ void setupDockWidgets(const QMap<QString, QSize> &customSizeHints);
+};
+
+
+#endif
diff --git a/demos/mainwindow/mainwindow.pro b/demos/mainwindow/mainwindow.pro
new file mode 100644
index 0000000..6e7d784
--- /dev/null
+++ b/demos/mainwindow/mainwindow.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+HEADERS += colorswatch.h mainwindow.h toolbar.h
+SOURCES += colorswatch.cpp mainwindow.cpp toolbar.cpp main.cpp
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+RESOURCES += mainwindow.qrc
+
+# install
+target.path = $$[QT_INSTALL_DEMOS]/mainwindow
+sources.files = $$SOURCES $$HEADERS $$FORMS $$RESOURCES *.png *.jpg *.pro
+sources.path = $$[QT_INSTALL_DEMOS]/mainwindow
+INSTALLS += target sources
+
+include($$QT_SOURCE_TREE/demos/demobase.pri)
+
diff --git a/demos/mainwindow/mainwindow.qrc b/demos/mainwindow/mainwindow.qrc
new file mode 100644
index 0000000..47ff22a
--- /dev/null
+++ b/demos/mainwindow/mainwindow.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/res">
+ <file>qt.png</file>
+ <file>titlebarLeft.png</file>
+ <file>titlebarCenter.png</file>
+ <file>titlebarRight.png</file>
+</qresource>
+</RCC>
diff --git a/demos/mainwindow/qt.png b/demos/mainwindow/qt.png
new file mode 100644
index 0000000..48fa9fc
--- /dev/null
+++ b/demos/mainwindow/qt.png
Binary files differ
diff --git a/demos/mainwindow/titlebarCenter.png b/demos/mainwindow/titlebarCenter.png
new file mode 100644
index 0000000..5cc1413
--- /dev/null
+++ b/demos/mainwindow/titlebarCenter.png
Binary files differ
diff --git a/demos/mainwindow/titlebarLeft.png b/demos/mainwindow/titlebarLeft.png
new file mode 100644
index 0000000..3151662
--- /dev/null
+++ b/demos/mainwindow/titlebarLeft.png
Binary files differ
diff --git a/demos/mainwindow/titlebarRight.png b/demos/mainwindow/titlebarRight.png
new file mode 100644
index 0000000..a450526
--- /dev/null
+++ b/demos/mainwindow/titlebarRight.png
Binary files differ
diff --git a/demos/mainwindow/toolbar.cpp b/demos/mainwindow/toolbar.cpp
new file mode 100644
index 0000000..9de1348
--- /dev/null
+++ b/demos/mainwindow/toolbar.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "toolbar.h"
+
+#include <QMainWindow>
+#include <QMenu>
+#include <QPainter>
+#include <QPainterPath>
+#include <QSpinBox>
+#include <QLabel>
+#include <QToolTip>
+
+#include <stdlib.h>
+
+static QPixmap genIcon(const QSize &iconSize, const QString &, const QColor &color)
+{
+ int w = iconSize.width();
+ int h = iconSize.height();
+
+ QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+
+ QPainter p(&image);
+
+ extern void render_qt_text(QPainter *, int, int, const QColor &);
+ render_qt_text(&p, w, h, color);
+
+ return QPixmap::fromImage(image, Qt::DiffuseDither | Qt::DiffuseAlphaDither);
+}
+
+static QPixmap genIcon(const QSize &iconSize, int number, const QColor &color)
+{ return genIcon(iconSize, QString::number(number), color); }
+
+ToolBar::ToolBar(const QString &title, QWidget *parent)
+ : QToolBar(parent), spinbox(0), spinboxAction(0)
+{
+ tip = 0;
+ setWindowTitle(title);
+ setObjectName(title);
+
+ setIconSize(QSize(32, 32));
+
+ QColor bg(palette().background().color());
+ menu = new QMenu("One", this);
+ menu->setIcon(genIcon(iconSize(), 1, Qt::black));
+ menu->addAction(genIcon(iconSize(), "A", Qt::blue), "A");
+ menu->addAction(genIcon(iconSize(), "B", Qt::blue), "B");
+ menu->addAction(genIcon(iconSize(), "C", Qt::blue), "C");
+ addAction(menu->menuAction());
+
+ QAction *two = addAction(genIcon(iconSize(), 2, Qt::white), "Two");
+ QFont boldFont;
+ boldFont.setBold(true);
+ two->setFont(boldFont);
+
+ addAction(genIcon(iconSize(), 3, Qt::red), "Three");
+ addAction(genIcon(iconSize(), 4, Qt::green), "Four");
+ addAction(genIcon(iconSize(), 5, Qt::blue), "Five");
+ addAction(genIcon(iconSize(), 6, Qt::yellow), "Six");
+ orderAction = new QAction(this);
+ orderAction->setText(tr("Order Items in Tool Bar"));
+ connect(orderAction, SIGNAL(triggered()), SLOT(order()));
+
+ randomizeAction = new QAction(this);
+ randomizeAction->setText(tr("Randomize Items in Tool Bar"));
+ connect(randomizeAction, SIGNAL(triggered()), SLOT(randomize()));
+
+ addSpinBoxAction = new QAction(this);
+ addSpinBoxAction->setText(tr("Add Spin Box"));
+ connect(addSpinBoxAction, SIGNAL(triggered()), SLOT(addSpinBox()));
+
+ removeSpinBoxAction = new QAction(this);
+ removeSpinBoxAction->setText(tr("Remove Spin Box"));
+ removeSpinBoxAction->setEnabled(false);
+ connect(removeSpinBoxAction, SIGNAL(triggered()), SLOT(removeSpinBox()));
+
+ movableAction = new QAction(tr("Movable"), this);
+ movableAction->setCheckable(true);
+ connect(movableAction, SIGNAL(triggered(bool)), SLOT(changeMovable(bool)));
+
+ allowedAreasActions = new QActionGroup(this);
+ allowedAreasActions->setExclusive(false);
+
+ allowLeftAction = new QAction(tr("Allow on Left"), this);
+ allowLeftAction->setCheckable(true);
+ connect(allowLeftAction, SIGNAL(triggered(bool)), SLOT(allowLeft(bool)));
+
+ allowRightAction = new QAction(tr("Allow on Right"), this);
+ allowRightAction->setCheckable(true);
+ connect(allowRightAction, SIGNAL(triggered(bool)), SLOT(allowRight(bool)));
+
+ allowTopAction = new QAction(tr("Allow on Top"), this);
+ allowTopAction->setCheckable(true);
+ connect(allowTopAction, SIGNAL(triggered(bool)), SLOT(allowTop(bool)));
+
+ allowBottomAction = new QAction(tr("Allow on Bottom"), this);
+ allowBottomAction->setCheckable(true);
+ connect(allowBottomAction, SIGNAL(triggered(bool)), SLOT(allowBottom(bool)));
+
+ allowedAreasActions->addAction(allowLeftAction);
+ allowedAreasActions->addAction(allowRightAction);
+ allowedAreasActions->addAction(allowTopAction);
+ allowedAreasActions->addAction(allowBottomAction);
+
+ areaActions = new QActionGroup(this);
+ areaActions->setExclusive(true);
+
+ leftAction = new QAction(tr("Place on Left") , this);
+ leftAction->setCheckable(true);
+ connect(leftAction, SIGNAL(triggered(bool)), SLOT(placeLeft(bool)));
+
+ rightAction = new QAction(tr("Place on Right") , this);
+ rightAction->setCheckable(true);
+ connect(rightAction, SIGNAL(triggered(bool)), SLOT(placeRight(bool)));
+
+ topAction = new QAction(tr("Place on Top") , this);
+ topAction->setCheckable(true);
+ connect(topAction, SIGNAL(triggered(bool)), SLOT(placeTop(bool)));
+
+ bottomAction = new QAction(tr("Place on Bottom") , this);
+ bottomAction->setCheckable(true);
+ connect(bottomAction, SIGNAL(triggered(bool)), SLOT(placeBottom(bool)));
+
+ areaActions->addAction(leftAction);
+ areaActions->addAction(rightAction);
+ areaActions->addAction(topAction);
+ areaActions->addAction(bottomAction);
+
+ toolBarBreakAction = new QAction(tr("Insert break"), this);
+ connect(toolBarBreakAction, SIGNAL(triggered(bool)), this, SLOT(insertToolBarBreak()));
+
+ connect(movableAction, SIGNAL(triggered(bool)), areaActions, SLOT(setEnabled(bool)));
+
+ connect(movableAction, SIGNAL(triggered(bool)), allowedAreasActions, SLOT(setEnabled(bool)));
+
+ menu = new QMenu(title, this);
+ menu->addAction(toggleViewAction());
+ menu->addSeparator();
+ menu->addAction(orderAction);
+ menu->addAction(randomizeAction);
+ menu->addSeparator();
+ menu->addAction(addSpinBoxAction);
+ menu->addAction(removeSpinBoxAction);
+ menu->addSeparator();
+ menu->addAction(movableAction);
+ menu->addSeparator();
+ menu->addActions(allowedAreasActions->actions());
+ menu->addSeparator();
+ menu->addActions(areaActions->actions());
+ menu->addSeparator();
+ menu->addAction(toolBarBreakAction);
+
+ connect(menu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
+
+ randomize();
+}
+
+void ToolBar::updateMenu()
+{
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ Q_ASSERT(mainWindow != 0);
+
+ const Qt::ToolBarArea area = mainWindow->toolBarArea(this);
+ const Qt::ToolBarAreas areas = allowedAreas();
+
+ movableAction->setChecked(isMovable());
+
+ allowLeftAction->setChecked(isAreaAllowed(Qt::LeftToolBarArea));
+ allowRightAction->setChecked(isAreaAllowed(Qt::RightToolBarArea));
+ allowTopAction->setChecked(isAreaAllowed(Qt::TopToolBarArea));
+ allowBottomAction->setChecked(isAreaAllowed(Qt::BottomToolBarArea));
+
+ if (allowedAreasActions->isEnabled()) {
+ allowLeftAction->setEnabled(area != Qt::LeftToolBarArea);
+ allowRightAction->setEnabled(area != Qt::RightToolBarArea);
+ allowTopAction->setEnabled(area != Qt::TopToolBarArea);
+ allowBottomAction->setEnabled(area != Qt::BottomToolBarArea);
+ }
+
+ leftAction->setChecked(area == Qt::LeftToolBarArea);
+ rightAction->setChecked(area == Qt::RightToolBarArea);
+ topAction->setChecked(area == Qt::TopToolBarArea);
+ bottomAction->setChecked(area == Qt::BottomToolBarArea);
+
+ if (areaActions->isEnabled()) {
+ leftAction->setEnabled(areas & Qt::LeftToolBarArea);
+ rightAction->setEnabled(areas & Qt::RightToolBarArea);
+ topAction->setEnabled(areas & Qt::TopToolBarArea);
+ bottomAction->setEnabled(areas & Qt::BottomToolBarArea);
+ }
+}
+
+void ToolBar::order()
+{
+ QList<QAction *> ordered, actions1 = actions(),
+ actions2 = qFindChildren<QAction *>(this);
+ while (!actions2.isEmpty()) {
+ QAction *action = actions2.takeFirst();
+ if (!actions1.contains(action))
+ continue;
+ actions1.removeAll(action);
+ ordered.append(action);
+ }
+
+ clear();
+ addActions(ordered);
+
+ orderAction->setEnabled(false);
+}
+
+void ToolBar::randomize()
+{
+ QList<QAction *> randomized, actions = this->actions();
+ while (!actions.isEmpty()) {
+ QAction *action = actions.takeAt(rand() % actions.size());
+ randomized.append(action);
+ }
+ clear();
+ addActions(randomized);
+
+ orderAction->setEnabled(true);
+}
+
+void ToolBar::addSpinBox()
+{
+ if (!spinbox) {
+ spinbox = new QSpinBox(this);
+ }
+ if (!spinboxAction)
+ spinboxAction = addWidget(spinbox);
+ else
+ addAction(spinboxAction);
+
+ addSpinBoxAction->setEnabled(false);
+ removeSpinBoxAction->setEnabled(true);
+}
+
+void ToolBar::removeSpinBox()
+{
+ if (spinboxAction)
+ removeAction(spinboxAction);
+
+ addSpinBoxAction->setEnabled(true);
+ removeSpinBoxAction->setEnabled(false);
+}
+
+void ToolBar::allow(Qt::ToolBarArea area, bool a)
+{
+ Qt::ToolBarAreas areas = allowedAreas();
+ areas = a ? areas | area : areas & ~area;
+ setAllowedAreas(areas);
+
+ if (areaActions->isEnabled()) {
+ leftAction->setEnabled(areas & Qt::LeftToolBarArea);
+ rightAction->setEnabled(areas & Qt::RightToolBarArea);
+ topAction->setEnabled(areas & Qt::TopToolBarArea);
+ bottomAction->setEnabled(areas & Qt::BottomToolBarArea);
+ }
+}
+
+void ToolBar::place(Qt::ToolBarArea area, bool p)
+{
+ if (!p)
+ return;
+
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ Q_ASSERT(mainWindow != 0);
+
+ mainWindow->addToolBar(area, this);
+
+ if (allowedAreasActions->isEnabled()) {
+ allowLeftAction->setEnabled(area != Qt::LeftToolBarArea);
+ allowRightAction->setEnabled(area != Qt::RightToolBarArea);
+ allowTopAction->setEnabled(area != Qt::TopToolBarArea);
+ allowBottomAction->setEnabled(area != Qt::BottomToolBarArea);
+ }
+}
+
+void ToolBar::changeMovable(bool movable)
+{ setMovable(movable); }
+
+void ToolBar::allowLeft(bool a)
+{ allow(Qt::LeftToolBarArea, a); }
+
+void ToolBar::allowRight(bool a)
+{ allow(Qt::RightToolBarArea, a); }
+
+void ToolBar::allowTop(bool a)
+{ allow(Qt::TopToolBarArea, a); }
+
+void ToolBar::allowBottom(bool a)
+{ allow(Qt::BottomToolBarArea, a); }
+
+void ToolBar::placeLeft(bool p)
+{ place(Qt::LeftToolBarArea, p); }
+
+void ToolBar::placeRight(bool p)
+{ place(Qt::RightToolBarArea, p); }
+
+void ToolBar::placeTop(bool p)
+{ place(Qt::TopToolBarArea, p); }
+
+void ToolBar::placeBottom(bool p)
+{ place(Qt::BottomToolBarArea, p); }
+
+void ToolBar::insertToolBarBreak()
+{
+ QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ Q_ASSERT(mainWindow != 0);
+
+ mainWindow->insertToolBarBreak(this);
+}
+
+void ToolBar::enterEvent(QEvent*)
+{
+/*
+ These labels on top of toolbars look darn ugly
+
+ if (tip == 0) {
+ tip = new QLabel(windowTitle(), this);
+ QPalette pal = tip->palette();
+ QColor c = Qt::black;
+ c.setAlpha(100);
+ pal.setColor(QPalette::Window, c);
+ pal.setColor(QPalette::Foreground, Qt::white);
+ tip->setPalette(pal);
+ tip->setAutoFillBackground(true);
+ tip->setMargin(3);
+ tip->setText(windowTitle());
+ }
+ QPoint c = rect().center();
+ QSize hint = tip->sizeHint();
+ tip->setGeometry(c.x() - hint.width()/2, c.y() - hint.height()/2,
+ hint.width(), hint.height());
+
+ tip->show();
+*/
+}
+
+void ToolBar::leaveEvent(QEvent*)
+{
+ if (tip != 0)
+ tip->hide();
+}
diff --git a/demos/mainwindow/toolbar.h b/demos/mainwindow/toolbar.h
new file mode 100644
index 0000000..a9b9af2
--- /dev/null
+++ b/demos/mainwindow/toolbar.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOLBAR_H
+#define TOOLBAR_H
+
+#include <QToolBar>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QActionGroup)
+QT_FORWARD_DECLARE_CLASS(QMenu)
+QT_FORWARD_DECLARE_CLASS(QSpinBox)
+QT_FORWARD_DECLARE_CLASS(QLabel)
+
+class ToolBar : public QToolBar
+{
+ Q_OBJECT
+
+ QSpinBox *spinbox;
+ QAction *spinboxAction;
+
+ QAction *orderAction;
+ QAction *randomizeAction;
+ QAction *addSpinBoxAction;
+ QAction *removeSpinBoxAction;
+
+ QAction *movableAction;
+
+ QActionGroup *allowedAreasActions;
+ QAction *allowLeftAction;
+ QAction *allowRightAction;
+ QAction *allowTopAction;
+ QAction *allowBottomAction;
+
+ QActionGroup *areaActions;
+ QAction *leftAction;
+ QAction *rightAction;
+ QAction *topAction;
+ QAction *bottomAction;
+
+ QAction *toolBarBreakAction;
+
+public:
+ ToolBar(const QString &title, QWidget *parent);
+
+ QMenu *menu;
+
+protected:
+ void enterEvent(QEvent*);
+ void leaveEvent(QEvent*);
+
+private:
+ void allow(Qt::ToolBarArea area, bool allow);
+ void place(Qt::ToolBarArea area, bool place);
+ QLabel *tip;
+
+private slots:
+ void order();
+ void randomize();
+ void addSpinBox();
+ void removeSpinBox();
+
+ void changeMovable(bool movable);
+
+ void allowLeft(bool a);
+ void allowRight(bool a);
+ void allowTop(bool a);
+ void allowBottom(bool a);
+
+ void placeLeft(bool p);
+ void placeRight(bool p);
+ void placeTop(bool p);
+ void placeBottom(bool p);
+
+ void updateMenu();
+ void insertToolBarBreak();
+
+};
+
+#endif