summaryrefslogtreecommitdiffstats
path: root/src/qt3support/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt3support/widgets')
-rw-r--r--src/qt3support/widgets/q3action.cpp2236
-rw-r--r--src/qt3support/widgets/q3action.h225
-rw-r--r--src/qt3support/widgets/q3button.cpp127
-rw-r--r--src/qt3support/widgets/q3button.h71
-rw-r--r--src/qt3support/widgets/q3buttongroup.cpp565
-rw-r--r--src/qt3support/widgets/q3buttongroup.h152
-rw-r--r--src/qt3support/widgets/q3combobox.cpp2356
-rw-r--r--src/qt3support/widgets/q3combobox.h224
-rw-r--r--src/qt3support/widgets/q3datetimeedit.cpp2826
-rw-r--r--src/qt3support/widgets/q3datetimeedit.h288
-rw-r--r--src/qt3support/widgets/q3dockarea.cpp1349
-rw-r--r--src/qt3support/widgets/q3dockarea.h199
-rw-r--r--src/qt3support/widgets/q3dockwindow.cpp2115
-rw-r--r--src/qt3support/widgets/q3dockwindow.h239
-rw-r--r--src/qt3support/widgets/q3frame.cpp200
-rw-r--r--src/qt3support/widgets/q3frame.h90
-rw-r--r--src/qt3support/widgets/q3grid.cpp138
-rw-r--r--src/qt3support/widgets/q3grid.h79
-rw-r--r--src/qt3support/widgets/q3gridview.cpp367
-rw-r--r--src/qt3support/widgets/q3gridview.h137
-rw-r--r--src/qt3support/widgets/q3groupbox.cpp964
-rw-r--r--src/qt3support/widgets/q3groupbox.h159
-rw-r--r--src/qt3support/widgets/q3hbox.cpp145
-rw-r--r--src/qt3support/widgets/q3hbox.h77
-rw-r--r--src/qt3support/widgets/q3header.cpp2040
-rw-r--r--src/qt3support/widgets/q3header.h225
-rw-r--r--src/qt3support/widgets/q3hgroupbox.cpp92
-rw-r--r--src/qt3support/widgets/q3hgroupbox.h69
-rw-r--r--src/qt3support/widgets/q3mainwindow.cpp2427
-rw-r--r--src/qt3support/widgets/q3mainwindow.h267
-rw-r--r--src/qt3support/widgets/q3mainwindow_p.h116
-rw-r--r--src/qt3support/widgets/q3popupmenu.cpp153
-rw-r--r--src/qt3support/widgets/q3popupmenu.h93
-rw-r--r--src/qt3support/widgets/q3progressbar.cpp464
-rw-r--r--src/qt3support/widgets/q3progressbar.h148
-rw-r--r--src/qt3support/widgets/q3rangecontrol.cpp550
-rw-r--r--src/qt3support/widgets/q3rangecontrol.h194
-rw-r--r--src/qt3support/widgets/q3scrollview.cpp2803
-rw-r--r--src/qt3support/widgets/q3scrollview.h253
-rw-r--r--src/qt3support/widgets/q3spinwidget.cpp473
-rw-r--r--src/qt3support/widgets/q3titlebar.cpp645
-rw-r--r--src/qt3support/widgets/q3titlebar_p.h134
-rw-r--r--src/qt3support/widgets/q3toolbar.cpp840
-rw-r--r--src/qt3support/widgets/q3toolbar.h122
-rw-r--r--src/qt3support/widgets/q3vbox.cpp72
-rw-r--r--src/qt3support/widgets/q3vbox.h67
-rw-r--r--src/qt3support/widgets/q3vgroupbox.cpp92
-rw-r--r--src/qt3support/widgets/q3vgroupbox.h69
-rw-r--r--src/qt3support/widgets/q3whatsthis.cpp220
-rw-r--r--src/qt3support/widgets/q3whatsthis.h89
-rw-r--r--src/qt3support/widgets/q3widgetstack.cpp571
-rw-r--r--src/qt3support/widgets/q3widgetstack.h112
-rw-r--r--src/qt3support/widgets/widgets.pri58
53 files changed, 28786 insertions, 0 deletions
diff --git a/src/qt3support/widgets/q3action.cpp b/src/qt3support/widgets/q3action.cpp
new file mode 100644
index 0000000..4e1a1bf
--- /dev/null
+++ b/src/qt3support/widgets/q3action.cpp
@@ -0,0 +1,2236 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3action.h"
+
+#ifndef QT_NO_ACTION
+
+#include "qevent.h"
+#include "q3toolbar.h"
+#include "qlist.h"
+#include "q3popupmenu.h"
+#include "q3accel.h"
+#include "qtoolbutton.h"
+#include "qcombobox.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#include "qstatusbar.h"
+#include "qaction.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3Action
+ \brief The Q3Action class provides an abstract user interface
+ action that can appear both in menus and tool bars.
+
+ \compat
+
+ In GUI applications many commands can be invoked via a menu
+ option, a toolbar button and a keyboard accelerator. Since the
+ same action must be performed regardless of how the action was
+ invoked, and since the menu and toolbar should be kept in sync, it
+ is useful to represent a command as an \e action. An action can be
+ added to a menu and a toolbar and will automatically keep them in
+ sync. For example, if the user presses a Bold toolbar button the
+ Bold menu item will automatically be checked.
+
+ A Q3Action may contain an icon, a menu text, an accelerator, a
+ status text, a "What's This?" text and a tool tip. Most of these can
+ be set in the constructor. They can also be set independently with
+ setIconSet(), setText(), setMenuText(), setToolTip(),
+ setStatusTip(), setWhatsThis() and setAccel().
+
+ An action may be a toggle action e.g. a Bold toolbar button, or a
+ command action, e.g. 'Open File' to invoke an open file dialog.
+ Toggle actions emit the toggled() signal when their state changes.
+ Both command and toggle actions emit the activated() signal when
+ they are invoked. Use setToggleAction() to set an action's toggled
+ status. To see if an action is a toggle action use
+ isToggleAction(). A toggle action may be "on", isOn() returns
+ true, or "off", isOn() returns false.
+
+ Actions are added to widgets (menus or toolbars) using addTo(),
+ and removed using removeFrom(). Note that when using Q3ToolBar and
+ Q3PopupMenu, their actions must be Q3Actions.
+
+ Once a Q3Action has been created it should be added to the relevant
+ menu and toolbar and then connected to the slot which will perform
+ the action.
+
+ We recommend that actions are created as children of the window
+ that they are used in. In most cases actions will be children of
+ the application's main window.
+
+ To prevent recursion, don't create an action as a child of a
+ widget that the action is later added to.
+*/
+
+class Q3ActionPrivate
+{
+public:
+ Q3ActionPrivate(Q3Action *act);
+ ~Q3ActionPrivate();
+ QIcon *icon;
+ QString text;
+ QString menutext;
+ QString tooltip;
+ QString statustip;
+ QString whatsthis;
+#ifndef QT_NO_ACCEL
+ QKeySequence key;
+ Q3Accel* accel;
+ int accelid;
+#endif
+ uint enabled : 1;
+ uint visible : 1;
+ uint toggleaction : 1;
+ uint on : 1;
+ uint forceDisabled : 1;
+ uint forceInvisible : 1;
+ Q3ActionGroupPrivate* d_group;
+ Q3Action *action;
+
+ struct MenuItem {
+ MenuItem():popup(0),id(0){}
+ Q3PopupMenu* popup;
+ int id;
+ };
+ // ComboItem is only necessary for actions that are
+ // in dropdown/exclusive actiongroups. The actiongroup
+ // will clean this up
+ struct ComboItem {
+ ComboItem():combo(0), id(0) {}
+ QComboBox *combo;
+ int id;
+ };
+ //just bindings to the Qt4.0 widgets
+ struct Action4Item {
+ Action4Item():widget(0){}
+ QWidget* widget;
+ static QAction *action;
+ };
+ QList<Action4Item *> action4items;
+ QList<MenuItem *> menuitems;
+ QList<QToolButton *> toolbuttons;
+ QList<ComboItem *> comboitems;
+
+ enum Update { Icons = 1, Visibility = 2, State = 4, EverythingElse = 8 };
+ void update(uint upd = EverythingElse);
+
+ QString menuText() const;
+ QString toolTip() const;
+ QString statusTip() const;
+};
+QAction *Q3ActionPrivate::Action4Item::action = 0;
+
+Q3ActionPrivate::Q3ActionPrivate(Q3Action *act)
+ : icon(0),
+#ifndef QT_NO_ACCEL
+ key(0), accel(0), accelid(0),
+#endif
+ enabled(true), visible(true), toggleaction(false), on(false),
+ forceDisabled(false), forceInvisible(false)
+ , d_group(0), action(act)
+{
+}
+
+Q3ActionPrivate::~Q3ActionPrivate()
+{
+ QList<QToolButton*>::Iterator ittb(toolbuttons.begin());
+ QToolButton *tb;
+
+ while (ittb != toolbuttons.end()) {
+ tb = *ittb;
+ ++ittb;
+ delete tb;
+ }
+
+ QList<Q3ActionPrivate::MenuItem*>::Iterator itmi(menuitems.begin());
+ Q3ActionPrivate::MenuItem* mi;
+ while (itmi != menuitems.end()) {
+ mi = *itmi;
+ ++itmi;
+ Q3PopupMenu* menu = mi->popup;
+ if (menu->findItem(mi->id))
+ menu->removeItem(mi->id);
+ }
+ qDeleteAll(menuitems);
+
+ QList<Q3ActionPrivate::Action4Item*>::Iterator itmi4(action4items.begin());
+ Q3ActionPrivate::Action4Item* mi4;
+ while (itmi4 != action4items.end()) {
+ mi4 = *itmi4;
+ ++itmi4;
+ mi4->widget->removeAction(mi4->action);
+ }
+ delete Q3ActionPrivate::Action4Item::action;
+ Q3ActionPrivate::Action4Item::action = 0;
+ qDeleteAll(action4items);
+
+ QList<Q3ActionPrivate::ComboItem*>::Iterator itci(comboitems.begin());
+ Q3ActionPrivate::ComboItem* ci;
+ while (itci != comboitems.end()) {
+ ci = *itci;
+ ++itci;
+ QComboBox* combo = ci->combo;
+ combo->clear();
+ Q3ActionGroup *group = qobject_cast<Q3ActionGroup*>(action->parent());
+ if (group) {
+ QObjectList siblings = group->queryList("Q3Action");
+
+ for (int i = 0; i < siblings.size(); ++i) {
+ Q3Action *sib = qobject_cast<Q3Action*>(siblings.at(i));
+ sib->removeFrom(combo);
+ }
+ for (int i = 0; i < siblings.size(); ++i) {
+ Q3Action *sib = qobject_cast<Q3Action*>(siblings.at(i));
+ if (sib == action)
+ continue;
+ sib->addTo(combo);
+ }
+ }
+ }
+ qDeleteAll(comboitems);
+
+#ifndef QT_NO_ACCEL
+ delete accel;
+#endif
+ delete icon;
+}
+
+class Q3ActionGroupPrivate
+{
+public:
+ uint exclusive: 1;
+ uint dropdown: 1;
+ QList<Q3Action*> actions;
+ Q3Action* selected;
+ Q3Action* separatorAction;
+
+ struct MenuItem {
+ MenuItem():popup(0),id(0){}
+ Q3PopupMenu* popup;
+ int id;
+ };
+ struct Action4Item {
+ Action4Item():widget(0){}
+ QWidget* widget;
+ static QAction *action;
+ };
+ QList<Action4Item *> action4items;
+ QList<QComboBox*> comboboxes;
+ QList<QToolButton*> menubuttons;
+ QList<MenuItem*> menuitems;
+ QList<Q3PopupMenu*> popupmenus;
+
+ void update(const Q3ActionGroup *);
+};
+QAction *Q3ActionGroupPrivate::Action4Item::action = 0;
+
+void Q3ActionPrivate::update(uint upd)
+{
+ for (QList<MenuItem*>::Iterator it(menuitems.begin()); it != menuitems.end(); ++it) {
+ MenuItem* mi = *it;
+ QString t = menuText();
+#ifndef QT_NO_ACCEL
+ if (key)
+ t += QLatin1Char('\t') + (QString)QKeySequence(key);
+#endif
+ if (upd & State) {
+ mi->popup->setItemEnabled(mi->id, enabled);
+ if (toggleaction)
+ mi->popup->setItemChecked(mi->id, on);
+ }
+ if (upd & Visibility)
+ mi->popup->setItemVisible(mi->id, visible);
+
+ if (upd & Icons) {
+ if (icon)
+ mi->popup->changeItem(mi->id, *icon, t);
+ else
+ mi->popup->changeItem(mi->id, QIcon(), t);
+ }
+ if (upd & EverythingElse) {
+ mi->popup->changeItem(mi->id, t);
+ if (!whatsthis.isEmpty())
+ mi->popup->setWhatsThis(mi->id, whatsthis);
+ if (toggleaction) {
+ mi->popup->setCheckable(true);
+ mi->popup->setItemChecked(mi->id, on);
+ }
+ }
+ }
+ if(QAction *act = Action4Item::action) {
+ if (upd & Visibility)
+ act->setVisible(visible);
+ if (upd & Icons) {
+ if (icon)
+ act->setIcon(*icon);
+ else
+ act->setIcon(QIcon());
+ }
+ if (upd & EverythingElse) {
+ QString text = action->menuText();
+#ifndef QT_NO_ACCEL
+ if (key)
+ text += QLatin1Char('\t') + (QString)QKeySequence(key);
+#endif
+ act->setText(text);
+ act->setToolTip(statusTip());
+ act->setWhatsThis(whatsthis);
+ }
+ }
+ for (QList<QToolButton*>::Iterator it2(toolbuttons.begin()); it2 != toolbuttons.end(); ++it2) {
+ QToolButton* btn = *it2;
+ if (upd & State) {
+ btn->setEnabled(enabled);
+ if (toggleaction)
+ btn->setOn(on);
+ }
+ if (upd & Visibility)
+ visible ? btn->show() : btn->hide();
+ if (upd & Icons) {
+ if (icon)
+ btn->setIconSet(*icon);
+ else
+ btn->setIconSet(QIcon());
+ }
+ if (upd & EverythingElse) {
+ btn->setToggleButton(toggleaction);
+ if (!text.isEmpty())
+ btn->setTextLabel(text, false);
+#ifndef QT_NO_TOOLTIP
+ btn->setToolTip(toolTip());
+#endif
+#ifndef QT_NO_STATUSTIP
+ btn->setStatusTip(statusTip());
+#endif
+#ifndef QT_NO_WHATSTHIS
+ QWhatsThis::remove(btn);
+ if (!whatsthis.isEmpty())
+ QWhatsThis::add(btn, whatsthis);
+#endif
+ }
+ }
+#ifndef QT_NO_ACCEL
+ if (accel) {
+ accel->setEnabled(enabled && visible);
+ if (!whatsthis.isEmpty())
+ accel->setWhatsThis(accelid, whatsthis);
+ }
+#endif
+ // Only used by actiongroup
+ for (QList<ComboItem*>::Iterator it3(comboitems.begin()); it3 != comboitems.end(); ++it3) {
+ ComboItem *ci = *it3;
+ if (!ci->combo)
+ return;
+ if (ci->id == -1) {
+ ci->id = ci->combo->count();
+ if (icon)
+ ci->combo->insertItem(icon->pixmap(), text);
+ else
+ ci->combo->insertItem(text);
+ } else {
+ if (icon)
+ ci->combo->changeItem(icon->pixmap(), text, ci->id);
+ else
+ ci->combo->changeItem(text, ci->id);
+ }
+ }
+}
+
+QString Q3ActionPrivate::menuText() const
+{
+ if (menutext.isNull()) {
+ QString t(text);
+ t.replace(QLatin1Char('&'), QLatin1String("&&"));
+ return t;
+ }
+ return menutext;
+}
+
+QString Q3ActionPrivate::toolTip() const
+{
+ if (tooltip.isNull()) {
+#ifndef QT_NO_ACCEL
+ if (accel)
+ return text + QLatin1String(" (") + (QString)QKeySequence(accel->key(accelid)) + QLatin1Char(')');
+#endif
+ return text;
+ }
+ return tooltip;
+}
+
+QString Q3ActionPrivate::statusTip() const
+{
+ if (statustip.isNull())
+ return toolTip();
+ return statustip;
+}
+
+/*
+ internal: guesses a descriptive text from a menu text
+ */
+static QString qt_stripMenuText(QString s)
+{
+ s.remove(QLatin1String("..."));
+ s.remove(QLatin1Char('&'));
+ return s.trimmed();
+};
+
+/*!
+ Constructs an action called \a name with parent \a parent.
+
+ If \a parent is a Q3ActionGroup, the new action inserts itself into
+ \a parent.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+
+ \warning To prevent recursion, don't create an action as a child
+ of a widget that the action is later added to.
+*/
+Q3Action::Q3Action(QObject* parent, const char* name)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ init();
+}
+
+/*!
+ Constructs an action called \a name with parent \a parent.
+
+ If \a toggle is true the action will be a toggle action, otherwise
+ it will be a command action.
+
+ If \a parent is a Q3ActionGroup, the new action inserts itself into
+ \a parent.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+*/
+Q3Action::Q3Action(QObject* parent, const char* name, bool toggle)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ d->toggleaction = toggle;
+ init();
+}
+
+
+#ifndef QT_NO_ACCEL
+
+/*!
+ This constructor creates an action with the following properties:
+ the icon or icon \a icon, the menu text \a menuText and
+ keyboard accelerator \a accel. It is a child of \a parent and
+ called \a name.
+
+ If \a parent is a Q3ActionGroup, the action automatically becomes
+ a member of it.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+
+ The action uses a stripped version of \a menuText (e.g. "\&Menu
+ Option..." becomes "Menu Option") as descriptive text for
+ tool buttons. You can override this by setting a specific
+ description with setText(). The same text and \a accel will be
+ used for tool tips and status tips unless you provide text for
+ these using setToolTip() and setStatusTip().
+
+ Call setToggleAction(true) to make the action a toggle action.
+
+ \warning To prevent recursion, don't create an action as a child
+ of a widget that the action is later added to.
+*/
+Q3Action::Q3Action(const QIcon& icon, const QString& menuText, QKeySequence accel,
+ QObject* parent, const char* name)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ if (!icon.isNull())
+ setIconSet(icon);
+ d->text = qt_stripMenuText(menuText);
+ d->menutext = menuText;
+ setAccel(accel);
+ init();
+}
+
+/*!
+ This constructor results in an icon-less action with the the menu
+ text \a menuText and keyboard accelerator \a accel. It is a child
+ of \a parent and called \a name.
+
+ If \a parent is a Q3ActionGroup, the action automatically becomes
+ a member of it.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+
+ The action uses a stripped version of \a menuText (e.g. "\&Menu
+ Option..." becomes "Menu Option") as descriptive text for
+ tool buttons. You can override this by setting a specific
+ description with setText(). The same text and \a accel will be
+ used for tool tips and status tips unless you provide text for
+ these using setToolTip() and setStatusTip().
+
+ Call setToggleAction(true) to make the action a toggle action.
+
+ \warning To prevent recursion, don't create an action as a child
+ of a widget that the action is later added to.
+*/
+Q3Action::Q3Action(const QString& menuText, QKeySequence accel,
+ QObject* parent, const char* name)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ d->text = qt_stripMenuText(menuText);
+ d->menutext = menuText;
+ setAccel(accel);
+ init();
+}
+
+/*!
+ This constructor creates an action with the following properties:
+ the description \a text, the icon or icon \a icon, the menu
+ text \a menuText and keyboard accelerator \a accel. It is a child
+ of \a parent and called \a name. If \a toggle is true the action
+ will be a toggle action, otherwise it will be a command action.
+
+ If \a parent is a Q3ActionGroup, the action automatically becomes
+ a member of it.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+
+ The \a text and \a accel will be used for tool tips and status
+ tips unless you provide specific text for these using setToolTip()
+ and setStatusTip().
+*/
+Q3Action::Q3Action(const QString& text, const QIcon& icon, const QString& menuText, QKeySequence accel, QObject* parent, const char* name, bool toggle)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ d->toggleaction = toggle;
+ if (!icon.isNull())
+ setIconSet(icon);
+
+ d->text = text;
+ d->menutext = menuText;
+ setAccel(accel);
+ init();
+}
+
+/*!
+ This constructor results in an icon-less action with the
+ description \a text, the menu text \a menuText and the keyboard
+ accelerator \a accel. Its parent is \a parent and it is called \a
+ name. If \a toggle is true the action will be a toggle action,
+ otherwise it will be a command action.
+
+ The action automatically becomes a member of \a parent if \a
+ parent is a Q3ActionGroup.
+
+ For accelerators and status tips to work, \a parent must either be
+ a widget, or an action group whose parent is a widget.
+
+ The \a text and \a accel will be used for tool tips and status
+ tips unless you provide specific text for these using setToolTip()
+ and setStatusTip().
+*/
+Q3Action::Q3Action(const QString& text, const QString& menuText, QKeySequence accel, QObject* parent, const char* name, bool toggle)
+ : QObject(parent, name)
+{
+ d = new Q3ActionPrivate(this);
+ d->toggleaction = toggle;
+ d->text = text;
+ d->menutext = menuText;
+ setAccel(accel);
+ init();
+}
+#endif
+
+/*!
+ \internal
+*/
+void Q3Action::init()
+{
+ if (qobject_cast<Q3ActionGroup*>(parent()))
+ ((Q3ActionGroup*) parent())->add(this); // insert into action group
+}
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+
+Q3Action::~Q3Action()
+{
+ delete d;
+}
+
+/*!
+ \property Q3Action::iconSet
+ \brief the action's icon
+
+ The icon is used as the tool button icon and in the menu to the
+ left of the menu text. There is no default icon.
+
+ If a null icon (QIcon::isNull() is passed into this function,
+ the icon of the action is cleared.
+
+ (See the action/toggleaction/toggleaction.cpp example.)
+
+*/
+void Q3Action::setIconSet(const QIcon& icon)
+{
+ register QIcon *i = d->icon;
+ if (!icon.isNull())
+ d->icon = new QIcon(icon);
+ else
+ d->icon = 0;
+ delete i;
+ d->update(Q3ActionPrivate::Icons);
+}
+
+QIcon Q3Action::iconSet() const
+{
+ if (d->icon)
+ return *d->icon;
+ return QIcon();
+}
+
+/*!
+ \property Q3Action::text
+ \brief the action's descriptive text
+
+ \sa setMenuText() setToolTip() setStatusTip()
+*/
+void Q3Action::setText(const QString& text)
+{
+ d->text = text;
+ d->update();
+}
+
+QString Q3Action::text() const
+{
+ return d->text;
+}
+
+
+/*!
+ \property Q3Action::menuText
+ \brief the action's menu text
+
+ If the action is added to a menu the menu option will consist of
+ the icon (if there is one), the menu text and the accelerator (if
+ there is one). If the menu text is not explicitly set in the
+ constructor or by using setMenuText() the action's description
+ text will be used as the menu text. There is no default menu text.
+
+ \sa text
+*/
+void Q3Action::setMenuText(const QString& text)
+{
+ if (d->menutext == text)
+ return;
+
+ d->menutext = text;
+ d->update();
+}
+
+QString Q3Action::menuText() const
+{
+ return d->menuText();
+}
+
+/*!
+ \property Q3Action::toolTip
+ \brief the action's tool tip
+
+ This text is used for the tool tip. If no status tip has been set
+ the tool tip will be used for the status tip.
+
+ If no tool tip is specified the action's text is used, and if that
+ hasn't been specified the description text is used as the tool tip
+ text.
+
+ There is no default tool tip text.
+
+ \sa setStatusTip() setAccel()
+*/
+void Q3Action::setToolTip(const QString& tip)
+{
+ if (d->tooltip == tip)
+ return;
+
+ d->tooltip = tip;
+ d->update();
+}
+
+QString Q3Action::toolTip() const
+{
+ return d->toolTip();
+}
+
+/*!
+ \property Q3Action::statusTip
+ \brief the action's status tip
+
+ The statusTip is displayed on all status bars that this action's
+ top-level parent widget provides.
+
+ If no status tip is defined, the action uses the tool tip text.
+
+ There is no default statusTip text.
+
+ \sa setToolTip()
+*/
+void Q3Action::setStatusTip(const QString& tip)
+{
+ // Old comment: ### Please reimp for Q3ActionGroup!
+ // For consistency reasons even action groups should show
+ // status tips (as they already do with tool tips)
+ // Please change Q3ActionGroup class doc appropriately after
+ // reimplementation.
+
+ if (d->statustip == tip)
+ return;
+
+ d->statustip = tip;
+ d->update();
+}
+
+QString Q3Action::statusTip() const
+{
+ return d->statusTip();
+}
+
+/*!
+ \property Q3Action::whatsThis
+ \brief the action's "What's This?" help text
+
+ The whats this text is used to provide a brief description of the
+ action. The text may contain rich text (HTML-like tags -- see
+ QStyleSheet for the list of supported tags). There is no default
+ "What's This?" text.
+
+ \sa QWhatsThis
+*/
+void Q3Action::setWhatsThis(const QString& whatsThis)
+{
+ if (d->whatsthis == whatsThis)
+ return;
+ d->whatsthis = whatsThis;
+ d->update();
+}
+
+QString Q3Action::whatsThis() const
+{
+ return d->whatsthis;
+}
+
+
+#ifndef QT_NO_ACCEL
+/*!
+ \property Q3Action::accel
+ \brief the action's accelerator key
+
+ The keycodes can be found in \l Qt::Key and \l Qt::Modifier. There
+ is no default accelerator key.
+*/
+//#### Please reimp for Q3ActionGroup!
+//#### For consistency reasons even Q3ActionGroups should respond to
+//#### their accelerators and e.g. open the relevant submenu.
+//#### Please change appropriate Q3ActionGroup class doc after
+//#### reimplementation.
+void Q3Action::setAccel(const QKeySequence& key)
+{
+ if (d->key == key)
+ return;
+
+ d->key = key;
+ delete d->accel;
+ d->accel = 0;
+
+ if (!(int)key) {
+ d->update();
+ return;
+ }
+
+ QObject* p = parent();
+ while (p && !p->isWidgetType()) {
+ p = p->parent();
+ }
+ if (p) {
+ d->accel = new Q3Accel((QWidget*)p, this, "qt_action_accel");
+ d->accelid = d->accel->insertItem(d->key);
+ d->accel->connectItem(d->accelid, this, SLOT(internalActivation()));
+ } else
+ qWarning("Q3Action::setAccel() (%s) requires widget in parent chain", objectName().toLocal8Bit().data());
+ d->update();
+}
+
+
+QKeySequence Q3Action::accel() const
+{
+ return d->key;
+}
+#endif
+
+
+/*!
+ \property Q3Action::toggleAction
+ \brief whether the action is a toggle action
+
+ A toggle action is one which has an on/off state. For example a
+ Bold toolbar button is either on or off. An action which is not a
+ toggle action is a command action; a command action is simply
+ executed, e.g. file save. This property's default is false.
+
+ In some situations, the state of one toggle action should depend
+ on the state of others. For example, "Left Align", "Center" and
+ "Right Align" toggle actions are mutually exclusive. To achieve
+ exclusive toggling, add the relevant toggle actions to a
+ Q3ActionGroup with the \l Q3ActionGroup::exclusive property set to
+ true.
+*/
+void Q3Action::setToggleAction(bool enable)
+{
+ if (enable == (bool)d->toggleaction)
+ return;
+
+ if (!enable)
+ d->on = false;
+
+ d->toggleaction = enable;
+ d->update();
+}
+
+bool Q3Action::isToggleAction() const
+{
+ return d->toggleaction;
+}
+
+/*!
+ Activates the action and executes all connected slots.
+ This only works for actions that are not toggle actions.
+
+ \sa toggle()
+*/
+void Q3Action::activate()
+{
+ if (isToggleAction()) {
+#if defined(QT_CHECK_STATE)
+ qWarning("Q3Action::%s() (%s) Toggle actions "
+ "can not be activated", "activate", objectName().toLocal8Bit().data());
+#endif
+ return;
+ }
+ emit activated();
+}
+
+/*!
+ Toggles the state of a toggle action.
+
+ \sa on, activate(), toggled(), isToggleAction()
+*/
+void Q3Action::toggle()
+{
+ if (!isToggleAction()) {
+ qWarning("Q3Action::%s() (%s) Only toggle actions "
+ "can be switched", "toggle", objectName().toLocal8Bit().data());
+ return;
+ }
+ setOn(!isOn());
+}
+
+/*!
+ \property Q3Action::on
+ \brief whether a toggle action is on
+
+ This property is always on (true) for command actions and
+ \l{Q3ActionGroup}s; setOn() has no effect on them. For action's
+ where isToggleAction() is true, this property's default value is
+ off (false).
+
+ \sa toggleAction
+*/
+void Q3Action::setOn(bool enable)
+{
+ if (!isToggleAction()) {
+ if (enable)
+ qWarning("Q3Action::%s() (%s) Only toggle actions "
+ "can be switched", "setOn", objectName().toLocal8Bit().data());
+ return;
+ }
+ if (enable == (bool)d->on)
+ return;
+ d->on = enable;
+ d->update(Q3ActionPrivate::State);
+ emit toggled(enable);
+}
+
+bool Q3Action::isOn() const
+{
+ return d->on;
+}
+
+/*!
+ \property Q3Action::enabled
+ \brief whether the action is enabled
+
+ Disabled actions can't be chosen by the user. They don't disappear
+ from the menu/tool bar but are displayed in a way which indicates
+ that they are unavailable, e.g. they might be displayed grayed
+ out.
+
+ What's this? help on disabled actions is still available provided
+ the \l Q3Action::whatsThis property is set.
+*/
+void Q3Action::setEnabled(bool enable)
+{
+ d->forceDisabled = !enable;
+
+ if ((bool)d->enabled == enable)
+ return;
+
+ d->enabled = enable;
+ d->update(Q3ActionPrivate::State);
+}
+
+bool Q3Action::isEnabled() const
+{
+ return d->enabled;
+}
+
+/*!
+ Disables the action if \a disable is true; otherwise
+ enables the action.
+
+ See the \l enabled documentation for more information.
+*/
+void Q3Action::setDisabled(bool disable)
+{
+ setEnabled(!disable);
+}
+
+/*!
+ \property Q3Action::visible
+ \brief whether the action can be seen (e.g. in menus and toolbars)
+
+ If \e visible is true the action can be seen (e.g. in menus and
+ toolbars) and chosen by the user; if \e visible is false the
+ action cannot be seen or chosen by the user.
+
+ Actions which are not visible are \e not grayed out; they do not
+ appear at all.
+*/
+void Q3Action::setVisible(bool visible)
+{
+ d->forceInvisible = !visible;
+
+ if ((bool)d->visible == visible)
+ return;
+
+ d->visible = visible;
+ d->update(Q3ActionPrivate::Visibility);
+}
+
+/*
+ Returns true if the action is visible (e.g. in menus and
+ toolbars); otherwise returns false.
+*/
+bool Q3Action::isVisible() const
+{
+ return d->visible;
+}
+
+/*! \internal
+*/
+void Q3Action::internalActivation()
+{
+ if (isToggleAction())
+ setOn(!isOn());
+ emit activated();
+}
+
+/*! \internal
+*/
+void Q3Action::toolButtonToggled(bool on)
+{
+ if (!isToggleAction())
+ return;
+ setOn(on);
+}
+
+/*!
+ Adds this action to widget \a w.
+
+ Currently actions may be added to Q3ToolBar and Q3PopupMenu widgets.
+
+ An action added to a tool bar is automatically displayed as a tool
+ button; an action added to a pop up menu appears as a menu option.
+
+ addTo() returns true if the action was added successfully and
+ false otherwise. (If \a w is not a Q3ToolBar or Q3PopupMenu the
+ action will not be added and false will be returned.)
+
+ \sa removeFrom()
+*/
+bool Q3Action::addTo(QWidget* w)
+{
+#ifndef QT_NO_TOOLBAR
+ if (qobject_cast<Q3ToolBar*>(w)) {
+ if (objectName() == QLatin1String("qt_separator_action")) {
+ ((Q3ToolBar*)w)->addSeparator();
+ } else {
+ QString bname = objectName() + QLatin1String("_action_button");
+ QToolButton* btn = new QToolButton((Q3ToolBar*) w);
+ btn->setObjectName(bname);
+ addedTo(btn, w);
+ btn->setToggleButton(d->toggleaction);
+ d->toolbuttons.append(btn);
+ if (d->icon)
+ btn->setIconSet(*d->icon);
+ d->update(Q3ActionPrivate::State | Q3ActionPrivate::Visibility | Q3ActionPrivate::EverythingElse) ;
+ connect(btn, SIGNAL(clicked()), this, SIGNAL(activated()));
+ connect(btn, SIGNAL(toggled(bool)), this, SLOT(toolButtonToggled(bool)));
+ connect(btn, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ }
+ } else
+#endif
+ if (qobject_cast<Q3PopupMenu*>(w)) {
+ Q3ActionPrivate::MenuItem* mi = new Q3ActionPrivate::MenuItem;
+ mi->popup = (Q3PopupMenu*) w;
+ QIcon* dicon = d->icon;
+ if (objectName() == QLatin1String("qt_separator_action"))
+ mi->id = ((Q3PopupMenu*)w)->insertSeparator();
+ else if (dicon)
+ mi->id = mi->popup->insertItem(*dicon, QString::fromLatin1(""));
+ else
+ mi->id = mi->popup->insertItem(QString::fromLatin1(""));
+ addedTo(mi->popup->indexOf(mi->id), mi->popup);
+ mi->popup->connectItem(mi->id, this, SLOT(internalActivation()));
+ d->menuitems.append(mi);
+ d->update(Q3ActionPrivate::State | Q3ActionPrivate::Visibility | Q3ActionPrivate::EverythingElse);
+ connect(mi->popup, SIGNAL(highlighted(int)), this, SLOT(menuStatusText(int)));
+ connect(mi->popup, SIGNAL(aboutToHide()), this, SLOT(clearStatusText()));
+ connect(mi->popup, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ // Makes only sense when called by Q3ActionGroup::addTo
+ } else if (qobject_cast<QComboBox*>(w)) {
+ Q3ActionPrivate::ComboItem *ci = new Q3ActionPrivate::ComboItem;
+ ci->combo = (QComboBox*)w;
+ connect(ci->combo, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ ci->id = ci->combo->count();
+ if (objectName() == QLatin1String("qt_separator_action")) {
+ if (d->icon)
+ ci->combo->insertItem(d->icon->pixmap(), text());
+ else
+ ci->combo->insertItem(text());
+ } else {
+ ci->id = -1;
+ }
+ d->comboitems.append(ci);
+ d->update(Q3ActionPrivate::State | Q3ActionPrivate::EverythingElse);
+ } else if(qobject_cast<QMenu*>(w)) {
+ Q3ActionPrivate::Action4Item *act = new Q3ActionPrivate::Action4Item;
+ if(!act->action) { //static
+ act->action = new QAction(this);
+ if (objectName() == QLatin1String("qt_separator_action"))
+ act->action->setSeparator(true);
+ }
+ act->widget = w;
+ act->widget->addAction(act->action);
+ d->action4items.append(act);
+ d->update(Q3ActionPrivate::State | Q3ActionPrivate::EverythingElse);
+ } else {
+ qWarning("Q3Action::addTo(), unknown object");
+ return false;
+ }
+ return true;
+}
+
+/*!
+ This function is called from the addTo() function when it has
+ created a widget (\a actionWidget) for the action in the \a
+ container.
+*/
+
+void Q3Action::addedTo(QWidget *actionWidget, QWidget *container)
+{
+ Q_UNUSED(actionWidget);
+ Q_UNUSED(container);
+}
+
+/*!
+ \overload
+
+ This function is called from the addTo() function when it has
+ created a menu item at the index position \a index in the popup
+ menu \a menu.
+*/
+
+void Q3Action::addedTo(int index, Q3PopupMenu *menu)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(menu);
+}
+
+/*!
+ Sets the status message to \a text
+*/
+void Q3Action::showStatusText(const QString& text)
+{
+#ifndef QT_NO_STATUSBAR
+ // find out whether we are clearing the status bar by the popup that actually set the text
+ static Q3PopupMenu *lastmenu = 0;
+ QObject *s = (QObject*)sender();
+ if (s) {
+ Q3PopupMenu *menu = qobject_cast<Q3PopupMenu*>(s);
+ if (menu && text.size())
+ lastmenu = menu;
+ else if (menu && text.isEmpty()) {
+ if (lastmenu && menu != lastmenu)
+ return;
+ lastmenu = 0;
+ }
+ }
+
+ QObject* par = parent();
+ QObject* lpar = 0;
+ QStatusBar *bar = 0;
+ while (par && !bar) {
+ lpar = par;
+ bar = (QStatusBar*)par->child(0, "QStatusBar", false);
+ par = par->parent();
+ }
+ if (!bar && lpar) {
+ QObjectList l = lpar->queryList("QStatusBar");
+ if (l.isEmpty())
+ return;
+ // #### hopefully the last one is the one of the mainwindow...
+ bar = static_cast<QStatusBar*>(l.at(l.size()-1));
+ }
+ if (bar) {
+ if (text.isEmpty())
+ bar->clearMessage();
+ else
+ bar->showMessage(text);
+ }
+#endif
+}
+
+/*!
+ Sets the status message to the menu item's status text, or to the
+ tooltip, if there is no status text.
+*/
+void Q3Action::menuStatusText(int id)
+{
+ static int lastId = 0;
+ QString text;
+ QList<Q3ActionPrivate::MenuItem*>::Iterator it(d->menuitems.begin());
+ while (it != d->menuitems.end()) {
+ if ((*it)->id == id) {
+ text = statusTip();
+ break;
+ }
+ ++it;
+ }
+
+ if (!text.isEmpty())
+ showStatusText(text);
+ else if (id != lastId)
+ clearStatusText();
+ lastId = id;
+}
+
+/*!
+ Clears the status text.
+*/
+void Q3Action::clearStatusText()
+{
+ if (!statusTip().isEmpty())
+ showStatusText(QString());
+}
+
+/*!
+ Removes the action from widget \a w.
+
+ Returns true if the action was removed successfully; otherwise
+ returns false.
+
+ \sa addTo()
+*/
+bool Q3Action::removeFrom(QWidget* w)
+{
+#ifndef QT_NO_TOOLBAR
+ if (qobject_cast<Q3ToolBar*>(w)) {
+ QList<QToolButton*>::Iterator it(d->toolbuttons.begin());
+ QToolButton* btn;
+ while (it != d->toolbuttons.end()) {
+ btn = *it;
+ ++it;
+ if (btn->parentWidget() == w) {
+ d->toolbuttons.removeAll(btn);
+ disconnect(btn, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ delete btn;
+ // no need to disconnect from status bar
+ }
+ }
+ } else
+#endif
+ if (qobject_cast<Q3PopupMenu*>(w)) {
+ QList<Q3ActionPrivate::MenuItem*>::Iterator it(d->menuitems.begin());
+ Q3ActionPrivate::MenuItem* mi;
+ while (it != d->menuitems.end()) {
+ mi = *it;
+ ++it;
+ if (mi->popup == w) {
+ disconnect(mi->popup, SIGNAL(highlighted(int)), this, SLOT(menuStatusText(int)));
+ disconnect(mi->popup, SIGNAL(aboutToHide()), this, SLOT(clearStatusText()));
+ disconnect(mi->popup, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ mi->popup->removeItem(mi->id);
+ d->menuitems.removeAll(mi);
+ delete mi;
+ }
+ }
+ } else if (qobject_cast<QComboBox*>(w)) {
+ QList<Q3ActionPrivate::ComboItem*>::Iterator it(d->comboitems.begin());
+ Q3ActionPrivate::ComboItem *ci;
+ while (it != d->comboitems.end()) {
+ ci = *it;
+ ++it;
+ if (ci->combo == w) {
+ disconnect(ci->combo, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ d->comboitems.removeAll(ci);
+ delete ci;
+ }
+ }
+ } else if (qobject_cast<QMenu*>(w)) {
+ QList<Q3ActionPrivate::Action4Item*>::Iterator it(d->action4items.begin());
+ Q3ActionPrivate::Action4Item *a4i;
+ while (it != d->action4items.end()) {
+ a4i = *it;
+ ++it;
+ if (a4i->widget == w) {
+ a4i->widget->removeAction(a4i->action);
+ d->action4items.removeAll(a4i);
+ delete a4i;
+ }
+ }
+ } else {
+ qWarning("Q3Action::removeFrom(), unknown object");
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+*/
+void Q3Action::objectDestroyed()
+{
+ const QObject* obj = sender();
+ Q3ActionPrivate::MenuItem* mi;
+ for (int i = 0; i < d->menuitems.size();) {
+ mi = d->menuitems.at(i);
+ ++i;
+ if (mi->popup == obj) {
+ d->menuitems.removeAll(mi);
+ delete mi;
+ }
+ }
+ Q3ActionPrivate::ComboItem *ci;
+ QList<Q3ActionPrivate::ComboItem*>::Iterator it2(d->comboitems.begin());
+ while (it2 != d->comboitems.end()) {
+ ci = *it2;
+ ++it2;
+ if (ci->combo == obj) {
+ d->comboitems.removeAll(ci);
+ delete ci;
+ }
+ }
+ d->toolbuttons.removeAll((QToolButton *)obj);
+}
+
+/*!
+ \fn void Q3Action::activated()
+
+ This signal is emitted when an action is activated by the user,
+ e.g. when the user clicks a menu option or a toolbar button or
+ presses an action's accelerator key combination.
+
+ Connect to this signal for command actions. Connect to the
+ toggled() signal for toggle actions.
+*/
+
+/*!
+ \fn void Q3Action::toggled(bool on)
+
+ This signal is emitted when a toggle action changes state; command
+ actions and \l{Q3ActionGroup}s don't emit toggled().
+
+ The \a on argument denotes the new state: If \a on is true the
+ toggle action is switched on, and if \a on is false the toggle
+ action is switched off.
+
+ To trigger a user command depending on whether a toggle action has
+ been switched on or off connect it to a slot that takes a bool to
+ indicate the state.
+
+ \sa activated() setToggleAction() setOn()
+*/
+
+void Q3ActionGroupPrivate::update(const Q3ActionGroup* that)
+{
+ for (QList<Q3Action*>::Iterator it(actions.begin()); it != actions.end(); ++it) {
+ if (that->isEnabled() && !(*it)->d->forceDisabled)
+ (*it)->setEnabled(true);
+ else if (!that->isEnabled() && (*it)->isEnabled()) {
+ (*it)->setEnabled(false);
+ (*it)->d->forceDisabled = false;
+ }
+ if (that->isVisible() && !(*it)->d->forceInvisible) {
+ (*it)->setVisible(true);
+ } else if (!that->isVisible() && (*it)->isVisible()) {
+ (*it)->setVisible(false);
+ (*it)->d->forceInvisible = false;
+ }
+ }
+ for (QList<QComboBox*>::Iterator cb(comboboxes.begin()); cb != comboboxes.end(); ++cb) {
+ QComboBox *combobox = *cb;
+ combobox->setEnabled(that->isEnabled());
+ combobox->setShown(that->isVisible());
+
+#ifndef QT_NO_TOOLTIP
+ QToolTip::remove(combobox);
+ if (that->toolTip().size())
+ QToolTip::add(combobox, that->toolTip());
+#endif
+#ifndef QT_NO_WHATSTHIS
+ QWhatsThis::remove(combobox);
+ if (that->whatsThis().size())
+ QWhatsThis::add(combobox, that->whatsThis());
+#endif
+
+ }
+ for (QList<QToolButton*>::Iterator mb(menubuttons.begin()); mb != menubuttons.end(); ++mb) {
+ QToolButton *button = *mb;
+ button->setEnabled(that->isEnabled());
+ button->setShown(that->isVisible());
+
+ if (!that->text().isNull())
+ button->setTextLabel(that->text());
+ if (!that->iconSet().isNull())
+ button->setIconSet(that->iconSet());
+
+#ifndef QT_NO_TOOLTIP
+ QToolTip::remove(*mb);
+ if (that->toolTip().size())
+ QToolTip::add(button, that->toolTip());
+#endif
+#ifndef QT_NO_WHATSTHIS
+ QWhatsThis::remove(button);
+ if (that->whatsThis().size())
+ QWhatsThis::add(button, that->whatsThis());
+#endif
+ }
+ if(QAction *act = Q3ActionGroupPrivate::Action4Item::action) {
+ act->setVisible(that->isVisible());
+ act->setEnabled(that->isEnabled());
+ }
+ for (QList<Q3ActionGroupPrivate::MenuItem*>::Iterator pu(menuitems.begin()); pu != menuitems.end(); ++pu) {
+ QWidget* parent = (*pu)->popup->parentWidget();
+ if (qobject_cast<Q3PopupMenu*>(parent)) {
+ Q3PopupMenu* ppopup = (Q3PopupMenu*)parent;
+ ppopup->setItemEnabled((*pu)->id, that->isEnabled());
+ ppopup->setItemVisible((*pu)->id, that->isVisible());
+ } else {
+ (*pu)->popup->setEnabled(that->isEnabled());
+ }
+ }
+ for (QList<Q3PopupMenu*>::Iterator pm(popupmenus.begin()); pm != popupmenus.end(); ++pm) {
+ Q3PopupMenu *popup = *pm;
+ Q3PopupMenu *parent = qobject_cast<Q3PopupMenu*>(popup->parentWidget());
+ if (!parent)
+ continue;
+
+ int index;
+ parent->findPopup(popup, &index);
+ int id = parent->idAt(index);
+ if (!that->iconSet().isNull())
+ parent->changeItem(id, that->iconSet(), that->menuText());
+ else
+ parent->changeItem(id, that->menuText());
+ parent->setItemEnabled(id, that->isEnabled());
+#ifndef QT_NO_ACCEL
+ parent->setAccel(that->accel(), id);
+#endif
+ }
+}
+
+/*!
+ \class Q3ActionGroup
+ \brief The Q3ActionGroup class groups actions together.
+
+ \compat
+
+ In some situations it is useful to group actions together. For
+ example, if you have a left justify action, a right justify action
+ and a center action, only one of these actions should be active at
+ any one time, and one simple way of achieving this is to group the
+ actions together in an action group.
+
+ An action group can also be added to a menu or a toolbar as a
+ single unit, with all the actions within the action group
+ appearing as separate menu options and toolbar buttons.
+
+ The actions in an action group emit their activated() (and for
+ toggle actions, toggled()) signals as usual.
+
+ The setExclusive() function is used to ensure that only one action
+ is active at any one time: it should be used with actions which
+ have their \c toggleAction set to true.
+
+ Action group actions appear as individual menu options and toolbar
+ buttons. For exclusive action groups use setUsesDropDown() to
+ display the actions in a subwidget of any widget the action group
+ is added to. For example, the actions would appear in a combobox
+ in a toolbar or as a submenu in a menu.
+
+ Actions can be added to an action group using add(), but normally
+ they are added by creating the action with the action group as
+ parent. Actions can have separators dividing them using
+ addSeparator(). Action groups are added to widgets with addTo().
+*/
+
+/*!
+ Constructs an action group called \a name, with parent \a parent.
+
+ The action group is exclusive by default. Call setExclusive(false) to make
+ the action group non-exclusive.
+*/
+Q3ActionGroup::Q3ActionGroup(QObject* parent, const char* name)
+ : Q3Action(parent, name)
+{
+ d = new Q3ActionGroupPrivate;
+ d->exclusive = true;
+ d->dropdown = false;
+ d->selected = 0;
+ d->separatorAction = 0;
+
+ connect(this, SIGNAL(selected(Q3Action*)), SLOT(internalToggle(Q3Action*)));
+}
+
+/*!
+ Constructs an action group called \a name, with parent \a parent.
+
+ If \a exclusive is true only one toggle action in the group will
+ ever be active.
+
+ \sa exclusive
+*/
+Q3ActionGroup::Q3ActionGroup(QObject* parent, const char* name, bool exclusive)
+ : Q3Action(parent, name)
+{
+ d = new Q3ActionGroupPrivate;
+ d->exclusive = exclusive;
+ d->dropdown = false;
+ d->selected = 0;
+ d->separatorAction = 0;
+
+ connect(this, SIGNAL(selected(Q3Action*)), SLOT(internalToggle(Q3Action*)));
+}
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+
+Q3ActionGroup::~Q3ActionGroup()
+{
+ QList<Q3ActionGroupPrivate::MenuItem*>::Iterator mit(d->menuitems.begin());
+ while (mit != d->menuitems.end()) {
+ Q3ActionGroupPrivate::MenuItem *mi = *mit;
+ ++mit;
+ if (mi->popup)
+ mi->popup->disconnect(SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ }
+
+ QList<QComboBox*>::Iterator cbit(d->comboboxes.begin());
+ while (cbit != d->comboboxes.end()) {
+ QComboBox *cb = *cbit;
+ ++cbit;
+ cb->disconnect(SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ }
+ QList<QToolButton*>::Iterator mbit(d->menubuttons.begin());
+ while (mbit != d->menubuttons.end()) {
+ QToolButton *mb = *mbit;
+ ++mbit;
+ mb->disconnect(SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ }
+ QList<Q3PopupMenu*>::Iterator pmit(d->popupmenus.begin());
+ while (pmit != d->popupmenus.end()) {
+ Q3PopupMenu *pm = *pmit;
+ ++pmit;
+ pm->disconnect(SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+ }
+
+ QList<Q3ActionGroupPrivate::Action4Item*>::Iterator itmi4(d->action4items.begin());
+ Q3ActionGroupPrivate::Action4Item* mi4;
+ while (itmi4 != d->action4items.end()) {
+ mi4 = *itmi4;
+ ++itmi4;
+ mi4->widget->removeAction(mi4->action);
+ }
+ delete Q3ActionPrivate::Action4Item::action;
+ Q3ActionPrivate::Action4Item::action = 0;
+
+ delete d->separatorAction;
+ while (!d->menubuttons.isEmpty())
+ delete d->menubuttons.takeFirst();
+ while (!d->comboboxes.isEmpty())
+ delete d->comboboxes.takeFirst();
+ while (!d->menuitems.isEmpty())
+ delete d->menuitems.takeFirst();
+ while (!d->popupmenus.isEmpty())
+ delete d->popupmenus.takeFirst();
+ delete d;
+}
+
+/*!
+ \property Q3ActionGroup::exclusive
+ \brief whether the action group does exclusive toggling
+
+ If exclusive is true only one toggle action in the action group
+ can ever be active at any one time. If the user chooses another
+ toggle action in the group the one they chose becomes active and
+ the one that was active becomes inactive.
+
+ \sa Q3Action::toggleAction
+*/
+void Q3ActionGroup::setExclusive(bool enable)
+{
+ d->exclusive = enable;
+}
+
+bool Q3ActionGroup::isExclusive() const
+{
+ return d->exclusive;
+}
+
+/*!
+ \property Q3ActionGroup::usesDropDown
+ \brief whether the group's actions are displayed in a subwidget of
+ the widgets the action group is added to
+
+ Exclusive action groups added to a toolbar display their actions
+ in a combobox with the action's \l Q3Action::text and \l
+ Q3Action::iconSet properties shown. Non-exclusive groups are
+ represented by a tool button showing their \l Q3Action::iconSet and
+ text() property.
+
+ In a popup menu the member actions are displayed in a submenu.
+
+ Changing usesDropDown only affects \e subsequent calls to addTo().
+
+ This property's default is false.
+
+*/
+void Q3ActionGroup::setUsesDropDown(bool enable)
+{
+ d->dropdown = enable;
+}
+
+bool Q3ActionGroup::usesDropDown() const
+{
+ return d->dropdown;
+}
+
+/*!
+ Adds action \a action to this group.
+
+ Normally an action is added to a group by creating it with the
+ group as parent, so this function is not usually used.
+
+ \sa addTo()
+*/
+void Q3ActionGroup::add(Q3Action* action)
+{
+ if (d->actions.contains(action))
+ return;
+
+ d->actions.append(action);
+
+ if (action->whatsThis().isNull())
+ action->setWhatsThis(whatsThis());
+ if (action->toolTip().isNull())
+ action->setToolTip(toolTip());
+ if (!action->d->forceDisabled)
+ action->d->enabled = isEnabled();
+ if (!action->d->forceInvisible)
+ action->d->visible = isVisible();
+
+ connect(action, SIGNAL(destroyed()), this, SLOT(childDestroyed()));
+ connect(action, SIGNAL(activated()), this, SIGNAL(activated()));
+ connect(action, SIGNAL(toggled(bool)), this, SLOT(childToggled(bool)));
+ connect(action, SIGNAL(activated()), this, SLOT(childActivated()));
+
+ for (QList<QComboBox*>::Iterator cb(d->comboboxes.begin()); cb != d->comboboxes.end(); ++cb)
+ action->addTo(*cb);
+ for (QList<QToolButton*>::Iterator mb(d->menubuttons.begin()); mb != d->menubuttons.end(); ++mb) {
+ QMenu* menu = (*mb)->popup();
+ if (!menu)
+ continue;
+ action->addTo(menu);
+ }
+ for (QList<Q3ActionGroupPrivate::Action4Item*>::Iterator ac(d->action4items.begin());
+ ac != d->action4items.end(); ++ac)
+ action->addTo((*ac)->action->menu());
+ for (QList<Q3ActionGroupPrivate::MenuItem*>::Iterator mi(d->menuitems.begin());
+ mi != d->menuitems.end(); ++mi) {
+ Q3PopupMenu* popup = (*mi)->popup;
+ if (!popup)
+ continue;
+ action->addTo(popup);
+ }
+}
+
+/*!
+ Adds a separator to the group.
+*/
+void Q3ActionGroup::addSeparator()
+{
+ if (!d->separatorAction)
+ d->separatorAction = new Q3Action(0, "qt_separator_action");
+ d->actions.append(d->separatorAction);
+}
+
+
+/*!
+ Adds this action group to the widget \a w.
+
+ If isExclusive() is false or usesDropDown() is false, the actions within
+ the group are added to the widget individually. For example, if the widget
+ is a menu, the actions will appear as individual menu options, and
+ if the widget is a toolbar, the actions will appear as toolbar buttons.
+
+ If both isExclusive() and usesDropDown() are true, the actions
+ are presented either in a combobox (if \a w is a toolbar) or in a
+ submenu (if \a w is a menu).
+
+ All actions should be added to the action group \e before the
+ action group is added to the widget. If actions are added to the
+ action group \e after the action group has been added to the
+ widget these later actions will \e not appear.
+
+ \sa setExclusive() setUsesDropDown() removeFrom()
+*/
+bool Q3ActionGroup::addTo(QWidget *w)
+{
+#ifndef QT_NO_TOOLBAR
+ if (qobject_cast<Q3ToolBar*>(w)) {
+ if (d->dropdown) {
+ if (!d->exclusive) {
+ QList<Q3Action*>::Iterator it(d->actions.begin());
+ if (it == d->actions.end() || !(*it))
+ return true;
+
+ Q3Action *defAction = *it;
+
+ QToolButton* btn = new QToolButton((Q3ToolBar*) w, "qt_actiongroup_btn");
+ addedTo(btn, w);
+ connect(btn, SIGNAL(destroyed()), SLOT(objectDestroyed()));
+ d->menubuttons.append(btn);
+
+ if (!iconSet().isNull())
+ btn->setIconSet(iconSet());
+ else if (!defAction->iconSet().isNull())
+ btn->setIconSet(defAction->iconSet());
+ if (text().size())
+ btn->setTextLabel(text());
+ else if (defAction->text().size())
+ btn->setTextLabel(defAction->text());
+#ifndef QT_NO_TOOLTIP
+ if (toolTip().size())
+ QToolTip::add(btn, toolTip());
+ else if (defAction->toolTip().size())
+ QToolTip::add(btn, defAction->toolTip());
+#endif
+#ifndef QT_NO_WHATSTHIS
+ if (whatsThis().size())
+ QWhatsThis::add(btn, whatsThis());
+ else if (defAction->whatsThis().size())
+ QWhatsThis::add(btn, defAction->whatsThis());
+#endif
+
+ connect(btn, SIGNAL(clicked()), defAction, SIGNAL(activated()));
+ connect(btn, SIGNAL(toggled(bool)), defAction, SLOT(toolButtonToggled(bool)));
+ connect(btn, SIGNAL(destroyed()), defAction, SLOT(objectDestroyed()));
+
+ Q3PopupMenu *menu = new Q3PopupMenu(btn, "qt_actiongroup_menu");
+ btn->setPopupDelay(0);
+ btn->setPopup(menu);
+ btn->setPopupMode(QToolButton::MenuButtonPopup);
+
+ while (it != d->actions.end()) {
+ (*it)->addTo(menu);
+ ++it;
+ }
+ d->update(this);
+ return true;
+ } else {
+ QComboBox *box = new QComboBox(false, w, "qt_actiongroup_combo");
+ addedTo(box, w);
+ connect(box, SIGNAL(destroyed()), SLOT(objectDestroyed()));
+ d->comboboxes.append(box);
+#ifndef QT_NO_TOOLTIP
+ if (toolTip().size())
+ QToolTip::add(box, toolTip());
+#endif
+#ifndef QT_NO_WHATSTHIS
+ if (whatsThis().size())
+ QWhatsThis::add(box, whatsThis());
+#endif
+ int onIndex = 0;
+ bool foundOn = false;
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ Q3Action *action = *it;
+ if (!foundOn)
+ foundOn = action->isOn();
+ if (action->objectName() != QLatin1String("qt_separator_action") && !foundOn)
+ onIndex++;
+ action->addTo(box);
+ }
+ if (foundOn)
+ box->setCurrentItem(onIndex);
+ connect(box, SIGNAL(activated(int)), this, SLOT(internalComboBoxActivated(int)));
+ connect(box, SIGNAL(highlighted(int)), this, SLOT(internalComboBoxHighlighted(int)));
+ d->update(this);
+ return true;
+ }
+ }
+ } else
+#endif
+ if (qobject_cast<Q3PopupMenu*>(w)) {
+ Q3PopupMenu *popup;
+ if (d->dropdown) {
+ Q3PopupMenu *menu = (Q3PopupMenu*)w;
+ popup = new Q3PopupMenu(w, "qt_actiongroup_menu");
+ d->popupmenus.append(popup);
+ connect(popup, SIGNAL(destroyed()), SLOT(objectDestroyed()));
+
+ int id;
+ if (!iconSet().isNull()) {
+ if (menuText().isEmpty())
+ id = menu->insertItem(iconSet(), text(), popup);
+ else
+ id = menu->insertItem(iconSet(), menuText(), popup);
+ } else {
+ if (menuText().isEmpty())
+ id = menu->insertItem(text(), popup);
+ else
+ id = menu->insertItem(menuText(), popup);
+ }
+
+ addedTo(menu->indexOf(id), menu);
+
+ Q3ActionGroupPrivate::MenuItem *item = new Q3ActionGroupPrivate::MenuItem;
+ item->id = id;
+ item->popup = popup;
+ d->menuitems.append(item);
+ } else {
+ popup = (Q3PopupMenu*)w;
+ }
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ // #### do an addedTo(index, popup, action), need to find out index
+ (*it)->addTo(popup);
+ }
+ return true;
+ }
+ if (qobject_cast<QMenu*>(w)) {
+ QMenu *menu = (QMenu*)w;
+ if (d->dropdown) {
+ Q3ActionGroupPrivate::Action4Item *ai = new Q3ActionGroupPrivate::Action4Item;
+ if(!ai->action) { //static
+ ai->action = menu->menuAction();
+ if (!iconSet().isNull())
+ ai->action->setIcon(iconSet());
+ if (menuText().isEmpty())
+ ai->action->setText(text());
+ else
+ ai->action->setText(menuText());
+ }
+ addedTo(w, w);
+ ai->widget = w;
+ ai->widget->addAction(Q3ActionGroupPrivate::Action4Item::action);
+ d->action4items.append(ai);
+ menu = ai->action->menu();
+ }
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it)
+ (*it)->addTo(menu);
+ return true;
+ }
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ // #### do an addedTo(index, popup, action), need to find out index
+ (*it)->addTo(w);
+ }
+ return true;
+}
+
+/*! \reimp
+*/
+bool Q3ActionGroup::removeFrom(QWidget* w)
+{
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it)
+ (*it)->removeFrom(w);
+
+#ifndef QT_NO_TOOLBAR
+ if (qobject_cast<Q3ToolBar*>(w)) {
+ QList<QComboBox*>::Iterator cb(d->comboboxes.begin());
+ while (cb != d->comboboxes.end()) {
+ QComboBox *box = *cb;
+ ++cb;
+ if (box->parentWidget() == w)
+ delete box;
+ }
+ QList<QToolButton*>::Iterator mb(d->menubuttons.begin());
+ while (mb != d->menubuttons.end()) {
+ QToolButton *btn = *mb;
+ ++mb;
+ if (btn->parentWidget() == w)
+ delete btn;
+ }
+ } else
+#endif
+ if (qobject_cast<Q3PopupMenu*>(w)) {
+ QList<Q3ActionGroupPrivate::MenuItem*>::Iterator pu(d->menuitems.begin());
+ while (pu != d->menuitems.end()) {
+ Q3ActionGroupPrivate::MenuItem *mi = *pu;
+ ++pu;
+ if (d->dropdown && mi->popup)
+ ((Q3PopupMenu*)w)->removeItem(mi->id);
+ delete mi->popup;
+ }
+ }
+ if (qobject_cast<QMenu*>(w)) {
+ QList<Q3ActionGroupPrivate::Action4Item*>::Iterator it(d->action4items.begin());
+ Q3ActionGroupPrivate::Action4Item *a4i;
+ while (it != d->action4items.end()) {
+ a4i = *it;
+ ++it;
+ if (a4i->widget == w) {
+ a4i->widget->removeAction(a4i->action);
+ d->action4items.removeAll(a4i);
+ delete a4i;
+ }
+ }
+ }
+ return true;
+}
+
+/*! \internal
+*/
+void Q3ActionGroup::childToggled(bool b)
+{
+ if (!isExclusive())
+ return;
+ Q3Action* s = qobject_cast<Q3Action*>(sender());
+ if (!s)
+ return;
+ if (b) {
+ if (s != d->selected) {
+ d->selected = s;
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ if ((*it)->isToggleAction() && (*it) != s)
+ (*it)->setOn(false);
+ }
+ emit selected(s);
+ }
+ } else {
+ if (s == d->selected) {
+ // at least one has to be selected
+ s->setOn(true);
+ }
+ }
+}
+
+/*! \internal
+*/
+void Q3ActionGroup::childActivated()
+{
+ Q3Action* s = qobject_cast<Q3Action*>(sender());
+ if (s) {
+ emit activated(s);
+ emit Q3Action::activated();
+ }
+}
+
+
+/*! \internal
+*/
+void Q3ActionGroup::childDestroyed()
+{
+ d->actions.removeAll((Q3Action *)sender());
+ if (d->selected == sender())
+ d->selected = 0;
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setEnabled(bool enable)
+{
+ if (enable == isEnabled())
+ return;
+ Q3Action::setEnabled(enable);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setToggleAction(bool toggle)
+{
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it)
+ (*it)->setToggleAction(toggle);
+ Q3Action::setToggleAction(true);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setOn(bool on)
+{
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ Q3Action *act = *it;
+ if (act->isToggleAction())
+ act->setOn(on);
+ }
+ Q3Action::setOn(on);
+ d->update(this);
+}
+
+/*! \reimp
+ */
+void Q3ActionGroup::setVisible(bool visible)
+{
+ Q3Action::setVisible(visible);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setIconSet(const QIcon& icon)
+{
+ Q3Action::setIconSet(icon);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setText(const QString& txt)
+{
+ if (txt == text())
+ return;
+
+ Q3Action::setText(txt);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setMenuText(const QString& text)
+{
+ if (text == menuText())
+ return;
+
+ Q3Action::setMenuText(text);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setToolTip(const QString& text)
+{
+ if (text == toolTip())
+ return;
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ if ((*it)->toolTip().isNull())
+ (*it)->setToolTip(text);
+ }
+ Q3Action::setToolTip(text);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::setWhatsThis(const QString& text)
+{
+ if (text == whatsThis())
+ return;
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ if ((*it)->whatsThis().isNull())
+ (*it)->setWhatsThis(text);
+ }
+ Q3Action::setWhatsThis(text);
+ d->update(this);
+}
+
+/*! \reimp
+*/
+void Q3ActionGroup::childEvent(QChildEvent *e)
+{
+ if (!e->removed())
+ return;
+
+ Q3Action *action = qobject_cast<Q3Action*>(e->child());
+ if (!action)
+ return;
+
+ for (QList<QComboBox*>::Iterator cb(d->comboboxes.begin());
+ cb != d->comboboxes.end(); ++cb) {
+ for (int i = 0; i < (*cb)->count(); i++) {
+ if ((*cb)->text(i) == action->text()) {
+ (*cb)->removeItem(i);
+ break;
+ }
+ }
+ }
+ for (QList<QToolButton*>::Iterator mb(d->menubuttons.begin());
+ mb != d->menubuttons.end(); ++mb) {
+ QMenu* popup = (*mb)->popup();
+ if (!popup)
+ continue;
+ action->removeFrom(popup);
+ }
+ for (QList<Q3ActionGroupPrivate::MenuItem*>::Iterator mi(d->menuitems.begin());
+ mi != d->menuitems.end(); ++mi) {
+ Q3PopupMenu* popup = (*mi)->popup;
+ if (!popup)
+ continue;
+ action->removeFrom(popup);
+ }
+ if(QAction *act = Q3ActionGroupPrivate::Action4Item::action)
+ action->removeFrom(act->menu());
+}
+
+/*!
+ \fn void Q3ActionGroup::selected(Q3Action* action)
+
+ This signal is emitted from exclusive groups when toggle actions
+ change state.
+
+ The argument is the \a action whose state changed to "on".
+
+ \sa setExclusive(), isOn() Q3Action::toggled()
+*/
+
+/*!
+ \fn void Q3ActionGroup::activated(Q3Action* action)
+
+ This signal is emitted from groups when one of its actions gets
+ activated.
+
+ The argument is the \a action which was activated.
+
+ \sa setExclusive(), isOn() Q3Action::toggled()
+*/
+
+
+/*! \internal
+*/
+void Q3ActionGroup::internalComboBoxActivated(int index)
+{
+ if (index == -1)
+ return;
+
+ Q3Action *a = 0;
+ for (int i = 0; i <= index && i < (int)d->actions.count(); ++i) {
+ a = d->actions.at(i);
+ if (a && a->objectName() == QLatin1String("qt_separator_action"))
+ index++;
+ }
+ a = d->actions.at(index);
+ if (a) {
+ if (a != d->selected) {
+ d->selected = a;
+ for (QList<Q3Action*>::Iterator it(d->actions.begin()); it != d->actions.end(); ++it) {
+ if ((*it)->isToggleAction() && (*it) != a)
+ (*it)->setOn(false);
+ }
+ if (a->isToggleAction())
+ a->setOn(true);
+
+ emit activated(a);
+ emit Q3Action::activated();
+ emit a->activated();
+ if (a->isToggleAction())
+ emit selected(d->selected);
+ } else if (!a->isToggleAction()) {
+ emit activated(a);
+ emit Q3Action::activated();
+ emit a->activated();
+ }
+ a->clearStatusText();
+ }
+}
+
+/*! \internal
+*/
+void Q3ActionGroup::internalComboBoxHighlighted(int index)
+{
+ Q3Action *a = 0;
+ for (int i = 0; i <= index && i < (int)d->actions.count(); ++i) {
+ a = d->actions.at(i);
+ if (a && a->objectName() == QLatin1String("qt_separator_action"))
+ index++;
+ }
+ a = d->actions.at(index);
+ if (a)
+ a->showStatusText(a->statusTip());
+ else
+ clearStatusText();
+}
+
+/*! \internal
+*/
+void Q3ActionGroup::internalToggle(Q3Action *a)
+{
+ int index = d->actions.indexOf(a);
+ if (index == -1)
+ return;
+
+ int lastItem = index;
+ for (int i=0; i<lastItem; ++i) {
+ Q3Action *action = d->actions.at(i);
+ if (action->objectName() == QLatin1String("qt_separator_action"))
+ --index;
+ }
+
+ for (QList<QComboBox*>::Iterator it(d->comboboxes.begin());
+ it != d->comboboxes.end(); ++it)
+ (*it)->setCurrentItem(index);
+}
+
+/*! \internal
+*/
+void Q3ActionGroup::objectDestroyed()
+{
+ const QObject* obj = sender();
+ d->menubuttons.removeAll((QToolButton *)obj);
+ for (QList<Q3ActionGroupPrivate::MenuItem *>::Iterator mi(d->menuitems.begin());
+ mi != d->menuitems.end(); ++mi) {
+ if ((*mi)->popup == obj) {
+ d->menuitems.removeAll(*mi);
+ delete *mi;
+ break;
+ }
+ }
+ d->popupmenus.removeAll((Q3PopupMenu*)obj);
+ d->comboboxes.removeAll((QComboBox*)obj);
+}
+
+/*!
+ This function is called from the addTo() function when it has
+ created a widget (\a actionWidget) for the child action \a a in
+ the \a container.
+*/
+
+void Q3ActionGroup::addedTo(QWidget *actionWidget, QWidget *container, Q3Action *a)
+{
+ Q_UNUSED(actionWidget);
+ Q_UNUSED(container);
+ Q_UNUSED(a);
+}
+
+/*!
+ \overload
+
+ This function is called from the addTo() function when it has
+ created a menu item for the child action at the index position \a
+ index in the popup menu \a menu.
+*/
+
+void Q3ActionGroup::addedTo(int index, Q3PopupMenu *menu, Q3Action *a)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(menu);
+ Q_UNUSED(a);
+}
+
+/*!
+ \reimp
+ \overload
+
+ This function is called from the addTo() function when it has
+ created a widget (\a actionWidget) in the \a container.
+*/
+
+void Q3ActionGroup::addedTo(QWidget *actionWidget, QWidget *container)
+{
+ Q_UNUSED(actionWidget);
+ Q_UNUSED(container);
+}
+
+/*!
+ \reimp
+ \overload
+
+ This function is called from the addTo() function when it has
+ created a menu item at the index position \a index in the popup
+ menu \a menu.
+*/
+
+void Q3ActionGroup::addedTo(int index, Q3PopupMenu *menu)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(menu);
+}
+
+/*!
+ \fn void Q3ActionGroup::insert(Q3Action *action)
+
+ Use add(\a action) instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qt3support/widgets/q3action.h b/src/qt3support/widgets/q3action.h
new file mode 100644
index 0000000..c079eac
--- /dev/null
+++ b/src/qt3support/widgets/q3action.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3ACTION_H
+#define Q3ACTION_H
+
+#include <QtGui/qicon.h>
+#include <QtGui/qkeysequence.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_ACTION
+
+class Q3ActionPrivate;
+class Q3ActionGroupPrivate;
+class QStatusBar;
+class Q3PopupMenu;
+class QToolTipGroup;
+class QWidget;
+
+class Q_COMPAT_EXPORT Q3Action : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool toggleAction READ isToggleAction WRITE setToggleAction)
+ Q_PROPERTY(bool on READ isOn WRITE setOn)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QIcon iconSet READ iconSet WRITE setIconSet)
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QString menuText READ menuText WRITE setMenuText)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
+#ifndef QT_NO_ACCEL
+ Q_PROPERTY(QKeySequence accel READ accel WRITE setAccel)
+#endif
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+
+public:
+ Q3Action(QObject* parent, const char* name = 0);
+#ifndef QT_NO_ACCEL
+ Q3Action(const QString& menuText, QKeySequence accel,
+ QObject* parent, const char* name = 0);
+ Q3Action(const QIcon& icon, const QString& menuText, QKeySequence accel,
+ QObject* parent, const char* name = 0);
+
+ Q3Action(const QString& text, const QIcon& icon, const QString& menuText, QKeySequence accel,
+ QObject* parent, const char* name = 0, bool toggle = false); // obsolete
+ Q3Action(const QString& text, const QString& menuText, QKeySequence accel, QObject* parent,
+ const char* name = 0, bool toggle = false); // obsolete
+#endif
+ Q3Action(QObject* parent, const char* name , bool toggle); // obsolete
+ ~Q3Action();
+
+ virtual void setIconSet(const QIcon&);
+ QIcon iconSet() const;
+ virtual void setText(const QString&);
+ QString text() const;
+ virtual void setMenuText(const QString&);
+ QString menuText() const;
+ virtual void setToolTip(const QString&);
+ QString toolTip() const;
+ virtual void setStatusTip(const QString&);
+ QString statusTip() const;
+ virtual void setWhatsThis(const QString&);
+ QString whatsThis() const;
+#ifndef QT_NO_ACCEL
+ virtual void setAccel(const QKeySequence& key);
+ QKeySequence accel() const;
+#endif
+ virtual void setToggleAction(bool);
+
+ bool isToggleAction() const;
+ bool isOn() const;
+ bool isEnabled() const;
+ bool isVisible() const;
+ virtual bool addTo(QWidget*);
+ virtual bool removeFrom(QWidget*);
+
+protected:
+ virtual void addedTo(QWidget *actionWidget, QWidget *container);
+ virtual void addedTo(int index, Q3PopupMenu *menu);
+
+public Q_SLOTS:
+ void activate();
+ void toggle();
+ virtual void setOn(bool);
+ virtual void setEnabled(bool);
+ void setDisabled(bool);
+ virtual void setVisible(bool);
+
+Q_SIGNALS:
+ void activated();
+ void toggled(bool);
+
+private Q_SLOTS:
+ void internalActivation();
+ void toolButtonToggled(bool);
+ void objectDestroyed();
+ void menuStatusText(int id);
+ void showStatusText(const QString&);
+ void clearStatusText();
+
+private:
+ Q_DISABLE_COPY(Q3Action)
+
+ void init();
+
+ Q3ActionPrivate* d;
+
+ friend class Q3ActionPrivate;
+ friend class Q3ActionGroup;
+ friend class Q3ActionGroupPrivate;
+};
+
+class Q_COMPAT_EXPORT Q3ActionGroup : public Q3Action
+{
+ Q_OBJECT
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
+ Q_PROPERTY(bool usesDropDown READ usesDropDown WRITE setUsesDropDown)
+
+public:
+ Q3ActionGroup(QObject* parent, const char* name = 0);
+ Q3ActionGroup(QObject* parent, const char* name , bool exclusive ); // obsolete
+ ~Q3ActionGroup();
+ void setExclusive(bool);
+ bool isExclusive() const;
+ void add(Q3Action* a);
+ void addSeparator();
+ bool addTo(QWidget*);
+ bool removeFrom(QWidget*);
+ void setEnabled(bool);
+ void setToggleAction(bool toggle);
+ void setOn(bool on);
+ void setVisible(bool);
+
+ void setUsesDropDown(bool enable);
+ bool usesDropDown() const;
+
+ void setIconSet(const QIcon &);
+ void setText(const QString&);
+ void setMenuText(const QString&);
+ void setToolTip(const QString&);
+ void setWhatsThis(const QString&);
+
+protected:
+ void childEvent(QChildEvent*);
+ virtual void addedTo(QWidget *actionWidget, QWidget *container, Q3Action *a);
+ virtual void addedTo(int index, Q3PopupMenu *menu, Q3Action *a);
+ virtual void addedTo(QWidget *actionWidget, QWidget *container);
+ virtual void addedTo(int index, Q3PopupMenu *menu);
+
+Q_SIGNALS:
+ void selected(Q3Action*);
+ void activated(Q3Action *);
+
+private Q_SLOTS:
+ void childToggled(bool);
+ void childActivated();
+ void childDestroyed();
+ void internalComboBoxActivated(int);
+ void internalComboBoxHighlighted(int);
+ void internalToggle(Q3Action*);
+ void objectDestroyed();
+
+private:
+ Q3ActionGroupPrivate* d;
+
+public:
+ void insert(Q3Action *a) { add(a); }
+
+private:
+ Q_DISABLE_COPY(Q3ActionGroup)
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3ACTION_H
diff --git a/src/qt3support/widgets/q3button.cpp b/src/qt3support/widgets/q3button.cpp
new file mode 100644
index 0000000..3871f56
--- /dev/null
+++ b/src/qt3support/widgets/q3button.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3button.h"
+#include "qpainter.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3Button
+ \brief The Q3Button class is a compatibility base class of button
+ widgets
+
+ \compat
+
+ \bold{In new code, use QAbstractButton.}
+
+ To subclass Q3Button, you must reimplement at least drawButton()
+ (to draw the button's outline) and drawButtonLabel() (to draw its
+ text or pixmap). It is generally advisable to reimplement
+ sizeHint() as well, and sometimes hitButton() (to determine
+ whether a button press is within the button).
+*/
+
+/*!
+ Constructs a standard button called \a name with parent \a parent,
+ using the widget flags \a f.
+*/
+
+Q3Button::Q3Button( QWidget *parent, const char *name, Qt::WindowFlags f )
+ : QAbstractButton( parent, name, f )
+{
+}
+
+/*!
+ Destroys the button.
+ */
+Q3Button::~Q3Button()
+{
+}
+
+/*!
+ \fn void Q3Button::paintEvent( QPaintEvent *event)
+
+ Handles paint events, received in \a event, for buttons. Small and
+ typically complex buttons are painted double-buffered to reduce
+ flicker. The actually drawing is done in the virtual functions
+ drawButton() and drawButtonLabel().
+
+ \sa drawButton(), drawButtonLabel()
+*/
+void Q3Button::paintEvent( QPaintEvent *)
+{
+ QPainter p(this);
+ drawButton( &p );
+}
+
+/*!
+ \fn void Q3Button::drawButton( QPainter *painter)
+
+ Draws the button on the given \a painter. The default
+ implementation does nothing.
+
+ This virtual function is reimplemented by subclasses to draw real
+ buttons. At some point, these reimplementations should call
+ drawButtonLabel().
+
+ \sa drawButtonLabel(), paintEvent()
+*/
+void Q3Button::drawButton( QPainter * )
+{
+}
+
+/*!
+ \fn void Q3Button::drawButtonLabel( QPainter *painter )
+
+ Draws the button text or pixmap on the given \a painter.
+
+ This virtual function is reimplemented by subclasses to draw real
+ buttons. It is invoked by drawButton().
+
+ \sa drawButton(), paintEvent()
+*/
+
+void Q3Button::drawButtonLabel( QPainter * )
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3button.h b/src/qt3support/widgets/q3button.h
new file mode 100644
index 0000000..fd6c0a1
--- /dev/null
+++ b/src/qt3support/widgets/q3button.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3BUTTON_H
+#define Q3BUTTON_H
+
+#include <QtGui/qabstractbutton.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3Button : public QAbstractButton
+{
+ Q_OBJECT
+public:
+ Q3Button( QWidget* parent=0, const char* name=0, Qt::WindowFlags f=0 );
+ ~Q3Button();
+
+protected:
+ virtual void drawButton( QPainter * );
+ virtual void drawButtonLabel( QPainter * );
+ void paintEvent( QPaintEvent * );
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3BUTTON_H
diff --git a/src/qt3support/widgets/q3buttongroup.cpp b/src/qt3support/widgets/q3buttongroup.cpp
new file mode 100644
index 0000000..b6021a1
--- /dev/null
+++ b/src/qt3support/widgets/q3buttongroup.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3buttongroup.h"
+#include "qabstractbutton.h"
+#include "qmap.h"
+#include "qapplication.h"
+#include "qradiobutton.h"
+#include "qevent.h"
+#include "qset.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3ButtonGroup
+ \brief The Q3ButtonGroup widget organizes QAbstractButton widgets in a group.
+
+ \compat
+
+ A button group widget makes it easier to deal with groups of
+ buttons. Each button in a button group has a unique identifier.
+ The button group emits a clicked() signal with this identifier
+ when a button in the group is clicked. This makes a button group
+ particularly useful when you have several similar buttons and want
+ to connect all their clicked() signals to a single slot.
+
+ An \link setExclusive() exclusive\endlink button group switches
+ off all toggle buttons except the one that was clicked. A button
+ group is, by default, non-exclusive. Note that all radio buttons
+ that are inserted into a button group are mutually exclusive even
+ if the button group is non-exclusive. (See
+ setRadioButtonExclusive().)
+
+ There are two ways of using a button group:
+ \list
+ \i The button group is the parent widget of a number of buttons,
+ i.e. the button group is the parent argument in the button
+ constructor. The buttons are assigned identifiers 0, 1, 2, etc.,
+ in the order they are created. A Q3ButtonGroup can display a frame
+ and a title because it inherits Q3GroupBox.
+ \i The button group is an invisible widget and the contained
+ buttons have some other parent widget. In this usage, each button
+ must be manually inserted, using insert(), into the button group
+ and given an identifier.
+ \endlist
+
+ A button can be removed from the group with remove(). A pointer to
+ a button with a given id can be obtained using find(). The id of a
+ button is available using id(). A button can be set \e on with
+ setButton(). The number of buttons in the group is returned by
+ count().
+
+ \sa QPushButton, QCheckBox, QRadioButton
+*/
+
+/*!
+ \property Q3ButtonGroup::exclusive
+ \brief whether the button group is exclusive
+
+ If this property is true, then the buttons in the group are
+ toggled, and to untoggle a button you must click on another button
+ in the group. The default value is false.
+*/
+
+/*!
+ \property Q3ButtonGroup::radioButtonExclusive
+ \brief whether the radio buttons in the group are exclusive
+
+ If this property is true (the default), the \link QRadioButton
+ radio buttons\endlink in the group are treated exclusively.
+*/
+
+
+/*!
+ Constructs a button group with no title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3ButtonGroup::Q3ButtonGroup(QWidget *parent, const char *name)
+ : Q3GroupBox(parent, name)
+{
+ init();
+}
+
+/*!
+ Constructs a button group with the title \a title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3ButtonGroup::Q3ButtonGroup(const QString &title, QWidget *parent,
+ const char *name)
+ : Q3GroupBox(title, parent, name)
+{
+ init();
+}
+
+/*!
+ Constructs a button group with no title. Child widgets will be
+ arranged in \a strips rows or columns (depending on \a
+ orientation).
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3ButtonGroup::Q3ButtonGroup(int strips, Qt::Orientation orientation,
+ QWidget *parent, const char *name)
+ : Q3GroupBox(strips, orientation, parent, name)
+{
+ init();
+}
+
+/*!
+ Constructs a button group with title \a title. Child widgets will
+ be arranged in \a strips rows or columns (depending on \a
+ orientation).
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3ButtonGroup::Q3ButtonGroup(int strips, Qt::Orientation orientation,
+ const QString &title, QWidget *parent,
+ const char *name)
+ : Q3GroupBox(strips, orientation, title, parent, name)
+{
+ init();
+}
+
+/*!
+ Initializes the button group.
+*/
+
+void Q3ButtonGroup::init()
+{
+ group.setExclusive(false);
+ radio_excl = true;
+}
+
+/*! Destructor. */
+
+Q3ButtonGroup::~Q3ButtonGroup()
+{
+}
+
+bool Q3ButtonGroup::isExclusive() const
+{
+ return group.exclusive();
+}
+
+void Q3ButtonGroup::setExclusive(bool enable)
+{
+ group.setExclusive(enable);
+}
+
+
+/*!
+ Inserts the \a button with the identifier \a id into the button
+ group. Returns the button identifier.
+
+ Buttons are normally inserted into a button group automatically by
+ passing the button group as the parent when the button is
+ constructed. So it is not necessary to manually insert buttons
+ that have this button group as their parent widget. An exception
+ is when you want custom identifiers instead of the default 0, 1,
+ 2, etc., or if you want the buttons to have some other parent.
+
+ The button is assigned the identifier \a id or an automatically
+ generated identifier. It works as follows: If \a id >= 0, this
+ identifier is assigned. If \a id == -1 (default), the identifier
+ is equal to the number of buttons in the group. If \a id is any
+ other negative integer, for instance -2, a unique identifier
+ (negative integer \<= -2) is generated. No button has an id of -1.
+
+ \sa find(), remove(), setExclusive()
+*/
+
+int Q3ButtonGroup::insert(QAbstractButton *button, int id)
+{
+ remove_helper(button);
+ return insert_helper(button, id);
+}
+
+int Q3ButtonGroup::insert_helper(QAbstractButton *button, int id)
+{
+ if (isExclusive() || !qobject_cast<QRadioButton*>(button))
+ group.addButton(button);
+
+ static int seq_no = -2;
+ if (id < -1)
+ id = seq_no--;
+ else if (id == -1)
+ id = buttonIds.count();
+ buttonIds.insert(id, button);
+ connect(button, SIGNAL(pressed()) , SLOT(buttonPressed()));
+ connect(button, SIGNAL(released()), SLOT(buttonReleased()));
+ connect(button, SIGNAL(clicked()) , SLOT(buttonClicked()));
+ connect(button, SIGNAL(destroyed()) , SLOT(buttonDestroyed()));
+ return id;
+}
+
+/*!
+ Returns the number of buttons in the group.
+*/
+int Q3ButtonGroup::count() const
+{
+ fixChildren();
+ return buttonIds.count();
+}
+
+/*!
+ Removes the \a button from the button group.
+
+ \sa insert()
+*/
+
+void Q3ButtonGroup::remove(QAbstractButton *button)
+{
+ fixChildren();
+ remove_helper(button);
+}
+
+void Q3ButtonGroup::remove_helper(QAbstractButton *button)
+{
+ QMap<int, QAbstractButton*>::Iterator it = buttonIds.begin();
+ while (it != buttonIds.end()) {
+ if (it.value() == button) {
+ buttonIds.erase(it);
+ button->disconnect(this);
+ group.removeButton(button);
+ break;
+ }
+ ++it;
+ }
+}
+
+
+/*!
+ Returns the button with the specified identifier \a id, or 0 if
+ the button was not found.
+*/
+
+QAbstractButton *Q3ButtonGroup::find(int id) const
+{
+ fixChildren();
+ return buttonIds.value(id);
+}
+
+
+/*!
+ \fn void Q3ButtonGroup::pressed(int id)
+
+ This signal is emitted when a button in the group is \link
+ QAbstractButton::pressed() pressed\endlink. The \a id argument is the
+ button's identifier.
+
+ \sa insert()
+*/
+
+/*!
+ \fn void Q3ButtonGroup::released(int id)
+
+ This signal is emitted when a button in the group is \link
+ QAbstractButton::released() released\endlink. The \a id argument is the
+ button's identifier.
+
+ \sa insert()
+*/
+
+/*!
+ \fn void Q3ButtonGroup::clicked(int id)
+
+ This signal is emitted when a button in the group is \link
+ QAbstractButton::clicked() clicked\endlink. The \a id argument is the
+ button's identifier.
+
+ \sa insert()
+*/
+
+
+/*!
+ \internal
+ This slot is activated when one of the buttons in the group emits the
+ QAbstractButton::pressed() signal.
+*/
+
+void Q3ButtonGroup::buttonPressed()
+{
+ QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
+ Q_ASSERT(senderButton);
+ int senderId = id(senderButton);
+ if (senderId != -1)
+ emit pressed(senderId);
+}
+
+/*!
+ \internal
+ This slot is activated when one of the buttons in the group emits the
+ QAbstractButton::released() signal.
+*/
+
+void Q3ButtonGroup::buttonReleased()
+{
+ QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
+ Q_ASSERT(senderButton);
+ int senderId = id(senderButton);
+ if (senderId != -1)
+ emit released(senderId);
+}
+
+/*!
+ \internal
+ This slot is activated when one of the buttons in the group emits the
+ QAbstractButton::clicked() signal.
+*/
+
+void Q3ButtonGroup::buttonClicked()
+{
+ QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
+ Q_ASSERT(senderButton);
+ int senderId = id(senderButton);
+ if (senderId != -1)
+ emit clicked(senderId);
+}
+
+/*!
+ \internal
+*/
+void Q3ButtonGroup::buttonDestroyed()
+{
+ int id = buttonIds.key(static_cast<QAbstractButton *>(sender()), -1);
+ if (id != -1)
+ buttonIds.remove(id);
+}
+
+void Q3ButtonGroup::setButton(int id)
+{
+ QAbstractButton *b = find(id);
+ if (b)
+ b->setOn(true);
+}
+
+void Q3ButtonGroup::setRadioButtonExclusive(bool on)
+{
+ radio_excl = on;
+}
+
+
+/*!
+ Returns the selected toggle button if exactly one is selected;
+ otherwise returns 0.
+
+ \sa selectedId()
+*/
+
+QAbstractButton *Q3ButtonGroup::selected() const
+{
+ fixChildren();
+ QAbstractButton *candidate = 0;
+ QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
+ while (it != buttonIds.constEnd()) {
+ if (it.value()->isCheckable() && it.value()->isChecked()) {
+ if (candidate)
+ return 0;
+ candidate = it.value();
+ }
+ ++it;
+ }
+ return candidate;
+}
+
+/*!
+ \property Q3ButtonGroup::selectedId
+ \brief The id of the selected toggle button.
+
+ If no toggle button is selected, id() returns -1.
+
+ If setButton() is called on an exclusive group, the button with
+ the given id will be set to on and all the others will be set to
+ off.
+
+ \sa selected()
+*/
+
+int Q3ButtonGroup::selectedId() const
+{
+ return id(selected());
+}
+
+
+/*!
+ Returns the id of \a button, or -1 if \a button is not a member of
+ this group.
+
+ \sa selectedId()
+*/
+
+int Q3ButtonGroup::id(QAbstractButton *button) const
+{
+ fixChildren();
+ QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
+ while (it != buttonIds.constEnd()) {
+ if (it.value() == button)
+ return it.key();
+ ++it;
+ }
+ return -1;
+}
+
+
+/*!
+ \reimp
+*/
+bool Q3ButtonGroup::event(QEvent * e)
+{
+ if (e->type() == QEvent::ChildInserted) {
+ QChildEvent * ce = (QChildEvent *) e;
+ if (QAbstractButton *button = qobject_cast<QAbstractButton*>(ce->child())) {
+ button->setAutoExclusive(false);
+ if (group.exclusive() || qobject_cast<QRadioButton*>(button)) {
+ button->setAutoExclusive(true);
+ QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
+ while (it != buttonIds.constEnd()) {
+ if (it.value() == button)
+ return Q3GroupBox::event(e);
+ ++it;
+ }
+ }
+ insert(button, id(button));
+ }
+ }
+ return Q3GroupBox::event(e);
+}
+
+void Q3ButtonGroup::fixChildren() const
+{
+ if (children().count() == buttonIds.count())
+ return; // small optimization, all our children have ids.
+
+ QSet<QAbstractButton*> set;
+ for (QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
+ it != buttonIds.constEnd(); ++it)
+ set.insert(*it);
+ // Use children() instead of qFindChildren<QAbstractButton*> because the search
+ // should not be recursive.We match with the behavior of Qt3
+ const QObjectList childList = children();
+ Q_FOREACH(QObject* obj, childList) {
+ QAbstractButton *button = qobject_cast<QAbstractButton*>(obj);
+ if ( button && !set.contains(button))
+ const_cast<Q3ButtonGroup*>(this)->insert_helper(button);
+ }
+}
+
+
+/*!
+ \class Q3HButtonGroup
+ \brief The Q3HButtonGroup widget organizes button widgets in a
+ group with one horizontal row.
+
+ \compat
+
+ Q3HButtonGroup is a convenience class that offers a thin layer on
+ top of Q3ButtonGroup. From a layout point of view it is effectively
+ a Q3HBoxWidget that offers a frame with a title and is specifically
+ designed for buttons. From a functionality point of view it is a
+ Q3ButtonGroup.
+
+ \sa Q3VButtonGroup
+*/
+
+/*!
+ \fn Q3HButtonGroup::Q3HButtonGroup(QWidget *parent, const char *name)
+
+ Constructs a horizontal button group with no title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+/*!
+ \fn Q3HButtonGroup::Q3HButtonGroup(const QString &title, QWidget *parent,
+ const char *name)
+
+ Constructs a horizontal button group with the title \a title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+/*!
+ \class Q3VButtonGroup
+ \brief The Q3VButtonGroup widget organizes button widgets in a
+ vertical column.
+
+ \compat
+
+ Q3VButtonGroup is a convenience class that offers a thin layer on top
+ of Q3ButtonGroup. Think of it as a QVBoxWidget that offers a frame with a
+ title and is specifically designed for buttons.
+
+ \sa Q3HButtonGroup
+*/
+
+/*!
+ \fn Q3VButtonGroup::Q3VButtonGroup(QWidget *parent, const char *name)
+
+ Constructs a vertical button group with no title.
+
+ The \a parent and \a name arguments are passed on to the QWidget
+ constructor.
+*/
+
+/*!
+ \fn Q3VButtonGroup::Q3VButtonGroup(const QString &title, QWidget *parent,
+ const char *name)
+
+ Constructs a vertical button group with the title \a title.
+
+ The \a parent and \a name arguments are passed on to the QWidget
+ constructor.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3buttongroup.h b/src/qt3support/widgets/q3buttongroup.h
new file mode 100644
index 0000000..680d351
--- /dev/null
+++ b/src/qt3support/widgets/q3buttongroup.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3BUTTONGROUP_H
+#define Q3BUTTONGROUP_H
+
+#include <QtGui/qbuttongroup.h>
+#include <Qt3Support/q3groupbox.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class QAbstractButton;
+
+class Q_COMPAT_EXPORT Q3ButtonGroup : public Q3GroupBox
+{
+ Q_OBJECT
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
+ Q_PROPERTY(bool radioButtonExclusive READ isRadioButtonExclusive WRITE setRadioButtonExclusive)
+ Q_PROPERTY(int selectedId READ selectedId WRITE setButton)
+
+public:
+ Q3ButtonGroup(QWidget* parent=0, const char* name=0);
+ Q3ButtonGroup(const QString &title,
+ QWidget* parent=0, const char* name=0);
+ Q3ButtonGroup(int columns, Qt::Orientation o,
+ QWidget* parent=0, const char* name=0);
+ Q3ButtonGroup(int columns, Qt::Orientation o, const QString &title,
+ QWidget* parent=0, const char* name=0);
+ ~Q3ButtonGroup();
+
+ bool isExclusive() const;
+ bool isRadioButtonExclusive() const { return radio_excl; }
+ void setExclusive(bool);
+ void setRadioButtonExclusive(bool);
+
+public:
+ int insert(QAbstractButton *, int id=-1);
+ void remove(QAbstractButton *);
+ QAbstractButton *find(int id) const;
+ int id(QAbstractButton *) const;
+ int count() const;
+
+ void setButton(int id);
+
+ QAbstractButton *selected() const;
+ int selectedId() const;
+
+Q_SIGNALS:
+ void pressed(int id);
+ void released(int id);
+ void clicked(int id);
+
+protected Q_SLOTS:
+ void buttonPressed();
+ void buttonReleased();
+ void buttonClicked();
+
+protected:
+ bool event(QEvent * e);
+
+private Q_SLOTS:
+ void buttonDestroyed();
+
+private:
+ Q_DISABLE_COPY(Q3ButtonGroup)
+
+ void init();
+ void fixChildren() const;
+ int insert_helper(QAbstractButton* , int id=-1);
+ void remove_helper(QAbstractButton *);
+
+ bool excl_grp; // Not used.
+ bool radio_excl;
+ QMap<int, QAbstractButton*> buttonIds;
+ QButtonGroup group;
+};
+
+class Q_COMPAT_EXPORT Q3VButtonGroup : public Q3ButtonGroup
+{
+ Q_OBJECT
+public:
+ inline Q3VButtonGroup(QWidget* parent=0, const char* name=0)
+ : Q3ButtonGroup(1, Qt::Horizontal /* sic! */, parent, name) {}
+ inline Q3VButtonGroup(const QString &title, QWidget* parent=0, const char* name=0)
+ : Q3ButtonGroup(1, Qt::Horizontal /* sic! */, title, parent, name) {}
+
+private:
+ Q_DISABLE_COPY(Q3VButtonGroup)
+};
+
+
+class Q_COMPAT_EXPORT Q3HButtonGroup : public Q3ButtonGroup
+{
+ Q_OBJECT
+public:
+ inline Q3HButtonGroup(QWidget* parent=0, const char* name=0)
+ : Q3ButtonGroup(1, Qt::Vertical /* sic! */, parent, name) {}
+ inline Q3HButtonGroup(const QString &title, QWidget* parent=0, const char* name=0)
+ : Q3ButtonGroup(1, Qt::Vertical /* sic! */, title, parent, name) {}
+
+private:
+ Q_DISABLE_COPY(Q3HButtonGroup)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3BUTTONGROUP_H
diff --git a/src/qt3support/widgets/q3combobox.cpp b/src/qt3support/widgets/q3combobox.cpp
new file mode 100644
index 0000000..3bac984
--- /dev/null
+++ b/src/qt3support/widgets/q3combobox.cpp
@@ -0,0 +1,2356 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3combobox.h"
+#ifndef QT_NO_COMBOBOX
+#include "qpainter.h"
+#include "qdrawutil.h"
+#include "qpixmap.h"
+#include "qtimer.h"
+#include "qapplication.h"
+#include "qlineedit.h"
+#include "qbitmap.h"
+#include "qstringlist.h"
+#include "qstyle.h"
+#include "qevent.h"
+#include "qmenu.h"
+#include "qmenudata.h"
+#include "qstyleoption.h"
+#include "qdesktopwidget.h"
+#include "q3popupmenu.h"
+#include "q3listbox.h"
+#include "q3strlist.h"
+#include "q3frame.h"
+#include <limits.h>
+#include <qdebug.h>
+#ifndef QT_NO_EFFECTS
+# include <private/qeffects_p.h>
+#endif
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+#include "qaccessible.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3ComboBox
+ \brief The Q3ComboBox widget is a combined button and popup list.
+ \since 4.1
+ \compat
+
+ A combobox is a selection widget which displays the current item
+ and can pop up a list of items. A combobox may be editable in
+ which case the user can enter arbitrary strings.
+
+ Comboboxes provide a means of showing the user's current choice
+ out of a list of options in a way that takes up the minimum amount
+ of screen space.
+
+ Q3ComboBox supports three different display styles: Aqua/Motif 1.x,
+ Motif 2.0 and Windows. In Motif 1.x, a combobox was called
+ XmOptionMenu. In Motif 2.0, OSF introduced an improved combobox
+ and named that XmComboBox. Q3ComboBox provides both.
+
+ Q3ComboBox provides two different constructors. The simplest
+ constructor creates an "old-style" combobox in Motif (or Aqua)
+ style:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 0
+
+ The other constructor creates a new-style combobox in Motif style,
+ and can create both read-only and editable comboboxes:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 1
+
+ New-style comboboxes use a list box in both Motif and Windows
+ styles, and both the content size and the on-screen size of the
+ list box can be limited with sizeLimit() and setMaxCount()
+ respectively. Old-style comboboxes use a popup in Aqua and Motif
+ style, and that popup will happily grow larger than the desktop if
+ you put enough data into it.
+
+ The two constructors create identical-looking comboboxes in
+ Windows style.
+
+ Comboboxes can contain pixmaps as well as strings; the
+ insertItem() and changeItem() functions are suitably overloaded.
+ For editable comboboxes, the function clearEdit() is provided,
+ to clear the displayed string without changing the combobox's
+ contents.
+
+ A combobox emits two signals, activated() and highlighted(), when
+ a new item has been activated (selected) or highlighted (made
+ current). Both signals exist in two versions, one with a \c
+ QString argument and one with an \c int argument. If the user
+ highlights or activates a pixmap, only the \c int signals are
+ emitted. Whenever the text of an editable combobox is changed the
+ textChanged() signal is emitted.
+
+ When the user enters a new string in an editable combobox, the
+ widget may or may not insert it, and it can insert it in several
+ locations. The default policy is is \c AtBottom but you can change
+ this using setInsertionPolicy().
+
+ It is possible to constrain the input to an editable combobox
+ using QValidator; see setValidator(). By default, any input is
+ accepted.
+
+ If the combobox is not editable then it has a default
+ focusPolicy() of \c TabFocus, i.e. it will not grab focus if
+ clicked. This differs from both Windows and Motif. If the combobox
+ is editable then it has a default focusPolicy() of \c StrongFocus,
+ i.e. it will grab focus if clicked.
+
+ A combobox can be populated using the insert functions,
+ insertStringList() and insertItem() for example. Items can be
+ changed with changeItem(). An item can be removed with
+ removeItem() and all items can be removed with clear(). The text
+ of the current item is returned by currentText(), and the text of
+ a numbered item is returned with text(). The current item can be
+ set with setCurrentItem() or setCurrentText(). The number of items
+ in the combobox is returned by count(); the maximum number of
+ items can be set with setMaxCount(). You can allow editing using
+ setEditable(). For editable comboboxes you can set auto-completion
+ using setAutoCompletion() and whether or not the user can add
+ duplicates is set with setDuplicatesEnabled().
+
+ Depending on the style, Q3ComboBox will use a list box or a
+ popup menu to display the list of items. See setListBox() for
+ more information.
+
+ \sa QComboBox, QLineEdit, QSpinBox
+ {GUI Design Handbook}{GUI Design Handbook: Combo Box, Drop-Down List Box}
+*/
+
+
+/*!
+ \enum Q3ComboBox::Policy
+
+ This enum specifies what the Q3ComboBox should do when a new string
+ is entered by the user.
+
+ \value NoInsertion the string will not be inserted into the
+ combobox.
+
+ \value AtTop insert the string as the first item in the combobox.
+
+ \value AtCurrent replace the previously selected item with the
+ string the user has entered.
+
+ \value AtBottom insert the string as the last item in the
+ combobox.
+
+ \value AfterCurrent insert the string after the previously
+ selected item.
+
+ \value BeforeCurrent insert the string before the previously
+ selected item.
+
+ activated() is always emitted when the string is entered.
+
+ If inserting the new string would cause the combobox to breach its
+ content size limit, the item at the other end of the list is
+ deleted. The definition of "other end" is
+ implementation-dependent.
+
+ \omitvalue NoInsert
+ \omitvalue InsertAtTop
+ \omitvalue InsertAtCurrent
+ \omitvalue InsertAtBottom
+ \omitvalue InsertAfterCurrent
+ \omitvalue InsertBeforeCurrent
+*/
+
+
+/*!
+ \fn void Q3ComboBox::activated( int index )
+
+ This signal is emitted when a new item has been activated
+ (selected). The \a index is the position of the item in the
+ combobox.
+
+ This signal is not emitted if the item is changed
+ programmatically, e.g. using setCurrentItem().
+*/
+
+/*!
+ \overload
+ \fn void Q3ComboBox::activated( const QString &string )
+
+ This signal is emitted when a new item has been activated
+ (selected). \a string is the selected string.
+
+ You can also use the activated(int) signal, but be aware that its
+ argument is meaningful only for selected strings, not for user
+ entered strings.
+*/
+
+/*!
+ \fn void Q3ComboBox::highlighted( int index )
+
+ This signal is emitted when a new item has been set to be the
+ current item. The \a index is the position of the item in the
+ combobox.
+
+ This signal is not emitted if the item is changed
+ programmatically, e.g. using setCurrentItem().
+*/
+
+/*!
+ \overload
+ \fn void Q3ComboBox::highlighted( const QString &string )
+
+ This signal is emitted when a new item has been set to be the
+ current item. \a string is the item's text.
+
+ You can also use the highlighted(int) signal.
+*/
+
+/*!
+ \fn void Q3ComboBox::textChanged( const QString &string )
+
+ This signal is used for editable comboboxes. It is emitted
+ whenever the contents of the text entry field changes. \a string
+ contains the new text.
+*/
+
+/*!
+ \property Q3ComboBox::autoCompletion
+ \brief whether auto-completion is enabled
+
+ This property can only be set for editable comboboxes, for
+ non-editable comboboxes it has no effect. It is false by default.
+*/
+
+/*!
+ \property Q3ComboBox::autoResize
+ \brief whether auto-resize is enabled
+ \obsolete
+
+ If this property is set to true then the combobox will resize
+ itself whenever its contents change. The default is false.
+*/
+
+/*!
+ \property Q3ComboBox::count
+ \brief the number of items in the combobox
+*/
+
+/*!
+ \property Q3ComboBox::currentItem
+ \brief the index of the current item in the combobox
+
+ Note that the activated() and highlighted() signals are only
+ emitted when the user changes the current item, not when it is
+ changed programmatically.
+*/
+
+/*!
+ \property Q3ComboBox::currentText
+ \brief the text of the combobox's current item
+*/
+
+/*!
+ \property Q3ComboBox::duplicatesEnabled
+ \brief whether duplicates are allowed
+
+ If the combobox is editable and the user enters some text in the
+ combobox's lineedit and presses Enter (and the insertionPolicy()
+ is not \c NoInsertion), then what happens is this:
+ \list
+ \i If the text is not already in the list, the text is inserted.
+ \i If the text is in the list and this property is true (the
+ default), the text is inserted.
+ \i If the text is in the list and this property is false, the text
+ is \e not inserted; instead the item which has matching text becomes
+ the current item.
+ \endlist
+
+ This property only affects user-interaction. You can use
+ insertItem() to insert duplicates if you wish regardless of this
+ setting.
+*/
+
+/*!
+ \property Q3ComboBox::editable
+ \brief whether the combobox is editable
+
+ This property's default is false. Note that the combobox will be
+ cleared if this property is set to true for a 1.x Motif style
+ combobox. To avoid this, use setEditable() before inserting any
+ items. Also note that the 1.x version of Motif didn't have any
+ editable comboboxes, so the combobox will change its appearance
+ to a 2.0 style Motif combobox is it is set to be editable.
+*/
+
+/*!
+ \property Q3ComboBox::insertionPolicy
+ \brief the position of the items inserted by the user
+
+ The default insertion policy is \c AtBottom. See \l Policy.
+*/
+
+/*!
+ \property Q3ComboBox::maxCount
+ \brief the maximum number of items allowed in the combobox
+*/
+
+/*!
+ \property Q3ComboBox::sizeLimit
+ \brief the maximum on-screen size of the combobox.
+
+ This property is ignored for both Motif 1.x style and non-editable
+ comboboxes in Mac style. The default limit is ten
+ lines. If the number of items in the combobox is or grows larger
+ than lines, a scroll bar is added.
+*/
+
+class Q3ComboBoxPopup : public Q3PopupMenu
+{
+public:
+ Q3ComboBoxPopup( QWidget *parent=0, const char *name=0 )
+ : Q3PopupMenu( parent, name )
+ {
+ }
+
+ int itemHeight( int index )
+ {
+ return Q3PopupMenu::itemHeight( index );
+ }
+};
+
+static inline QString escapedComboString(const QString &str)
+{
+ QString stringToReturn = str;
+ return stringToReturn.replace(QLatin1Char('&'), QLatin1String("&&"));
+}
+
+class Q3ComboBoxPopupItem : public QMenuItem
+{
+ Q3ListBoxItem *li;
+ QSize sc; // Size cache optimization
+public:
+ Q3ComboBoxPopupItem(Q3ListBoxItem *i) : QMenuItem(), li(i), sc(0, 0) { }
+ virtual bool fullSpan() const { return true; }
+ virtual void paint( QPainter*, const QColorGroup&, bool, bool, int, int, int, int);
+ virtual QSize sizeHint() { if (sc.isNull()) sc = QSize(li->width(li->listBox()), QMAX(25, li->height(li->listBox()))); return sc; }
+};
+void Q3ComboBoxPopupItem::paint( QPainter* p, const QColorGroup&, bool,
+ bool, int x, int y, int, int)
+{
+ p->save();
+ p->translate(x, y + ((sizeHint().height() / 2) - (li->height(li->listBox()) / 2)));
+ li->paint(p);
+ p->restore();
+}
+
+
+class Q3ComboBoxData
+{
+public:
+ Q3ComboBoxData( Q3ComboBox *cb ): current( 0 ), arrowDown(false), ed( 0 ), usingLBox( false ), pop( 0 ), lBox( 0 ), combo( cb )
+ {
+ duplicatesEnabled = true;
+ cb->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
+ }
+
+ inline bool usingListBox() { return usingLBox; }
+ inline Q3ListBox * listBox() { return lBox; }
+ inline Q3ComboBoxPopup * popup() { return pop; }
+ void updateLinedGeometry();
+
+ void setListBox( Q3ListBox *l ) { lBox = l ; usingLBox = true;
+ l->setMouseTracking( true );}
+
+ void setPopupMenu( Q3ComboBoxPopup * pm, bool isPopup=true )
+ { pop = pm; if(isPopup) usingLBox = false; }
+
+ QStyleOptionComboBox getStyleOption() const
+ {
+ QStyleOptionComboBox opt;
+ opt.init(combo);
+ if (!combo->editable() && combo->hasFocus())
+ opt.state |= QStyle::State_Selected;
+ opt.subControls = QStyle::SC_All;
+ if (arrowDown) {
+ opt.activeSubControls = QStyle::SC_ComboBoxArrow;
+ opt.state |= QStyle::State_Sunken;
+ }
+ opt.editable = combo->editable();
+ opt.frame = 1; // ### get from style?
+ if (current > -1 && current < combo->count()) {
+ opt.currentText = combo->text(current);
+ if (combo->pixmap(current))
+ opt.currentIcon = QIcon(*combo->pixmap(current));
+ }
+ opt.iconSize = QSize(22, 22); // ### need a sane value here
+// if (container && container->isVisible())
+// opt.state |= QStyle::State_On;
+ return opt;
+ }
+
+ int current;
+ int maxCount;
+ int sizeLimit;
+ Q3ComboBox::Policy p;
+ bool autoresize;
+ bool poppedUp;
+ bool mouseWasInsidePopup;
+ bool arrowPressed;
+ bool arrowDown;
+ bool discardNextMousePress;
+ bool shortClick;
+ bool useCompletion;
+ bool completeNow;
+ int completeAt;
+ bool duplicatesEnabled;
+ int fullHeight, currHeight;
+
+ QLineEdit * ed; // /bin/ed rules!
+ QTimer *completionTimer;
+
+ QSize sizeHint;
+ QHash<int, QPixmap> popupPixmaps;
+
+private:
+ bool usingLBox;
+ Q3ComboBoxPopup *pop;
+ Q3ListBox *lBox;
+ Q3ComboBox *combo;
+};
+
+void Q3ComboBoxData::updateLinedGeometry()
+{
+ if ( !ed || !combo )
+ return;
+
+ QStyleOptionComboBox opt = getStyleOption();
+ QRect r = combo->style()->subControlRect(
+ QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, combo);
+
+ const QPixmap *pix = current < combo->count() ? combo->pixmap( current ) : 0;
+ if ( pix && pix->width() < r.width() )
+ r.setLeft( r.left() + pix->width() + 4 );
+ if ( r != ed->geometry() )
+ ed->setGeometry( r );
+}
+
+static inline bool checkInsertIndex( const char *method, const char * name,
+ int count, int *index)
+{
+ bool range_err = (*index > count);
+#if defined(QT_CHECK_RANGE)
+ if ( range_err )
+ qWarning( "Q3ComboBox::%s: (%s) Index %d out of range",
+ method, name ? name : "<no name>", *index );
+#else
+ Q_UNUSED( method )
+ Q_UNUSED( name )
+#endif
+ if ( *index < 0 ) // append
+ *index = count;
+ return !range_err;
+}
+
+
+static inline bool checkIndex( const char *method, const char * name,
+ int count, int index )
+{
+ bool range_err = (index >= count);
+#if defined(QT_CHECK_RANGE)
+ if ( range_err )
+ qWarning( "Q3ComboBox::%s: (%s) Index %i out of range",
+ method, name ? name : "<no name>", index );
+#else
+ Q_UNUSED( method )
+ Q_UNUSED( name )
+#endif
+ return !range_err;
+}
+
+
+
+/*!
+ Constructs a combobox widget with parent \a parent called \a name.
+
+ This constructor creates a popup list if the program uses Motif
+ (or Aqua) look and feel; this is compatible with Motif 1.x and
+ Aqua.
+
+ Note: If you use this constructor to create your Q3ComboBox, then
+ the pixmap() function will always return 0. To workaround this,
+ use the other constructor.
+
+*/
+
+
+
+Q3ComboBox::Q3ComboBox( QWidget *parent, const char *name )
+ : QWidget( parent, name, Qt::WNoAutoErase )
+{
+ d = new Q3ComboBoxData( this );
+ QStyleOptionComboBox opt;
+ opt.init(this);
+ if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) ||
+ style()->styleHint(QStyle::SH_GUIStyle, &opt, this) == Qt::MotifStyle ) {
+ d->setPopupMenu( new Q3ComboBoxPopup( this, "in-combo" ) );
+ d->popup()->setFont( font() );
+ connect( d->popup(), SIGNAL(activated(int)),
+ SLOT(internalActivate(int)) );
+ connect( d->popup(), SIGNAL(highlighted(int)),
+ SLOT(internalHighlight(int)) );
+ } else {
+ setUpListBox();
+ }
+ d->ed = 0;
+ d->current = 0;
+ d->maxCount = INT_MAX;
+ d->sizeLimit = 10;
+ d->p = AtBottom;
+ d->autoresize = false;
+ d->poppedUp = false;
+ d->arrowDown = false;
+ d->arrowPressed = false;
+ d->discardNextMousePress = false;
+ d->shortClick = false;
+ d->useCompletion = false;
+ d->completeAt = 0;
+ d->completeNow = false;
+ d->completionTimer = new QTimer( this );
+
+ setFocusPolicy( Qt::TabFocus );
+ setBackgroundMode( Qt::PaletteButton );
+}
+
+
+/*!
+ Constructs a combobox with a maximum size and either Motif 2.0 or
+ Windows look and feel.
+
+ The input field can be edited if \a rw is true, otherwise the user
+ may only choose one of the items in the combobox.
+
+ The \a parent and \a name arguments are passed on to the QWidget
+ constructor.
+*/
+
+
+Q3ComboBox::Q3ComboBox( bool rw, QWidget *parent, const char *name )
+ : QWidget( parent, name, Qt::WNoAutoErase )
+{
+ d = new Q3ComboBoxData( this );
+ setUpListBox();
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
+ d->popup()->setItemChecked(d->current, false);
+ d->maxCount = INT_MAX;
+ setSizeLimit(10);
+ d->p = AtBottom;
+ d->autoresize = false;
+ d->poppedUp = false;
+ d->arrowDown = false;
+ d->discardNextMousePress = false;
+ d->shortClick = false;
+ d->useCompletion = false;
+ d->completeAt = 0;
+ d->completeNow = false;
+ d->completionTimer = new QTimer( this );
+
+ setFocusPolicy( Qt::StrongFocus );
+
+ d->ed = 0;
+ if ( rw )
+ setUpLineEdit();
+ setBackgroundMode( Qt::PaletteButton, Qt::PaletteBase );
+}
+
+
+
+/*!
+ Destroys the combobox.
+*/
+
+Q3ComboBox::~Q3ComboBox()
+{
+ delete d;
+}
+
+void Q3ComboBox::setDuplicatesEnabled( bool enable )
+{
+ d->duplicatesEnabled = enable;
+}
+
+bool Q3ComboBox::duplicatesEnabled() const
+{
+ return d->duplicatesEnabled;
+}
+
+int Q3ComboBox::count() const
+{
+ if ( d->usingListBox() )
+ return d->listBox()->count();
+ else if (d->popup())
+ return d->popup()->count();
+ else
+ return 0;
+}
+
+
+/*!
+ \overload
+
+ Inserts the \a list of strings at position \a index in the
+ combobox.
+
+ This is only for compatibility since it does not support Unicode
+ strings. See insertStringList().
+*/
+
+void Q3ComboBox::insertStrList( const Q3StrList &list, int index )
+{
+ insertStrList( &list, index );
+}
+
+/*!
+ \overload
+
+ Inserts the \a list of strings at position \a index in the
+ combobox.
+
+ This is only for compatibility since it does not support Unicode
+ strings. See insertStringList().
+*/
+
+void Q3ComboBox::insertStrList( const Q3StrList *list, int index )
+{
+ if ( !list ) {
+#if defined(QT_CHECK_NULL)
+ Q_ASSERT( list != 0 );
+#endif
+ return;
+ }
+ Q3StrListIterator it( *list );
+ const char* tmp;
+ if ( index < 0 )
+ index = count();
+ while ( (tmp=it.current()) ) {
+ ++it;
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( QString::fromLatin1(tmp), index );
+ else
+ d->popup()->insertItem( escapedComboString(QString::fromLatin1(tmp)), index, index );
+ if ( index++ == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ currentChanged();
+ }
+ }
+ if ( index != count() )
+ reIndex();
+}
+
+/*!
+ Inserts the \a list of strings at position \a index in the
+ combobox.
+*/
+
+void Q3ComboBox::insertStringList( const QStringList &list, int index )
+{
+ QStringList::ConstIterator it = list.begin();
+ if ( index < 0 )
+ index = count();
+ while ( it != list.end() ) {
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( *it, index );
+ else
+ d->popup()->insertItem( escapedComboString(*it), index, index );
+ if ( index++ == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ currentChanged();
+ }
+ ++it;
+ }
+ if ( index != count() )
+ reIndex();
+}
+
+/*!
+ Inserts the array of char * \a strings at position \a index in the
+ combobox.
+
+ The \a numStrings argument is the number of strings. If \a
+ numStrings is -1 (default), the \a strings array must be
+ terminated with 0.
+
+ Example:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3combobox.cpp 2
+
+ \sa insertStringList()
+*/
+
+void Q3ComboBox::insertStrList( const char **strings, int numStrings, int index)
+{
+ if ( !strings ) {
+#if defined(QT_CHECK_NULL)
+ Q_ASSERT( strings != 0 );
+#endif
+ return;
+ }
+ if ( index < 0 )
+ index = count();
+ int i = 0;
+ while ( (numStrings<0 && strings[i]!=0) || i<numStrings ) {
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( QString::fromLatin1(strings[i]), index );
+ else
+ d->popup()->insertItem( escapedComboString(QString::fromLatin1(strings[i])), index, index );
+ i++;
+ if ( index++ == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ currentChanged();
+ }
+ }
+ if ( index != count() )
+ reIndex();
+}
+
+
+/*!
+ Inserts a text item with text \a t, at position \a index. The item
+ will be appended if \a index is negative.
+*/
+
+void Q3ComboBox::insertItem( const QString &t, int index )
+{
+ int cnt = count();
+ if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( t, index );
+ else
+ d->popup()->insertItem( escapedComboString(t), index, index );
+ if ( index != cnt )
+ reIndex();
+ if ( index == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ }
+ if ( index == d->current )
+ currentChanged();
+}
+
+/*!
+ \overload
+
+ Inserts a \a pixmap item at position \a index. The item will be
+ appended if \a index is negative.
+*/
+
+void Q3ComboBox::insertItem( const QPixmap &pixmap, int index )
+{
+ int cnt = count();
+ if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( pixmap, index );
+ else
+ d->popup()->insertItem( pixmap, index, index );
+ if ( index != cnt )
+ reIndex();
+ if ( index == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ }
+ if ( index == d->current )
+ currentChanged();
+}
+
+/*!
+ \overload
+
+ Inserts a \a pixmap item with additional text \a text at position
+ \a index. The item will be appended if \a index is negative.
+*/
+
+void Q3ComboBox::insertItem( const QPixmap &pixmap, const QString& text, int index )
+{
+ int cnt = count();
+ if ( !checkInsertIndex( "insertItem", name(), cnt, &index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->insertItem( pixmap, text, index );
+ else
+ d->popup()->insertItem( pixmap, escapedComboString(text), index, index );
+ if ( index != cnt )
+ reIndex();
+ if ( index == d->current && d->current < count() ) {
+ if ( d->ed ) {
+ d->ed->setText( this->text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ }
+ if ( index == d->current )
+ currentChanged();
+}
+
+
+/*!
+ Removes the item at position \a index.
+*/
+
+void Q3ComboBox::removeItem( int index )
+{
+ int cnt = count();
+ if ( !checkIndex( "removeItem", name(), cnt, index ) )
+ return;
+ if ( d->usingListBox() ) {
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && d->popup() )
+ d->popup()->removeItemAt( index );
+ d->listBox()->removeItem( index );
+ } else {
+ d->popup()->removeItemAt( index );
+ }
+ if ( index != cnt-1 )
+ reIndex();
+ if ( index == d->current ) {
+ if ( d->ed ) {
+ QString s = QString::fromLatin1("");
+ if (d->current < cnt - 1)
+ s = text( d->current );
+ d->ed->setText( s );
+ d->updateLinedGeometry();
+ }
+ else {
+ if ( d->usingListBox() ) {
+ d->current = d->listBox()->currentItem();
+ } else {
+ if (d->current > count()-1 && d->current > 0)
+ d->current--;
+ }
+ update();
+ }
+ currentChanged();
+ }
+ else {
+ if ( !d->ed ) {
+ if (d->current < cnt - 1)
+ setCurrentItem( d->current );
+ else
+ setCurrentItem( d->current - 1 );
+ }
+ }
+
+}
+
+
+/*!
+ Removes all combobox items.
+*/
+
+void Q3ComboBox::clear()
+{
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if ( d->usingListBox() ) {
+ if ( style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && d->popup() )
+ d->popup()->clear();
+ d->listBox()->resize( 0, 0 );
+ d->listBox()->clear();
+ } else {
+ d->popup()->clear();
+ }
+
+ if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
+ d->popup()->setItemChecked(d->current, false);
+ d->current = 0;
+ if ( d->ed ) {
+ d->ed->setText( QString::fromLatin1("") );
+ d->updateLinedGeometry();
+ }
+ currentChanged();
+}
+
+
+QString Q3ComboBox::currentText() const
+{
+ if ( d->ed )
+ return d->ed->text();
+ else if ( d->current < count() )
+ return text( currentItem() );
+ else
+ return QString::null;
+}
+
+void Q3ComboBox::setCurrentText( const QString& txt )
+{
+ int i;
+ for ( i = 0; i < count(); i++)
+ if ( text( i ) == txt )
+ break;
+ if ( i < count() )
+ setCurrentItem( i );
+ else if ( d->ed )
+ d->ed->setText( txt );
+ else
+ changeItem( txt, currentItem() );
+}
+
+
+/*!
+ Returns the text item at position \a index, or QString::null if
+ the item is not a string.
+
+ \sa currentText()
+*/
+
+QString Q3ComboBox::text( int index ) const
+{
+ if ( !checkIndex( "text", name(), count(), index ) )
+ return QString::null;
+ if ( d->usingListBox() ) {
+ return d->listBox()->text( index );
+ } else {
+ QString retText = d->popup()->text(index);
+ retText.replace(QLatin1String("&&"), QString(QLatin1Char('&')));
+ return retText;
+ }
+}
+
+/*!
+ Returns the pixmap item at position \a index, or 0 if the item is
+ not a pixmap.
+*/
+
+const QPixmap *Q3ComboBox::pixmap( int index ) const
+{
+ if ( !checkIndex( "pixmap", name(), count(), index ) )
+ return 0;
+
+ if (d->usingListBox()) {
+ return d->listBox()->pixmap( index );
+ } else {
+ d->popupPixmaps[index] = d->popup()->pixmap(index);
+ return d->popupPixmaps[index].isNull() ? 0 : &d->popupPixmaps[index];
+ }
+}
+
+/*!
+ Replaces the item at position \a index with the text \a t.
+*/
+
+void Q3ComboBox::changeItem( const QString &t, int index )
+{
+ if ( !checkIndex( "changeItem", name(), count(), index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->changeItem( t, index );
+ else
+ d->popup()->changeItem(index, t);
+ if ( index == d->current ) {
+ if ( d->ed ) {
+ d->ed->setText( text( d->current ) );
+ d->updateLinedGeometry();
+ } else
+ update();
+ }
+}
+
+/*!
+ \overload
+
+ Replaces the item at position \a index with the pixmap \a im,
+ unless the combobox is editable.
+
+ \sa insertItem()
+*/
+
+void Q3ComboBox::changeItem( const QPixmap &im, int index )
+{
+ if ( !checkIndex( "changeItem", name(), count(), index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->changeItem( im, index );
+ else
+ d->popup()->changeItem(index, im);
+ if ( index == d->current )
+ update();
+}
+
+/*!
+ \overload
+
+ Replaces the item at position \a index with the pixmap \a im and
+ the text \a t.
+
+ \sa insertItem()
+*/
+
+void Q3ComboBox::changeItem( const QPixmap &im, const QString &t, int index )
+{
+ if ( !checkIndex( "changeItem", name(), count(), index ) )
+ return;
+ if ( d->usingListBox() )
+ d->listBox()->changeItem( im, t, index );
+ else
+ d->popup()->changeItem(index, im, t);
+ if ( index == d->current )
+ update();
+}
+
+
+int Q3ComboBox::currentItem() const
+{
+ return d->current;
+}
+
+void Q3ComboBox::setCurrentItem( int index )
+{
+ if ( index == d->current && !d->ed ) {
+ return;
+ }
+ if ( !checkIndex( "setCurrentItem", name(), count(), index ) ) {
+ return;
+ }
+
+ if ( d->usingListBox() && !( listBox()->item(index) && listBox()->item(index)->isSelectable() ) )
+ return;
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
+ d->popup()->setItemChecked(d->current, false);
+ d->current = index;
+ d->completeAt = 0;
+ if ( d->ed ) {
+ d->ed->setText( text( index ) );
+ d->updateLinedGeometry();
+ }
+ // ### We want to keep ListBox's currentItem in sync, even if NOT popuped...
+ if ( d->usingListBox() && d->listBox() ) {
+ d->listBox()->setCurrentItem( index );
+ } else {
+ internalHighlight( index );
+ // internalActivate( index ); ### this leads to weird behavior, as in 3.0.1
+ }
+
+ currentChanged();
+}
+
+/*!
+ Returns true if auto-resize is enabled; otherwise returns false.
+
+ \sa autoResize
+*/
+
+bool Q3ComboBox::autoResize() const
+{
+ return d->autoresize;
+}
+
+/*!
+ If \a enable is true, enable auto-resize; disable it otherwise.
+
+ \sa autoResize
+*/
+
+void Q3ComboBox::setAutoResize( bool enable )
+{
+ if ( (bool)d->autoresize != enable ) {
+ d->autoresize = enable;
+ if ( enable )
+ adjustSize();
+ }
+}
+
+
+/*!
+ \reimp
+
+ This implementation caches the size hint to avoid resizing when
+ the contents change dynamically. To invalidate the cached value
+ call setFont().
+*/
+QSize Q3ComboBox::sizeHint() const
+{
+ if ( isVisible() && d->sizeHint.isValid() )
+ return d->sizeHint;
+
+ constPolish();
+ int i, w;
+ QFontMetrics fm = fontMetrics();
+
+ int maxW = count() ? 18 : 7 * fm.width(QLatin1Char('x')) + 18;
+ int maxH = QMAX( fm.lineSpacing(), 14 ) + 2;
+
+ if ( !d->usingListBox() ) {
+ w = d->popup()->sizeHint().width() - 2* d->popup()->frameWidth();
+ if ( w > maxW )
+ maxW = w;
+ } else {
+ for( i = 0; i < count(); i++ ) {
+ w = d->listBox()->item( i )->width( d->listBox() );
+ if ( w > maxW )
+ maxW = w;
+ }
+ }
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ d->sizeHint = (style()->sizeFromContents(QStyle::CT_ComboBox, &opt, QSize(maxW, maxH), this).
+ expandedTo(QApplication::globalStrut()));
+
+ return d->sizeHint;
+}
+
+
+/*!
+ \internal
+ Receives activated signals from an internal popup list and emits
+ the activated() signal.
+*/
+
+void Q3ComboBox::internalActivate( int index )
+{
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if ( d->current != index ) {
+ if ( !d->usingListBox() || listBox()->item( index )->isSelectable() ) {
+ if (d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
+ d->popup()->setItemChecked(d->current, false);
+ d->current = index;
+ currentChanged();
+ }
+ }
+ if ( d->usingListBox() )
+ popDownListBox();
+ else
+ d->popup()->removeEventFilter( this );
+ d->poppedUp = false;
+
+ QString t( text( index ) );
+ if ( d->ed ) {
+ d->ed->setText( t );
+ d->updateLinedGeometry();
+ }
+ emit activated( index );
+ emit activated( t );
+}
+
+/*!
+ \internal
+ Receives highlighted signals from an internal popup list and emits
+ the highlighted() signal.
+*/
+
+void Q3ComboBox::internalHighlight( int index )
+{
+ emit highlighted( index );
+ QString t = text( index );
+ if ( !t.isNull() )
+ emit highlighted( t );
+}
+
+/*!
+ \internal
+ Receives timeouts after a click. Used to decide if a Motif style
+ popup should stay up or not after a click.
+*/
+void Q3ComboBox::internalClickTimeout()
+{
+ d->shortClick = false;
+}
+
+/*!
+ Sets the palette for both the combobox button and the combobox
+ popup list to \a palette.
+*/
+
+void Q3ComboBox::setPalette( const QPalette &palette )
+{
+ QWidget::setPalette( palette );
+ if ( d->listBox() )
+ d->listBox()->setPalette( palette );
+ if ( d->popup() )
+ d->popup()->setPalette( palette );
+}
+
+/*!
+ Sets the font for both the combobox button and the combobox popup
+ list to \a font.
+*/
+
+void Q3ComboBox::setFont( const QFont &font )
+{
+ d->sizeHint = QSize(); // invalidate size hint
+ QWidget::setFont( font );
+ if ( d->usingListBox() )
+ d->listBox()->setFont( font );
+ else
+ d->popup()->setFont( font );
+ if (d->ed)
+ d->ed->setFont( font );
+ if ( d->autoresize )
+ adjustSize();
+}
+
+
+/*!\reimp
+*/
+
+void Q3ComboBox::resizeEvent( QResizeEvent * e )
+{
+ if ( d->ed )
+ d->updateLinedGeometry();
+ if ( d->listBox() )
+ d->listBox()->resize( width(), d->listBox()->height() );
+ QWidget::resizeEvent( e );
+}
+
+/*!\reimp
+*/
+
+void Q3ComboBox::paintEvent( QPaintEvent * )
+{
+ QPainter p( this );
+ const QColorGroup & g = colorGroup();
+ p.setPen(g.text());
+
+ if ( width() < 5 || height() < 5 ) {
+ qDrawShadePanel( &p, rect(), g, false, 2,
+ &g.brush( QColorGroup::Button ) );
+ return;
+ }
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ bool reverse = QApplication::reverseLayout();
+ if ( !d->usingListBox() &&
+ style()->styleHint(QStyle::SH_GUIStyle) == Qt::MotifStyle) { // motif 1.x style
+ int dist, buttonH, buttonW;
+ dist = 8;
+ buttonH = 7;
+ buttonW = 11;
+ int xPos;
+ int x0;
+ int w = width() - dist - buttonW - 1;
+ if ( reverse ) {
+ xPos = dist + 1;
+ x0 = xPos + 4;
+ } else {
+ xPos = w;
+ x0 = 4;
+ }
+ qDrawShadePanel( &p, rect(), g, false,
+ style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this),
+ &g.brush( QColorGroup::Button ) );
+ qDrawShadePanel( &p, xPos, (height() - buttonH)/2,
+ buttonW, buttonH, g, false,
+ style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this) );
+ QRect clip( x0, 2, w - 2 - 4 - 5, height() - 4 );
+ QString str = d->popup()->text( this->d->current );
+ if ( !str.isNull() ) {
+ p.drawText( clip, Qt::AlignCenter | Qt::TextSingleLine, str );
+ }
+
+ QPixmap pix = d->popup()->pixmap( this->d->current );
+ QIcon iconSet = d->popup()->iconSet( this->d->current );
+ if (!pix.isNull() || !iconSet.isNull()) {
+ QPixmap pm = ( !pix.isNull() ? pix : iconSet.pixmap() );
+ p.setClipRect( clip );
+ p.drawPixmap( 4, (height()-pm.height())/2, pm );
+ p.setClipping( false );
+ }
+
+ if ( hasFocus() )
+ p.drawRect( xPos - 5, 4, width() - xPos + 1 , height() - 8 );
+ } else if(!d->usingListBox()) {
+ style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this);
+ QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxEditField, this);
+ p.setClipRect( re );
+
+ QString str = d->popup()->text( this->d->current );
+ QPixmap pix = d->popup()->pixmap( this->d->current );
+ if ( !str.isNull() ) {
+ p.save();
+ p.setFont(font());
+ QFontMetrics fm(font());
+ int x = re.x(), y = re.y() + fm.ascent();
+ x += pix.width() + 5;
+ p.drawText( x, y, str );
+ p.restore();
+ }
+ if (!pix.isNull()) {
+ p.fillRect(re.x(), re.y(), pix.width() + 4, re.height(),
+ colorGroup().brush(QColorGroup::Base));
+ p.drawPixmap(re.x() + 2, re.y() + (re.height() - pix.height()) / 2, pix);
+ }
+ } else {
+ style()->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this);
+ QRect re = style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxEditField, this);
+ p.setClipRect(re);
+
+ if ( !d->ed ) {
+ Q3ListBoxItem * item = d->listBox()->item( d->current );
+ if ( item ) {
+ int itemh = item->height( d->listBox() );
+ p.translate( re.x(), re.y() + (re.height() - itemh)/2 );
+ item->paint( &p );
+ }
+ } else if ( d->listBox() && d->listBox()->item( d->current ) ) {
+ Q3ListBoxItem * item = d->listBox()->item( d->current );
+ const QPixmap *pix = item->pixmap();
+ if ( pix ) {
+ p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
+ colorGroup().brush( QColorGroup::Base ) );
+ p.drawPixmap( re.x() + 2, re.y() +
+ ( re.height() - pix->height() ) / 2, *pix );
+ }
+ }
+ p.setClipping( false );
+ }
+}
+
+
+/*!\reimp
+*/
+
+void Q3ComboBox::mousePressEvent( QMouseEvent *e )
+{
+ if ( e->button() != Qt::LeftButton )
+ return;
+ if ( d->discardNextMousePress ) {
+ d->discardNextMousePress = false;
+ return;
+ }
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow
+ , this);
+
+ // Correction for motif style, where arrow is smaller
+ // and thus has a rect that doesn't fit the button.
+ arrowRect.setHeight( QMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
+
+ if ( count() && ( !editable() || arrowRect.contains( e->pos() ) ) ) {
+ d->arrowPressed = false;
+
+ if ( d->usingListBox() ) {
+ listBox()->blockSignals( true );
+ qApp->sendEvent( listBox(), e ); // trigger the listbox's autoscroll
+ listBox()->setCurrentItem(d->current);
+ listBox()->blockSignals( false );
+ popup();
+ if ( arrowRect.contains( e->pos() ) ) {
+ d->arrowPressed = true;
+ d->arrowDown = true;
+ repaint( false );
+ }
+ } else {
+ popup();
+ }
+ QTimer::singleShot( 200, this, SLOT(internalClickTimeout()));
+ d->shortClick = true;
+ }
+}
+
+/*!\reimp
+*/
+
+void Q3ComboBox::mouseMoveEvent( QMouseEvent * )
+{
+}
+
+/*!\reimp
+*/
+
+void Q3ComboBox::mouseReleaseEvent( QMouseEvent * )
+{
+}
+
+/*!\reimp
+*/
+
+void Q3ComboBox::mouseDoubleClickEvent( QMouseEvent *e )
+{
+ mousePressEvent( e );
+}
+
+
+/*!\reimp
+*/
+
+void Q3ComboBox::keyPressEvent( QKeyEvent *e )
+{
+ bool handleEventHere = d->usingListBox() || !d->poppedUp;
+
+ int c = currentItem();
+ if ( ( e->key() == Qt::Key_F4 && e->state() == 0 ) ||
+ ( e->key() == Qt::Key_Down && (e->state() & Qt::AltModifier) ) ||
+ ( !d->ed && e->key() == Qt::Key_Space ) ) {
+ if ( count() ) {
+ if ( !d->usingListBox() )
+ d->popup()->setActiveItem( this->d->current );
+ popup();
+ }
+ return;
+ } else if ( handleEventHere && e->key() == Qt::Key_Up ) {
+ if ( c > 0 )
+ setCurrentItem( c-1 );
+ } else if ( handleEventHere && e->key() == Qt::Key_Down ) {
+ if ( ++c < count() )
+ setCurrentItem( c );
+ } else if ( handleEventHere && e->key() == Qt::Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) {
+ setCurrentItem( 0 );
+ } else if ( handleEventHere && e->key() == Qt::Key_End && ( !d->ed || !d->ed->hasFocus() ) ) {
+ setCurrentItem( count()-1 );
+ } else if ( !d->ed && e->ascii() >= 32 && !e->text().isEmpty() ) {
+ if ( !d->completionTimer->isActive() ) {
+ d->completeAt = 0;
+ c = completionIndex( e->text(), ++c );
+ if ( c >= 0 ) {
+ setCurrentItem( c );
+ d->completeAt = e->text().length();
+ }
+ } else {
+ d->completionTimer->stop();
+ QString ct = currentText().left( d->completeAt ) + e->text();
+ c = completionIndex( ct, c );
+ if ( c < 0 && d->completeAt > 0 ) {
+ c = completionIndex( e->text(), 0 );
+ ct = e->text();
+ }
+ d->completeAt = 0;
+ if ( c >= 0 ) {
+ setCurrentItem( c );
+ d->completeAt = ct.length();
+ }
+ }
+ d->completionTimer->start( 400, true );
+ } else {
+ e->ignore();
+ return;
+ }
+
+ c = currentItem();
+ if ( count() && !text( c ).isNull() )
+ emit activated( text( c ) );
+ emit activated( c );
+}
+
+
+/*!\reimp
+*/
+
+void Q3ComboBox::focusInEvent( QFocusEvent * e )
+{
+ QWidget::focusInEvent( e );
+ d->completeNow = false;
+ d->completeAt = 0;
+}
+
+/*!\reimp
+*/
+
+void Q3ComboBox::focusOutEvent( QFocusEvent * e )
+{
+ QWidget::focusOutEvent( e );
+ d->completeNow = false;
+ d->completeAt = 0;
+}
+
+/*!\reimp
+*/
+#ifndef QT_NO_WHEELEVENT
+void Q3ComboBox::wheelEvent( QWheelEvent *e )
+{
+ if ( d->poppedUp ) {
+ if ( d->usingListBox() ) {
+ QApplication::sendEvent( d->listBox(), e );
+ }
+ } else {
+ if ( e->delta() > 0 ) {
+ int c = currentItem();
+ if ( c > 0 ) {
+ setCurrentItem( c-1 );
+ emit activated( currentItem() );
+ emit activated( currentText() );
+ }
+ } else {
+ int c = currentItem();
+ if ( ++c < count() ) {
+ setCurrentItem( c );
+ emit activated( currentItem() );
+ emit activated( currentText() );
+ }
+ }
+ e->accept();
+ }
+}
+#endif
+
+/*!
+ \internal
+ Calculates the listbox height needed to contain all items, or as
+ many as the list box is supposed to contain.
+*/
+static int listHeight( Q3ListBox *l, int sl )
+{
+ if ( l->count() > 0 )
+ return QMIN( l->count(), (uint)sl) * l->item( 0 )->height(l);
+ else
+ return l->sizeHint().height();
+}
+
+
+/*!
+ Pops up the combobox popup list.
+
+ If the list is empty, no items appear.
+*/
+
+void Q3ComboBox::popup()
+{
+ if ( !count() || d->poppedUp )
+ return;
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if( !d->usingListBox() || style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) ) {
+ if(d->usingListBox()) {
+ if(!d->popup()) {
+ Q3ComboBoxPopup *p = new Q3ComboBoxPopup( this, "in-combo" );
+ d->setPopupMenu( p, false );
+ p->setFont( font() );
+ connect( p, SIGNAL(activated(int)), SLOT(internalActivate(int)) );
+ connect( p, SIGNAL(highlighted(int)), SLOT(internalHighlight(int)) );
+ }
+ d->popup()->clear();
+ for(unsigned int i = 0; i < d->listBox()->count(); i++) {
+ Q3ListBoxItem *item = d->listBox()->item(i);
+ if(item->rtti() == Q3ListBoxText::RTTI) {
+ d->popup()->insertItem(escapedComboString(item->text()), i, i);
+ } else if(item->rtti() == Q3ListBoxPixmap::RTTI) {
+ if(item->pixmap())
+ d->popup()->insertItem(QIcon(*item->pixmap()), escapedComboString(item->text()), i, i);
+ else
+ d->popup()->insertItem(escapedComboString(item->text()), i, i);
+ } else {
+ d->popup()->insertItem(new Q3ComboBoxPopupItem(item), i, i);
+ }
+ }
+ }
+ d->popup()->installEventFilter( this );
+ if(d->popup() && style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this))
+ d->popup()->setItemChecked(this->d->current, true);
+ d->popup()->popup( mapToGlobal( QPoint(0,0) ), this->d->current );
+ update();
+ } else {
+ // Send all listbox events to eventFilter():
+ Q3ListBox* lb = d->listBox();
+ lb->triggerUpdate( true );
+ lb->installEventFilter( this );
+ d->mouseWasInsidePopup = false;
+ int w = lb->variableWidth() ? lb->sizeHint().width() : width();
+ int h = listHeight( lb, d->sizeLimit ) + 2;
+ QRect screen = QApplication::desktop()->availableGeometry( this );
+
+ int sx = screen.x(); // screen pos
+ int sy = screen.y();
+ int sw = screen.width(); // screen width
+ int sh = screen.height(); // screen height
+ QPoint pos = mapToGlobal( QPoint(0,height()) );
+ // ## Similar code is in QPopupMenu
+ int x = pos.x();
+ int y = pos.y();
+
+ // the complete widget must be visible
+ if ( x + w > sx + sw )
+ x = sx+sw - w;
+ if ( x < sx )
+ x = sx;
+ if (y + h > sy+sh && y - h - height() >= 0 )
+ y = y - h - height();
+
+ opt.rect = QRect(x, y, w, h);
+ QRect rect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxListBoxPopup, this);
+
+ // work around older styles that don't implement the combobox
+ // listbox popup subcontrol
+ if ( rect.isNull() )
+ rect.setRect( x, y, w, h );
+ lb->setGeometry( rect );
+
+ lb->raise();
+ bool block = lb->signalsBlocked();
+ lb->blockSignals( true );
+ Q3ListBoxItem* currentLBItem = 0;
+ if ( editable() && currentText() != text( currentItem() ) )
+ currentLBItem = lb->findItem( currentText() );
+
+ currentLBItem = currentLBItem ? currentLBItem : lb->item( d->current );
+
+ lb->setCurrentItem( currentLBItem );
+ lb->setContentsPos( lb->contentsX(),
+ lb->viewportToContents( lb->itemRect( currentLBItem ).topLeft() ).y() );
+
+ // set the current item to also be the selected item if it isn't already
+ if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() )
+ lb->setSelected( currentLBItem, true );
+ lb->blockSignals( block );
+ lb->setVScrollBarMode(Q3ScrollView::Auto);
+
+#ifndef QT_NO_EFFECTS
+ if ( QApplication::isEffectEnabled( Qt::UI_AnimateCombo ) ) {
+ if ( lb->y() < mapToGlobal(QPoint(0,0)).y() )
+ qScrollEffect( lb, QEffects::UpScroll );
+ else
+ qScrollEffect( lb );
+ } else
+#endif
+ lb->show();
+ }
+ d->poppedUp = true;
+}
+
+
+/*!
+ Updates the widget mask.
+
+ \sa QWidget::setMask()
+*/
+void Q3ComboBox::updateMask()
+{
+ QBitmap bm( size() );
+ bm.fill( Qt::color0 );
+
+ QStyleOptionComboBox opt = d->getStyleOption();
+ {
+ QPainter p(&bm);
+ p.initFrom(this);
+ p.fillRect(opt.rect, Qt::color1); // qcommonstyle old drawComplexControl implementation
+ }
+
+ setMask( bm );
+}
+
+/*!
+ \internal
+ Pops down (removes) the combobox popup list box.
+*/
+void Q3ComboBox::popDownListBox()
+{
+ Q_ASSERT( d->usingListBox() );
+ d->listBox()->removeEventFilter( this );
+ d->listBox()->viewport()->removeEventFilter( this );
+ d->listBox()->hide();
+ d->listBox()->setCurrentItem( d->current );
+ if ( d->arrowDown ) {
+ d->arrowDown = false;
+ repaint( false );
+ }
+ d->poppedUp = false;
+}
+
+
+/*!
+ \internal
+ Re-indexes the identifiers in the popup list.
+*/
+
+void Q3ComboBox::reIndex()
+{
+ if ( !d->usingListBox() ) {
+ int cnt = count();
+ while ( cnt-- )
+ d->popup()->setId( cnt, cnt );
+ }
+}
+
+/*!
+ \internal
+ Repaints the combobox.
+*/
+
+void Q3ComboBox::currentChanged()
+{
+ if ( d->autoresize )
+ adjustSize();
+ update();
+
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+}
+
+/*! \reimp
+
+ \internal
+
+ The event filter steals events from the popup or listbox when they
+ are popped up. It makes the popup stay up after a short click in
+ motif style. In windows style it toggles the arrow button of the
+ combobox field, and activates an item and takes down the listbox
+ when the mouse button is released.
+*/
+
+bool Q3ComboBox::eventFilter( QObject *object, QEvent *event )
+{
+ QStyleOptionComboBox opt = d->getStyleOption();
+ if ( !event )
+ return true;
+ else if ( object == d->ed ) {
+ if ( event->type() == QEvent::KeyPress ) {
+ bool isAccepted = ( (QKeyEvent*)event )->isAccepted();
+ keyPressEvent( (QKeyEvent *)event );
+ if ( ((QKeyEvent *)event)->isAccepted() ) {
+ d->completeNow = false;
+ return true;
+ } else if ( ((QKeyEvent *)event)->key() != Qt::Key_End ) {
+ d->completeNow = true;
+ d->completeAt = d->ed->cursorPosition();
+ }
+ if ( isAccepted )
+ ( (QKeyEvent*)event )->accept();
+ else
+ ( (QKeyEvent*)event )->ignore();
+ } else if ( event->type() == QEvent::KeyRelease ) {
+ keyReleaseEvent( (QKeyEvent *)event );
+ return ((QKeyEvent *)event)->isAccepted();
+ } else if ( event->type() == QEvent::FocusIn ) {
+ focusInEvent( (QFocusEvent *)event );
+ } else if ( event->type() == QEvent::FocusOut ) {
+ focusOutEvent( (QFocusEvent *)event );
+ } else if ( d->useCompletion && d->completeNow ) {
+ d->completeNow = false;
+ if ( !d->ed->text().isNull() &&
+ d->ed->cursorPosition() > d->completeAt &&
+ d->ed->cursorPosition() == (int)d->ed->text().length() ) {
+ QString ct( d->ed->text() );
+ int i = completionIndex( ct, currentItem() );
+ if ( i > -1 ) {
+ QString it = text( i );
+ d->ed->validateAndSet( it, ct.length(),
+ ct.length(), it.length() );
+ d->current = i;
+ // ### sets current item without emitting signals. This is to
+ // make sure the right item is current if you change current with
+ // wheel/up/down. While typing current is not valid anyway. Fix properly
+ // in 4.0.
+ }
+ }
+ }
+ } else if ( d->usingListBox() && ( object == d->listBox() ||
+ object == d->listBox()->viewport() )) {
+ QMouseEvent *e = (QMouseEvent*)event;
+ switch( event->type() ) {
+ case QEvent::MouseMove:
+ if ( !d->mouseWasInsidePopup ) {
+ QPoint pos = e->pos();
+ if ( d->listBox()->rect().contains( pos ) )
+ d->mouseWasInsidePopup = true;
+ // Check if arrow button should toggle
+ if ( d->arrowPressed ) {
+ QPoint comboPos;
+ comboPos = mapFromGlobal( d->listBox()->mapToGlobal(pos) );
+ QRect arrowRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxArrow, this);
+ if ( arrowRect.contains( comboPos ) ) {
+ if ( !d->arrowDown ) {
+ d->arrowDown = true;
+ repaint( false );
+ }
+ } else {
+ if ( d->arrowDown ) {
+ d->arrowDown = false;
+ repaint( false );
+ }
+ }
+ }
+ } else if ((e->state() & ( Qt::RightButton | Qt::LeftButton | Qt::MidButton ) ) == 0 &&
+ style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, this)) {
+ QWidget *mouseW = QApplication::widgetAt( e->globalPos(), true );
+ if ( mouseW == d->listBox()->viewport() ) { //###
+ QMouseEvent m( QEvent::MouseMove, e->pos(), e->globalPos(),
+ Qt::NoButton, Qt::LeftButton );
+ QApplication::sendEvent( object, &m ); //### Evil
+ return true;
+ }
+ }
+
+ break;
+ case QEvent::MouseButtonRelease:
+ if ( d->listBox()->rect().contains( e->pos() ) ) {
+ QMouseEvent tmp( QEvent::MouseButtonDblClick,
+ e->pos(), e->button(), e->state() ) ;
+ // will hide popup
+ QApplication::sendEvent( object, &tmp );
+ return true;
+ } else {
+ if ( d->mouseWasInsidePopup ) {
+ popDownListBox();
+ } else {
+ d->arrowPressed = false;
+ if ( d->arrowDown ) {
+ d->arrowDown = false;
+ repaint( false );
+ }
+ }
+ }
+ break;
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ if ( !d->listBox()->rect().contains( e->pos() ) ) {
+ QPoint globalPos = d->listBox()->mapToGlobal(e->pos());
+ if ( QApplication::widgetAt( globalPos, true ) == this ) {
+ d->discardNextMousePress = true;
+ // avoid popping up again
+ }
+ popDownListBox();
+ return true;
+ }
+ break;
+ case QEvent::KeyPress:
+ switch( ((QKeyEvent *)event)->key() ) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ if ( !(((QKeyEvent *)event)->state() & Qt::AltModifier) )
+ break;
+ case Qt::Key_F4:
+ case Qt::Key_Escape:
+ if ( d->poppedUp ) {
+ popDownListBox();
+ return true;
+ }
+ break;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ // work around QDialog's enter handling
+ return false;
+ default:
+ break;
+ }
+ break;
+ case QEvent::Hide:
+ popDownListBox();
+ break;
+ default:
+ break;
+ }
+ } else if ( (!d->usingListBox() || style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) &&
+ object == d->popup() ) {
+ QMouseEvent *e = (QMouseEvent*)event;
+ switch ( event->type() ) {
+ case QEvent::MouseButtonRelease:
+ if ( d->shortClick ) {
+ QMouseEvent tmp( QEvent::MouseMove,
+ e->pos(), e->button(), e->state() ) ;
+ // highlight item, but don't pop down:
+ QApplication::sendEvent( object, &tmp );
+ return true;
+ }
+ break;
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ if ( !d->popup()->rect().contains( e->pos() ) ) {
+ d->poppedUp = false;
+ d->arrowDown = false;
+ // remove filter, event will take down popup:
+ d->popup()->removeEventFilter( this );
+ // ### uglehack!
+ // call internalHighlight so the highlighed signal
+ // will be emitted at least as often as necessary.
+ // it may be called more often than necessary
+ internalHighlight( d->current );
+ }
+ break;
+ case QEvent::Hide:
+ d->poppedUp = false;
+ break;
+ default:
+ break;
+ }
+ }
+ return QWidget::eventFilter( object, event );
+}
+
+
+/*!
+ Returns the index of the first item \e after \a startingAt of
+ which \a prefix is a case-insensitive prefix. Returns -1 if no
+ items start with \a prefix.
+*/
+
+int Q3ComboBox::completionIndex( const QString & prefix,
+ int startingAt = 0 ) const
+{
+ int start = startingAt;
+ if ( start < 0 || start >= count() )
+ start = 0;
+ if ( start >= count() )
+ return -1;
+ QString match = prefix.lower();
+ if ( match.length() < 1 )
+ return start;
+
+ QString current;
+ int i = start;
+ do {
+ current = text( i ).lower();
+ if ( current.startsWith( match ) )
+ return i;
+ i++;
+ if ( i == count() )
+ i = 0;
+ } while ( i != start );
+ return -1;
+}
+
+int Q3ComboBox::sizeLimit() const
+{
+ return d ? d->sizeLimit : INT_MAX;
+}
+
+void Q3ComboBox::setSizeLimit( int lines )
+{
+ d->sizeLimit = lines;
+}
+
+
+int Q3ComboBox::maxCount() const
+{
+ return d ? d->maxCount : INT_MAX;
+}
+
+void Q3ComboBox::setMaxCount( int count )
+{
+ int l = this->count();
+ while( --l > count )
+ removeItem( l );
+ d->maxCount = count;
+}
+
+Q3ComboBox::Policy Q3ComboBox::insertionPolicy() const
+{
+ return d->p;
+}
+
+void Q3ComboBox::setInsertionPolicy( Policy policy )
+{
+ d->p = policy;
+}
+
+
+
+/*!
+ Internal slot to keep the line editor up to date.
+*/
+
+void Q3ComboBox::returnPressed()
+{
+ QString s( d->ed->text() );
+
+ if ( s.isEmpty() )
+ return;
+
+ int c = 0;
+ bool doInsert = true;
+ if ( !d->duplicatesEnabled ) {
+ for ( int i = 0; i < count(); ++i ) {
+ if ( s == text( i ) ) {
+ doInsert = false;
+ c = i;
+ break;
+ }
+ }
+ }
+
+ if ( doInsert ) {
+ if ( insertionPolicy() != NoInsert ) {
+ int cnt = count();
+ while ( cnt >= d->maxCount ) {
+ removeItem( --cnt );
+ }
+ }
+
+ switch ( insertionPolicy() ) {
+ case InsertAtCurrent:
+ if (count() == 0)
+ insertItem(s);
+ else if ( s != text( currentItem() ) )
+ changeItem( s, currentItem() );
+ emit activated( currentItem() );
+ emit activated( s );
+ return;
+ case NoInsert:
+ emit activated( s );
+ return;
+ case InsertAtTop:
+ c = 0;
+ break;
+ case InsertAtBottom:
+ c = count();
+ break;
+ case InsertBeforeCurrent:
+ c = currentItem();
+ break;
+ case InsertAfterCurrent:
+ c = count() == 0 ? 0 : currentItem() + 1;
+ break;
+ }
+ insertItem( s, c );
+ }
+
+ setCurrentItem( c );
+ emit activated( c );
+ emit activated( s );
+}
+
+
+/*!
+ Enables the combobox if \a enable is true; otherwise disables it.
+
+ \sa QWidget::enabled
+*/
+
+void Q3ComboBox::setEnabled( bool enable )
+{
+ if ( !enable ) {
+ if ( d->usingListBox() ) {
+ popDownListBox();
+ } else {
+ d->popup()->removeEventFilter( this );
+ d->popup()->close();
+ d->poppedUp = false;
+ }
+ }
+ QWidget::setEnabled( enable );
+}
+
+
+
+/*!
+ Applies the validator \a v to the combobox so that only text which
+ is valid according to \a v is accepted.
+
+ This function does nothing if the combobox is not editable.
+
+ \sa validator() clearValidator() QValidator
+*/
+
+void Q3ComboBox::setValidator( const QValidator * v )
+{
+ if ( d && d->ed )
+ d->ed->setValidator( v );
+}
+
+
+/*!
+ Returns the validator which constrains editing for this combobox
+ if there is one; otherwise returns 0.
+
+ \sa setValidator() clearValidator() QValidator
+*/
+
+const QValidator * Q3ComboBox::validator() const
+{
+ return d && d->ed ? d->ed->validator() : 0;
+}
+
+
+/*!
+ This slot is equivalent to setValidator( 0 ).
+*/
+
+void Q3ComboBox::clearValidator()
+{
+ if ( d && d->ed )
+ d->ed->setValidator( 0 );
+}
+
+
+/*!
+ Sets the combobox to use \a newListBox instead of the current list
+ box or popup. As a side effect, it clears the combobox of its
+ current contents.
+
+ \warning Q3ComboBox assumes that newListBox->text(n) returns
+ non-null for 0 \<= n \< newListbox->count(). This assumption is
+ necessary because of the line edit in Q3ComboBox.
+*/
+
+void Q3ComboBox::setListBox( Q3ListBox * newListBox )
+{
+ clear();
+
+ if ( d->usingListBox() ) {
+ delete d->listBox();
+ } else {
+ delete d->popup();
+ d->setPopupMenu(0, false);
+ }
+
+ newListBox->reparent( this, Qt::WType_Popup, QPoint(0,0), false );
+ d->setListBox( newListBox );
+ d->listBox()->setFont( font() );
+ d->listBox()->setPalette( palette() );
+ d->listBox()->setVScrollBarMode(Q3ScrollView::AlwaysOff);
+ d->listBox()->setHScrollBarMode(Q3ScrollView::AlwaysOff);
+ d->listBox()->setFrameStyle( Q3Frame::Box | Q3Frame::Plain );
+ d->listBox()->setLineWidth( 1 );
+ d->listBox()->resize( 100, 10 );
+
+ connect( d->listBox(), SIGNAL(selected(int)),
+ SLOT(internalActivate(int)) );
+ connect( d->listBox(), SIGNAL(highlighted(int)),
+ SLOT(internalHighlight(int)));
+}
+
+
+/*!
+ Returns the current list box, or 0 if there is no list box.
+ (Q3ComboBox can use QPopupMenu instead of QListBox.) Provided to
+ match setListBox().
+
+ \sa setListBox()
+*/
+
+Q3ListBox * Q3ComboBox::listBox() const
+{
+ return d && d->usingListBox() ? d->listBox() : 0;
+}
+
+/*!
+ Returns the line edit, or 0 if there is no line edit.
+
+ Only editable listboxes have a line editor.
+*/
+QLineEdit* Q3ComboBox::lineEdit() const
+{
+ return d->ed;
+}
+
+
+
+/*!
+ Clears the line edit without changing the combobox's contents.
+ Does nothing if the combobox isn't editable.
+
+ This is particularly useful when using a combobox as a line edit
+ with history. For example you can connect the combobox's
+ activated() signal to clearEdit() in order to present the user
+ with a new, empty line as soon as Enter is pressed.
+
+ \sa setEditText()
+*/
+
+void Q3ComboBox::clearEdit()
+{
+ if ( d && d->ed )
+ d->ed->clear();
+}
+
+
+/*!
+ Sets the text in the line edit to \a newText without changing the
+ combobox's contents. Does nothing if the combobox isn't editable.
+
+ This is useful e.g. for providing a good starting point for the
+ user's editing and entering the change in the combobox only when
+ the user presses Enter.
+
+ \sa clearEdit() insertItem()
+*/
+
+void Q3ComboBox::setEditText( const QString &newText )
+{
+ if ( d && d->ed ) {
+ d->updateLinedGeometry();
+ d->ed->setText( newText );
+ }
+}
+
+void Q3ComboBox::setAutoCompletion( bool enable )
+{
+ d->useCompletion = enable;
+ d->completeNow = false;
+}
+
+
+bool Q3ComboBox::autoCompletion() const
+{
+ return d->useCompletion;
+}
+
+/*!\reimp
+ */
+void Q3ComboBox::styleChange( QStyle& s )
+{
+ d->sizeHint = QSize(); // invalidate size hint...
+ if ( d->ed )
+ d->updateLinedGeometry();
+ QWidget::styleChange( s );
+}
+
+bool Q3ComboBox::editable() const
+{
+ return d->ed != 0;
+}
+
+void Q3ComboBox::setEditable( bool y )
+{
+ if ( y == editable() )
+ return;
+ if ( y ) {
+ if ( !d->usingListBox() )
+ setUpListBox();
+ setUpLineEdit();
+ d->ed->show();
+ if ( currentItem() )
+ setEditText( currentText() );
+ } else {
+ delete d->ed;
+ d->ed = 0;
+ }
+
+ setFocusPolicy(Qt::StrongFocus);
+ updateGeometry();
+ update();
+}
+
+
+void Q3ComboBox::setUpListBox()
+{
+ d->setListBox( new Q3ListBox( this, "in-combo", Qt::WType_Popup ) );
+ d->listBox()->setFont( font() );
+ d->listBox()->setPalette( palette() );
+ d->listBox()->setVScrollBarMode( Q3ListBox::AlwaysOff );
+ d->listBox()->setHScrollBarMode( Q3ListBox::AlwaysOff );
+ d->listBox()->setFrameStyle( Q3Frame::Box | Q3Frame::Plain );
+ d->listBox()->setLineWidth( 1 );
+ d->listBox()->resize( 100, 10 );
+
+ connect( d->listBox(), SIGNAL(selected(int)),
+ SLOT(internalActivate(int)) );
+ connect( d->listBox(), SIGNAL(highlighted(int)),
+ SLOT(internalHighlight(int)));
+}
+
+
+void Q3ComboBox::setUpLineEdit()
+{
+ if ( !d->ed )
+ setLineEdit( new QLineEdit( this, "combo edit" ) );
+}
+
+/*!
+ Sets the line edit to use \a edit instead of the current line edit.
+*/
+
+void Q3ComboBox::setLineEdit( QLineEdit *edit )
+{
+ if ( !edit ) {
+#if defined(QT_CHECK_NULL)
+ Q_ASSERT( edit != 0 );
+#endif
+ return;
+ }
+
+ edit->setText( currentText() );
+ delete d->ed;
+ d->ed = edit;
+
+ if ( edit->parent() != this )
+ edit->reparent( this, QPoint(0,0), false );
+
+ connect (edit, SIGNAL(textChanged(QString)),
+ this, SIGNAL(textChanged(QString)) );
+ connect( edit, SIGNAL(returnPressed()), SLOT(returnPressed()) );
+
+ edit->setFrame( false );
+ d->updateLinedGeometry();
+ edit->installEventFilter( this );
+ setFocusProxy( edit );
+ setFocusPolicy(Qt::StrongFocus);
+ setInputMethodEnabled( true );
+
+ if ( !d->usingListBox() )
+ setUpListBox();
+
+ if ( isVisible() )
+ edit->show();
+
+ updateGeometry();
+ update();
+}
+
+/*!
+ Hides the combobox.
+
+ \sa QWidget::hide()
+*/
+void Q3ComboBox::hide()
+{
+ QWidget::hide();
+
+ if (listBox())
+ listBox()->hide();
+ else if (d->popup())
+ d->popup()->hide();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_COMBOBOX
diff --git a/src/qt3support/widgets/q3combobox.h b/src/qt3support/widgets/q3combobox.h
new file mode 100644
index 0000000..f9a0093
--- /dev/null
+++ b/src/qt3support/widgets/q3combobox.h
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3COMBOBOX_H
+#define Q3COMBOBOX_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_COMBOBOX
+
+class Q3StrList;
+class QStringList;
+class QLineEdit;
+class QValidator;
+class Q3ListBox;
+class Q3ComboBoxData;
+class QWheelEvent;
+
+class Q_COMPAT_EXPORT Q3ComboBox : public QWidget
+{
+ Q_OBJECT
+ Q_ENUMS( Policy )
+ Q_PROPERTY( bool editable READ editable WRITE setEditable )
+ Q_PROPERTY( int count READ count )
+ Q_PROPERTY( QString currentText READ currentText WRITE setCurrentText DESIGNABLE false )
+ Q_PROPERTY( int currentItem READ currentItem WRITE setCurrentItem )
+ Q_PROPERTY( bool autoResize READ autoResize WRITE setAutoResize DESIGNABLE false )
+ Q_PROPERTY( int sizeLimit READ sizeLimit WRITE setSizeLimit )
+ Q_PROPERTY( int maxCount READ maxCount WRITE setMaxCount )
+ Q_PROPERTY( Policy insertionPolicy READ insertionPolicy WRITE setInsertionPolicy )
+ Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
+ Q_PROPERTY( bool duplicatesEnabled READ duplicatesEnabled WRITE setDuplicatesEnabled )
+
+public:
+ Q3ComboBox( QWidget* parent=0, const char* name=0 );
+ Q3ComboBox( bool rw, QWidget* parent=0, const char* name=0 );
+ ~Q3ComboBox();
+
+ int count() const;
+
+ void insertStringList( const QStringList &, int index=-1 );
+ void insertStrList( const Q3StrList &, int index=-1 );
+ void insertStrList( const Q3StrList *, int index=-1 );
+ void insertStrList( const char **, int numStrings=-1, int index=-1);
+
+ void insertItem( const QString &text, int index=-1 );
+ void insertItem( const QPixmap &pixmap, int index=-1 );
+ void insertItem( const QPixmap &pixmap, const QString &text, int index=-1 );
+
+ void removeItem( int index );
+
+ int currentItem() const;
+ virtual void setCurrentItem( int index );
+
+ QString currentText() const;
+ virtual void setCurrentText( const QString& );
+
+ QString text( int index ) const;
+ const QPixmap *pixmap( int index ) const;
+
+ void changeItem( const QString &text, int index );
+ void changeItem( const QPixmap &pixmap, int index );
+ void changeItem( const QPixmap &pixmap, const QString &text, int index );
+
+ bool autoResize() const;
+ virtual void setAutoResize( bool );
+ QSize sizeHint() const;
+
+ void setPalette( const QPalette & );
+ void setFont( const QFont & );
+ void setEnabled( bool );
+
+ virtual void setSizeLimit( int );
+ int sizeLimit() const;
+
+ virtual void setMaxCount( int );
+ int maxCount() const;
+
+ enum Policy { NoInsertion,
+ AtTop,
+ AtCurrent,
+ AtBottom,
+ AfterCurrent,
+ BeforeCurrent,
+ NoInsert = NoInsertion,
+ InsertAtTop = AtTop,
+ InsertAtCurrent = AtCurrent,
+ InsertAtBottom = AtBottom,
+ InsertAfterCurrent = AfterCurrent,
+ InsertBeforeCurrent = BeforeCurrent
+ };
+
+ virtual void setInsertionPolicy( Policy policy );
+ Policy insertionPolicy() const;
+
+ virtual void setValidator( const QValidator * );
+ const QValidator * validator() const;
+
+ virtual void setListBox( Q3ListBox * );
+ Q3ListBox * listBox() const;
+
+ virtual void setLineEdit( QLineEdit *edit );
+ QLineEdit* lineEdit() const;
+
+ virtual void setAutoCompletion( bool );
+ bool autoCompletion() const;
+
+ bool eventFilter( QObject *object, QEvent *event );
+
+ void setDuplicatesEnabled( bool enable );
+ bool duplicatesEnabled() const;
+
+ bool editable() const;
+ void setEditable( bool );
+
+ virtual void popup();
+
+ void hide();
+
+public Q_SLOTS:
+ void clear();
+ void clearValidator();
+ void clearEdit();
+ virtual void setEditText( const QString &);
+
+Q_SIGNALS:
+ void activated( int index );
+ void highlighted( int index );
+ void activated( const QString &);
+ void highlighted( const QString &);
+ void textChanged( const QString &);
+
+private Q_SLOTS:
+ void internalActivate( int );
+ void internalHighlight( int );
+ void internalClickTimeout();
+ void returnPressed();
+
+protected:
+ void paintEvent( QPaintEvent * );
+ void resizeEvent( QResizeEvent * );
+ void mousePressEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void mouseDoubleClickEvent( QMouseEvent * );
+ void keyPressEvent( QKeyEvent *e );
+ void focusInEvent( QFocusEvent *e );
+ void focusOutEvent( QFocusEvent *e );
+#ifndef QT_NO_WHEELEVENT
+ void wheelEvent( QWheelEvent *e );
+#endif
+ void styleChange( QStyle& );
+
+ void updateMask();
+
+private:
+ void setUpListBox();
+ void setUpLineEdit();
+ void popDownListBox();
+ void reIndex();
+ void currentChanged();
+ int completionIndex( const QString &, int ) const;
+
+ Q3ComboBoxData *d;
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ Q3ComboBox( const Q3ComboBox & );
+ Q3ComboBox &operator=( const Q3ComboBox & );
+#endif
+};
+
+
+#endif // QT_NO_COMBOBOX
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3COMBOBOX_H
diff --git a/src/qt3support/widgets/q3datetimeedit.cpp b/src/qt3support/widgets/q3datetimeedit.cpp
new file mode 100644
index 0000000..3d02687
--- /dev/null
+++ b/src/qt3support/widgets/q3datetimeedit.cpp
@@ -0,0 +1,2826 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3datetimeedit.h"
+
+#ifndef QT_NO_DATETIMEEDIT
+
+#include <private/q3richtext_p.h>
+#include "qevent.h"
+#include "q3rangecontrol.h"
+#include "qapplication.h"
+#include "qpixmap.h"
+#include "qlist.h"
+#include "qstring.h"
+#include "qstyle.h"
+
+#if defined(Q_WS_WIN)
+#include "qt_windows.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define QDATETIMEEDIT_HIDDEN_CHAR QLatin1Char('0')
+
+class Q_COMPAT_EXPORT QNumberSection
+{
+public:
+ QNumberSection(int selStart = 0, int selEnd = 0, bool separat = true, int actual = -1)
+ : selstart(selStart), selend(selEnd), act(actual), sep(separat)
+ {}
+ int selectionStart() const { return selstart; }
+ void setSelectionStart(int s) { selstart = s; }
+ int selectionEnd() const { return selend; }
+ void setSelectionEnd(int s) { selend = s; }
+ int width() const { return selend - selstart; }
+ int index() const { return act; }
+ bool separator() const { return sep; }
+ Q_DUMMY_COMPARISON_OPERATOR(QNumberSection)
+private:
+ signed int selstart :12;
+ signed int selend :12;
+ signed int act :7;
+ bool sep :1;
+};
+
+static QString *lDateSep = 0;
+static QString *lTimeSep = 0;
+static bool lAMPM = false;
+static QString *lAM = 0;
+static QString *lPM = 0;
+static Q3DateEdit::Order lOrder = Q3DateEdit::YMD;
+static int refcount = 0;
+
+static void cleanup()
+{
+ delete lDateSep;
+ lDateSep = 0;
+ delete lTimeSep;
+ lTimeSep = 0;
+ delete lAM;
+ lAM = 0;
+ delete lPM;
+ lPM = 0;
+}
+
+/*!
+\internal
+try to get the order of DMY and the date/time separator from the locale settings
+*/
+static void readLocaleSettings()
+{
+ int dpos, mpos, ypos;
+ cleanup();
+
+ lDateSep = new QString();
+ lTimeSep = new QString();
+
+#if defined(Q_WS_WIN)
+ QT_WA({
+ TCHAR data[10];
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, data, 10);
+ *lDateSep = QString::fromUtf16((ushort*)data);
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, data, 10);
+ *lTimeSep = QString::fromUtf16((ushort*)data);
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, data, 10);
+ lAMPM = QString::fromUtf16((ushort*)data).toInt()==0;
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, data, 10);
+ QString am = QString::fromUtf16((ushort*)data);
+ if (!am.isEmpty())
+ lAM = new QString(am);
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, data, 10);
+ QString pm = QString::fromUtf16((ushort*)data);
+ if (!pm.isEmpty() )
+ lPM = new QString(pm);
+ } , {
+ char data[10];
+ GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, (char*)&data, 10);
+ *lDateSep = QString::fromLocal8Bit(data);
+ GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STIME, (char*)&data, 10);
+ *lTimeSep = QString::fromLocal8Bit(data);
+ GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ITIME, (char*)&data, 10);
+ lAMPM = QString::fromLocal8Bit(data).toInt()==0;
+ GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_S1159, (char*)&data, 10);
+ QString am = QString::fromLocal8Bit(data);
+ if (!am.isEmpty())
+ lAM = new QString(am);
+ GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_S2359, (char*)&data, 10);
+ QString pm = QString::fromLocal8Bit(data);
+ if (!pm.isEmpty())
+ lPM = new QString(pm);
+ });
+#else
+ *lDateSep = QLatin1Char('-');
+ *lTimeSep = QLatin1Char(':');
+#endif
+ QString d = QDate(1999, 11, 22).toString(Qt::LocalDate);
+ dpos = d.indexOf(QLatin1String("22"));
+ mpos = d.indexOf(QLatin1String("11"));
+ ypos = d.indexOf(QLatin1String("99"));
+ if (dpos > -1 && mpos > -1 && ypos > -1) {
+ // test for DMY, MDY, YMD, YDM
+ if (dpos < mpos && mpos < ypos) {
+ lOrder = Q3DateEdit::DMY;
+ } else if (mpos < dpos && dpos < ypos) {
+ lOrder = Q3DateEdit::MDY;
+ } else if (ypos < mpos && mpos < dpos) {
+ lOrder = Q3DateEdit::YMD;
+ } else if (ypos < dpos && dpos < mpos) {
+ lOrder = Q3DateEdit::YDM;
+ } else {
+ // cannot determine the dateformat - use the default
+ return;
+ }
+
+ // this code needs to change if new formats are added
+
+#ifndef Q_WS_WIN
+ QString sep = d.mid(qMin(dpos, mpos) + 2, QABS(dpos - mpos) - 2);
+ if (d.count(sep) == 2) {
+ *lDateSep = sep;
+ }
+#endif
+ }
+
+#ifndef Q_WS_WIN
+ QString t = QTime(11, 22, 33).toString(Qt::LocalDate);
+ dpos = t.indexOf(QLatin1String("11"));
+ mpos = t.indexOf(QLatin1String("22"));
+ ypos = t.indexOf(QLatin1String("33"));
+ // We only allow hhmmss
+ if (dpos > -1 && dpos < mpos && mpos < ypos) {
+ QString sep = t.mid(dpos + 2, mpos - dpos - 2);
+ if (sep == t.mid(mpos + 2, ypos - mpos - 2)) {
+ *lTimeSep = sep;
+ }
+ }
+#endif
+}
+
+static Q3DateEdit::Order localOrder() {
+ if (!lDateSep) {
+ readLocaleSettings();
+ }
+ return lOrder;
+}
+
+static QString localDateSep() {
+ if (!lDateSep) {
+ readLocaleSettings();
+ }
+ return *lDateSep;
+}
+
+static QString localTimeSep() {
+ if (!lTimeSep) {
+ readLocaleSettings();
+ }
+ return *lTimeSep;
+}
+
+class Q3DateTimeEditorPrivate
+{
+public:
+ Q3DateTimeEditorPrivate()
+ : frm(true),
+ parag(new Q3TextParagraph(0, 0, 0, false)),
+ focusSec(0)
+ {
+ parag->formatter()->setWrapEnabled(false);
+ cursor = new Q3TextCursor(0);
+ cursor->setParagraph(parag);
+ offset = 0;
+ sep = localDateSep();
+ refcount++;
+ }
+ ~Q3DateTimeEditorPrivate()
+ {
+ delete parag;
+ delete cursor;
+ if (!--refcount)
+ cleanup();
+ }
+
+ void appendSection(const QNumberSection& sec)
+ {
+ sections.append(sec);
+
+ }
+ void clearSections()
+ {
+ sections.clear();
+ }
+ void setSectionSelection(int sec, int selstart, int selend)
+ {
+ if (sec < 0 || sec >= sections.count())
+ return;
+ sections[sec].setSelectionStart(selstart);
+ sections[sec].setSelectionEnd(selend);
+ }
+ uint sectionCount() const { return (uint)sections.count(); }
+ void setSeparator(const QString& s) { sep = s; }
+ QString separator() const { return sep; }
+
+ void setFrame(bool f) { frm = f; }
+ bool frame() const { return frm; }
+
+ int focusSection() const { return focusSec; }
+ int section(const QPoint& p)
+ {
+ cursor->place(p + QPoint(offset, 0), parag);
+ int idx = cursor->index();
+ for (int i = 0; i < sections.count(); ++i) {
+ if (idx >= sections[i].selectionStart() &&
+ idx <= sections[i].selectionEnd())
+ return i;
+ }
+ return -1;
+ }
+ QNumberSection section(int idx) const
+ {
+ return sections[idx];
+ }
+ bool setFocusSection(int idx)
+ {
+ if (idx > (int)sections.count()-1 || idx < 0)
+ return false;
+ if (idx != focusSec) {
+ focusSec = idx;
+ applyFocusSelection();
+ return true;
+ }
+ return false;
+ }
+
+ bool inSectionSelection(int idx)
+ {
+ for (int i = 0; i < sections.count(); ++i) {
+ if (idx >= sections[i].selectionStart() &&
+ idx <= sections[i].selectionEnd())
+ return true;
+ }
+ return false;
+ }
+
+ void paint(const QString& txt, bool focus, QPainter& p,
+ const QPalette&pal, const QRect& rect, QStyle *style)
+ {
+ int fw = 0;
+ if (frm)
+ fw = style->pixelMetric(QStyle::PM_DefaultFrameWidth);
+
+ parag->truncate(0);
+ parag->append(txt);
+ if (!focus)
+ parag->removeSelection(Q3TextDocument::Standard);
+ else {
+ applyFocusSelection();
+ }
+
+ /* color all QDATETIMEEDIT_HIDDEN_CHAR chars to background color */
+ Q3TextFormat *fb = parag->formatCollection()->format(p.font(),
+ pal.base().color());
+ Q3TextFormat *nf = parag->formatCollection()->format(p.font(),
+ pal.text().color());
+ for (int i = 0; i < txt.length(); ++i) {
+ parag->setFormat(i, 1, nf);
+ if (inSectionSelection(i))
+ continue;
+ if (txt.at(i) == QDATETIMEEDIT_HIDDEN_CHAR)
+ parag->setFormat(i, 1, fb);
+ else
+ parag->setFormat(i, 1, nf);
+ }
+ fb->removeRef();
+ nf->removeRef();
+
+ QRect r(rect.x(), rect.y(), rect.width() - 2 * (2 + fw), rect.height());
+ parag->pseudoDocument()->docRect = r;
+ parag->invalidate(0);
+ parag->format();
+
+ int xoff = 2 + fw - offset;
+ int yoff = (rect.height() - parag->rect().height() + 1) / 2;
+ if (yoff < 0)
+ yoff = 0;
+
+ p.translate(xoff, yoff);
+ parag->paint(p, pal, 0, true);
+ if (frm)
+ p.translate(-xoff, -yoff);
+ }
+
+ void resize(const QSize& size) { sz = size; }
+
+ int mapSection(int sec)
+ {
+ return (sec >= 0 && sec < sections.count() ? sections[sec].index() : -1);
+ }
+
+protected:
+ void applyFocusSelection()
+ {
+ if (focusSec > -1 && focusSec < sections.count()) {
+ int selstart = sections[focusSec].selectionStart();
+ int selend = sections[focusSec].selectionEnd();
+ parag->setSelection(Q3TextDocument::Standard, selstart, selend);
+ parag->format();
+ if (parag->at(selstart)->x < offset ||
+ parag->at(selend)->x + parag->string()->width(selend) > offset + sz.width()) {
+ offset = parag->at(selstart)->x;
+ }
+ }
+ }
+private:
+ bool frm;
+ Q3TextParagraph *parag;
+ Q3TextCursor *cursor;
+ QSize sz;
+ int focusSec;
+ QList< QNumberSection > sections;
+ QString sep;
+ int offset;
+};
+
+class Q3DateTimeEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ Q3DateTimeEditor(Q3DateTimeEditBase *widget, QWidget *parent, const char* name=0);
+ ~Q3DateTimeEditor();
+
+ void setControlWidget(Q3DateTimeEditBase * widget);
+ Q3DateTimeEditBase * controlWidget() const;
+
+ void setSeparator(const QString& s);
+ QString separator() const;
+
+ int focusSection() const;
+ bool setFocusSection(int s);
+ void appendSection(const QNumberSection& sec);
+ void clearSections();
+ void setSectionSelection(int sec, int selstart, int selend);
+ bool eventFilter(QObject *o, QEvent *e);
+ int sectionAt(const QPoint &p);
+ int mapSection(int sec);
+
+protected:
+ void init();
+ bool event(QEvent *e);
+ void resizeEvent(QResizeEvent *);
+ void paintEvent(QPaintEvent *);
+ void mousePressEvent(QMouseEvent *e);
+
+private:
+ Q3DateTimeEditBase* cw;
+ Q3DateTimeEditorPrivate* d;
+};
+
+class QDateTimeSpinWidget : public Q3SpinWidget
+{
+ Q_OBJECT
+public:
+ QDateTimeSpinWidget(QWidget *parent, const char *name)
+ : Q3SpinWidget(parent, name)
+ {
+ }
+
+ void changeEvent(QEvent *e)
+ {
+ if (e->type() == QEvent::EnabledChange && isEnabled()) {
+ Q3DateEdit *de = qobject_cast<Q3DateEdit*>(parentWidget());
+ if (de) {
+ setUpEnabled(de->date() < de->maxValue());
+ setDownEnabled(de->date() > de->minValue());
+ } else {
+ setUpEnabled(true);
+ setDownEnabled(true);
+ }
+ }
+ }
+ void enabledChange(bool notenabled)
+ {
+ Q3DateEdit *de = qobject_cast<Q3DateEdit*>(parentWidget());
+ if (de && !notenabled) {
+ setUpEnabled(de->date() < de->maxValue());
+ setDownEnabled(de->date() > de->minValue());
+ } else {
+ setUpEnabled(!notenabled);
+ setDownEnabled(!notenabled);
+ }
+ }
+
+
+protected:
+#ifndef QT_NO_WHEELEVENT
+ void wheelEvent(QWheelEvent *e)
+ {
+ Q3DateTimeEditor *editor = qobject_cast<Q3DateTimeEditor*>(editWidget());
+ Q_ASSERT(editor);
+ if (!editor)
+ return;
+
+ int section = editor->sectionAt(e->pos());
+ editor->setFocusSection(section);
+
+ if (section == -1)
+ return;
+ Q3SpinWidget::wheelEvent(e);
+ }
+#endif
+};
+
+/*!
+ Constructs an empty datetime editor with parent \a parent and
+ called \a name.
+*/
+Q3DateTimeEditor::Q3DateTimeEditor(Q3DateTimeEditBase *widget, QWidget *parent, const char * name)
+ : QWidget(parent, name)
+{
+ d = new Q3DateTimeEditorPrivate();
+ cw = widget;
+ init();
+}
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3DateTimeEditor::~Q3DateTimeEditor()
+{
+ delete d;
+}
+
+/*! \internal
+
+*/
+
+void Q3DateTimeEditor::init()
+{
+ setBackgroundRole(QPalette::Base);
+ setFocusSection(-1);
+ installEventFilter(this);
+ setFocusPolicy(Qt::WheelFocus);
+}
+
+
+/*! \reimp
+
+*/
+
+bool Q3DateTimeEditor::event(QEvent *e)
+{
+ if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut) {
+ if (e->type() == QEvent::FocusOut)
+ qApp->sendEvent(cw, e);
+ update(rect());
+ } else if (e->type() == QEvent::ShortcutOverride) {
+ QKeyEvent* ke = (QKeyEvent*) e;
+ switch (ke->key()) {
+ case Qt::Key_Delete:
+ case Qt::Key_Backspace:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ return QWidget::event(e);
+}
+
+/*! \reimp
+
+*/
+
+void Q3DateTimeEditor::resizeEvent(QResizeEvent *e)
+{
+ d->resize(e->size());
+ QWidget::resizeEvent(e);
+}
+
+
+/*! \reimp
+
+*/
+
+void Q3DateTimeEditor::paintEvent(QPaintEvent *)
+{
+ QString txt;
+ for (uint i = 0; i < d->sectionCount(); ++i) {
+ txt += cw->sectionFormattedText(i);
+ if (i < d->sectionCount()-1) {
+ if (d->section(i+1).separator())
+ txt += d->separator();
+ else
+ txt += QLatin1Char(' ');
+ }
+ }
+
+ QPainter p(this);
+ const QBrush &bg = palette().brush(isEnabled() ? QPalette::Base : QPalette::Window);
+ p.fillRect(0, 0, width(), height(), bg);
+ d->paint(txt, hasFocus(), p, palette(), rect(), style());
+}
+
+
+/*!
+ Returns the section index at point \a p.
+*/
+int Q3DateTimeEditor::sectionAt(const QPoint &p)
+{
+ return d->section(p);
+}
+
+int Q3DateTimeEditor::mapSection(int sec)
+{
+ return d->mapSection(sec);
+}
+
+
+/*! \reimp
+
+*/
+
+void Q3DateTimeEditor::mousePressEvent(QMouseEvent *e)
+{
+ QPoint p(e->pos().x(), 0);
+ int sec = sectionAt(p);
+ if (sec != -1) {
+ cw->setFocusSection(sec);
+ repaint(rect());
+ }
+}
+
+/*! \reimp
+
+*/
+bool Q3DateTimeEditor::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == this) {
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ switch (ke->key()) {
+ case Qt::Key_Right:
+ if (d->focusSection() < (int)d->sectionCount()-1) {
+ if (cw->setFocusSection(focusSection()+1))
+ repaint(rect());
+ }
+ return true;
+ case Qt::Key_Left:
+ if (d->focusSection() > 0) {
+ if (cw->setFocusSection(focusSection()-1))
+ repaint(rect());
+ }
+ return true;
+ case Qt::Key_Up:
+ cw->stepUp();
+ return true;
+ case Qt::Key_Down:
+ cw->stepDown();
+ return true;
+ case Qt::Key_Backspace:
+ if (qobject_cast<Q3DateEdit*>(cw))
+ ((Q3DateEdit*)cw)->removeFirstNumber(d->focusSection());
+ else if (qobject_cast<Q3TimeEdit*>(cw))
+ ((Q3TimeEdit*)cw)->removeFirstNumber(d->focusSection());
+ return true;
+ case Qt::Key_Delete:
+ cw->removeLastNumber(d->focusSection());
+ return true;
+ case Qt::Key_Tab:
+ case Qt::Key_BackTab: {
+ if (ke->state() == Qt::ControlButton)
+ return false;
+ QWidget *w = this;
+ bool hadDateEdit = false;
+ while (w) {
+ if (qobject_cast<QDateTimeSpinWidget*>(w) || qobject_cast<Q3DateTimeEdit*>(w))
+ break;
+ hadDateEdit = hadDateEdit || qobject_cast<Q3DateEdit*>(w);
+ w = w->parentWidget();
+ }
+ if (w) {
+ if (!qobject_cast<Q3DateTimeEdit*>(w)) {
+ w = w->parentWidget();
+ } else {
+ Q3DateTimeEdit *ed = (Q3DateTimeEdit*)w;
+ if (hadDateEdit && ke->key() == Qt::Key_Tab) {
+ ed->timeEdit()->setFocus();
+ return true;
+ } else if (!hadDateEdit && ke->key() == Qt::Key_BackTab) {
+ ed->dateEdit()->setFocus();
+ return true;
+ } else {
+ while (w && !qobject_cast<Q3DateTimeEdit*>(w))
+ w = w->parentWidget();
+ }
+ }
+ qApp->sendEvent(w, e);
+ return true;
+ }
+ } break;
+ default:
+ QString txt = ke->text().toLower();
+ if (!txt.isEmpty() && !separator().isEmpty() && txt[0] == separator()[0]) {
+ // do the same thing as KEY_RIGHT when the user presses the separator key
+ if (d->focusSection() < 2) {
+ if (cw->setFocusSection(focusSection()+1))
+ repaint(rect());
+ }
+ return true;
+ } else if (!txt.isEmpty() && qobject_cast<Q3TimeEdit*>(cw) && focusSection() == (int) d->sectionCount()-1) {
+ // the first character of the AM/PM indicator toggles if the section has focus
+ Q3TimeEdit *te = (Q3TimeEdit*)cw;
+ QTime time = te->time();
+ if (lAMPM && lAM && lPM && (te->display()&Q3TimeEdit::AMPM)) {
+ if (txt[0] == (*lAM).toLower()[0] && time.hour() >= 12) {
+ time.setHMS(time.hour()-12, time.minute(), time.second(), time.msec());
+ te->setTime(time);
+ } else if (txt[0] == (*lPM).toLower()[0] && time.hour() < 12) {
+ time.setHMS(time.hour()+12, time.minute(), time.second(), time.msec());
+ te->setTime(time);
+ }
+ }
+ }
+
+ int num = txt[0].digitValue();
+ if (num != -1) {
+ cw->addNumber(d->focusSection(), num);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+/*!
+ Appends the number section \a sec to the editor.
+*/
+
+void Q3DateTimeEditor::appendSection(const QNumberSection& sec)
+{
+ d->appendSection(sec);
+}
+
+/*!
+ Removes all sections from the editor.
+*/
+
+void Q3DateTimeEditor::clearSections()
+{
+ d->clearSections();
+}
+
+/*!
+ Sets the selection of \a sec to start at \a selstart and end at \a
+ selend.
+*/
+
+void Q3DateTimeEditor::setSectionSelection(int sec, int selstart, int selend)
+{
+ d->setSectionSelection(sec, selstart, selend);
+}
+
+/*!
+ Sets the separator for all numbered sections to \a s. Note that
+ currently, only the first character of \a s is used.
+*/
+
+void Q3DateTimeEditor::setSeparator(const QString& s)
+{
+ d->setSeparator(s);
+ update();
+}
+
+
+/*!
+ Returns the editor's separator.
+*/
+
+QString Q3DateTimeEditor::separator() const
+{
+ return d->separator();
+}
+
+/*!
+ Returns the number of the section that has focus.
+*/
+
+int Q3DateTimeEditor::focusSection() const
+{
+ return d->focusSection();
+}
+
+
+/*!
+ Sets the focus to section \a sec. If \a sec does not exist,
+ nothing happens.
+*/
+
+bool Q3DateTimeEditor::setFocusSection(int sec)
+{
+ return d->setFocusSection(sec);
+}
+
+/*!
+ \class Q3DateTimeEditBase
+ \brief The Q3DateTimeEditBase class provides an abstraction for date and edit editors.
+
+ \compat
+
+ Small abstract class that provides some functions that are common
+ for both Q3DateEdit and Q3TimeEdit. It is used internally by
+ Q3DateTimeEditor.
+*/
+
+/*!
+ \fn Q3DateTimeEditBase::Q3DateTimeEditBase(QWidget *, const char*)
+ \internal
+*/
+
+/*!
+ \fn Q3DateTimeEditBase::setFocusSection(int)
+ \internal
+*/
+
+/*! \fn QString Q3DateTimeEditBase::sectionFormattedText(int sec)
+ \internal
+
+ Pure virtual function which returns the formatted text of section \a
+ sec.
+
+*/
+
+/*! \fn void Q3DateTimeEditBase::stepUp()
+ \internal
+
+ Pure virtual slot which is called whenever the user increases the
+ number in a section by pressing the widget's arrow buttons or the
+ keyboard's arrow keys.
+*/
+
+/*! \fn void Q3DateTimeEditBase::stepDown()
+ \internal
+
+ Pure virtual slot which is called whenever the user decreases the
+ number in a section by pressing the widget's arrow buttons or the
+ keyboard's arrow keys.
+
+*/
+
+/*! \fn void Q3DateTimeEditBase::addNumber(int sec, int num)
+ \internal
+
+ Pure virtual function which is called whenever the user types a number.
+ \a sec indicates the section where the number should be added. \a
+ num is the number that was pressed.
+*/
+
+/*! \fn void Q3DateTimeEditBase::removeLastNumber(int sec)
+ \internal
+
+ Pure virtual function which is called whenever the user tries to
+ remove the last number from \a sec by pressing the delete key.
+*/
+
+////////////////
+
+class Q3DateEditPrivate
+{
+public:
+ int y;
+ int m;
+ int d;
+ // remembers the last entry for the day.
+ // if the day is 31 and you cycle through the months,
+ // the day will be 31 again if you reach a month with 31 days
+ // otherwise it will be the highest day in the month
+ int dayCache;
+ int yearSection;
+ int monthSection;
+ int daySection;
+ Q3DateEdit::Order ord;
+ bool overwrite;
+ bool adv;
+ int timerId;
+ bool typing;
+ QDate min;
+ QDate max;
+ bool changed;
+ Q3DateTimeEditor *ed;
+ Q3SpinWidget *controls;
+};
+
+
+/*!
+ \class Q3DateEdit
+ \brief The Q3DateEdit class provides a date editor.
+
+ \compat
+
+ Q3DateEdit allows the user to edit dates by using the keyboard or
+ the arrow keys to increase/decrease date values. The arrow keys
+ can be used to move from section to section within the Q3DateEdit
+ box. Dates appear in accordance with the local date/time settings
+ or in year, month, day order if the system doesn't provide this
+ information. It is recommended that the Q3DateEdit be initialised
+ with a date, e.g.
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 0
+
+ Here we've created a new Q3DateEdit object initialised with today's
+ date and restricted the valid date range to today plus or minus
+ 365 days. We've set the order to month, day, year. If the auto
+ advance property is true (as we've set it here) when the user
+ completes a section of the date, e.g. enters two digits for the
+ month, they are automatically taken to the next section.
+
+ The maximum and minimum values for a date value in the date editor
+ default to the maximum and minimum values for a QDate. You can
+ change this by calling setMinValue(), setMaxValue() or setRange().
+
+ Terminology: A Q3DateEdit widget comprises three 'sections', one
+ each for the year, month and day. You can change the separator
+ character using Q3DateTimeEditor::setSeparator(), by default the
+ separator will be taken from the systems settings. If that is
+ not possible, it defaults to "-".
+
+ \img datetimewidgets.png Date Time Widgets
+
+ \sa QDate Q3TimeEdit Q3DateTimeEdit
+*/
+
+/*!
+ \enum Q3DateEdit::Order
+
+ This enum defines the order in which the sections that comprise a
+ date appear.
+
+ \value MDY month-day-year
+ \value DMY day-month-year
+ \value YMD year-month-day (the default)
+ \omitvalue YDM
+*/
+
+/*!
+ \enum Q3TimeEdit::Display
+
+ This enum defines the sections that comprise a time
+
+ \value Hours The hours section
+ \value Minutes The minutes section
+ \value Seconds The seconds section
+ \value AMPM The AM/PM section
+
+ The values can be or'ed together to show any combination.
+*/
+
+/*!
+ Constructs an empty date editor which is a child of \a parent and
+ called name \a name.
+*/
+
+Q3DateEdit::Q3DateEdit(QWidget * parent, const char * name)
+ : Q3DateTimeEditBase(parent, name)
+{
+ init();
+ updateButtons();
+}
+
+/*!
+ \overload
+
+ Constructs a date editor with the initial value \a date, parent \a
+ parent and called \a name.
+
+ The date editor is initialized with \a date.
+*/
+
+Q3DateEdit::Q3DateEdit(const QDate& date, QWidget * parent, const char * name)
+ : Q3DateTimeEditBase(parent, name)
+{
+ init();
+ setDate(date);
+}
+
+/*! \internal
+*/
+void Q3DateEdit::init()
+{
+ d = new Q3DateEditPrivate();
+ d->controls = new QDateTimeSpinWidget(this, 0);
+ d->ed = new Q3DateTimeEditor(this, d->controls);
+ d->controls->setEditWidget(d->ed);
+ setFocusProxy(d->ed);
+ connect(d->controls, SIGNAL(stepUpPressed()), SLOT(stepUp()));
+ connect(d->controls, SIGNAL(stepDownPressed()), SLOT(stepDown()));
+ connect(this, SIGNAL(valueChanged(QDate)), SLOT(updateButtons()));
+ d->ed->appendSection(QNumberSection(0,4));
+ d->ed->appendSection(QNumberSection(5,7));
+ d->ed->appendSection(QNumberSection(8,10));
+
+ d->yearSection = -1;
+ d->monthSection = -1;
+ d->daySection = -1;
+
+ d->y = 0;
+ d->m = 0;
+ d->d = 0;
+ d->dayCache = 0;
+ setOrder(localOrder());
+ setFocusSection(0);
+ d->overwrite = true;
+ d->adv = false;
+ d->timerId = 0;
+ d->typing = false;
+ d->min = QDate(1752, 9, 14);
+ d->max = QDate(8000, 12, 31);
+ d->changed = false;
+
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ refcount++;
+}
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3DateEdit::~Q3DateEdit()
+{
+ delete d;
+ if (!--refcount)
+ cleanup();
+}
+
+/*!
+ \property Q3DateEdit::minValue
+
+ \brief the editor's minimum value
+
+ Setting the minimum date value is equivalent to calling
+ Q3DateEdit::setRange(\e d, maxValue()), where \e d is the minimum
+ date. The default minimum date is 1752-09-14.
+
+ \sa maxValue setRange()
+*/
+
+QDate Q3DateEdit::minValue() const
+{
+ return d->min;
+}
+
+/*!
+ \property Q3DateEdit::maxValue
+
+ \brief the editor's maximum value
+
+ Setting the maximum date value for the editor is equivalent to
+ calling Q3DateEdit::setRange(minValue(), \e d), where \e d is the
+ maximum date. The default maximum date is 8000-12-31.
+
+ \sa minValue setRange()
+*/
+
+QDate Q3DateEdit::maxValue() const
+{
+ return d->max;
+}
+
+
+/*!
+ Sets the valid input range for the editor to be from \a min to \a
+ max inclusive. If \a min is invalid no minimum date will be set.
+ Similarly, if \a max is invalid no maximum date will be set.
+*/
+
+void Q3DateEdit::setRange(const QDate& min, const QDate& max)
+{
+ if (min.isValid())
+ d->min = min;
+ if (max.isValid())
+ d->max = max;
+}
+
+/*!
+ Sets the separator to \a s. Note that currently only the first
+ character of \a s is used.
+*/
+
+void Q3DateEdit::setSeparator(const QString& s)
+{
+ d->ed->setSeparator(s);
+}
+
+/*!
+ Returns the editor's separator.
+*/
+
+QString Q3DateEdit::separator() const
+{
+ return d->ed->separator();
+}
+
+
+/*!
+ Enables/disables the push buttons according to the min/max date
+ for this widget.
+*/
+
+void Q3DateEdit::updateButtons()
+{
+ if (!isEnabled())
+ return;
+
+ bool upEnabled = date() < maxValue();
+ bool downEnabled = date() > minValue();
+
+ d->controls->setUpEnabled(upEnabled);
+ d->controls->setDownEnabled(downEnabled);
+}
+
+/*! \reimp
+ */
+void Q3DateEdit::resizeEvent(QResizeEvent *)
+{
+ d->controls->resize(width(), height());
+}
+
+/*! \reimp
+
+*/
+QSize Q3DateEdit::sizeHint() const
+{
+ ensurePolished();
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this);
+ int h = qMax(fm.lineSpacing(), 14) + 2;
+ int w = 2 + fm.width(QLatin1Char('9')) * 8 + fm.width(d->ed->separator()) * 2 + d->controls->upRect().width() + fw * 4;
+
+ return QSize(w, qMax(h + fw * 2,20)).expandedTo(QApplication::globalStrut());
+}
+
+/*! \reimp
+
+*/
+QSize Q3DateEdit::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+
+/*!
+ Returns the formatted number for section \a sec. This will
+ correspond to either the year, month or day section, depending on
+ the current display order.
+
+ \sa setOrder()
+*/
+
+QString Q3DateEdit::sectionFormattedText(int sec)
+{
+ QString txt;
+ txt = sectionText(sec);
+ if (d->typing && sec == d->ed->focusSection())
+ d->ed->setSectionSelection(sec, sectionOffsetEnd(sec) - txt.length(),
+ sectionOffsetEnd(sec));
+ else
+ d->ed->setSectionSelection(sec, sectionOffsetEnd(sec) - sectionLength(sec),
+ sectionOffsetEnd(sec));
+ txt = txt.rightJustified(sectionLength(sec), QDATETIMEEDIT_HIDDEN_CHAR);
+ return txt;
+}
+
+
+/*!
+ Returns the desired length (number of digits) of section \a sec.
+ This will correspond to either the year, month or day section,
+ depending on the current display order.
+
+ \sa setOrder()
+*/
+
+int Q3DateEdit::sectionLength(int sec) const
+{
+ int val = 0;
+ if (sec == d->yearSection) {
+ val = 4;
+ } else if (sec == d->monthSection) {
+ val = 2;
+ } else if (sec == d->daySection) {
+ val = 2;
+ }
+ return val;
+}
+
+/*!
+ Returns the text of section \a sec. This will correspond to either
+ the year, month or day section, depending on the current display
+ order.
+
+ \sa setOrder()
+*/
+
+QString Q3DateEdit::sectionText(int sec) const
+{
+ int val = 0;
+ if (sec == d->yearSection) {
+ val = d->y;
+ } else if (sec == d->monthSection) {
+ val = d->m;
+ } else if (sec == d->daySection) {
+ val = d->d;
+ }
+ return QString::number(val);
+}
+
+/*! \internal
+
+ Returns the end of the section offset \a sec.
+
+*/
+
+int Q3DateEdit::sectionOffsetEnd(int sec) const
+{
+ if (sec == d->yearSection) {
+ switch(d->ord) {
+ case DMY:
+ case MDY:
+ return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec);
+ case YMD:
+ case YDM:
+ return sectionLength(sec);
+ }
+ } else if (sec == d->monthSection) {
+ switch(d->ord) {
+ case DMY:
+ case YDM:
+ case YMD:
+ return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec);
+ case MDY:
+ return sectionLength(sec);
+ }
+ } else if (sec == d->daySection) {
+ switch(d->ord) {
+ case DMY:
+ return sectionLength(sec);
+ case YMD:
+ case MDY:
+ case YDM:
+ return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec);
+ }
+ }
+ return 0;
+}
+
+
+/*!
+ \property Q3DateEdit::order
+ \brief the order in which the year, month and day appear
+
+ The default order is locale dependent.
+
+ \sa Order
+*/
+
+void Q3DateEdit::setOrder(Q3DateEdit::Order order)
+{
+ d->ord = order;
+ switch(d->ord) {
+ case DMY:
+ d->yearSection = 2;
+ d->monthSection = 1;
+ d->daySection = 0;
+ break;
+ case MDY:
+ d->yearSection = 2;
+ d->monthSection = 0;
+ d->daySection = 1;
+ break;
+ case YMD:
+ d->yearSection = 0;
+ d->monthSection = 1;
+ d->daySection = 2;
+ break;
+ case YDM:
+ d->yearSection = 0;
+ d->monthSection = 2;
+ d->daySection = 1;
+ break;
+ }
+ if (isVisible())
+ d->ed->repaint(d->ed->rect());
+}
+
+
+Q3DateEdit::Order Q3DateEdit::order() const
+{
+ return d->ord;
+}
+
+
+/*! \reimp
+
+*/
+void Q3DateEdit::stepUp()
+{
+ int sec = d->ed->focusSection();
+ bool accepted = false;
+ if (sec == d->yearSection) {
+ if (!outOfRange(d->y+1, d->m, d->d)) {
+ accepted = true;
+ setYear(d->y+1);
+ }
+ } else if (sec == d->monthSection) {
+ if (!outOfRange(d->y, d->m+1, d->d)) {
+ accepted = true;
+ setMonth(d->m+1);
+ }
+ } else if (sec == d->daySection) {
+ if (!outOfRange(d->y, d->m, d->d+1)) {
+ accepted = true;
+ setDay(d->d+1);
+ }
+ }
+ if (accepted) {
+ d->changed = false;
+ emit valueChanged(date());
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+
+
+/*! \reimp
+
+*/
+
+void Q3DateEdit::stepDown()
+{
+ int sec = d->ed->focusSection();
+ bool accepted = false;
+ if (sec == d->yearSection) {
+ if (!outOfRange(d->y-1, d->m, d->d)) {
+ accepted = true;
+ setYear(d->y-1);
+ }
+ } else if (sec == d->monthSection) {
+ if (!outOfRange(d->y, d->m-1, d->d)) {
+ accepted = true;
+ setMonth(d->m-1);
+ }
+ } else if (sec == d->daySection) {
+ if (!outOfRange(d->y, d->m, d->d-1)) {
+ accepted = true;
+ setDay(d->d-1);
+ }
+ }
+ if (accepted) {
+ d->changed = false;
+ emit valueChanged(date());
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+/*!
+ Sets the year to \a year, which must be a valid year. The range
+ currently supported is from 1752 to 8000.
+
+ \sa QDate
+*/
+
+void Q3DateEdit::setYear(int year)
+{
+ if (year < 1752)
+ year = 1752;
+ if (year > 8000)
+ year = 8000;
+ if (!outOfRange(year, d->m, d->d)) {
+ d->y = year;
+ setMonth(d->m);
+ int tmp = d->dayCache;
+ setDay(d->dayCache);
+ d->dayCache = tmp;
+ }
+}
+
+
+/*!
+ Sets the month to \a month, which must be a valid month, i.e.
+ between 1 and 12.
+*/
+
+void Q3DateEdit::setMonth(int month)
+{
+ if (month < 1)
+ month = 1;
+ if (month > 12)
+ month = 12;
+ if (!outOfRange(d->y, month, d->d)) {
+ d->m = month;
+ int tmp = d->dayCache;
+ setDay(d->dayCache);
+ d->dayCache = tmp;
+ }
+}
+
+
+/*!
+ Sets the day to \a day, which must be a valid day. The function
+ will ensure that the \a day set is valid for the month and year.
+*/
+
+void Q3DateEdit::setDay(int day)
+{
+ if (day < 1)
+ day = 1;
+ if (day > 31)
+ day = 31;
+ if (d->m > 0 && d->y > 1752) {
+ while (!QDate::isValid(d->y, d->m, day))
+ --day;
+ if (!outOfRange(d->y, d->m, day))
+ d->d = day;
+ } else if (d->m > 0) {
+ if (day > 0 && day < 32) {
+ if (!outOfRange(d->y, d->m, day))
+ d->d = day;
+ }
+ }
+ d->dayCache = d->d;
+}
+
+
+/*!
+ \property Q3DateEdit::date
+ \brief the editor's date value.
+
+ If the date property is not valid, the editor displays all zeroes
+ and Q3DateEdit::date() will return an invalid date. It is strongly
+ recommended that the editor is given a default date value (e.g.
+ currentDate()). That way, attempts to set the date property to an
+ invalid date will fail.
+
+ When changing the date property, if the date is less than
+ minValue(), or is greater than maxValue(), nothing happens.
+*/
+
+void Q3DateEdit::setDate(const QDate& date)
+{
+ if (!date.isValid()) {
+ d->y = 0;
+ d->m = 0;
+ d->d = 0;
+ d->dayCache = 0;
+ } else {
+ if (date > maxValue() || date < minValue())
+ return;
+ d->y = date.year();
+ d->m = date.month();
+ d->d = date.day();
+ d->dayCache = d->d;
+ emit valueChanged(date);
+ }
+ d->changed = false;
+ d->ed->repaint(d->ed->rect());
+}
+
+QDate Q3DateEdit::date() const
+{
+ if (QDate::isValid(d->y, d->m, d->d))
+ return QDate(d->y, d->m, d->d);
+ return QDate();
+}
+
+/*! \internal
+
+ Returns true if \a y, \a m, \a d is out of range, otherwise returns
+ false.
+
+ \sa setRange()
+
+*/
+
+bool Q3DateEdit::outOfRange(int y, int m, int d) const
+{
+ if (QDate::isValid(y, m, d)) {
+ QDate currentDate(y, m, d);
+ if (currentDate > maxValue() ||
+ currentDate < minValue()) {
+ //## outOfRange should set overwrite?
+ return true;
+ }
+ return false;
+ }
+ return false; /* assume ok */
+}
+
+/*! \reimp
+
+*/
+
+void Q3DateEdit::addNumber(int sec, int num)
+{
+ if (sec == -1)
+ return;
+ if (d->timerId)
+ killTimer(d->timerId);
+ d->timerId = 0;
+ bool overwrite = false;
+ bool accepted = false;
+ d->typing = true;
+ QString txt;
+ if (sec == d->yearSection) {
+ txt = QString::number(d->y);
+ if (d->overwrite || txt.length() == 4) {
+ accepted = true;
+ d->y = num;
+ } else {
+ txt += QString::number(num);
+ if (txt.length() == 4 ) {
+ const int val = qBound(1792, txt.toInt(), 8000);
+ if (outOfRange(val, d->m, d->d)) {
+ txt = QString::number(d->y);
+ } else {
+ accepted = true;
+ d->y = val;
+ }
+ } else {
+ accepted = true;
+ d->y = txt.toInt();
+ }
+ if (d->adv && txt.length() == 4) {
+ d->ed->setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ } else if (sec == d->monthSection) {
+ txt = QString::number(d->m);
+ if (d->overwrite || txt.length() == 2) {
+ accepted = true;
+ d->m = num;
+ } else {
+ txt += QString::number(num);
+ int temp = txt.toInt();
+ if (temp > 12)
+ temp = num;
+ if (outOfRange(d->y, temp, d->d))
+ txt = QString::number(d->m);
+ else {
+ accepted = true;
+ d->m = temp;
+ }
+ if (d->adv && txt.length() == 2) {
+ d->ed->setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ } else if (sec == d->daySection) {
+ txt = QString::number(d->d);
+ if (d->overwrite || txt.length() == 2) {
+ accepted = true;
+ d->d = num;
+ d->dayCache = d->d;
+ } else {
+ txt += QString::number(num);
+ int temp = txt.toInt();
+ if (temp > 31)
+ temp = num;
+ if (outOfRange(d->y, d->m, temp))
+ txt = QString::number(d->d);
+ else {
+ accepted = true;
+ d->d = temp;
+ d->dayCache = d->d;
+ }
+ if (d->adv && txt.length() == 2) {
+ d->ed->setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ }
+ if (accepted) {
+ d->changed = false;
+ emit valueChanged(date());
+ }
+ d->overwrite = overwrite;
+ d->timerId = startTimer(qApp->doubleClickInterval()*4);
+ d->ed->repaint(d->ed->rect());
+}
+
+
+/*! \reimp
+
+*/
+
+bool Q3DateEdit::setFocusSection(int s)
+{
+ if (s != d->ed->focusSection()) {
+ if (d->timerId)
+ killTimer(d->timerId);
+ d->timerId = 0;
+ d->overwrite = true;
+ d->typing = false;
+ fix(); // will emit valueChanged if necessary
+ }
+ return d->ed->setFocusSection(s);
+}
+
+
+/*!
+ Attempts to fix any invalid date entries.
+
+ The rules applied are as follows:
+
+ \list
+ \i If the year has four digits it is left unchanged.
+ \i If the year has two digits, the year will be changed to four
+ digits in the range current year - 70 to current year + 29.
+ \i If the year has three digits in the range 100..999, the
+ current millennium, i.e. 2000, will be added giving a year
+ in the range 2100..2999.
+ \i If the day or month is 0 then it will be set to 1 or the
+ minimum valid day/month in the range.
+ \endlist
+*/
+
+void Q3DateEdit::fix()
+{
+ bool changed = false;
+ int currentYear = QDate::currentDate().year();
+ int year = d->y;
+ if (year < 100) {
+ int currentCentury = currentYear / 100;
+ year += currentCentury * 100;
+ if (currentYear > year) {
+ if (currentYear > year + 70)
+ year += 100;
+ } else {
+ if (year >= currentYear + 30)
+ year -= 100;
+ }
+ changed = true;
+ } else if (year < 1000) {
+ int currentMillennium = currentYear / 10;
+ year += currentMillennium * 10;
+ changed = true;
+ } else if (d->d == 0) {
+ d->d = 1;
+ changed = true;
+ } else if (d->m == 0) {
+ d->m = 1;
+ changed = true;
+ }
+ if (outOfRange(year, d->m, d->d)) {
+ if (minValue().isValid() && date() < minValue()) {
+ d->d = minValue().day();
+ d->dayCache = d->d;
+ d->m = minValue().month();
+ d->y = minValue().year();
+ }
+ if (date() > maxValue()) {
+ d->d = maxValue().day();
+ d->dayCache = d->d;
+ d->m = maxValue().month();
+ d->y = maxValue().year();
+ }
+ changed = true;
+ } else if (changed)
+ setYear(year);
+ if (changed) {
+ emit valueChanged(date());
+ d->changed = false;
+ }
+}
+
+
+/*! \reimp
+
+*/
+
+bool Q3DateEdit::event(QEvent *e)
+{
+ if(e->type() == QEvent::FocusOut) {
+ d->typing = false;
+ fix();
+ // the following can't be done in fix() because fix() called
+ // from all over the place and it will break the old behaviour
+ if (!QDate::isValid(d->y, d->m, d->d)) {
+ d->dayCache = d->d;
+ int i = d->d;
+ for (; i > 0; i--) {
+ d->d = i;
+ if (QDate::isValid(d->y, d->m, d->d))
+ break;
+ }
+ d->changed = true;
+ }
+ if (d->changed) {
+ emit valueChanged(date());
+ d->changed = false;
+ }
+ } else if (e->type() == QEvent::LocaleChange) {
+ readLocaleSettings();
+ d->ed->setSeparator(localDateSep());
+ setOrder(localOrder());
+ }
+ return Q3DateTimeEditBase::event(e);
+}
+
+/*!
+ \internal
+
+ Function which is called whenever the user tries to
+ remove the first number from \a sec by pressing the backspace key.
+*/
+
+void Q3DateEdit::removeFirstNumber(int sec)
+{
+ if (sec == -1)
+ return;
+ QString txt;
+ if (sec == d->yearSection) {
+ txt = QString::number(d->y);
+ txt = txt.mid(1, txt.length()) + QLatin1Char('0');
+ d->y = txt.toInt();
+ } else if (sec == d->monthSection) {
+ txt = QString::number(d->m);
+ txt = txt.mid(1, txt.length()) + QLatin1Char('0');
+ d->m = txt.toInt();
+ } else if (sec == d->daySection) {
+ txt = QString::number(d->d);
+ txt = txt.mid(1, txt.length()) + QLatin1Char('0');
+ d->d = txt.toInt();
+ d->dayCache = d->d;
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+/*! \reimp
+
+*/
+
+void Q3DateEdit::removeLastNumber(int sec)
+{
+ if (sec == -1)
+ return;
+ QString txt;
+ if (sec == d->yearSection) {
+ txt = QString::number(d->y);
+ txt = txt.mid(0, txt.length()-1);
+ d->y = txt.toInt();
+ } else if (sec == d->monthSection) {
+ txt = QString::number(d->m);
+ txt = txt.mid(0, txt.length()-1);
+ d->m = txt.toInt();
+ } else if (sec == d->daySection) {
+ txt = QString::number(d->d);
+ txt = txt.mid(0, txt.length()-1);
+ d->d = txt.toInt();
+ d->dayCache = d->d;
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+/*!
+ \property Q3DateEdit::autoAdvance
+ \brief whether the editor automatically advances to the next
+ section
+
+ If autoAdvance is true, the editor will automatically advance
+ focus to the next date section if a user has completed a section.
+ The default is false.
+*/
+
+void Q3DateEdit::setAutoAdvance(bool advance)
+{
+ d->adv = advance;
+}
+
+
+bool Q3DateEdit::autoAdvance() const
+{
+ return d->adv;
+}
+
+/*! \reimp
+*/
+
+void Q3DateEdit::timerEvent(QTimerEvent *)
+{
+ d->overwrite = true;
+}
+
+/*!
+ \fn void Q3DateEdit::valueChanged(const QDate& date)
+
+ This signal is emitted whenever the editor's value changes. The \a
+ date parameter is the new value.
+*/
+
+///////////
+
+class Q3TimeEditPrivate
+{
+public:
+ int h;
+ int m;
+ int s;
+ uint display;
+ bool adv;
+ bool overwrite;
+ int timerId;
+ bool typing;
+ QTime min;
+ QTime max;
+ bool changed;
+ Q3DateTimeEditor *ed;
+ Q3SpinWidget *controls;
+};
+
+/*!
+ \class Q3TimeEdit
+ \brief The Q3TimeEdit class provides a time editor.
+
+ \compat
+
+ Q3TimeEdit allows the user to edit times by using the keyboard or
+ the arrow keys to increase/decrease time values. The arrow keys
+ can be used to move from section to section within the Q3TimeEdit
+ box. The user can automatically be moved to the next section once
+ they complete a section using setAutoAdvance(). Times appear in
+ hour, minute, second order. It is recommended that the Q3TimeEdit
+ is initialised with a time, e.g.
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 1
+ Here we've created a Q3TimeEdit widget set to the current time.
+ We've also set the minimum value to the current time and the
+ maximum time to one hour from now.
+
+ The maximum and minimum values for a time value in the time editor
+ default to the maximum and minimum values for a QTime. You can
+ change this by calling setMinValue(), setMaxValue() or setRange().
+
+ Terminology: A QTimeWidget consists of three sections, one each
+ for the hour, minute and second. You can change the separator
+ character using setSeparator(), by default the separator is read
+ from the system's settings.
+
+ \img datetimewidgets.png Date Time Widgets
+
+ \sa QTime Q3DateEdit Q3DateTimeEdit
+*/
+
+
+/*!
+ Constructs an empty time edit with parent \a parent and called \a
+ name.
+*/
+
+Q3TimeEdit::Q3TimeEdit(QWidget * parent, const char * name)
+ : Q3DateTimeEditBase(parent, name)
+{
+ init();
+}
+
+/*!
+ \overload
+
+ Constructs a time edit with the initial time value, \a time,
+ parent \a parent and called \a name.
+*/
+
+Q3TimeEdit::Q3TimeEdit(const QTime& time, QWidget * parent, const char * name)
+ : Q3DateTimeEditBase(parent, name)
+{
+ init();
+ setTime(time);
+}
+
+/*! \internal
+ */
+
+void Q3TimeEdit::init()
+{
+ d = new Q3TimeEditPrivate();
+ d->controls = new QDateTimeSpinWidget(this, 0);
+ d->ed = new Q3DateTimeEditor(this, d->controls, "time edit base");
+ d->controls->setEditWidget(d->ed);
+ setFocusProxy(d->ed);
+ connect(d->controls, SIGNAL(stepUpPressed()), SLOT(stepUp()));
+ connect(d->controls, SIGNAL(stepDownPressed()), SLOT(stepDown()));
+
+ d->ed->appendSection(QNumberSection(0,0, true, 0));
+ d->ed->appendSection(QNumberSection(0,0, true, 1));
+ d->ed->appendSection(QNumberSection(0,0, true, 2));
+ d->ed->setSeparator(localTimeSep());
+
+ d->h = 0;
+ d->m = 0;
+ d->s = 0;
+ d->display = Hours | Minutes | Seconds;
+ if (lAMPM) {
+ d->display |= AMPM;
+ d->ed->appendSection(QNumberSection(0,0, false, 3));
+ }
+ d->adv = false;
+ d->overwrite = true;
+ d->timerId = 0;
+ d->typing = false;
+ d->min = QTime(0, 0, 0);
+ d->max = QTime(23, 59, 59);
+ d->changed = false;
+
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ refcount++;
+}
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3TimeEdit::~Q3TimeEdit()
+{
+ delete d;
+ if (!--refcount)
+ cleanup();
+}
+
+/*!
+ \property Q3TimeEdit::minValue
+ \brief the minimum time value
+
+ Setting the minimum time value is equivalent to calling
+ Q3TimeEdit::setRange(\e t, maxValue()), where \e t is the minimum
+ time. The default minimum time is 00:00:00.
+
+ \sa maxValue setRange()
+*/
+
+QTime Q3TimeEdit::minValue() const
+{
+ return d->min;
+}
+
+/*!
+ \property Q3TimeEdit::maxValue
+ \brief the maximum time value
+
+ Setting the maximum time value is equivalent to calling
+ Q3TimeEdit::setRange(minValue(), \e t), where \e t is the maximum
+ time. The default maximum time is 23:59:59.
+
+ \sa minValue setRange()
+*/
+
+QTime Q3TimeEdit::maxValue() const
+{
+ return d->max;
+}
+
+
+/*!
+ Sets the valid input range for the editor to be from \a min to \a
+ max inclusive. If \a min is invalid no minimum time is set.
+ Similarly, if \a max is invalid no maximum time is set.
+*/
+
+void Q3TimeEdit::setRange(const QTime& min, const QTime& max)
+{
+ if (min.isValid())
+ d->min = min;
+ if (max.isValid())
+ d->max = max;
+}
+
+/*!
+ \property Q3TimeEdit::display
+ \brief the sections that are displayed in the time edit
+
+ The value can be any combination of the values in the Display enum.
+ By default, the widget displays hours, minutes and seconds.
+*/
+void Q3TimeEdit::setDisplay(uint display)
+{
+ if (d->display == display)
+ return;
+
+ d->ed->clearSections();
+ d->display = display;
+ if (d->display & Hours)
+ d->ed->appendSection(QNumberSection(0,0, true, 0));
+ if (d->display & Minutes)
+ d->ed->appendSection(QNumberSection(0,0, true, 1));
+ if (d->display & Seconds)
+ d->ed->appendSection(QNumberSection(0,0, true, 2));
+ if (d->display & AMPM)
+ d->ed->appendSection(QNumberSection(0,0, false, 3));
+
+ d->ed->setFocusSection(0);
+ d->ed->update();
+}
+
+uint Q3TimeEdit::display() const
+{
+ return d->display;
+}
+
+/*!
+ \property Q3TimeEdit::time
+ \brief the editor's time value.
+
+ When changing the time property, if the time is less than
+ minValue(), or is greater than maxValue(), nothing happens.
+*/
+
+void Q3TimeEdit::setTime(const QTime& time)
+{
+ if (!time.isValid()) {
+ d->h = 0;
+ d->m = 0;
+ d->s = 0;
+ } else {
+ if (time > maxValue() || time < minValue())
+ return;
+ d->h = time.hour();
+ d->m = time.minute();
+ d->s = time.second();
+ emit valueChanged(time);
+ }
+ d->changed = false;
+ d->ed->repaint(d->ed->rect());
+}
+
+QTime Q3TimeEdit::time() const
+{
+ if (QTime::isValid(d->h, d->m, d->s))
+ return QTime(d->h, d->m, d->s);
+ return QTime();
+}
+
+/*!
+ \property Q3TimeEdit::autoAdvance
+ \brief whether the editor automatically advances to the next
+ section
+
+ If autoAdvance is true, the editor will automatically advance
+ focus to the next time section if a user has completed a section.
+ The default is false.
+*/
+
+void Q3TimeEdit::setAutoAdvance(bool advance)
+{
+ d->adv = advance;
+}
+
+bool Q3TimeEdit::autoAdvance() const
+{
+ return d->adv;
+}
+
+/*!
+ Sets the separator to \a s. Note that currently only the first
+ character of \a s is used.
+*/
+
+void Q3TimeEdit::setSeparator(const QString& s)
+{
+ d->ed->setSeparator(s);
+}
+
+/*!
+ Returns the editor's separator.
+*/
+
+QString Q3TimeEdit::separator() const
+{
+ return d->ed->separator();
+}
+
+
+/*!
+ \fn void Q3TimeEdit::valueChanged(const QTime& time)
+
+ This signal is emitted whenever the editor's value changes. The \a
+ time parameter is the new value.
+*/
+
+/*! \reimp
+
+*/
+
+bool Q3TimeEdit::event(QEvent *e)
+{
+ if (e->type() == QEvent::FocusOut) {
+ d->typing = false;
+ if (d->changed) {
+ emit valueChanged(time());
+ d->changed = false;
+ }
+ } else if (e->type() == QEvent::LocaleChange) {
+ readLocaleSettings();
+ d->ed->setSeparator(localTimeSep());
+ }
+ return Q3DateTimeEditBase::event(e);
+}
+
+/*! \reimp
+
+*/
+
+void Q3TimeEdit::timerEvent(QTimerEvent *)
+{
+ d->overwrite = true;
+}
+
+
+/*! \reimp
+
+*/
+
+void Q3TimeEdit::stepUp()
+{
+ int sec = d->ed->mapSection(d->ed->focusSection());
+ bool accepted = true;
+ switch(sec) {
+ case 0:
+ if (!outOfRange(d->h+1, d->m, d->s))
+ setHour(d->h+1);
+ else
+ setHour(d->min.hour());
+ break;
+ case 1:
+ if (!outOfRange(d->h, d->m+1, d->s))
+ setMinute(d->m+1);
+ else
+ setMinute(d->min.minute());
+ break;
+ case 2:
+ if (!outOfRange(d->h, d->m, d->s+1))
+ setSecond(d->s+1);
+ else
+ setSecond(d->min.second());
+ break;
+ case 3:
+ if (d->h < 12)
+ setHour(d->h+12);
+ else
+ setHour(d->h-12);
+ break;
+ default:
+ accepted = false;
+ qWarning("Q3TimeEdit::stepUp: Focus section out of range!");
+ break;
+ }
+ if (accepted) {
+ d->changed = false;
+ emit valueChanged(time());
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+
+/*! \reimp
+
+*/
+
+void Q3TimeEdit::stepDown()
+{
+ int sec = d->ed->mapSection(d->ed->focusSection());
+
+ bool accepted = true;
+ switch(sec) {
+ case 0:
+ if (!outOfRange(d->h-1, d->m, d->s))
+ setHour(d->h-1);
+ else
+ setHour(d->max.hour());
+ break;
+ case 1:
+ if (!outOfRange(d->h, d->m-1, d->s))
+ setMinute(d->m-1);
+ else
+ setMinute(d->max.minute());
+ break;
+ case 2:
+ if (!outOfRange(d->h, d->m, d->s-1))
+ setSecond(d->s-1);
+ else
+ setSecond(d->max.second());
+ break;
+ case 3:
+ if (d->h > 11)
+ setHour(d->h-12);
+ else
+ setHour(d->h+12);
+ break;
+ default:
+ accepted = false;
+ qWarning("Q3TimeEdit::stepDown: Focus section out of range!");
+ break;
+ }
+ if (accepted) {
+ d->changed = false;
+ emit valueChanged(time());
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+
+/*!
+ Returns the formatted number for section \a sec. This will
+ correspond to either the hour, minute or second section, depending
+ on \a sec.
+*/
+
+QString Q3TimeEdit::sectionFormattedText(int sec)
+{
+ QString txt;
+ txt = sectionText(sec);
+ txt = txt.rightJustified(2, QDATETIMEEDIT_HIDDEN_CHAR);
+ int offset = sec*2+sec*separator().length() + txt.length();
+ if (d->typing && sec == d->ed->focusSection())
+ d->ed->setSectionSelection(sec, offset - txt.length(), offset);
+ else
+ d->ed->setSectionSelection(sec, offset - txt.length(), offset);
+
+ return txt;
+}
+
+
+/*! \reimp
+
+*/
+
+bool Q3TimeEdit::setFocusSection(int sec)
+{
+ if (sec != d->ed->focusSection()) {
+ if (d->timerId)
+ killTimer(d->timerId);
+ d->timerId = 0;
+ d->overwrite = true;
+ d->typing = false;
+ QString txt = sectionText(sec);
+ txt = txt.rightJustified(2, QDATETIMEEDIT_HIDDEN_CHAR);
+ int offset = sec*2+sec*separator().length() + txt.length();
+ d->ed->setSectionSelection(sec, offset - txt.length(), offset);
+ if (d->changed) {
+ emit valueChanged(time());
+ d->changed = false;
+ }
+ }
+ return d->ed->setFocusSection(sec);
+}
+
+
+/*!
+ Sets the hour to \a h, which must be a valid hour, i.e. in the
+ range 0..24.
+*/
+
+void Q3TimeEdit::setHour(int h)
+{
+ if (h < 0)
+ h = 0;
+ if (h > 23)
+ h = 23;
+ d->h = h;
+}
+
+
+/*!
+ Sets the minute to \a m, which must be a valid minute, i.e. in the
+ range 0..59.
+*/
+
+void Q3TimeEdit::setMinute(int m)
+{
+ if (m < 0)
+ m = 0;
+ if (m > 59)
+ m = 59;
+ d->m = m;
+}
+
+
+/*!
+ Sets the second to \a s, which must be a valid second, i.e. in the
+ range 0..59.
+*/
+
+void Q3TimeEdit::setSecond(int s)
+{
+ if (s < 0)
+ s = 0;
+ if (s > 59)
+ s = 59;
+ d->s = s;
+}
+
+
+/*! \internal
+
+ Returns the text of section \a sec.
+
+*/
+
+QString Q3TimeEdit::sectionText(int sec)
+{
+ sec = d->ed->mapSection(sec);
+
+ QString txt;
+ switch(sec) {
+ case 0:
+ if (!(d->display & AMPM) || (d->h < 13 && d->h)) { // I wished the day stared at 0:00 for everybody
+ txt = QString::number(d->h);
+ } else {
+ if (d->h)
+ txt = QString::number(d->h - 12);
+ else
+ txt = QLatin1String("12");
+ }
+ break;
+ case 1:
+ txt = QString::number(d->m);
+ break;
+ case 2:
+ txt = QString::number(d->s);
+ break;
+ case 3:
+ if (d->h < 12) {
+ if (lAM)
+ txt = *lAM;
+ else
+ txt = QString::fromLatin1("AM");
+ } else {
+ if (lPM)
+ txt = *lPM;
+ else
+ txt = QString::fromLatin1("PM");
+ }
+ break;
+ default:
+ break;
+ }
+ return txt;
+}
+
+
+/*! \internal
+ Returns true if \a h, \a m, and \a s are out of range.
+ */
+
+bool Q3TimeEdit::outOfRange(int h, int m, int s) const
+{
+ if (QTime::isValid(h, m, s)) {
+ QTime currentTime(h, m, s);
+ if (currentTime > maxValue() ||
+ currentTime < minValue())
+ return true;
+ else
+ return false;
+ }
+ return true;
+}
+
+/*! \reimp
+
+*/
+
+void Q3TimeEdit::addNumber(int sec, int num)
+{
+ if (sec == -1)
+ return;
+ sec = d->ed->mapSection(sec);
+ if (d->timerId)
+ killTimer(d->timerId);
+ d->timerId = 0;
+ bool overwrite = false;
+ bool accepted = false;
+ d->typing = true;
+ QString txt;
+
+ switch(sec) {
+ case 0:
+ txt = (d->display & AMPM && d->h > 12) ?
+ QString::number(d->h - 12) : QString::number(d->h);
+
+ if (d->overwrite || txt.length() == 2) {
+ if (d->display & AMPM && num == 0)
+ break; // Don't process 0 in 12 hour clock mode
+ if (d->display & AMPM && d->h > 11)
+ num += 12;
+ if (!outOfRange(num, d->m, d->s)) {
+ accepted = true;
+ d->h = num;
+ }
+ } else {
+ txt += QString::number(num);
+ int temp = txt.toInt();
+
+ if (d->display & AMPM) {
+ if (temp == 12) {
+ if (d->h < 12) {
+ temp = 0;
+ }
+ accepted = true;
+ } else if (outOfRange(temp + 12, d->m, d->s)) {
+ txt = QString::number(d->h);
+ } else {
+ if (d->h > 11) {
+ temp += 12;
+ }
+ accepted = true;
+ }
+ } else if (!(d->display & AMPM) && outOfRange(temp, d->m, d->s)) {
+ txt = QString::number(d->h);
+ } else {
+ accepted = true;
+ }
+
+ if (accepted)
+ d->h = temp;
+
+ if (d->adv && txt.length() == 2) {
+ setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ break;
+
+ case 1:
+ txt = QString::number(d->m);
+ if (d->overwrite || txt.length() == 2) {
+ if (!outOfRange(d->h, num, d->s)) {
+ accepted = true;
+ d->m = num;
+ }
+ } else {
+ txt += QString::number(num);
+ int temp = txt.toInt();
+ if (temp > 59)
+ temp = num;
+ if (outOfRange(d->h, temp, d->s))
+ txt = QString::number(d->m);
+ else {
+ accepted = true;
+ d->m = temp;
+ }
+ if (d->adv && txt.length() == 2) {
+ setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ break;
+
+ case 2:
+ txt = QString::number(d->s);
+ if (d->overwrite || txt.length() == 2) {
+ if (!outOfRange(d->h, d->m, num)) {
+ accepted = true;
+ d->s = num;
+ }
+ } else {
+ txt += QString::number(num);
+ int temp = txt.toInt();
+ if (temp > 59)
+ temp = num;
+ if (outOfRange(d->h, d->m, temp))
+ txt = QString::number(d->s);
+ else {
+ accepted = true;
+ d->s = temp;
+ }
+ if (d->adv && txt.length() == 2) {
+ setFocusSection(d->ed->focusSection()+1);
+ overwrite = true;
+ }
+ }
+ break;
+
+ case 3:
+ break;
+
+ default:
+ break;
+ }
+ d->changed = !accepted;
+ if (accepted)
+ emit valueChanged(time());
+ d->overwrite = overwrite;
+ d->timerId = startTimer(qApp->doubleClickInterval()*4);
+ d->ed->repaint(d->ed->rect());
+}
+
+
+/*!
+ \internal
+
+ Function which is called whenever the user tries to
+ remove the first number from \a sec by pressing the backspace key.
+*/
+
+void Q3TimeEdit::removeFirstNumber(int sec)
+{
+ if (sec == -1)
+ return;
+ sec = d->ed->mapSection(sec);
+ QString txt;
+ switch(sec) {
+ case 0:
+ txt = QString::number(d->h);
+ break;
+ case 1:
+ txt = QString::number(d->m);
+ break;
+ case 2:
+ txt = QString::number(d->s);
+ break;
+ }
+ txt = txt.mid(1, txt.length()) + QLatin1Char('0');
+ switch(sec) {
+ case 0:
+ d->h = txt.toInt();
+ break;
+ case 1:
+ d->m = txt.toInt();
+ break;
+ case 2:
+ d->s = txt.toInt();
+ break;
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+/*! \reimp
+
+*/
+void Q3TimeEdit::removeLastNumber(int sec)
+{
+ if (sec == -1)
+ return;
+ sec = d->ed->mapSection(sec);
+ QString txt;
+ switch(sec) {
+ case 0:
+ txt = QString::number(d->h);
+ break;
+ case 1:
+ txt = QString::number(d->m);
+ break;
+ case 2:
+ txt = QString::number(d->s);
+ break;
+ }
+ txt = txt.mid(0, txt.length()-1);
+ switch(sec) {
+ case 0:
+ d->h = txt.toInt();
+ break;
+ case 1:
+ d->m = txt.toInt();
+ break;
+ case 2:
+ d->s = txt.toInt();
+ break;
+ }
+ d->ed->repaint(d->ed->rect());
+}
+
+/*! \reimp
+ */
+void Q3TimeEdit::resizeEvent(QResizeEvent *)
+{
+ d->controls->resize(width(), height());
+}
+
+/*! \reimp
+*/
+QSize Q3TimeEdit::sizeHint() const
+{
+ ensurePolished();
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this);
+ int h = fm.lineSpacing() + 2;
+ int w = 2 + fm.width(QLatin1Char('9')) * 6 + fm.width(d->ed->separator()) * 2 +
+ d->controls->upRect().width() + fw * 4;
+ if (d->display & AMPM) {
+ if (lAM)
+ w += fm.width(*lAM) + 4;
+ else
+ w += fm.width(QString::fromLatin1("AM")) + 4;
+ }
+
+ return QSize(w, qMax(h + fw * 2,20)).expandedTo(QApplication::globalStrut());
+}
+
+/*! \reimp
+*/
+QSize Q3TimeEdit::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+/*!
+ \internal
+ Enables/disables the push buttons according to the min/max time
+ for this widget.
+*/
+
+void Q3TimeEdit::updateButtons()
+{
+ if (!isEnabled())
+ return;
+
+ bool upEnabled = time() < maxValue();
+ bool downEnabled = time() > minValue();
+
+ d->controls->setUpEnabled(upEnabled);
+ d->controls->setDownEnabled(downEnabled);
+}
+
+
+class Q3DateTimeEditPrivate
+{
+public:
+ bool adv;
+};
+
+/*!
+ \class Q3DateTimeEdit
+ \brief The Q3DateTimeEdit class combines a Q3DateEdit and Q3TimeEdit
+ widget into a single widget for editing datetimes.
+
+ \compat
+
+ Q3DateTimeEdit consists of a Q3DateEdit and Q3TimeEdit widget placed
+ side by side and offers the functionality of both. The user can
+ edit the date and time by using the keyboard or the arrow keys to
+ increase/decrease date or time values. The Tab key can be used to
+ move from section to section within the Q3DateTimeEdit widget, and
+ the user can be moved automatically when they complete a section
+ using setAutoAdvance(). The datetime can be set with
+ setDateTime().
+
+ The date format is read from the system's locale settings. It is
+ set to year, month, day order if that is not possible. See
+ Q3DateEdit::setOrder() to change this. Times appear in the order
+ hours, minutes, seconds using the 24 hour clock.
+
+ It is recommended that the Q3DateTimeEdit is initialised with a
+ datetime, e.g.
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 2
+ Here we've created a new Q3DateTimeEdit set to the current date and
+ time, and set the date to have a minimum date of now and a maximum
+ date of a week from now.
+
+ Terminology: A Q3DateEdit widget consists of three 'sections', one
+ each for the year, month and day. Similarly a Q3TimeEdit consists
+ of three sections, one each for the hour, minute and second. The
+ character that separates each date section is specified with
+ setDateSeparator(); similarly setTimeSeparator() is used for the
+ time sections.
+
+ \img datetimewidgets.png Date Time Widgets
+
+ \sa Q3DateEdit Q3TimeEdit
+*/
+
+/*!
+ Constructs an empty datetime edit with parent \a parent and called
+ \a name.
+*/
+Q3DateTimeEdit::Q3DateTimeEdit(QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+}
+
+
+/*!
+ \overload
+
+ Constructs a datetime edit with the initial value \a datetime,
+ parent \a parent and called \a name.
+*/
+Q3DateTimeEdit::Q3DateTimeEdit(const QDateTime& datetime,
+ QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+ setDateTime(datetime);
+}
+
+
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3DateTimeEdit::~Q3DateTimeEdit()
+{
+ delete d;
+}
+
+
+/*!
+ \reimp
+
+ Intercepts and handles resize events which have special meaning
+ for the Q3DateTimeEdit.
+*/
+
+void Q3DateTimeEdit::resizeEvent(QResizeEvent *)
+{
+ int dw = de->sizeHint().width();
+ int tw = te->sizeHint().width();
+ int w = width();
+ int h = height();
+ int extra = w - (dw + tw);
+
+ if (tw + extra < 0) {
+ dw = w;
+ } else {
+ dw += 9 * extra / 16;
+ }
+ tw = w - dw;
+
+ de->setGeometry(0, 0, dw, h);
+ te->setGeometry(dw, 0, tw, h);
+}
+
+/*! \reimp
+*/
+
+QSize Q3DateTimeEdit::minimumSizeHint() const
+{
+ QSize dsh = de->minimumSizeHint();
+ QSize tsh = te->minimumSizeHint();
+ return QSize(dsh.width() + tsh.width(),
+ qMax(dsh.height(), tsh.height()));
+}
+
+/*! \internal
+ */
+
+void Q3DateTimeEdit::init()
+{
+ d = new Q3DateTimeEditPrivate();
+ de = new Q3DateEdit(this, "qt_datetime_dateedit");
+ te = new Q3TimeEdit(this, "qt_datetime_timeedit");
+ d->adv = false;
+ connect(de, SIGNAL(valueChanged(QDate)), this, SLOT(newValue(QDate)));
+ connect(te, SIGNAL(valueChanged(QTime)), this, SLOT(newValue(QTime)));
+ setFocusProxy(de);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+}
+
+/*! \reimp
+ */
+
+QSize Q3DateTimeEdit::sizeHint() const
+{
+ ensurePolished();
+ QSize dsh = de->sizeHint();
+ QSize tsh = te->sizeHint();
+ return QSize(dsh.width() + tsh.width(),
+ qMax(dsh.height(), tsh.height()));
+}
+
+/*!
+ \property Q3DateTimeEdit::dateTime
+ \brief the editor's datetime value
+
+ The datetime edit's datetime which may be an invalid datetime.
+*/
+
+void Q3DateTimeEdit::setDateTime(const QDateTime & dt)
+{
+ if (dt.isValid()) {
+ de->setDate(dt.date());
+ te->setTime(dt.time());
+ emit valueChanged(dt);
+ }
+}
+
+QDateTime Q3DateTimeEdit::dateTime() const
+{
+ return QDateTime(de->date(), te->time());
+}
+
+/*!
+ \fn void Q3DateTimeEdit::valueChanged(const QDateTime& datetime)
+
+ This signal is emitted every time the date or time changes. The \a
+ datetime argument is the new datetime.
+*/
+
+
+/*! \internal
+
+ Re-emits the value \a d.
+ */
+
+void Q3DateTimeEdit::newValue(const QDate&)
+{
+ QDateTime dt = dateTime();
+ emit valueChanged(dt);
+}
+
+/*! \internal
+ \overload
+ Re-emits the value \a t.
+ */
+
+void Q3DateTimeEdit::newValue(const QTime&)
+{
+ QDateTime dt = dateTime();
+ emit valueChanged(dt);
+}
+
+
+/*!
+ Sets the auto advance property of the editor to \a advance. If set
+ to true, the editor will automatically advance focus to the next
+ date or time section if the user has completed a section.
+*/
+
+void Q3DateTimeEdit::setAutoAdvance(bool advance)
+{
+ de->setAutoAdvance(advance);
+ te->setAutoAdvance(advance);
+}
+
+/*!
+ Returns true if auto-advance is enabled, otherwise returns false.
+
+ \sa setAutoAdvance()
+*/
+
+bool Q3DateTimeEdit::autoAdvance() const
+{
+ return de->autoAdvance();
+}
+
+/*!
+ \fn Q3DateEdit* Q3DateTimeEdit::dateEdit()
+
+ Returns the internal widget used for editing the date part of the
+ datetime.
+*/
+
+/*!
+ \fn Q3TimeEdit* Q3DateTimeEdit::timeEdit()
+
+ Returns the internal widget used for editing the time part of the
+ datetime.
+*/
+
+QT_END_NAMESPACE
+
+#include "q3datetimeedit.moc"
+
+#endif
diff --git a/src/qt3support/widgets/q3datetimeedit.h b/src/qt3support/widgets/q3datetimeedit.h
new file mode 100644
index 0000000..71edbdd
--- /dev/null
+++ b/src/qt3support/widgets/q3datetimeedit.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3DATETIMEEDIT_H
+#define Q3DATETIMEEDIT_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_DATETIMEEDIT
+
+class Q_COMPAT_EXPORT Q3DateTimeEditBase : public QWidget
+{
+ Q_OBJECT
+public:
+ Q3DateTimeEditBase(QWidget* parent=0, const char* name=0)
+ : QWidget(parent) { setObjectName(QString::fromAscii(name)); }
+
+ virtual bool setFocusSection(int sec) = 0;
+ virtual QString sectionFormattedText(int sec) = 0;
+ virtual void addNumber(int sec, int num) = 0;
+ virtual void removeLastNumber(int sec) = 0;
+
+public Q_SLOTS:
+ virtual void stepUp() = 0;
+ virtual void stepDown() = 0;
+
+private:
+ Q_DISABLE_COPY(Q3DateTimeEditBase)
+};
+
+class Q3DateEditPrivate;
+
+class Q_COMPAT_EXPORT Q3DateEdit : public Q3DateTimeEditBase
+{
+ Q_OBJECT
+ Q_ENUMS(Order)
+ Q_PROPERTY(Order order READ order WRITE setOrder)
+ Q_PROPERTY(QDate date READ date WRITE setDate USER true)
+ Q_PROPERTY(bool autoAdvance READ autoAdvance WRITE setAutoAdvance)
+ Q_PROPERTY(QDate maxValue READ maxValue WRITE setMaxValue)
+ Q_PROPERTY(QDate minValue READ minValue WRITE setMinValue)
+
+public:
+ Q3DateEdit(QWidget* parent=0, const char* name=0);
+ Q3DateEdit(const QDate& date, QWidget* parent=0, const char* name=0);
+ ~Q3DateEdit();
+
+ enum Order { DMY, MDY, YMD, YDM };
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+public Q_SLOTS:
+ virtual void setDate(const QDate& date);
+
+public:
+ QDate date() const;
+ virtual void setOrder(Order order);
+ Order order() const;
+ virtual void setAutoAdvance(bool advance);
+ bool autoAdvance() const;
+
+ virtual void setMinValue(const QDate& d) { setRange(d, maxValue()); }
+ QDate minValue() const;
+ virtual void setMaxValue(const QDate& d) { setRange(minValue(), d); }
+ QDate maxValue() const;
+ virtual void setRange(const QDate& min, const QDate& max);
+ QString separator() const;
+ virtual void setSeparator(const QString& s);
+
+ // Make removeFirstNumber() virtual in Q3DateTimeEditBase in 4.0
+ void removeFirstNumber(int sec);
+
+Q_SIGNALS:
+ void valueChanged(const QDate& date);
+
+protected:
+ bool event(QEvent *e);
+ void timerEvent(QTimerEvent *);
+ void resizeEvent(QResizeEvent *);
+ void stepUp();
+ void stepDown();
+ QString sectionFormattedText(int sec);
+ void addNumber(int sec, int num);
+
+ void removeLastNumber(int sec);
+ bool setFocusSection(int s);
+
+ virtual void setYear(int year);
+ virtual void setMonth(int month);
+ virtual void setDay(int day);
+ virtual void fix();
+ virtual bool outOfRange(int y, int m, int d) const;
+
+protected Q_SLOTS:
+ void updateButtons();
+
+private:
+ Q_DISABLE_COPY(Q3DateEdit)
+
+ void init();
+ int sectionOffsetEnd(int sec) const;
+ int sectionLength(int sec) const;
+ QString sectionText(int sec) const;
+ Q3DateEditPrivate* d;
+};
+
+class Q3TimeEditPrivate;
+
+class Q_COMPAT_EXPORT Q3TimeEdit : public Q3DateTimeEditBase
+{
+ Q_OBJECT
+ Q_FLAGS(Display)
+ Q_PROPERTY(QTime time READ time WRITE setTime USER true)
+ Q_PROPERTY(bool autoAdvance READ autoAdvance WRITE setAutoAdvance)
+ Q_PROPERTY(QTime maxValue READ maxValue WRITE setMaxValue)
+ Q_PROPERTY(QTime minValue READ minValue WRITE setMinValue)
+ Q_PROPERTY(Display display READ display WRITE setDisplay)
+
+public:
+ enum Display {
+ Hours = 0x01,
+ Minutes = 0x02,
+ Seconds = 0x04,
+ /*Reserved = 0x08,*/
+ AMPM = 0x10
+ };
+
+ Q3TimeEdit(QWidget* parent=0, const char* name=0);
+ Q3TimeEdit(const QTime& time, QWidget* parent=0, const char* name=0);
+ ~Q3TimeEdit();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+public Q_SLOTS:
+ virtual void setTime(const QTime& time);
+
+public:
+ QTime time() const;
+ virtual void setAutoAdvance(bool advance);
+ bool autoAdvance() const;
+
+ virtual void setMinValue(const QTime& d) { setRange(d, maxValue()); }
+ QTime minValue() const;
+ virtual void setMaxValue(const QTime& d) { setRange(minValue(), d); }
+ QTime maxValue() const;
+ virtual void setRange(const QTime& min, const QTime& max);
+ QString separator() const;
+ virtual void setSeparator(const QString& s);
+
+ uint display() const;
+ void setDisplay(uint disp);
+
+ // Make removeFirstNumber() virtual in Q3DateTimeEditBase in 4.0
+ void removeFirstNumber(int sec);
+
+Q_SIGNALS:
+ void valueChanged(const QTime& time);
+
+protected:
+ bool event(QEvent *e);
+ void timerEvent(QTimerEvent *e);
+ void resizeEvent(QResizeEvent *);
+ void stepUp();
+ void stepDown();
+ QString sectionFormattedText(int sec);
+ void addNumber(int sec, int num);
+ void removeLastNumber(int sec);
+ bool setFocusSection(int s);
+
+ virtual bool outOfRange(int h, int m, int s) const;
+ virtual void setHour(int h);
+ virtual void setMinute(int m);
+ virtual void setSecond(int s);
+
+protected Q_SLOTS:
+ void updateButtons();
+
+private:
+ Q_DISABLE_COPY(Q3TimeEdit)
+
+ void init();
+ QString sectionText(int sec);
+ Q3TimeEditPrivate* d;
+};
+
+
+class Q3DateTimeEditPrivate;
+
+class Q_COMPAT_EXPORT Q3DateTimeEdit : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime USER true)
+
+public:
+ Q3DateTimeEdit(QWidget* parent=0, const char* name=0);
+ Q3DateTimeEdit(const QDateTime& datetime, QWidget* parent=0,
+ const char* name=0);
+ ~Q3DateTimeEdit();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+public Q_SLOTS:
+ virtual void setDateTime(const QDateTime & dt);
+
+public:
+ QDateTime dateTime() const;
+
+ Q3DateEdit* dateEdit() { return de; }
+ Q3TimeEdit* timeEdit() { return te; }
+
+ virtual void setAutoAdvance(bool advance);
+ bool autoAdvance() const;
+
+Q_SIGNALS:
+ void valueChanged(const QDateTime& datetime);
+
+protected:
+ void init();
+ void resizeEvent(QResizeEvent *);
+
+protected Q_SLOTS:
+ void newValue(const QDate& d);
+ void newValue(const QTime& t);
+
+private:
+ Q_DISABLE_COPY(Q3DateTimeEdit)
+
+ Q3DateEdit* de;
+ Q3TimeEdit* te;
+ Q3DateTimeEditPrivate* d;
+};
+
+#endif // QT_NO_DATETIMEEDIT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3DATETIMEEDIT_H
diff --git a/src/qt3support/widgets/q3dockarea.cpp b/src/qt3support/widgets/q3dockarea.cpp
new file mode 100644
index 0000000..1609aa4
--- /dev/null
+++ b/src/qt3support/widgets/q3dockarea.cpp
@@ -0,0 +1,1349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3dockarea.h"
+
+#ifndef QT_NO_MAINWINDOW
+#include "qsplitter.h"
+#include "qevent.h"
+#include "qlayout.h"
+#include "qapplication.h"
+#include "qpainter.h"
+#include "qmap.h"
+#include "q3mainwindow.h"
+#include "q3toolbar.h"
+
+QT_BEGIN_NAMESPACE
+
+//#define QDOCKAREA_DEBUG
+
+struct Q3DockData
+{
+ Q3DockData() : w(0), rect() {}
+ Q3DockData(Q3DockWindow *dw, const QRect &r) : w(dw), rect(r) {}
+ Q3DockWindow *w;
+ QRect rect;
+
+ Q_DUMMY_COMPARISON_OPERATOR(Q3DockData)
+};
+
+static int fix_x(Q3DockWindow* w, int width = -1) {
+ if (QApplication::reverseLayout()) {
+ if (width < 0)
+ width = w->width();
+ return w->parentWidget()->width() - w->x() - width;
+ }
+ return w->x();
+}
+static int fix_x(Q3DockWindow* w, int x, int width = -1) {
+ if (QApplication::reverseLayout()) {
+ if (width < 0)
+ width = w->width();
+ return w->parentWidget()->width() - x - width;
+ }
+ return x;
+}
+
+static QPoint fix_pos(Q3DockWindow* w) {
+ if (QApplication::reverseLayout()) {
+ QPoint p = w->pos();
+ p.rx() = w->parentWidget()->width() - p.x() - w->width();
+ return p;
+ }
+ return w->pos();
+}
+
+
+void Q3DockAreaLayout::setGeometry(const QRect &r)
+{
+ QLayout::setGeometry(r);
+ layoutItems(r);
+}
+
+QLayoutItem *Q3DockAreaLayout::itemAt(int) const
+{
+ return 0; //###
+}
+
+QLayoutItem *Q3DockAreaLayout::takeAt(int)
+{
+ return 0; //###
+}
+
+int Q3DockAreaLayout::count() const
+{
+ return 0; //###
+}
+
+
+QSize Q3DockAreaLayout::sizeHint() const
+{
+ if (dockWindows->isEmpty())
+ return QSize(0, 0);
+
+ if (dirty) {
+ Q3DockAreaLayout *that = (Q3DockAreaLayout *) this;
+ that->layoutItems(geometry());
+ }
+
+ int w = 0;
+ int h = 0;
+ int y = -1;
+ int x = -1;
+ int ph = 0;
+ int pw = 0;
+ for (int i = 0; i < dockWindows->size(); ++i) {
+ Q3DockWindow *dw = dockWindows->at(i);
+ int plush = 0, plusw = 0;
+ if (dw->isHidden())
+ continue;
+ if (hasHeightForWidth()) {
+ if (y != dw->y())
+ plush = ph;
+ y = dw->y();
+ ph = dw->height();
+ } else {
+ if (x != dw->x())
+ plusw = pw;
+ x = dw->x();
+ pw = dw->width();
+ }
+ h = qMax(h, dw->height() + plush);
+ w = qMax(w, dw->width() + plusw);
+ }
+
+ if (hasHeightForWidth())
+ return QSize(0, h);
+ return QSize(w, 0);
+}
+
+bool Q3DockAreaLayout::hasHeightForWidth() const
+{
+ return orient == Qt::Horizontal;
+}
+
+void Q3DockAreaLayout::init()
+{
+ dirty = true;
+ cached_width = 0;
+ cached_height = 0;
+ cached_hfw = -1;
+ cached_wfh = -1;
+}
+
+void Q3DockAreaLayout::invalidate()
+{
+ dirty = true;
+ cached_width = 0;
+ cached_height = 0;
+ QLayout::invalidate();
+}
+
+static int start_pos(const QRect &r, Qt::Orientation o)
+{
+ if (o == Qt::Horizontal) {
+ return qMax(0, r.x());
+ } else {
+ return qMax(0, r.y());
+ }
+}
+
+static void add_size(int s, int &pos, Qt::Orientation o)
+{
+ if (o == Qt::Horizontal) {
+ pos += s;
+ } else {
+ pos += s;
+ }
+}
+
+static int space_left(const QRect &r, int pos, Qt::Orientation o)
+{
+ if (o == Qt::Horizontal) {
+ return (r.x() + r.width()) - pos;
+ } else {
+ return (r.y() + r.height()) - pos;
+ }
+}
+
+static int dock_extent(Q3DockWindow *w, Qt::Orientation o, int maxsize)
+{
+ if (o == Qt::Horizontal)
+ return qMin(maxsize, qMax(w->sizeHint().width(), w->fixedExtent().width()));
+ else
+ return qMin(maxsize, qMax(w->sizeHint().height(), w->fixedExtent().height()));
+}
+
+static int dock_strut(Q3DockWindow *w, Qt::Orientation o)
+{
+ if (o != Qt::Horizontal) {
+ int wid;
+ if ((wid = w->fixedExtent().width()) != -1)
+ return qMax(wid, qMax(w->minimumSize().width(), w->minimumSizeHint().width()));
+ return qMax(w->sizeHint().width(), qMax(w->minimumSize().width(), w->minimumSizeHint().width()));
+ } else {
+ int hei;
+ if ((hei = w->fixedExtent().height()) != -1)
+ return qMax(hei, qMax(w->minimumSizeHint().height(), w->minimumSize().height()));
+ return qMax(w->sizeHint().height(), qMax(w->minimumSizeHint().height(), w->minimumSize().height()));
+ }
+}
+
+static void set_geometry(Q3DockWindow *w, int pos, int sectionpos, int extent, int strut, Qt::Orientation o)
+{
+ if (o == Qt::Horizontal)
+ w->setGeometry(fix_x(w, pos, extent), sectionpos, extent, strut);
+ else
+ w->setGeometry(sectionpos, pos, strut, extent);
+}
+
+static int size_extent(const QSize &s, Qt::Orientation o, bool swap = false)
+{
+ return o == Qt::Horizontal ? (swap ? s.height() : s.width()) : (swap ? s.width() : s.height());
+}
+
+static int point_pos(const QPoint &p, Qt::Orientation o, bool swap = false)
+{
+ return o == Qt::Horizontal ? (swap ? p.y() : p.x()) : (swap ? p.x() : p.y());
+}
+
+static void shrink_extend(Q3DockWindow *dw, int &dockExtend, int /*spaceLeft*/, Qt::Orientation o)
+{
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(dw);
+ if (o == Qt::Horizontal) {
+ int mw = 0;
+ if (!tb)
+ mw = dw->minimumWidth();
+ else
+ mw = dw->sizeHint().width();
+ dockExtend = mw;
+ } else {
+ int mh = 0;
+ if (!tb)
+ mh = dw->minimumHeight();
+ else
+ mh = dw->sizeHint().height();
+ dockExtend = mh;
+ }
+}
+
+static void place_line(QList<Q3DockData> &lastLine, Qt::Orientation o, int linestrut, int fullextent, int tbstrut, int maxsize, Q3DockAreaLayout *)
+{
+ Q3DockWindow *last = 0;
+ QRect lastRect;
+ for (QList<Q3DockData>::Iterator it = lastLine.begin(); it != lastLine.end(); ++it) {
+ if (tbstrut != -1 && qobject_cast<Q3ToolBar*>((*it).w))
+ (*it).rect.setHeight(tbstrut);
+ if (!last) {
+ last = (*it).w;
+ lastRect = (*it).rect;
+ continue;
+ }
+ if (!last->isStretchable()) {
+ int w = qMin(lastRect.width(), maxsize);
+ set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o);
+ } else {
+ int w = qMin((*it).rect.x() - lastRect.x(), maxsize);
+ set_geometry(last, lastRect.x(), lastRect.y(), w,
+ last->isResizeEnabled() ? linestrut : lastRect.height(), o);
+ }
+ last = (*it).w;
+ lastRect = (*it).rect;
+ }
+ if (!last)
+ return;
+ if (!last->isStretchable()) {
+ int w = qMin(lastRect.width(), maxsize);
+ set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o);
+ } else {
+ int w = qMin(fullextent - lastRect.x() - (o == Qt::Vertical ? 1 : 0), maxsize);
+ set_geometry(last, lastRect.x(), lastRect.y(), w,
+ last->isResizeEnabled() ? linestrut : lastRect.height(), o);
+ }
+}
+
+QSize Q3DockAreaLayout::minimumSize() const
+{
+ if (dockWindows->isEmpty())
+ return QSize(0, 0);
+
+ if (dirty) {
+ Q3DockAreaLayout *that = (Q3DockAreaLayout *) this;
+ that->layoutItems(geometry());
+ }
+
+ int s = 0;
+
+ for (int i = 0; i < dockWindows->size(); ++i) {
+ Q3DockWindow *dw = dockWindows->at(i);
+ if (dw->isHidden())
+ continue;
+ s = qMax(s, dock_strut(dw, orientation()));
+ }
+
+ return orientation() == Qt::Horizontal ? QSize(0, s ? s+2 : 0) : QSize(s, 0);
+}
+
+
+
+int Q3DockAreaLayout::layoutItems(const QRect &rect, bool testonly)
+{
+ if (dockWindows->isEmpty())
+ return 0;
+
+ dirty = false;
+
+ // some corrections
+ QRect r = rect;
+ if (orientation() == Qt::Vertical)
+ r.setHeight(r.height() - 3);
+
+ // init
+ lines.clear();
+ ls.clear();
+ int start = start_pos(r, orientation());
+ int pos = start;
+ int sectionpos = 0;
+ int linestrut = 0;
+ QList<Q3DockData> lastLine;
+ int tbstrut = -1;
+ int maxsize = size_extent(rect.size(), orientation());
+ int visibleWindows = 0;
+
+ // go through all widgets in the dock
+ for (int i = 0; i < dockWindows->size(); ++i) {
+ Q3DockWindow *dw = dockWindows->at(i);
+ if (dw->isHidden())
+ continue;
+ ++visibleWindows;
+ // find position for the widget: This is the maximum of the
+ // end of the previous widget and the offset of the widget. If
+ // the position + the width of the widget dosn't fit into the
+ // dock, try moving it a bit back, if possible.
+ int op = pos;
+ int dockExtend = dock_extent(dw, orientation(), maxsize);
+ if (!dw->isStretchable()) {
+ pos = qMax(pos, dw->offset());
+ if (pos + dockExtend > size_extent(r.size(), orientation()) - 1)
+ pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend);
+ }
+ if (!lastLine.isEmpty() && !dw->newLine() && space_left(rect, pos, orientation()) < dockExtend)
+ shrink_extend(dw, dockExtend, space_left(rect, pos, orientation()), orientation());
+ // if the current widget doesn't fit into the line anymore and it is not the first widget of the line
+ if (!lastLine.isEmpty() &&
+ (space_left(rect, pos, orientation()) < dockExtend || dw->newLine())) {
+ if (!testonly) // place the last line, if not in test mode
+ place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this);
+ // remember the line coordinats of the last line
+ if (orientation() == Qt::Horizontal)
+ lines.append(QRect(0, sectionpos, r.width(), linestrut));
+ else
+ lines.append(QRect(sectionpos, 0, linestrut, r.height()));
+ // do some clearing for the next line
+ lastLine.clear();
+ sectionpos += linestrut;
+ linestrut = 0;
+ pos = start;
+ tbstrut = -1;
+ }
+
+ // remember first widget of a line
+ if (lastLine.isEmpty()) {
+ ls.append(dw);
+ // try to make the best position
+ int op = pos;
+ if (!dw->isStretchable())
+ pos = qMax(pos, dw->offset());
+ if (pos + dockExtend > size_extent(r.size(), orientation()) - 1)
+ pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend);
+ }
+ // do some calculations and add the remember the rect which the docking widget requires for the placing
+ QRect dwRect(pos, sectionpos, dockExtend, dock_strut(dw, orientation() ));
+ lastLine.append(Q3DockData(dw, dwRect));
+ if (qobject_cast<Q3ToolBar*>(dw))
+ tbstrut = qMax(tbstrut, dock_strut(dw, orientation()));
+ linestrut = qMax(dock_strut(dw, orientation()), linestrut);
+ add_size(dockExtend, pos, orientation());
+ }
+
+ // if some stuff was not placed/stored yet, do it now
+ if (!testonly)
+ place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this);
+ if (orientation() == Qt::Horizontal)
+ lines.append(QRect(0, sectionpos, r.width(), linestrut));
+ else
+ lines.append(QRect(sectionpos, 0, linestrut, r.height()));
+ if (lines.size() >= 2 && *(--lines.end()) == *(--(--lines.end())))
+ lines.removeLast();
+
+ bool hadResizable = false;
+ for (int i = 0; i < dockWindows->size(); ++i) {
+ Q3DockWindow *dw = dockWindows->at(i);
+ if (!dw->isVisibleTo(parentWidget))
+ continue;
+ hadResizable = hadResizable || dw->isResizeEnabled();
+ dw->updateSplitterVisibility(visibleWindows > 1); //!dw->area()->isLastDockWindow(dw));
+ if (Q3ToolBar *tb = qobject_cast<Q3ToolBar *>(dw))
+ tb->checkForExtension(dw->size());
+ }
+ return sectionpos + linestrut;
+}
+
+int Q3DockAreaLayout::heightForWidth(int w) const
+{
+ if (dockWindows->isEmpty() && parentWidget)
+ return parentWidget->minimumHeight();
+
+ if (cached_width != w) {
+ Q3DockAreaLayout * mthis = (Q3DockAreaLayout*)this;
+ mthis->cached_width = w;
+ int h = mthis->layoutItems(QRect(0, 0, w, 0), true);
+ mthis->cached_hfw = h;
+ return h;
+ }
+
+ return cached_hfw;
+}
+
+int Q3DockAreaLayout::widthForHeight(int h) const
+{
+ if (cached_height != h) {
+ Q3DockAreaLayout * mthis = (Q3DockAreaLayout*)this;
+ mthis->cached_height = h;
+ int w = mthis->layoutItems(QRect(0, 0, 0, h), true);
+ mthis->cached_wfh = w;
+ return w;
+ }
+ return cached_wfh;
+}
+
+
+
+
+/*!
+ \class Q3DockArea
+ \brief The Q3DockArea class manages and lays out Q3DockWindows.
+
+ \compat
+
+ A Q3DockArea is a container which manages a list of
+ \l{Q3DockWindow}s which it lays out within its area. In cooperation
+ with the \l{Q3DockWindow}s it is responsible for the docking and
+ undocking of \l{Q3DockWindow}s and moving them inside the dock
+ area. Q3DockAreas also handle the wrapping of \l{Q3DockWindow}s to
+ fill the available space as compactly as possible. Q3DockAreas can
+ contain Q3ToolBars since Q3ToolBar is a Q3DockWindow subclass.
+
+ QMainWindow contains four Q3DockAreas which you can use for your
+ Q3ToolBars and Q3DockWindows, so in most situations you do not need
+ to use the Q3DockArea class directly. Although QMainWindow contains
+ support for its own dock areas it isn't convenient for adding new
+ Q3DockAreas. If you need to create your own dock areas we suggest
+ that you create a subclass of QWidget and add your Q3DockAreas to
+ your subclass.
+
+ \img qmainwindow-qdockareas.png QMainWindow's Q3DockAreas
+
+ \target lines
+ \e Lines. Q3DockArea uses the concept of lines. A line is a
+ horizontal region which may contain dock windows side-by-side. A
+ dock area may have room for more than one line. When dock windows
+ are docked into a dock area they are usually added at the right
+ hand side of the top-most line that has room (unless manually
+ placed by the user). When users move dock windows they may leave
+ empty lines or gaps in non-empty lines. Qt::Dock windows can be lined
+ up to minimize wasted space using the lineUp() function.
+
+ The Q3DockArea class maintains a position list of all its child
+ dock windows. Qt::Dock windows are added to a dock area from position
+ 0 onwards. Qt::Dock windows are laid out sequentially in position
+ order from left to right, and in the case of multiple lines of
+ dock windows, from top to bottom. If a dock window is floated it
+ still retains its position since this is where the window will
+ return if the user double clicks its caption. A dock window's
+ position can be determined with hasDockWindow(). The position can
+ be changed with moveDockWindow().
+
+ To dock or undock a dock window use Q3DockWindow::dock() and
+ Q3DockWindow::undock() respectively. If you want to control which
+ dock windows can dock in a dock area use setAcceptDockWindow(). To
+ see if a dock area contains a particular dock window use
+ \l{hasDockWindow()}; to see how many dock windows a dock area
+ contains use count().
+
+ The streaming operators can write the positions of the dock
+ windows in the dock area to a QTextStream. The positions can be
+ read back later to restore the saved positions.
+
+ Save the positions to a QTextStream:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockarea.cpp 0
+
+ Restore the positions from a QTextStream:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockarea.cpp 1
+*/
+
+/*!
+ \property Q3DockArea::handlePosition
+ \brief where the dock window splitter handle is placed in the dock
+ area
+
+ The default position is \c Normal.
+*/
+
+/*!
+ \property Q3DockArea::orientation
+ \brief the dock area's orientation
+
+ There is no default value; the orientation is specified in the
+ constructor.
+*/
+
+/*!
+ \enum Q3DockArea::HandlePosition
+
+ A dock window has two kinds of handles, the dock window handle
+ used for dragging the dock window, and the splitter handle used to
+ resize the dock window in relation to other dock windows using a
+ splitter. (The splitter handle is only visible for docked
+ windows.)
+
+ This enum specifies where the dock window splitter handle is
+ placed in the dock area.
+
+ \value Normal The splitter handles of dock windows are placed at
+ the right or bottom.
+
+ \value Reverse The splitter handles of dock windows are placed at
+ the left or top.
+*/
+
+/*!
+ Constructs a Q3DockArea with orientation \a o, HandlePosition \a h,
+ parent \a parent and called \a name.
+*/
+
+Q3DockArea::Q3DockArea(Qt::Orientation o, HandlePosition h, QWidget *parent, const char *name)
+ : QWidget(parent, name), orient(o), layout(0), hPos(h)
+{
+ layout = new Q3DockAreaLayout(this, o, &dockWindows, 0, 0, "toollayout");
+ installEventFilter(this);
+}
+
+/*!
+ Destroys the dock area and all the dock windows docked in the dock
+ area.
+
+ Does not affect any floating dock windows or dock windows in other
+ dock areas, even if they first appeared in this dock area.
+ Floating dock windows are effectively top level windows and are
+ not child windows of the dock area. When a floating dock window is
+ docked (dragged into a dock area) its parent becomes the dock
+ area.
+*/
+
+Q3DockArea::~Q3DockArea()
+{
+ while (!dockWindows.isEmpty())
+ delete dockWindows.takeFirst();
+}
+
+/*!
+ Moves the Q3DockWindow \a w within the dock area. If \a w is not
+ already docked in this area, \a w is docked first. If \a index is
+ -1 or larger than the number of docked widgets, \a w is appended
+ at the end, otherwise it is inserted at the position \a index.
+*/
+
+void Q3DockArea::moveDockWindow(Q3DockWindow *w, int index)
+{
+ invalidateFixedSizes();
+ Q3DockWindow *dockWindow = 0;
+ int dockWindowIndex = findDockWindow(w);
+ if (dockWindowIndex == -1) {
+ dockWindow = w;
+ bool vis = dockWindow->isVisible();
+ dockWindow->setParent(this);
+ dockWindow->move(0, 0);
+ if(vis)
+ dockWindow->show();
+ w->installEventFilter(this);
+ updateLayout();
+ setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
+ orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
+ dockWindows.append(w);
+ } else {
+ if (w->parent() != this) {
+ bool vis = w->isVisible();
+ w->setParent(this);
+ w->move(0, 0);
+ if(vis)
+ w->show();
+ }
+ if (index == -1) {
+ dockWindows.removeAll(w);
+ dockWindows.append(w);
+ }
+ }
+
+ w->dockArea = this;
+ w->curPlace = Q3DockWindow::InDock;
+ w->updateGui();
+
+ if (index != -1 && index < (int)dockWindows.count()) {
+ dockWindows.removeAll(w);
+ dockWindows.insert(index, w);
+ }
+}
+
+/*!
+ Returns true if the dock area contains the dock window \a w;
+ otherwise returns false. If \a index is not 0 it will be set as
+ follows: if the dock area contains the dock window *\a{index} is
+ set to \a w's index position; otherwise *\a{index} is set to -1.
+*/
+
+bool Q3DockArea::hasDockWindow(Q3DockWindow *w, int *index)
+{
+ int i = dockWindows.indexOf(w);
+ if (index)
+ *index = i;
+ return i != -1;
+}
+
+int Q3DockArea::lineOf(int index)
+{
+ QList<Q3DockWindow *> lineStarts = layout->lineStarts();
+ int i = 0;
+ for (; i < lineStarts.size(); ++i) {
+ Q3DockWindow *w = lineStarts.at(i);
+ if (dockWindows.indexOf(w) >= index)
+ return i;
+ }
+ return i;
+}
+
+/*!
+ \overload
+
+ Moves the dock window \a w inside the dock area where \a p is the
+ new position (in global screen coordinates), \a r is the suggested
+ rectangle of the dock window and \a swap specifies whether or not
+ the orientation of the docked widget needs to be changed.
+
+ This function is used internally by Q3DockWindow. You shouldn't
+ need to call it yourself.
+*/
+
+void Q3DockArea::moveDockWindow(Q3DockWindow *w, const QPoint &p, const QRect &r, bool swap)
+{
+ invalidateFixedSizes();
+ int mse = -10;
+ bool hasResizable = false;
+ for (int i = 0; i < dockWindows.size(); ++i) {
+ Q3DockWindow *dw = dockWindows.at(i);
+ if (dw->isHidden())
+ continue;
+ if (dw->isResizeEnabled())
+ hasResizable = true;
+ if (orientation() != Qt::Horizontal)
+ mse = qMax(qMax(dw->fixedExtent().width(), dw->width()), mse);
+ else
+ mse = qMax(qMax(dw->fixedExtent().height(), dw->height()), mse);
+ }
+ if (!hasResizable && w->isResizeEnabled()) {
+ if (orientation() != Qt::Horizontal)
+ mse = qMax(w->fixedExtent().width(), mse);
+ else
+ mse = qMax(w->fixedExtent().height(), mse);
+ }
+
+ Q3DockWindow *dockWindow = 0;
+ int dockWindowIndex = findDockWindow(w);
+ QList<Q3DockWindow *> lineStarts = layout->lineStarts();
+ QList<QRect> lines = layout->lineList();
+ bool wasAloneInLine = false;
+ QPoint pos = mapFromGlobal(p);
+ int line = lineOf(dockWindowIndex);
+ QRect lr;
+ if (line < lines.size())
+ lr = lines.at(line);
+ if (dockWindowIndex != -1) {
+ if (lineStarts.contains(w)
+ && ((dockWindowIndex < dockWindows.count() - 1
+ && lineStarts.contains(dockWindows.at(dockWindowIndex + 1)))
+ || dockWindowIndex == dockWindows.count() - 1))
+ wasAloneInLine = true;
+ dockWindow = dockWindows.takeAt(dockWindowIndex);
+ if (!wasAloneInLine) { // only do the pre-layout if the widget isn't the only one in its line
+ if (lineStarts.contains(dockWindow) && dockWindowIndex < dockWindows.count())
+ dockWindows.at(dockWindowIndex)->setNewLine(true);
+ layout->layoutItems(QRect(0, 0, width(), height()), true);
+ }
+ } else {
+ dockWindow = w;
+ bool vis = dockWindow->isVisible();
+ dockWindow->setParent(this);
+ dockWindow->move(0, 0);
+ if(vis)
+ dockWindow->show();
+ if (swap)
+ dockWindow->resize(dockWindow->height(), dockWindow->width());
+ w->installEventFilter(this);
+ }
+
+ lineStarts = layout->lineStarts();
+ lines = layout->lineList();
+
+ QRect rect = QRect(mapFromGlobal(r.topLeft()), r.size());
+ if (orientation() == Qt::Horizontal && QApplication::reverseLayout()) {
+ rect = QRect(width() - rect.x() - rect.width(), rect.y(), rect.width(), rect.height());
+ pos.rx() = width() - pos.x();
+ }
+ dockWindow->setOffset(point_pos(rect.topLeft(), orientation()));
+ if (orientation() == Qt::Horizontal) {
+ int offs = dockWindow->offset();
+ if (width() - offs < dockWindow->minimumWidth())
+ dockWindow->setOffset(width() - dockWindow->minimumWidth());
+ } else {
+ int offs = dockWindow->offset();
+ if (height() - offs < dockWindow->minimumHeight())
+ dockWindow->setOffset(height() - dockWindow->minimumHeight());
+ }
+
+ if (dockWindows.isEmpty()) {
+ dockWindows.append(dockWindow);
+ } else {
+ int dockLine = -1;
+ bool insertLine = false;
+ int i = 0;
+ QRect lineRect;
+ // find the line which we touched with the mouse
+ for (QList<QRect>::Iterator it = lines.begin(); it != lines.end(); ++it, ++i) {
+ if (point_pos(pos, orientation(), true) >= point_pos((*it).topLeft(), orientation(), true) &&
+ point_pos(pos, orientation(), true) <= point_pos((*it).topLeft(), orientation(), true) +
+ size_extent((*it).size(), orientation(), true)) {
+ dockLine = i;
+ lineRect = *it;
+ break;
+ }
+ }
+ if (dockLine == -1) { // outside the dock...
+ insertLine = true;
+ if (point_pos(pos, orientation(), true) < 0) // insert as first line
+ dockLine = 0;
+ else
+ dockLine = (int)lines.count(); // insert after the last line ### size_t/int cast
+ } else { // inside the dock (we have found a dockLine)
+ if (point_pos(pos, orientation(), true) <
+ point_pos(lineRect.topLeft(), orientation(), true) + 4) { // mouse was at the very beginning of the line
+ insertLine = true; // insert a new line before that with the docking widget
+ } else if (point_pos(pos, orientation(), true) >
+ point_pos(lineRect.topLeft(), orientation(), true) +
+ size_extent(lineRect.size(), orientation(), true) - 4) { // mouse was at the very and of the line
+ insertLine = true; // insert a line after that with the docking widget
+ dockLine++;
+ }
+ }
+
+ if (!insertLine && wasAloneInLine && lr.contains(pos)) // if we are alone in a line and just moved in there, re-insert it
+ insertLine = true;
+
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("insert in line %d, and insert that line: %d", dockLine, insertLine);
+ qDebug(" (btw, we have %d lines)", lines.count());
+#endif
+ Q3DockWindow *dw = 0;
+ if (dockLine >= (int)lines.count()) { // insert after last line
+ dockWindows.append(dockWindow);
+ dockWindow->setNewLine(true);
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("insert at the end");
+#endif
+ } else if (dockLine == 0 && insertLine) { // insert before first line
+ dockWindows.insert(0, dockWindow);
+ dockWindows.at(1)->setNewLine(true);
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("insert at the begin");
+#endif
+ } else { // insert somewhere in between
+ // make sure each line start has a new line
+ for (int i = 0; i < lineStarts.size(); ++i) {
+ dw = lineStarts.at(i);
+ dw->setNewLine(true);
+ }
+
+ // find the index of the first widget in the search line
+ int searchLine = dockLine;
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("search line start of %d", searchLine);
+#endif
+ Q3DockWindow *lsw = lineStarts.at(searchLine);
+ int index = dockWindows.indexOf(lsw);
+ if (index == -1) { // the linestart widget hasn't been found, try to find it harder
+ if (lsw == w && dockWindowIndex <= dockWindows.count())
+ index = dockWindowIndex;
+ else
+ index = 0;
+ }
+#if defined(QDOCKAREA_DEBUG)
+ qDebug(" which starts at %d", index);
+#endif
+ if (!insertLine) { // if we insert the docking widget in the existing line
+ // find the index for the widget
+ bool inc = true;
+ bool firstTime = true;
+ for (int i = index; i < dockWindows.size(); ++i) {
+ dw = dockWindows.at(i);
+ if (orientation() == Qt::Horizontal)
+ dw->setFixedExtentWidth(-1);
+ else
+ dw->setFixedExtentHeight(-1);
+ if (!firstTime && lineStarts.contains(dw)) // we are in the next line, so break
+ break;
+ if (point_pos(pos, orientation()) <
+ point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2) {
+ inc = false;
+ }
+ if (inc)
+ index++;
+ firstTime = false;
+ }
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("insert at index: %d", index);
+#endif
+ // if we insert it just before a widget which has a new line, transfer the newline to the docking widget
+ // but not if we didn't only mave a widget in its line which was alone in the line before
+ if (!(wasAloneInLine && lr.contains(pos))
+ && index >= 0 && index < dockWindows.count() &&
+ dockWindows.at(index)->newLine() && lineOf(index) == dockLine) {
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("get rid of the old newline and get me one");
+#endif
+ dockWindows.at(index)->setNewLine(false);
+ dockWindow->setNewLine(true);
+ } else if (wasAloneInLine && lr.contains(pos)) {
+ dockWindow->setNewLine(true);
+ } else { // if we are somewhere in a line, get rid of the newline
+ dockWindow->setNewLine(false);
+ }
+ } else { // insert in a new line, so make sure the dock widget and the widget which will be after it have a newline
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("insert a new line");
+#endif
+ if (index < dockWindows.count()) {
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("give the widget at %d a newline", index);
+#endif
+ Q3DockWindow* nldw = dockWindows.at(index);
+ if (nldw)
+ nldw->setNewLine(true);
+ }
+#if defined(QDOCKAREA_DEBUG)
+ qDebug("give me a newline");
+#endif
+ dockWindow->setNewLine(true);
+ }
+ // finally insert the widget
+ dockWindows.insert(index, dockWindow);
+ }
+ }
+
+ if (mse != -10 && w->isResizeEnabled()) {
+ if (orientation() != Qt::Horizontal)
+ w->setFixedExtentWidth(qMin(qMax(w->minimumWidth(), mse), w->sizeHint().width()));
+ else
+ w->setFixedExtentHeight(qMin(qMax(w->minimumHeight(), mse), w->sizeHint().height()));
+ }
+
+ updateLayout();
+ setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
+ orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
+}
+
+/*!
+ Removes the dock window \a w from the dock area. If \a
+ makeFloating is true, \a w gets floated, and if \a swap is true,
+ the orientation of \a w gets swapped. If \a fixNewLines is true
+ (the default) newlines in the area will be fixed.
+
+ You should never need to call this function yourself. Use
+ Q3DockWindow::dock() and Q3DockWindow::undock() instead.
+*/
+
+void Q3DockArea::removeDockWindow(Q3DockWindow *w, bool makeFloating, bool swap, bool fixNewLines)
+{
+ w->removeEventFilter(this);
+ Q3DockWindow *dockWindow = 0;
+ int i = findDockWindow(w);
+ if (i == -1)
+ return;
+ dockWindow = dockWindows.at(i);
+ dockWindows.removeAt(i);
+ QList<Q3DockWindow *> lineStarts = layout->lineStarts();
+ if (fixNewLines && lineStarts.contains(dockWindow) && i < dockWindows.count())
+ dockWindows.at(i)->setNewLine(true);
+ if (makeFloating) {
+ QWidget *p = parentWidget() ? parentWidget() : window();
+ dockWindow->setParent(p, Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool);
+ dockWindow->move(0, 0);
+ }
+ if (swap)
+ dockWindow->resize(dockWindow->height(), dockWindow->width());
+ updateLayout();
+ if (dockWindows.isEmpty())
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
+}
+
+int Q3DockArea::findDockWindow(Q3DockWindow *w)
+{
+ return dockWindows.indexOf(w);
+}
+
+void Q3DockArea::updateLayout()
+{
+ layout->invalidate();
+ layout->activate();
+}
+
+/*! \reimp
+ */
+
+bool Q3DockArea::eventFilter(QObject *o, QEvent *e)
+{
+ if (e->type() == QEvent::Close) {
+ if (qobject_cast<Q3DockWindow*>(o)) {
+ o->removeEventFilter(this);
+ QApplication::sendEvent(o, e);
+ if (((QCloseEvent*)e)->isAccepted())
+ removeDockWindow((Q3DockWindow*)o, false, false);
+ return true;
+ }
+ }
+ return false;
+}
+
+/*! \internal
+
+ Invalidates the offset of the next dock window in the dock area.
+ */
+
+void Q3DockArea::invalidNextOffset(Q3DockWindow *dw)
+{
+ int i = dockWindows.indexOf(dw);
+ if (i == -1 || i >= (int)dockWindows.count() - 1)
+ return;
+ if ((dw = dockWindows.at(++i)))
+ dw->setOffset(0);
+}
+
+/*!
+ \property Q3DockArea::count
+ \brief the number of dock windows in the dock area
+*/
+int Q3DockArea::count() const
+{
+ return dockWindows.count();
+}
+
+/*!
+ \property Q3DockArea::empty
+ \brief whether the dock area is empty
+*/
+
+bool Q3DockArea::isEmpty() const
+{
+ return dockWindows.isEmpty();
+}
+
+
+/*!
+ Returns a list of the dock windows in the dock area.
+*/
+
+QList<Q3DockWindow *> Q3DockArea::dockWindowList() const
+{
+ return dockWindows;
+}
+
+/*!
+ Lines up the dock windows in this dock area to minimize wasted
+ space. If \a keepNewLines is true, only space within lines is
+ cleaned up. If \a keepNewLines is false the number of lines might
+ be changed.
+*/
+
+void Q3DockArea::lineUp(bool keepNewLines)
+{
+ for (int i = 0; i < dockWindows.size(); ++i) {
+ Q3DockWindow *dw = dockWindows.at(i);
+ dw->setOffset(0);
+ if (!keepNewLines)
+ dw->setNewLine(false);
+ }
+ layout->activate();
+}
+
+Q3DockArea::DockWindowData *Q3DockArea::dockWindowData(Q3DockWindow *w)
+{
+ DockWindowData *data = new DockWindowData;
+ data->index = findDockWindow(w);
+ if (data->index == -1) {
+ delete data;
+ return 0;
+ }
+ QList<Q3DockWindow *> lineStarts = layout->lineStarts();
+ int i = -1;
+ for (int j = 0; j < dockWindows.size(); ++j) {
+ Q3DockWindow *dw = dockWindows.at(j);
+ if (lineStarts.contains(dw))
+ ++i;
+ if (dw == w)
+ break;
+ }
+ data->line = i;
+ data->offset = point_pos(QPoint(fix_x(w), w->y()), orientation());
+ data->area = this;
+ data->fixedExtent = w->fixedExtent();
+ return data;
+}
+
+void Q3DockArea::dockWindow(Q3DockWindow *dockWindow, DockWindowData *data)
+{
+ if (!data)
+ return;
+
+ dockWindow->setParent(this);
+ dockWindow->move(0, 0);
+
+ dockWindow->installEventFilter(this);
+ dockWindow->dockArea = this;
+ dockWindow->updateGui();
+
+ if (dockWindows.isEmpty()) {
+ dockWindows.append(dockWindow);
+ } else {
+ QList<Q3DockWindow *> lineStarts = layout->lineStarts();
+ int index = 0;
+ if (lineStarts.count() > data->line)
+ index = dockWindows.indexOf(lineStarts.at(data->line));
+ if (index == -1)
+ index = 0;
+ bool firstTime = true;
+ int offset = data->offset;
+ for (int i = index; i < dockWindows.size(); ++i) {
+ Q3DockWindow *dw = dockWindows.at(i);
+ if (!firstTime && lineStarts.contains(dw))
+ break;
+ if (offset <
+ point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2)
+ break;
+ index++;
+ firstTime = false;
+ }
+ if (index >= 0 && index < dockWindows.count() &&
+ dockWindows.at(index)->newLine() && lineOf(index) == data->line) {
+ dockWindows.at(index)->setNewLine(false);
+ dockWindow->setNewLine(true);
+ } else {
+ dockWindow->setNewLine(false);
+ }
+
+ dockWindows.insert(index, dockWindow);
+ }
+ dockWindow->show();
+
+ dockWindow->setFixedExtentWidth(data->fixedExtent.width());
+ dockWindow->setFixedExtentHeight(data->fixedExtent.height());
+
+ updateLayout();
+ setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
+ orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
+
+}
+
+/*!
+ Returns true if dock window \a dw could be docked into the dock
+ area; otherwise returns false.
+
+ \sa setAcceptDockWindow()
+*/
+
+bool Q3DockArea::isDockWindowAccepted(Q3DockWindow *dw)
+{
+ if (!dw)
+ return false;
+ if (forbiddenWidgets.contains(dw))
+ return false;
+
+ Q3MainWindow *mw = qobject_cast<Q3MainWindow*>(parentWidget());
+ if (!mw)
+ return true;
+ if (!mw->hasDockWindow(dw))
+ return false;
+ if (!mw->isDockEnabled(this))
+ return false;
+ if (!mw->isDockEnabled(dw, this))
+ return false;
+ return true;
+}
+
+/*!
+ If \a accept is true, dock window \a dw can be docked in the dock
+ area. If \a accept is false, dock window \a dw cannot be docked in
+ the dock area.
+
+ \sa isDockWindowAccepted()
+*/
+
+void Q3DockArea::setAcceptDockWindow(Q3DockWindow *dw, bool accept)
+{
+ if (accept)
+ forbiddenWidgets.removeAll(dw);
+ else if (forbiddenWidgets.contains(dw))
+ forbiddenWidgets.append(dw);
+}
+
+void Q3DockArea::invalidateFixedSizes()
+{
+ for (int i = 0; i < dockWindows.size(); ++i) {
+ Q3DockWindow *dw = dockWindows.at(i);
+ if (orientation() == Qt::Horizontal)
+ dw->setFixedExtentWidth(-1);
+ else
+ dw->setFixedExtentHeight(-1);
+ }
+}
+
+int Q3DockArea::maxSpace(int hint, Q3DockWindow *dw)
+{
+ int index = findDockWindow(dw);
+ if (index == -1 || index + 1 >= (int)dockWindows.count()) {
+ if (orientation() == Qt::Horizontal)
+ return dw->width();
+ return dw->height();
+ }
+
+ Q3DockWindow *w = 0;
+ int i = 0;
+ do {
+ w = dockWindows.at(index + (++i));
+ } while (i + 1 < (int)dockWindows.count() && (!w || w->isHidden()));
+ if (!w || !w->isResizeEnabled() || i >= (int)dockWindows.count()) {
+ if (orientation() == Qt::Horizontal)
+ return dw->width();
+ return dw->height();
+ }
+ int min = 0;
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(w);
+ if (orientation() == Qt::Horizontal) {
+ w->setFixedExtentWidth(-1);
+ if (!tb)
+ min = qMax(w->minimumSize().width(), w->minimumSizeHint().width());
+ else
+ min = w->sizeHint().width();
+ } else {
+ w->setFixedExtentHeight(-1);
+ if (!tb)
+ min = qMax(w->minimumSize().height(), w->minimumSizeHint().height());
+ else
+ min = w->sizeHint().height();
+ }
+
+ int diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height());
+
+ if ((orientation() == Qt::Horizontal ? w->width() : w->height()) - diff < min)
+ hint = (orientation() == Qt::Horizontal ? dw->width() : dw->height()) + (orientation() == Qt::Horizontal ? w->width() : w->height()) - min;
+
+ diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height());
+ if (orientation() == Qt::Horizontal)
+ w->setFixedExtentWidth(w->width() - diff);
+ else
+ w->setFixedExtentHeight(w->height() - diff);
+ return hint;
+}
+
+void Q3DockArea::setFixedExtent(int d, Q3DockWindow *dw)
+{
+ QList<Q3DockWindow *> lst;
+ for (int i = 0; i < dockWindows.size(); ++i) {
+ Q3DockWindow *w = dockWindows.at(i);
+ if (w->isHidden())
+ continue;
+ if (orientation() == Qt::Horizontal) {
+ if (dw->y() != w->y())
+ continue;
+ } else {
+ if (dw->x() != w->x())
+ continue;
+ }
+ if (orientation() == Qt::Horizontal)
+ d = qMax(d, w->minimumHeight());
+ else
+ d = qMax(d, w->minimumWidth());
+ if (w->isResizeEnabled())
+ lst.append(w);
+ }
+ for (int i = 0; i < lst.size(); ++i) {
+ Q3DockWindow *w = lst.at(i);
+ if (orientation() == Qt::Horizontal)
+ w->setFixedExtentHeight(d);
+ else
+ w->setFixedExtentWidth(d);
+ }
+}
+
+bool Q3DockArea::isLastDockWindow(Q3DockWindow *dw)
+{
+ int i = dockWindows.indexOf(dw);
+ if (i == -1 || i >= (int)dockWindows.count() - 1)
+ return true;
+ Q3DockWindow *w = 0;
+ if ((w = dockWindows.at(++i))) {
+ if (orientation() == Qt::Horizontal && dw->y() < w->y())
+ return true;
+ if (orientation() == Qt::Vertical && dw->x() < w->x())
+ return true;
+ } else {
+ return true;
+ }
+ return false;
+}
+
+#ifndef QT_NO_TEXTSTREAM
+
+/*!
+ \relates Q3DockArea
+
+ Writes the layout of the dock windows in dock area \a dockArea to
+ the text stream \a ts.
+*/
+
+QTextStream &operator<<(QTextStream &ts, const Q3DockArea &dockArea)
+{
+ QString str;
+ QList<Q3DockWindow *> l = dockArea.dockWindowList();
+
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ str += QLatin1Char('[') + QString(dw->windowTitle()) + QLatin1Char(',') + QString::number((int)dw->offset()) +
+ QLatin1Char(',') + QString::number((int)dw->newLine()) + QLatin1Char(',') + QString::number(dw->fixedExtent().width()) +
+ QLatin1Char(',') + QString::number(dw->fixedExtent().height()) + QLatin1Char(',') + QString::number((int)!dw->isHidden()) + QLatin1Char(']');
+ }
+ ts << str << endl;
+
+ return ts;
+}
+
+/*!
+ \relates Q3DockArea
+
+ Reads the layout description of the dock windows in dock area \a
+ dockArea from the text stream \a ts and restores it. The layout
+ description must have been previously written by the operator<<()
+ function.
+*/
+
+QTextStream &operator>>(QTextStream &ts, Q3DockArea &dockArea)
+{
+ QString s = ts.readLine();
+
+ QString name, offset, newLine, width, height, visible;
+
+ enum State { Pre, Name, Offset, NewLine, Width, Height, Visible, Post };
+ int state = Pre;
+ QChar c;
+ QList<Q3DockWindow *> l = dockArea.dockWindowList();
+
+ for (int i = 0; i < s.length(); ++i) {
+ c = s[i];
+ if (state == Pre && c == QLatin1Char('[')) {
+ state++;
+ continue;
+ }
+ if (c == QLatin1Char(',') &&
+ (state == Name || state == Offset || state == NewLine || state == Width || state == Height)) {
+ state++;
+ continue;
+ }
+ if (state == Visible && c == QLatin1Char(']')) {
+ for (int j = 0; j < l.size(); ++j) {
+ Q3DockWindow *dw = l.at(j);
+ if (QString(dw->windowTitle()) == name) {
+ dw->setNewLine((bool)newLine.toInt());
+ dw->setOffset(offset.toInt());
+ dw->setFixedExtentWidth(width.toInt());
+ dw->setFixedExtentHeight(height.toInt());
+ if (!(bool)visible.toInt())
+ dw->hide();
+ else
+ dw->show();
+ break;
+ }
+ }
+
+ name = offset = newLine = width = height = visible = QLatin1String("");
+
+ state = Pre;
+ continue;
+ }
+ if (state == Name)
+ name += c;
+ else if (state == Offset)
+ offset += c;
+ else if (state == NewLine)
+ newLine += c;
+ else if (state == Width)
+ width += c;
+ else if (state == Height)
+ height += c;
+ else if (state == Visible)
+ visible += c;
+ }
+
+ dockArea.QWidget::layout()->invalidate();
+ dockArea.QWidget::layout()->activate();
+ return ts;
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_MAINWINDOW
diff --git a/src/qt3support/widgets/q3dockarea.h b/src/qt3support/widgets/q3dockarea.h
new file mode 100644
index 0000000..20aba63
--- /dev/null
+++ b/src/qt3support/widgets/q3dockarea.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3DOCKAREA_H
+#define Q3DOCKAREA_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qlist.h>
+#include <Qt3Support/q3dockwindow.h>
+#include <QtGui/qlayout.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_MAINWINDOW
+
+class QBoxLayout;
+class Q3DockAreaLayout;
+class QMouseEvent;
+class Q3DockWindowResizeHandle;
+class Q3DockAreaPrivate;
+class QTextStream;
+
+class Q_COMPAT_EXPORT Q3DockAreaLayout : public QLayout
+{
+ Q_OBJECT
+ friend class Q3DockArea;
+
+public:
+ Q3DockAreaLayout(QWidget* parent, Qt::Orientation o, QList<Q3DockWindow *> *wl, int space = -1, int margin = -1, const char *name = 0)
+ : QLayout(parent), orient(o), dirty(true), dockWindows(wl), parentWidget(parent)
+ {
+ if (space != -1)
+ setSpacing(space);
+ if (margin != -1)
+ setMargin(margin);
+ setObjectName(QString::fromAscii(name));
+ init();
+ }
+ ~Q3DockAreaLayout() {}
+
+ void addItem(QLayoutItem *) {}
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int widthForHeight(int) const;
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QLayoutItem *itemAt(int) const;
+ QLayoutItem *takeAt(int);
+ int count() const;
+ Qt::Orientations expandingDirections() const { return Qt::Orientations(0); }
+ void invalidate();
+ Qt::Orientation orientation() const { return orient; }
+ QList<QRect> lineList() const { return lines; }
+ QList<Q3DockWindow *> lineStarts() const { return ls; }
+
+protected:
+ void setGeometry(const QRect&);
+
+private:
+ Q_DISABLE_COPY(Q3DockAreaLayout)
+
+ void init();
+ int layoutItems(const QRect&, bool testonly = false);
+ Qt::Orientation orient;
+ bool dirty;
+ int cached_width, cached_height;
+ int cached_hfw, cached_wfh;
+ QList<Q3DockWindow *> *dockWindows;
+ QWidget *parentWidget;
+ QList<QRect> lines;
+ QList<Q3DockWindow *> ls;
+};
+
+class Q_COMPAT_EXPORT Q3DockArea : public QWidget
+{
+ Q_OBJECT
+ Q_ENUMS(HandlePosition)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(bool empty READ isEmpty)
+ Q_PROPERTY(HandlePosition handlePosition READ handlePosition)
+
+ friend class Q3DockWindow;
+ friend class Q3DockWindowResizeHandle;
+ friend class Q3DockAreaLayout;
+
+public:
+ enum HandlePosition { Normal, Reverse };
+
+ Q3DockArea(Qt::Orientation o, HandlePosition h = Normal, QWidget* parent=0, const char* name=0);
+ ~Q3DockArea();
+
+ void moveDockWindow(Q3DockWindow *w, const QPoint &globalPos, const QRect &rect, bool swap);
+ void removeDockWindow(Q3DockWindow *w, bool makeFloating, bool swap, bool fixNewLines = true);
+ void moveDockWindow(Q3DockWindow *w, int index = -1);
+ bool hasDockWindow(Q3DockWindow *w, int *index = 0);
+
+ void invalidNextOffset(Q3DockWindow *dw);
+
+ Qt::Orientation orientation() const { return orient; }
+ HandlePosition handlePosition() const { return hPos; }
+
+ bool eventFilter(QObject *, QEvent *);
+ bool isEmpty() const;
+ int count() const;
+ QList<Q3DockWindow *> dockWindowList() const;
+
+ bool isDockWindowAccepted(Q3DockWindow *dw);
+ void setAcceptDockWindow(Q3DockWindow *dw, bool accept);
+
+public Q_SLOTS:
+ void lineUp(bool keepNewLines);
+
+private:
+ struct DockWindowData
+ {
+ int index;
+ int offset;
+ int line;
+ QSize fixedExtent;
+ QPointer<Q3DockArea> area;
+ };
+
+ int findDockWindow(Q3DockWindow *w);
+ int lineOf(int index);
+ DockWindowData *dockWindowData(Q3DockWindow *w);
+ void dockWindow(Q3DockWindow *dockWindow, DockWindowData *data);
+ void updateLayout();
+ void invalidateFixedSizes();
+ int maxSpace(int hint, Q3DockWindow *dw);
+ void setFixedExtent(int d, Q3DockWindow *dw);
+ bool isLastDockWindow(Q3DockWindow *dw);
+
+private:
+ Q_DISABLE_COPY(Q3DockArea)
+
+ Qt::Orientation orient;
+ QList<Q3DockWindow *> dockWindows;
+ Q3DockAreaLayout *layout;
+ HandlePosition hPos;
+ QList<Q3DockWindow *> forbiddenWidgets;
+ Q3DockAreaPrivate *d;
+};
+
+#ifndef QT_NO_TEXTSTREAM
+Q_COMPAT_EXPORT QTextStream &operator<<(QTextStream &, const Q3DockArea &);
+Q_COMPAT_EXPORT QTextStream &operator>>(QTextStream &, Q3DockArea &);
+#endif
+
+#endif // QT_NO_MAINWINDOW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3DOCKAREA_H
diff --git a/src/qt3support/widgets/q3dockwindow.cpp b/src/qt3support/widgets/q3dockwindow.cpp
new file mode 100644
index 0000000..7bb2275
--- /dev/null
+++ b/src/qt3support/widgets/q3dockwindow.cpp
@@ -0,0 +1,2115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3dockwindow.h"
+
+#ifndef QT_NO_MAINWINDOW
+#include "qapplication.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "q3dockarea.h"
+#include "qevent.h"
+#include "qlayout.h"
+#include "q3mainwindow.h"
+#include "qpainter.h"
+#include "qpointer.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+#include "q3toolbar.h"
+#include "qtoolbutton.h"
+#include "qtooltip.h"
+#include <private/q3titlebar_p.h>
+#include <private/qwidgetresizehandler_p.h>
+#include <qrubberband.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_MAC
+static bool default_opaque = true;
+#else
+static bool default_opaque = false;
+#endif
+
+class Q3DockWindowPrivate
+{
+};
+
+class Q3DockWindowResizeHandle : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent, Q3DockWindow *w, const char* /*name*/=0);
+ void setOrientation(Qt::Orientation o);
+ Qt::Orientation orientation() const { return orient; }
+
+ QSize sizeHint() const;
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ bool event(QEvent *event);
+
+private:
+ void startLineDraw();
+ void endLineDraw();
+ void drawLine(const QPoint &globalPos);
+
+private:
+ Qt::Orientation orient;
+ bool mousePressed;
+ QRubberBand *rubberBand;
+ QPoint lastPos, firstPos;
+ Q3DockWindow *dockWindow;
+ bool mouseOver;
+};
+
+Q3DockWindowResizeHandle::Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent,
+ Q3DockWindow *w, const char *)
+ : QWidget(parent, "qt_dockwidget_internal"), mousePressed(false), rubberBand(0), dockWindow(w),
+ mouseOver(false)
+{
+ setOrientation(o);
+}
+
+QSize Q3DockWindowResizeHandle::sizeHint() const
+{
+ QStyleOptionQ3DockWindow opt;
+ opt.init(this);
+ if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal)
+ opt.state |= QStyle::State_Horizontal;
+
+ opt.rect = rect();
+ opt.docked = dockWindow->area();
+ opt.closeEnabled = dockWindow->isCloseEnabled();
+ int sw = 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, &opt, this) / 3;
+ return (style()->sizeFromContents(QStyle::CT_Q3DockWindow, &opt, QSize(sw, sw), this).expandedTo(QApplication::globalStrut()));
+}
+
+void Q3DockWindowResizeHandle::setOrientation(Qt::Orientation o)
+{
+ orient = o;
+ if (o == Qt::Horizontal) {
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::splitVCursor);
+#endif
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ } else {
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::splitHCursor);
+#endif
+ setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
+ }
+}
+
+void Q3DockWindowResizeHandle::mousePressEvent(QMouseEvent *e)
+{
+ e->ignore();
+ if (e->button() != Qt::LeftButton)
+ return;
+ e->accept();
+ mousePressed = true;
+ if (!dockWindow->opaqueMoving())
+ startLineDraw();
+ lastPos = firstPos = e->globalPos();
+ if (!dockWindow->opaqueMoving())
+ drawLine(e->globalPos());
+}
+
+void Q3DockWindowResizeHandle::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!mousePressed)
+ return;
+ if (!dockWindow->opaqueMoving()) {
+ if (orientation() != dockWindow->area()->orientation()) {
+ if (orientation() == Qt::Horizontal) {
+ int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y();
+ int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y() + dockWindow->area()->height();
+ if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos)
+ return;
+ } else {
+ int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x();
+ int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x() + dockWindow->area()->width();
+ if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos)
+ return;
+ }
+ } else {
+ QWidget *w = dockWindow->area()->window();
+ if (w) {
+ if (orientation() == Qt::Horizontal) {
+ int minpos = w->mapToGlobal(QPoint(0, 0)).y();
+ int maxpos = w->mapToGlobal(QPoint(0, 0)).y() + w->height();
+ if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos)
+ return;
+ } else {
+ int minpos = w->mapToGlobal(QPoint(0, 0)).x();
+ int maxpos = w->mapToGlobal(QPoint(0, 0)).x() + w->width();
+ if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos)
+ return;
+ }
+ }
+ }
+ }
+
+ if (!dockWindow->opaqueMoving())
+ drawLine(lastPos);
+ lastPos = e->globalPos();
+ if (dockWindow->opaqueMoving()) {
+ mouseReleaseEvent(e);
+ mousePressed = true;
+ firstPos = e->globalPos();
+ }
+ if (!dockWindow->opaqueMoving())
+ drawLine(e->globalPos());
+}
+
+void Q3DockWindowResizeHandle::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (mousePressed) {
+ if (!dockWindow->opaqueMoving()) {
+ drawLine(lastPos);
+ endLineDraw();
+ }
+ if (orientation() != dockWindow->area()->orientation())
+ dockWindow->area()->invalidNextOffset(dockWindow);
+ if (orientation() == Qt::Horizontal) {
+ int dy;
+ if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation())
+ dy = e->globalPos().y() - firstPos.y();
+ else
+ dy = firstPos.y() - e->globalPos().y();
+ int d = dockWindow->height() + dy;
+ if (orientation() != dockWindow->area()->orientation()) {
+ dockWindow->setFixedExtentHeight(-1);
+ d = qMax(d, dockWindow->minimumHeight());
+ int ms = dockWindow->area()->maxSpace(d, dockWindow);
+ d = qMin(d, ms);
+ dockWindow->setFixedExtentHeight(d);
+ } else {
+ dockWindow->area()->setFixedExtent(d, dockWindow);
+ }
+ } else {
+ int dx;
+ if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation())
+ dx = e->globalPos().x() - firstPos.x();
+ else
+ dx = firstPos.x() - e->globalPos().x();
+ int d = dockWindow->width() + dx;
+ if (orientation() != dockWindow->area()->orientation()) {
+ dockWindow->setFixedExtentWidth(-1);
+ d = qMax(d, dockWindow->minimumWidth());
+ int ms = dockWindow->area()->maxSpace(d, dockWindow);
+ d = qMin(d, ms);
+ dockWindow->setFixedExtentWidth(d);
+ } else {
+ dockWindow->area()->setFixedExtent(d, dockWindow);
+ }
+ }
+ }
+
+ QApplication::postEvent(dockWindow->area(), new QEvent(QEvent::LayoutHint));
+ mousePressed = false;
+}
+
+bool Q3DockWindowResizeHandle::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::HoverEnter:
+ if (!mouseOver) {
+ mouseOver = true;
+ update();
+ }
+ break;
+ case QEvent::HoverLeave:
+ if (mouseOver) {
+ mouseOver = false;
+ update();
+ }
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+}
+
+void Q3DockWindowResizeHandle::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ QStyleOption opt(0);
+ opt.init(this);
+ if (orientation() == Qt::Horizontal)
+ opt.state |= QStyle::State_Horizontal;
+ style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, &p, this);
+}
+
+void Q3DockWindowResizeHandle::startLineDraw()
+{
+ if (rubberBand)
+ endLineDraw();
+ rubberBand = new QRubberBand(QRubberBand::Line);
+ rubberBand->setGeometry(-1, -1, 1, 1);
+ rubberBand->show();
+}
+
+void Q3DockWindowResizeHandle::endLineDraw()
+{
+ delete rubberBand;
+ rubberBand = 0;
+}
+
+void Q3DockWindowResizeHandle::drawLine(const QPoint &globalPos)
+{
+ QPoint start = mapToGlobal(QPoint(0, 0));
+ QPoint starta = dockWindow->area()->mapToGlobal(QPoint(0, 0));
+ QPoint end = globalPos;
+ if (orientation() == Qt::Horizontal) {
+ if (orientation() == dockWindow->orientation())
+ rubberBand->setGeometry(starta.x(), end.y(), dockWindow->area()->width(), height());
+ else
+ rubberBand->setGeometry(start.x(), end.y(), width(), height());
+ } else {
+ if (orientation() == dockWindow->orientation())
+ rubberBand->setGeometry(end.x(), starta.y(), width(), dockWindow->area()->height());
+ else
+ rubberBand->setGeometry(end.x(), start.y(), width(), height());
+ }
+}
+
+static QPoint realWidgetPos(Q3DockWindow *w)
+{
+ if (!w->parentWidget() || w->place() == Q3DockWindow::OutsideDock)
+ return w->pos();
+ return w->parentWidget()->mapToGlobal(w->geometry().topLeft());
+}
+
+class Q3DockWindowHandle : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString windowTitle READ windowTitle)
+ friend class Q3DockWindow;
+ friend class Q3DockWindowTitleBar;
+
+public:
+ Q3DockWindowHandle(Q3DockWindow *dw);
+ void updateGui();
+
+ QSize minimumSizeHint() const;
+ QSize minimumSize() const { return minimumSizeHint(); }
+ QSize sizeHint() const { return minimumSize(); }
+ void setOpaqueMoving(bool b) { opaque = b; }
+
+ QString windowTitle() const { return dockWindow->windowTitle(); }
+
+signals:
+ void doubleClicked();
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void resizeEvent(QResizeEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+ void changeEvent(QEvent *);
+
+private slots:
+ void minimize();
+
+private:
+ Q3DockWindow *dockWindow;
+ QPoint offset;
+ QToolButton *closeButton;
+ QTimer *timer;
+ uint opaque : 1;
+ uint mousePressed : 1;
+ uint hadDblClick : 1;
+ uint ctrlDown : 1;
+ QPointer<QWidget> oldFocus;
+};
+
+class Q3DockWindowTitleBar : public Q3TitleBar
+{
+ Q_OBJECT
+ friend class Q3DockWindow;
+ friend class Q3DockWindowHandle;
+
+public:
+ Q3DockWindowTitleBar(Q3DockWindow *dw);
+ void updateGui();
+ void setOpaqueMoving(bool b) { opaque = b; }
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+
+private:
+ Q3DockWindow *dockWindow;
+ QPoint offset;
+ uint mousePressed : 1;
+ uint hadDblClick : 1;
+ uint opaque : 1;
+ uint ctrlDown : 1;
+ QPointer<QWidget> oldFocus;
+
+};
+
+Q3DockWindowHandle::Q3DockWindowHandle(Q3DockWindow *dw)
+ : QWidget(dw, "qt_dockwidget_internal"), dockWindow(dw),
+ closeButton(0), opaque(default_opaque), mousePressed(false)
+{
+ ctrlDown = false;
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(minimize()));
+#ifdef Q_WS_WIN
+ setCursor(Qt::SizeAllCursor);
+#endif
+}
+
+void Q3DockWindowHandle::paintEvent(QPaintEvent *e)
+{
+ if (!dockWindow->dockArea && !opaque)
+ return;
+ QPainter p(this);
+ QStyleOptionQ3DockWindow opt;
+ opt.init(this);
+ if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal)
+ opt.state |= QStyle::State_Horizontal;
+
+ opt.rect = rect();
+ opt.docked = dockWindow->area();
+ opt.closeEnabled = dockWindow->isCloseEnabled();
+ opt.rect = QStyle::visualRect(opt.direction, opt.rect,
+ style()->subElementRect(QStyle::SE_Q3DockWindowHandleRect, &opt, this));
+ style()->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
+ QWidget::paintEvent(e);
+}
+
+void Q3DockWindowHandle::keyPressEvent(QKeyEvent *e)
+{
+ if (!mousePressed)
+ return;
+ if (e->key() == Qt::Key_Control) {
+ ctrlDown = true;
+ dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
+ }
+}
+
+void Q3DockWindowHandle::keyReleaseEvent(QKeyEvent *e)
+{
+ if (!mousePressed)
+ return;
+ if (e->key() == Qt::Key_Control) {
+ ctrlDown = false;
+ dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
+ }
+}
+
+void Q3DockWindowHandle::mousePressEvent(QMouseEvent *e)
+{
+ if (!dockWindow->dockArea)
+ return;
+ ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
+ oldFocus = qApp->focusWidget();
+ setFocus();
+ e->ignore();
+ if (e->button() != Qt::LeftButton)
+ return;
+ e->accept();
+ hadDblClick = false;
+ mousePressed = true;
+ offset = e->pos();
+ dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque);
+ if (!opaque)
+ qApp->installEventFilter(dockWindow);
+}
+
+void Q3DockWindowHandle::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!mousePressed || e->pos() == offset)
+ return;
+ ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
+ dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque);
+ if (opaque)
+ dockWindow->updatePosition(e->globalPos());
+}
+
+void Q3DockWindowHandle::mouseReleaseEvent(QMouseEvent *e)
+{
+ ctrlDown = false;
+ qApp->removeEventFilter(dockWindow);
+ if (oldFocus)
+ oldFocus->setFocus();
+ if (!mousePressed)
+ return;
+ dockWindow->endRectDraw(!opaque);
+ mousePressed = false;
+#ifdef Q_WS_MAC
+ releaseMouse();
+#endif
+ if (!hadDblClick && offset == e->pos()) {
+ timer->start(QApplication::doubleClickInterval(), true);
+ } else if (!hadDblClick) {
+ dockWindow->updatePosition(e->globalPos());
+ }
+ if (opaque)
+ dockWindow->titleBar->mousePressed = false;
+ if (dockWindow->parentWidget())
+ QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
+}
+
+void Q3DockWindowHandle::minimize()
+{
+ if (!dockWindow->area())
+ return;
+
+ Q3MainWindow *mw = qobject_cast<Q3MainWindow*>(dockWindow->area()->parentWidget());
+ if (mw && mw->isDockEnabled(dockWindow, Qt::DockMinimized))
+ mw->moveDockWindow(dockWindow, Qt::DockMinimized);
+}
+
+void Q3DockWindowHandle::resizeEvent(QResizeEvent *)
+{
+ updateGui();
+}
+
+void Q3DockWindowHandle::updateGui()
+{
+ updateGeometry();
+
+ if (!closeButton) {
+ closeButton = new QToolButton(this, "qt_close_button1");
+#ifndef QT_NO_CURSOR
+ closeButton->setCursor(Qt::ArrowCursor);
+#endif
+ QStyleOption opt(0);
+ opt.init(closeButton);
+ closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton, &opt,
+ closeButton));
+ closeButton->setFixedSize(12, 12);
+ connect(closeButton, SIGNAL(clicked()),
+ dockWindow, SLOT(hide()));
+ }
+
+ if (dockWindow->isCloseEnabled() && dockWindow->area())
+ closeButton->show();
+ else
+ closeButton->hide();
+
+ if (!dockWindow->area())
+ return;
+
+ if (dockWindow->area()->orientation() == Qt::Horizontal) {
+ int off = (width() - closeButton->width() - 1) / 2;
+ closeButton->move(off, 2);
+ } else {
+ int off = (height() - closeButton->height() - 1) / 2;
+ int x = QApplication::reverseLayout() ? 2 : width() - closeButton->width() - 2;
+ closeButton->move(x, off);
+ }
+}
+
+void Q3DockWindowHandle::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::StyleChange) {
+ if (closeButton) {
+ QStyleOption opt(0);
+ opt.init(closeButton);
+ closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton,
+ &opt, closeButton));
+ }
+ }
+ QWidget::changeEvent(ev);
+}
+
+QSize Q3DockWindowHandle::minimumSizeHint() const
+{
+ if (!dockWindow->dockArea)
+ return QSize(0, 0);
+ int wh = dockWindow->isCloseEnabled() ? 17 : style()->pixelMetric(QStyle::PM_ToolBarHandleExtent, 0, this);
+ if (dockWindow->orientation() == Qt::Horizontal)
+ return QSize(wh, 0);
+ return QSize(0, wh);
+}
+
+void Q3DockWindowHandle::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ e->ignore();
+ if (e->button() != Qt::LeftButton)
+ return;
+ e->accept();
+ timer->stop();
+ emit doubleClicked();
+ hadDblClick = true;
+ if (dockWindow->parentWidget())
+ QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
+}
+
+Q3DockWindowTitleBar::Q3DockWindowTitleBar(Q3DockWindow *dw)
+ : Q3TitleBar(0, dw), dockWindow(dw),
+ mousePressed(false), hadDblClick(false), opaque(default_opaque)
+{
+ setObjectName(QLatin1String("qt_dockwidget_internal"));
+ ctrlDown = false;
+ setMouseTracking(true);
+ QStyleOptionTitleBar opt = getStyleOption();
+ setFixedHeight(style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
+ connect(this, SIGNAL(doClose()), dockWindow, SLOT(hide()));
+}
+
+void Q3DockWindowTitleBar::keyPressEvent(QKeyEvent *e)
+{
+ if (!mousePressed)
+ return;
+ if (e->key() == Qt::Key_Control) {
+ ctrlDown = true;
+ dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
+ }
+}
+
+void Q3DockWindowTitleBar::keyReleaseEvent(QKeyEvent *e)
+{
+ if (!mousePressed)
+ return;
+ if (e->key() == Qt::Key_Control) {
+ ctrlDown = false;
+ dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
+ }
+}
+
+void Q3DockWindowTitleBar::mousePressEvent(QMouseEvent *e)
+{
+ QStyleOptionTitleBar opt;
+ opt.init(this);
+ opt.subControls = QStyle::SC_All;
+ opt.activeSubControls = QStyle::SC_None;
+ opt.text = windowTitle();
+ //################
+ QIcon icon = windowIcon();
+ QSize s = icon.actualSize(QSize(64, 64));
+ opt.icon = icon.pixmap(s);
+ opt.titleBarState = window() ? window()->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
+ opt.titleBarFlags = fakeWindowFlags();
+ QStyle::SubControl tbctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
+ e->pos(), this);
+
+ if (tbctrl < QStyle::SC_TitleBarLabel && tbctrl != QStyle::SC_None) {
+ Q3TitleBar::mousePressEvent(e);
+ return;
+ }
+
+ ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
+ oldFocus = qApp->focusWidget();
+// setFocus activates the window, which deactivates the main window
+// not what we want, and not required anyway on Windows
+#ifndef Q_WS_WIN
+ setFocus();
+#endif
+
+ e->ignore();
+ if (e->button() != Qt::LeftButton)
+ return;
+ if (e->y() < 3 && dockWindow->isResizeEnabled())
+ return;
+
+ e->accept();
+ bool oldPressed = mousePressed;
+ mousePressed = true;
+ hadDblClick = false;
+ offset = e->pos();
+ dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque);
+// grabMouse resets the Windows mouse press count, so we never receive a double click on Windows
+// not required on Windows, and did work on X11, too, but no problem there in the first place
+#ifndef Q_WS_WIN
+ if(!oldPressed && dockWindow->opaqueMoving())
+ grabMouse();
+#else
+ Q_UNUSED(oldPressed);
+#endif
+}
+
+void Q3DockWindowTitleBar::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!mousePressed) {
+ Q3TitleBar::mouseMoveEvent(e);
+ return;
+ }
+
+ ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
+ e->accept();
+ dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque);
+}
+
+void Q3DockWindowTitleBar::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (!mousePressed) {
+ Q3TitleBar::mouseReleaseEvent(e);
+ return;
+ }
+
+ ctrlDown = false;
+ qApp->removeEventFilter(dockWindow);
+ if (oldFocus)
+ oldFocus->setFocus();
+
+ if (dockWindow->place() == Q3DockWindow::OutsideDock)
+ dockWindow->raise();
+
+ if(dockWindow->opaqueMoving())
+ releaseMouse();
+ if (!mousePressed)
+ return;
+ dockWindow->endRectDraw(!opaque);
+ mousePressed = false;
+ if (!hadDblClick)
+ dockWindow->updatePosition(e->globalPos());
+ if (opaque) {
+ dockWindow->horHandle->mousePressed = false;
+ dockWindow->verHandle->mousePressed = false;
+ }
+ if (dockWindow->parentWidget())
+ QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
+}
+
+void Q3DockWindowTitleBar::resizeEvent(QResizeEvent *e)
+{
+ updateGui();
+ Q3TitleBar::resizeEvent(e);
+}
+
+void Q3DockWindowTitleBar::updateGui()
+{
+ if (dockWindow->isCloseEnabled()) {
+ setFakeWindowFlags(fakeWindowFlags() | Qt::WStyle_SysMenu);
+ } else {
+ setFakeWindowFlags(fakeWindowFlags() & ~Qt::WStyle_SysMenu);
+ }
+}
+
+void Q3DockWindowTitleBar::mouseDoubleClickEvent(QMouseEvent *)
+{
+ emit doubleClicked();
+ hadDblClick = true;
+ if (dockWindow->parentWidget())
+ QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
+}
+
+/*!
+ \class Q3DockWindow
+ \brief The Q3DockWindow class provides a widget which can be docked
+ inside a Q3DockArea or floated as a top level window on the
+ desktop.
+
+ \compat
+
+ This class handles moving, resizing, docking and undocking dock
+ windows. Q3ToolBar is a subclass of Q3DockWindow so the
+ functionality provided for dock windows is available with the same
+ API for toolbars.
+
+ \img qmainwindow-qdockareas.png Q3DockWindows in a Q3DockArea
+ \caption Two Q3DockWindows (\l{Q3ToolBar}s) in a \l Q3DockArea
+
+ \img qdockwindow.png A Q3DockWindow
+ \caption A Floating Q3DockWindow
+
+ If the user drags the dock window into the dock area the dock
+ window will be docked. If the user drags the dock area outside any
+ dock areas the dock window will be undocked (floated) and will
+ become a top level window. Double clicking a floating dock
+ window's title bar will dock the dock window to the last dock area
+ it was docked in. Double clicking a docked dock window's handle
+ will undock (float) the dock window.
+ \omit
+ Single clicking a docked dock window's handle will minimize the
+ dock window (only its handle will appear, below the menu bar).
+ Single clicking the minimized handle will restore the dock window
+ to the last dock area that it was docked in.
+ \endomit
+ If the user clicks the close button (which appears on floating
+ dock windows by default) the dock window will disappear. You can
+ control whether or not a dock window has a close button with
+ setCloseMode().
+
+ Q3MainWindow provides four dock areas (top, left, right and bottom)
+ which can be used by dock windows. For many applications using the
+ dock areas provided by Q3MainWindow is sufficient. (See the \l
+ Q3DockArea documentation if you want to create your own dock
+ areas.) In Q3MainWindow a right-click popup menu (the dock window
+ menu) is available which lists dock windows and can be used to
+ show or hide them. (The popup menu only lists dock windows that
+ have a \link QWidget::setWindowTitle() caption\endlink.)
+
+ When you construct a dock window you \e must pass it a Q3DockArea
+ or a Q3MainWindow as its parent if you want it docked. Pass 0 for
+ the parent if you want it floated.
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockwindow.cpp 0
+
+ In the example above we create a new Q3ToolBar in the constructor
+ of a Q3MainWindow subclass (so that the \e this pointer points to
+ the Q3MainWindow). By default the toolbar will be added to the \c
+ Top dock area, but we've moved it to the \c Left dock area.
+
+ A dock window is often used to contain a single widget. In these
+ cases the widget can be set by calling setWidget(). If you're
+ constructing a dock window that contains multiple widgets, e.g. a
+ toolbar, arrange the widgets within a box layout inside the dock
+ window. To do this use the boxLayout() function to get a pointer
+ to the dock window's box layout, then add widgets to the layout
+ using the box layout's QBoxLayout::addWidget() function. The dock
+ window will dynamically set the orientation of the layout to be
+ vertical or horizontal as necessary, although you can control this
+ yourself with setOrientation().
+
+ Although a common use of dock windows is for toolbars, they can be
+ used with any widgets. When using larger
+ widgets it may make sense for the dock window to be resizable by
+ calling setResizeEnabled(). Resizable dock windows are given
+ splitter-like handles to allow the user to resize them within
+ their dock area. When resizable dock windows are undocked they
+ become top level windows and can be resized like any other top
+ level windows, e.g. by dragging a corner or edge.
+
+ Qt::Dock windows can be docked and undocked using dock() and undock().
+ A dock window's orientation can be set with setOrientation(). You
+ can also use Q3DockArea::moveDockWindow(). If you're using a
+ Q3MainWindow, Q3MainWindow::moveDockWindow() and
+ Q3MainWindow::removeDockWindow() are available.
+
+ A dock window can have some preferred settings, for example, you
+ can set a preferred offset from the left edge (or top edge for
+ vertical dock areas) of the dock area using setOffset(). If you'd
+ prefer a dock window to start on a new line when it is docked use
+ setNewLine(). The setFixedExtentWidth() and setFixedExtentHeight()
+ functions can be used to define the dock window's preferred size,
+ and the setHorizontallyStretchable() and setVerticallyStretchable()
+ functions set whether the dock window can be stretched or not.
+ Dock windows can be moved by default, but this can be changed with
+ setMovingEnabled(). When a dock window is moved it is shown as a
+ rectangular outline, but it can be shown normally using
+ setOpaqueMoving().
+
+ When a dock window's visibility changes, i.e. it is shown or
+ hidden, the visibilityChanged() signal is emitted. When a dock
+ window is docked, undocked or moved inside the dock area the
+ placeChanged() signal is emitted.
+*/
+
+/*!
+ \enum Q3DockWindow::Place
+
+ This enum specifies the possible locations for a Q3DockWindow:
+
+ \value InDock Inside a Q3DockArea.
+ \value OutsideDock Floating as a top level window on the desktop.
+*/
+
+/*!
+ \enum Q3DockWindow::CloseMode
+
+ This enum type specifies when (if ever) a dock window has a close
+ button.
+
+ \value Never The dock window never has a close button and cannot
+ be closed by the user.
+ \value Docked The dock window has a close button only when
+ docked.
+ \value Undocked The dock window has a close button only when
+ floating.
+ \value Always The dock window always has a close button.
+ \omit
+ Note that dock windows can always be minimized if the user clicks
+ their dock window handle when they are docked.
+ \endomit
+*/
+
+/*!
+ \fn void Q3DockWindow::setHorizontalStretchable(bool b)
+
+ If \a b is true the dock window is set to be horizontally
+ stretchable.
+*/
+/*!
+ \fn void Q3DockWindow::setVerticalStretchable(bool b)
+
+ If \a b is true the dock window is set to be vertically
+ stretchable.
+*/
+/*!
+ \fn bool Q3DockWindow::isHorizontalStretchable() const
+
+ Returns true if the dock window can be stretched horizontally;
+ otherwise returns false.
+*/
+/*!
+ \fn bool Q3DockWindow::isVerticalStretchable() const
+
+ Returns true if the dock window can be stretched vertically;
+ otherwise returns false.
+*/
+/*!
+ \fn void Q3DockWindow::orientationChanged(Qt::Orientation o)
+
+ This signal is emitted when the orientation of the dock window is
+ changed. The new orientation is \a o.
+*/
+
+/*!
+ \fn void Q3DockWindow::placeChanged(Q3DockWindow::Place p)
+
+ This signal is emitted when the dock window is docked (\a p is \c
+ InDock), undocked (\a p is \c OutsideDock) or moved inside the
+ the dock area.
+
+ \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(),
+ Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow()
+*/
+
+/*!
+ \fn void Q3DockWindow::visibilityChanged(bool visible)
+
+ This signal is emitted when the visibility of the dock window
+ relatively to its dock area is changed. If \a visible is true, the
+ Q3DockWindow is now visible to the dock area, otherwise it has been
+ hidden.
+
+ A dock window can be hidden if it has a close button which the
+ user has clicked. In the case of a Q3MainWindow a dock window can
+ have its visibility changed (hidden or shown) by clicking its name
+ in the dock window menu that lists the Q3MainWindow's dock windows.
+*/
+
+/*!
+ \fn Q3DockArea *Q3DockWindow::area() const
+
+ Returns the dock area in which this dock window is docked, or 0 if
+ the dock window is floating.
+*/
+
+/*!
+ \property Q3DockWindow::place
+ \brief the location where the dock window is placed
+
+ This is either \c InDock or \c OutsideDock.
+
+ \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(),
+ Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow()
+*/
+
+/*!
+ Constructs a Q3DockWindow with parent \a parent, called \a name and
+ with widget flags \a f.
+*/
+
+Q3DockWindow::Q3DockWindow(QWidget* parent, const char* name, Qt::WindowFlags f)
+ : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
+{
+ curPlace = InDock;
+ isToolbar = false;
+ init();
+}
+
+/*!
+ Constructs a Q3DockWindow with parent \a parent, called \a name and
+ with widget flags \a f.
+
+ If \a p is \c InDock, the dock window is docked into a dock area
+ and \a parent \e must be a Q3DockArea or a Q3MainWindow. If the \a
+ parent is a Q3MainWindow the dock window will be docked in the main
+ window's \c Top dock area.
+
+ If \a p is \c OutsideDock, the dock window is created as a floating
+ window.
+
+ We recommend creating the dock area \c InDock with a Q3MainWindow
+ as parent then calling Q3MainWindow::moveDockWindow() to move the
+ dock window where you want it.
+*/
+
+Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f)
+ : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
+{
+ curPlace = p;
+ isToolbar = false;
+ init();
+}
+
+/*! \internal
+*/
+
+Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f, bool toolbar)
+ : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
+{
+ curPlace = p;
+ isToolbar = toolbar;
+ init();
+}
+
+class Q3DockWindowGridLayout : public QGridLayout
+{
+public:
+ Q3DockWindowGridLayout(QWidget *parent, int nRows, int nCols)
+ : QGridLayout(parent, nRows, nCols) {};
+
+ Qt::Orientations expandingDirections() const
+ {
+ return 0;
+ }
+};
+
+void Q3DockWindow::init()
+{
+ wid = 0;
+ rubberBand = 0;
+ dockArea = 0;
+ tmpDockArea = 0;
+ resizeEnabled = false;
+ moveEnabled = true;
+ nl = false;
+ opaque = default_opaque;
+ cMode = Never;
+ offs = 0;
+ fExtent = QSize(-1, -1);
+ dockWindowData = 0;
+ lastPos = QPoint(-1, -1);
+ lastSize = QSize(-1, -1);
+ stretchable[Qt::Horizontal] = false;
+ stretchable[Qt::Vertical] = false;
+
+ widgetResizeHandler = new QWidgetResizeHandler(this);
+ widgetResizeHandler->setMovingEnabled(false);
+
+ titleBar = new Q3DockWindowTitleBar(this);
+ verHandle = new Q3DockWindowHandle(this);
+ verHandle->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
+ horHandle = new Q3DockWindowHandle(this);
+ horHandle->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+
+ vHandleLeft = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle");
+ vHandleRight = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle");
+ hHandleTop = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle");
+ hHandleBottom = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle");
+
+ // Creating inner layout
+ hbox = new QVBoxLayout();
+ vbox = new QHBoxLayout();
+ childBox = new QBoxLayout(QBoxLayout::LeftToRight);
+ vbox->addSpacing(2);
+ vbox->addWidget(verHandle);
+ vbox->addStretch(0);
+ vbox->addLayout(childBox, 1);
+ vbox->addStretch(0);
+
+ hbox->setResizeMode(QLayout::FreeResize);
+ hbox->setMargin(isResizeEnabled() || curPlace == OutsideDock ? 2 : 0);
+ hbox->setSpacing(1);
+ hbox->addWidget(titleBar);
+ hbox->addWidget(horHandle);
+ hbox->addLayout(vbox);
+
+ // Set up the initial handle layout for Qt::Vertical
+ // Handle layout will change on calls to setOrienation()
+ QGridLayout *glayout = new Q3DockWindowGridLayout(this, 3, 3);
+ glayout->setResizeMode(QLayout::Minimum);
+ glayout->addMultiCellWidget(hHandleTop, 0, 0, 1, 1);
+ glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1);
+ glayout->addMultiCellWidget(vHandleLeft, 0, 2, 0, 0);
+ glayout->addMultiCellWidget(vHandleRight, 0, 2, 2, 2);
+ glayout->addLayout(hbox, 1, 1);
+ glayout->setRowStretch(1, 1);
+ glayout->setColStretch(1, 1);
+
+ hHandleBottom->hide();
+ vHandleRight->hide();
+ hHandleTop->hide();
+ vHandleLeft->hide();
+ setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Raised);
+ setLineWidth(2);
+
+ if (parentWidget())
+ parentWidget()->installEventFilter(this);
+ QWidget *mw = parentWidget();
+ Q3DockArea *da = qobject_cast<Q3DockArea*>(parentWidget());
+ if (da) {
+ if (curPlace == InDock)
+ da->moveDockWindow(this);
+ mw = da->parentWidget();
+ }
+ if (qobject_cast<Q3MainWindow*>(mw)) {
+ if (place() == InDock) {
+ Qt::Dock myDock = Qt::DockTop;
+ // make sure we put the window in the correct dock.
+ if (dockArea) {
+ Q3MainWindow *mainw = (Q3MainWindow*)mw;
+ // I'm not checking if it matches the top because I've
+ // done the assignment to it above.
+ if (dockArea == mainw->leftDock())
+ myDock = Qt::DockLeft;
+ else if (dockArea == mainw->rightDock())
+ myDock = Qt::DockRight;
+ else if (dockArea == mainw->bottomDock())
+ myDock = Qt::DockBottom;
+ }
+ ((Q3MainWindow*)mw)->addDockWindow(this, myDock);
+ }
+ moveEnabled = ((Q3MainWindow*)mw)->dockWindowsMovable();
+ opaque = ((Q3MainWindow*)mw)->opaqueMoving();
+ }
+
+ updateGui();
+
+ connect(titleBar, SIGNAL(doubleClicked()), this, SLOT(dock()));
+ connect(verHandle, SIGNAL(doubleClicked()), this, SLOT(undock()));
+ connect(horHandle, SIGNAL(doubleClicked()), this, SLOT(undock()));
+ connect(this, SIGNAL(orientationChanged(Qt::Orientation)),
+ this, SLOT(setOrientation(Qt::Orientation)));
+}
+
+/*!
+ Sets the orientation of the dock window to \a o. The orientation
+ is propagated to the layout boxLayout().
+
+ \warning All undocked Q3ToolBars will always have a horizontal orientation.
+*/
+
+void Q3DockWindow::setOrientation(Qt::Orientation o)
+{
+ QGridLayout *glayout = (QGridLayout*)layout();
+ glayout->removeWidget(hHandleTop);
+ glayout->removeWidget(hHandleBottom);
+ glayout->removeWidget(vHandleLeft);
+ glayout->removeWidget(vHandleRight);
+
+ if (o == Qt::Horizontal) {
+ // Set up the new layout as
+ // 3 3 3 1 = vHandleLeft 4 = hHandleBottom
+ // 1 X 2 2 = vHandleRight X = Inner Layout
+ // 4 4 4 3 = hHandleTop
+ glayout->addMultiCellWidget(hHandleTop, 0, 0, 0, 2);
+ glayout->addMultiCellWidget(hHandleBottom, 2, 2, 0, 2);
+ glayout->addMultiCellWidget(vHandleLeft, 1, 1, 0, 0);
+ glayout->addMultiCellWidget(vHandleRight, 1, 1, 2, 2);
+ } else {
+ // Set up the new layout as
+ // 1 3 2 1 = vHandleLeft 4 = hHandleBottom
+ // 1 X 2 2 = vHandleRight X = Inner Layout
+ // 1 4 2 3 = hHandleTop
+ glayout->addMultiCellWidget(hHandleTop, 0, 0, 1, 1);
+ glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1);
+ glayout->addMultiCellWidget(vHandleLeft, 0, 2, 0, 0);
+ glayout->addMultiCellWidget(vHandleRight, 0, 2, 2, 2);
+ }
+ boxLayout()->setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
+ QApplication::sendPostedEvents(this, QEvent::LayoutHint);
+ QEvent *e = new QEvent(QEvent::LayoutHint);
+ QApplication::postEvent(this, e);
+}
+
+/*!
+ Destroys the dock window and its child widgets.
+*/
+
+Q3DockWindow::~Q3DockWindow()
+{
+ qApp->removeEventFilter(this);
+ if (area())
+ area()->removeDockWindow(this, false, false);
+ Q3DockArea *a = area();
+ if (!a && dockWindowData)
+ a = ((Q3DockArea::DockWindowData*)dockWindowData)->area;
+ Q3MainWindow *mw = a ? qobject_cast<Q3MainWindow*>(a->parentWidget()) : 0;
+ if (mw)
+ mw->removeDockWindow(this);
+
+ delete (Q3DockArea::DockWindowData*)dockWindowData;
+}
+
+/*! \reimp
+*/
+
+void Q3DockWindow::resizeEvent(QResizeEvent *e)
+{
+ Q3Frame::resizeEvent(e);
+ updateGui();
+}
+
+
+void Q3DockWindow::swapRect(QRect &r, Qt::Orientation o, const QPoint &offset, Q3DockArea *)
+{
+ r.setSize(QSize(r.height(), r.width()));
+ bool reverse = QApplication::reverseLayout();
+ if (o == Qt::Horizontal)
+ r.moveBy(-r.width()/2, 0);
+ else
+ r.moveBy(reverse ? - r.width() : 0, -r.height() / 2 );
+ r.moveBy(offset.x(), offset.y());
+}
+
+QWidget *Q3DockWindow::areaAt(const QPoint &gp)
+{
+ QWidget *w = qApp->widgetAt(gp);
+
+ if (w && (w == this || w == titleBar) && parentWidget())
+ w = parentWidget()->childAt(parentWidget()->mapFromGlobal(gp));
+
+ while (w) {
+ if (qobject_cast<Q3DockArea*>(w)) {
+ Q3DockArea *a = (Q3DockArea*)w;
+ if (a->isDockWindowAccepted(this))
+ return w;
+ }
+ if (qobject_cast<Q3MainWindow*>(w)) {
+ Q3MainWindow *mw = (Q3MainWindow*)w;
+ Q3DockArea *a = mw->dockingArea(mw->mapFromGlobal(gp));
+ if (a && a->isDockWindowAccepted(this))
+ return a;
+ }
+ w = w->isWindow() ? 0 : (QWidget *)w->parent();
+ }
+ return 0;
+}
+
+void Q3DockWindow::handleMove(const QPoint &pos, const QPoint &gp, bool drawRect)
+{
+ if (!rubberBand)
+ return;
+
+ currRect = QRect(realWidgetPos(this), size());
+ QWidget *w = areaAt(gp);
+ if (titleBar->ctrlDown || horHandle->ctrlDown || verHandle->ctrlDown)
+ w = 0;
+ currRect.moveBy(pos.x(), pos.y());
+ if (!qobject_cast<Q3DockArea*>(w)) {
+ if (startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this))
+ swapRect(currRect, Qt::Horizontal, startOffset, (Q3DockArea*)w);
+ if (drawRect) {
+ rubberBand->setGeometry(currRect);
+ } else {
+ QPoint mp(mapToGlobal(pos));
+ if(place() == InDock) {
+ undock();
+ if(titleBar) {
+ mp = QPoint(titleBar->width() / 2, titleBar->height() / 2);
+ QMouseEvent me(QEvent::MouseButtonPress, mp, Qt::LeftButton, 0);
+ QApplication::sendEvent(titleBar, &me);
+ mp = titleBar->mapToGlobal(mp);
+ }
+ }
+ move(mp);
+ }
+ state = OutsideDock;
+ return;
+ }
+
+ Q3DockArea *area = (Q3DockArea*)w;
+ if(area->isVisible()) {
+ state = InDock;
+ Qt::Orientation o = (area ? area->orientation() :
+ (boxLayout()->direction() == QBoxLayout::LeftToRight ||
+ boxLayout()->direction() == QBoxLayout::RightToLeft ?
+ Qt::Horizontal : Qt::Vertical));
+ if (startOrientation != o)
+ swapRect(currRect, o, startOffset, area);
+ if (drawRect) {
+ rubberBand->setGeometry(currRect);
+ }
+ tmpDockArea = area;
+ }
+}
+
+void Q3DockWindow::updateGui()
+{
+ if (curPlace == OutsideDock) {
+ hbox->setMargin(2);
+ horHandle->hide();
+ verHandle->hide();
+ if (moveEnabled)
+ titleBar->show();
+ else
+ titleBar->hide();
+ titleBar->updateGui();
+ hHandleTop->hide();
+ vHandleLeft->hide();
+ hHandleBottom->hide();
+ vHandleRight->hide();
+ setLineWidth(2);
+ widgetResizeHandler->setActive(isResizeEnabled());
+ } else {
+ hbox->setMargin(0);
+ titleBar->hide();
+ if (orientation() == Qt::Horizontal) {
+ horHandle->hide();
+ if (moveEnabled)
+ verHandle->show();
+ else
+ verHandle->hide();
+#ifdef Q_WS_MAC
+ if(horHandle->mousePressed) {
+ horHandle->mousePressed = false;
+ verHandle->mousePressed = true;
+ verHandle->grabMouse();
+ }
+#endif
+ verHandle->updateGui();
+ } else {
+ if (moveEnabled)
+ horHandle->show();
+ else
+ horHandle->hide();
+ horHandle->updateGui();
+#ifdef Q_WS_MAC
+ if(verHandle->mousePressed) {
+ verHandle->mousePressed = false;
+ horHandle->mousePressed = true;
+ horHandle->grabMouse();
+ }
+#endif
+ verHandle->hide();
+ }
+ if (isResizeEnabled()) {
+ if (orientation() == Qt::Horizontal) {
+ hHandleBottom->raise();
+ hHandleTop->raise();
+ } else {
+ vHandleRight->raise();
+ vHandleLeft->raise();
+ }
+
+ if (area()) {
+ if (orientation() == Qt::Horizontal) {
+ if (area()->handlePosition() == Q3DockArea::Normal) {
+ hHandleBottom->show();
+ hHandleTop->hide();
+ } else {
+ hHandleTop->show();
+ hHandleBottom->hide();
+ }
+ if (!area()->isLastDockWindow(this))
+ vHandleRight->show();
+ else
+ vHandleRight->hide();
+ vHandleLeft->hide();
+ } else {
+ if ((area()->handlePosition() == Q3DockArea::Normal) != QApplication::reverseLayout()) {
+ vHandleRight->show();
+ vHandleLeft->hide();
+ } else {
+ vHandleLeft->show();
+ vHandleRight->hide();
+ }
+ if (!area()->isLastDockWindow(this))
+ hHandleBottom->show();
+ else
+ hHandleBottom->hide();
+ hHandleTop->hide();
+ }
+ }
+ }
+#ifndef Q_OS_WINCE
+ if (moveEnabled)
+ setLineWidth(1);
+ else
+ setLineWidth(0);
+#endif
+ widgetResizeHandler->setActive(false);
+ }
+}
+
+void Q3DockWindow::updatePosition(const QPoint &globalPos)
+{
+ if (curPlace == OutsideDock && state == InDock)
+ lastSize = size();
+
+ bool doAdjustSize = curPlace != state && state == OutsideDock;
+ bool doUpdate = true;
+ bool doOrientationChange = true;
+ if (state != curPlace && state == InDock) {
+ doUpdate = false;
+ curPlace = state;
+ updateGui();
+ QApplication::sendPostedEvents();
+ }
+ Qt::Orientation oo = orientation();
+
+ if (state == InDock) {
+ if (tmpDockArea) {
+ bool differentDocks = false;
+ if (dockArea && dockArea != tmpDockArea) {
+ differentDocks = true;
+ delete (Q3DockArea::DockWindowData*)dockWindowData;
+ dockWindowData = dockArea->dockWindowData(this);
+ dockArea->removeDockWindow(this, false, false);
+ }
+ dockArea = tmpDockArea;
+ if (differentDocks) {
+ if (doUpdate) {
+ doUpdate = false;
+ curPlace = state;
+ updateGui();
+ }
+ emit orientationChanged(tmpDockArea->orientation());
+ doOrientationChange = false;
+ } else {
+ updateGui();
+ }
+ dockArea->moveDockWindow(this, globalPos, currRect, startOrientation != oo);
+ }
+ } else {
+ if (dockArea) {
+ Q3MainWindow *mw = (Q3MainWindow*)dockArea->parentWidget();
+ if (qobject_cast<Q3MainWindow*>(mw) &&
+ (!mw->isDockEnabled(Qt::DockTornOff) ||
+ !mw->isDockEnabled(this, Qt::DockTornOff)))
+ return;
+ delete (Q3DockArea::DockWindowData*)dockWindowData;
+ dockWindowData = dockArea->dockWindowData(this);
+ dockArea->removeDockWindow(this, true,
+ startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this));
+ }
+ dockArea = 0;
+ QPoint topLeft = currRect.topLeft();
+ QRect screen = qApp->desktop()->availableGeometry(topLeft);
+ if (!screen.contains(topLeft)) {
+ topLeft.setY(qMax(topLeft.y(), screen.top()));
+ topLeft.setY(qMin(topLeft.y(), screen.bottom()-height()));
+ topLeft.setX(qMax(topLeft.x(), screen.left()));
+ topLeft.setX(qMin(topLeft.x(), screen.right()-width()));
+ }
+ move(topLeft);
+ }
+
+ if (curPlace == InDock && state == OutsideDock && !qobject_cast<Q3ToolBar*>(this)) {
+ if (lastSize != QSize(-1, -1))
+ resize(lastSize);
+ }
+
+ if (doUpdate) {
+ curPlace = state;
+ updateGui();
+ }
+ if (doOrientationChange)
+ emit orientationChanged(orientation());
+ tmpDockArea = 0;
+ if (doAdjustSize) {
+ QApplication::sendPostedEvents(this, QEvent::LayoutHint);
+ if (qobject_cast<Q3ToolBar*>(this))
+ adjustSize();
+ if (lastSize == QSize(-1, -1))
+ setAttribute(Qt::WA_Resized, false); // Ensures size is recalculated (non-opaque).
+ show();
+ if (parentWidget() && isWindow())
+ parentWidget()->setActiveWindow();
+
+ }
+
+ emit placeChanged(curPlace);
+}
+
+/*!
+ Sets the dock window's main widget to \a w.
+
+ \sa boxLayout()
+*/
+
+void Q3DockWindow::setWidget(QWidget *w)
+{
+ wid = w;
+ boxLayout()->addWidget(w);
+ updateGui();
+}
+
+/*!
+ Returns the dock window's main widget.
+
+ \sa setWidget()
+*/
+
+QWidget *Q3DockWindow::widget() const
+{
+ return wid;
+}
+
+void Q3DockWindow::startRectDraw(const QPoint &so, bool drawRect)
+{
+ state = place();
+ if (rubberBand)
+ endRectDraw(!opaque);
+ rubberBand = new QRubberBand(QRubberBand::Rectangle);
+ currRect = QRect(realWidgetPos(this), size());
+ if (drawRect) {
+ rubberBand->setGeometry(currRect);
+ }
+ startOrientation = orientation();
+ startOffset = mapFromGlobal(so);
+ rubberBand->show();
+}
+
+void Q3DockWindow::endRectDraw(bool)
+{
+ delete rubberBand;
+ rubberBand = 0;
+}
+
+/*!
+ \reimp
+*/
+void Q3DockWindow::drawFrame(QPainter *p)
+{
+ if (place() == InDock) {
+ Q3Frame::drawFrame(p);
+ return;
+ }
+
+ QStyleOptionFrame opt;
+ opt.rect = rect();
+ opt.palette = palette();
+ opt.state = QStyle::State_None;
+ if (titleBar->isActive())
+ opt.state |= QStyle::State_Active;
+ opt.lineWidth = lineWidth();
+ opt.midLineWidth = midLineWidth();
+
+ style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, p, this);
+}
+
+/*!
+ \reimp
+*/
+void Q3DockWindow::drawContents(QPainter *p)
+{
+ // This is only used by the PocketPC style. We probably need to revist later.
+ QStyleOption opt(0, QStyleOption::SO_Default);
+ opt.init(this);
+ if (titleBar->isActive())
+ opt.state |= QStyle::State_Active;
+ style()->drawControl(QStyle::CE_Q3DockWindowEmptyArea, &opt, p, this);
+}
+
+/*!
+ \property Q3DockWindow::resizeEnabled
+ \brief whether the dock window is resizeable
+
+ A resizeable dock window can be resized using splitter-like
+ handles inside a dock area and like every other top level window
+ when floating.
+
+ A dock window is both horizontally and vertically stretchable if
+ you call setResizeEnabled(true).
+
+ This property is false by default.
+
+ \sa setVerticallyStretchable() setHorizontallyStretchable()
+*/
+
+void Q3DockWindow::setResizeEnabled(bool b)
+{
+ resizeEnabled = b;
+ updateGui();
+}
+
+/*!
+ \property Q3DockWindow::movingEnabled
+ \brief whether the user can move the dock window within the dock
+ area, move the dock window to another dock area, or float the dock
+ window.
+
+ This property is true by default.
+*/
+
+void Q3DockWindow::setMovingEnabled(bool b)
+{
+ moveEnabled = b;
+ updateGui();
+}
+
+bool Q3DockWindow::isResizeEnabled() const
+{
+ return resizeEnabled;
+}
+
+bool Q3DockWindow::isMovingEnabled() const
+{
+ return moveEnabled;
+}
+
+/*!
+ \property Q3DockWindow::closeMode
+ \brief the close mode of a dock window
+
+ Defines when (if ever) the dock window has a close button. The
+ choices are \c Never, \c Docked (i.e. only when docked), \c
+ Undocked (only when undocked, i.e. floated) or \c Always.
+
+ The default is \c Never.
+*/
+
+void Q3DockWindow::setCloseMode(int m)
+{
+ cMode = m;
+ if (place() == InDock) {
+ horHandle->updateGui();
+ verHandle->updateGui();
+ } else {
+ titleBar->updateGui();
+ }
+}
+
+/*!
+ Returns true if the dock window has a close button; otherwise
+ returns false. The result depends on the dock window's \l Place
+ and its \l CloseMode.
+
+ \sa setCloseMode()
+*/
+
+bool Q3DockWindow::isCloseEnabled() const
+{
+ return (((cMode & Docked) == Docked && place() == InDock) ||
+ ((cMode & Undocked) == Undocked && place() == OutsideDock));
+}
+
+int Q3DockWindow::closeMode() const
+{
+ return cMode;
+}
+
+/*!
+ \property Q3DockWindow::horizontallyStretchable
+ \brief whether the dock window is horizontally stretchable.
+
+ A dock window is horizontally stretchable if you call
+ setHorizontallyStretchable(true) or setResizeEnabled(true).
+
+ \warning Stretchability is broken. You must call
+ setResizeEnabled(true) to get proper behavior and even then
+ Q3DockWindow does not limit stretchablilty.
+
+ \sa setResizeEnabled()
+*/
+
+void Q3DockWindow::setHorizontallyStretchable(bool b)
+{
+ stretchable[Qt::Horizontal] = b;
+}
+
+/*!
+ \property Q3DockWindow::verticallyStretchable
+ \brief whether the dock window is vertically stretchable.
+
+ A dock window is vertically stretchable if you call
+ setVerticallyStretchable(true) or setResizeEnabled(true).
+
+ \sa setResizeEnabled()
+
+ \warning Stretchability is broken. You must call
+ setResizeEnabled(true) to get proper behavior and even then
+ Q3DockWindow does not limit stretchablilty.
+*/
+
+void Q3DockWindow::setVerticallyStretchable(bool b)
+{
+ stretchable[Qt::Vertical] = b;
+}
+
+bool Q3DockWindow::isHorizontallyStretchable() const
+{
+ return isResizeEnabled() || stretchable[Qt::Horizontal];
+}
+
+bool Q3DockWindow::isVerticallyStretchable() const
+{
+ return isResizeEnabled() || stretchable[Qt::Vertical];
+}
+
+/*!
+ \property Q3DockWindow::stretchable
+ \brief whether the dock window is stretchable in the current
+ orientation()
+
+ This property can be set using setHorizontallyStretchable() and
+ setVerticallyStretchable(), or with setResizeEnabled().
+
+ \warning Stretchability is broken. You must call
+ setResizeEnabled(true) to get proper behavior and even then
+ Q3DockWindow does not limit stretchablilty.
+
+ \sa setResizeEnabled()
+*/
+
+bool Q3DockWindow::isStretchable() const
+{
+ if (orientation() == Qt::Horizontal)
+ return isHorizontallyStretchable();
+ return isVerticallyStretchable();
+}
+
+/*!
+ Returns the orientation of the dock window.
+
+ \sa orientationChanged()
+*/
+
+Qt::Orientation Q3DockWindow::orientation() const
+{
+ if (dockArea)
+ return dockArea->orientation();
+ if (qobject_cast<const Q3ToolBar*>(this))
+ return Qt::Horizontal;
+ return (((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::LeftToRight ||
+ ((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::RightToLeft ?
+ Qt::Horizontal : Qt::Vertical);
+}
+
+int Q3DockWindow::offset() const
+{
+ return offs;
+}
+
+/*!
+ \property Q3DockWindow::offset
+ \brief the dock window's preferred offset from the dock area's
+ left edge (top edge for vertical dock areas)
+
+ The default is 0.
+*/
+
+void Q3DockWindow::setOffset(int o)
+{
+ offs = o;
+}
+
+/*!
+ Returns the dock window's preferred size (fixed extent).
+
+ \sa setFixedExtentWidth() setFixedExtentHeight()
+*/
+
+QSize Q3DockWindow::fixedExtent() const
+{
+ return fExtent;
+}
+
+/*!
+ Sets the dock window's preferred width for its fixed extent (size)
+ to \a w.
+
+ \sa setFixedExtentHeight()
+*/
+
+void Q3DockWindow::setFixedExtentWidth(int w)
+{
+ fExtent.setWidth(w);
+}
+
+/*!
+ Sets the dock window's preferred height for its fixed extent
+ (size) to \a h.
+
+ \sa setFixedExtentWidth()
+*/
+
+void Q3DockWindow::setFixedExtentHeight(int h)
+{
+ fExtent.setHeight(h);
+}
+
+/*!
+ \property Q3DockWindow::newLine
+ \brief whether the dock window prefers to start a new line in the
+ dock area.
+
+ The default is false, i.e. the dock window doesn't require a new
+ line in the dock area.
+*/
+
+void Q3DockWindow::setNewLine(bool b)
+{
+ nl = b;
+}
+
+bool Q3DockWindow::newLine() const
+{
+ return nl;
+}
+
+/*!
+ Returns the layout which is used for adding widgets to the dock
+ window. The layout's orientation is set automatically to match the
+ orientation of the dock window. You can add widgets to the layout
+ using the box layout's QBoxLayout::addWidget() function.
+
+ If the dock window only needs to contain a single widget use
+ setWidget() instead.
+
+ \sa setWidget() setOrientation()
+*/
+
+QBoxLayout *Q3DockWindow::boxLayout()
+{
+ return childBox;
+}
+
+/*! \reimp
+ */
+
+QSize Q3DockWindow::sizeHint() const
+{
+ QSize sh(Q3Frame::sizeHint());
+ if (place() == InDock)
+ sh = sh.expandedTo(fixedExtent());
+ sh = sh.expandedTo(QSize(16, 16));
+ if (area()) {
+ if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
+ sh.setWidth(sh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
+ sh.setHeight(sh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ }
+ return sh;
+}
+
+/*! \internal
+ */
+
+QSize Q3DockWindow::minimumSize() const
+{
+ QSize ms(Q3Frame::minimumSize());
+ if (place() == InDock)
+ ms = ms.expandedTo(fixedExtent());
+ ms = ms.expandedTo(QSize(16, 16));
+ if (area()) {
+ if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
+ ms.setWidth(ms.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
+ ms.setHeight(ms.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ }
+ return ms;
+}
+
+/*! \reimp
+ */
+
+QSize Q3DockWindow::minimumSizeHint() const
+{
+ QSize msh(Q3Frame::minimumSize());
+ if (place() == InDock)
+ msh = msh.expandedTo(fixedExtent());
+ msh = msh.expandedTo(QSize(16, 16));
+ if (area()) {
+ if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
+ msh.setWidth(msh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
+ msh.setHeight(msh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
+ }
+ return msh;
+}
+
+/*!
+ \fn void Q3DockWindow::undock()
+
+ Undocks the Q3DockWindow from its current dock area if it is
+ docked; otherwise does nothing.
+
+ \sa dock() Q3DockArea::moveDockWindow(),
+ Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
+ Q3MainWindow::removeDockWindow()
+*/
+
+/*!
+ \fn void Q3DockWindow::undock(QWidget *widget)
+
+ Undocks the specified \a widget from its current dock area if it is
+ docked; otherwise does nothing.
+
+ \sa dock() Q3DockArea::moveDockWindow(),
+ Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
+ Q3MainWindow::removeDockWindow()
+*/
+void Q3DockWindow::undock(QWidget *w)
+{
+ Q3MainWindow *mw = 0;
+ if (area())
+ mw = qobject_cast<Q3MainWindow*>(area()->parentWidget());
+ if (mw && !mw->isDockEnabled(this, Qt::DockTornOff))
+ return;
+ if ((place() == OutsideDock && !w))
+ return;
+
+ QPoint p(50, 50);
+ if (window())
+ p = window()->pos() + QPoint(20, 20);
+ if (dockArea) {
+ delete (Q3DockArea::DockWindowData*)dockWindowData;
+ dockWindowData = dockArea->dockWindowData(this);
+ dockArea->removeDockWindow(this, true, orientation() != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this));
+ }
+ dockArea = 0;
+ if (lastPos != QPoint(-1, -1) && lastPos.x() > 0 && lastPos.y() > 0)
+ move(lastPos);
+ else
+ move(p);
+ if (lastSize != QSize(-1, -1))
+ resize(lastSize);
+ curPlace = OutsideDock;
+ updateGui();
+ emit orientationChanged(orientation());
+ QApplication::sendPostedEvents(this, QEvent::LayoutHint);
+ if (qobject_cast<Q3ToolBar*>(this))
+ adjustSize();
+ if (!w) {
+ if (!parentWidget() || parentWidget()->isVisible()) {
+ if (lastSize == QSize(-1, -1))
+ setAttribute(Qt::WA_Resized, false);// Ensures size is recalculated (opaque).
+ show();
+ }
+ } else {
+ setParent(w, 0);
+ move(-width() - 5, -height() - 5);
+ resize(1, 1);
+ show();
+ }
+ if (parentWidget() && isWindow())
+ parentWidget()->setActiveWindow();
+ emit placeChanged(place());
+}
+
+void Q3DockWindow::removeFromDock(bool fixNewLines)
+{
+ if (dockArea)
+ dockArea->removeDockWindow(this, false, false, fixNewLines);
+}
+
+/*!
+ Docks the dock window into the last dock area in which it was
+ docked.
+
+ If the dock window has no last dock area (e.g. it was created as a
+ floating window and has never been docked), or if the last dock
+ area it was docked in does not exist (e.g. the dock area has been
+ deleted), nothing happens.
+
+ The dock window will dock with the dock area regardless of the return value
+ of Q3DockArea::isDockWindowAccepted().
+
+ \sa undock() Q3DockArea::moveDockWindow(),
+ Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
+ Q3MainWindow::removeDockWindow(), Q3DockArea::isDockWindowAccepted()
+
+*/
+
+void Q3DockWindow::dock()
+{
+ if (!(Q3DockArea::DockWindowData*)dockWindowData ||
+ !((Q3DockArea::DockWindowData*)dockWindowData)->area)
+ return;
+ curPlace = InDock;
+ lastPos = pos();
+ lastSize = size();
+ ((Q3DockArea::DockWindowData*)dockWindowData)->
+ area->dockWindow(this, (Q3DockArea::DockWindowData*)dockWindowData);
+ emit orientationChanged(orientation());
+ emit placeChanged(place());
+}
+
+/*! \reimp
+ */
+
+void Q3DockWindow::hideEvent(QHideEvent *e)
+{
+ Q3Frame::hideEvent(e);
+}
+
+/*! \reimp
+ */
+
+void Q3DockWindow::showEvent(QShowEvent *e)
+{
+ if (curPlace == OutsideDock && (parent() && parent()->objectName() == QLatin1String("qt_hide_dock"))) {
+ QRect sr = qApp->desktop()->availableGeometry(this);
+ if (!sr.contains(pos())) {
+ int nx = qMin(qMax(x(), sr.x()), sr.right()-width());
+ int ny = qMin(qMax(y(), sr.y()), sr.bottom()-height());
+ move(nx, ny);
+ }
+ }
+
+ Q3Frame::showEvent(e);
+}
+
+/*!
+ \property Q3DockWindow::opaqueMoving
+ \brief whether the dock window will be shown normally whilst it is
+ being moved.
+
+ If this property is false, (the default), the dock window will be
+ represented by an outline rectangle whilst it is being moved.
+
+ \warning Currently opaque moving has some problems and we do not
+ recommend using it at this time. We expect to fix these problems
+ in a future release.
+*/
+
+void Q3DockWindow::setOpaqueMoving(bool b)
+{
+ opaque = b;
+ horHandle->setOpaqueMoving(b);
+ verHandle->setOpaqueMoving(b);
+ titleBar->setOpaqueMoving(b);
+}
+
+bool Q3DockWindow::opaqueMoving() const
+{
+ return opaque;
+}
+
+void Q3DockWindow::updateSplitterVisibility(bool visible)
+{
+ if (area() && isResizeEnabled()) {
+ if (orientation() == Qt::Horizontal) {
+ if (visible)
+ vHandleRight->show();
+ else
+ vHandleRight->hide();
+ vHandleLeft->hide();
+ } else {
+ if (visible)
+ hHandleBottom->show();
+ else
+ hHandleBottom->hide();
+ hHandleTop->hide();
+ }
+ }
+}
+
+/*! \reimp */
+bool Q3DockWindow::eventFilter(QObject * o, QEvent *e)
+{
+ if (!o->isWidgetType())
+ return false;
+
+ if (e->type() == QEvent::KeyPress &&
+ (horHandle->mousePressed ||
+ verHandle->mousePressed ||
+ titleBar->mousePressed)) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ if (ke->key() == Qt::Key_Escape) {
+ horHandle->mousePressed =
+ verHandle->mousePressed =
+ titleBar->mousePressed = false;
+ endRectDraw(!opaque);
+ qApp->removeEventFilter(this);
+ return true;
+ }
+ } else if (((QWidget*)o)->window() != this && place() == OutsideDock && isWindow()) {
+ if ((e->type() == QEvent::WindowDeactivate ||
+ e->type() == QEvent::WindowActivate))
+ event(e);
+ }
+ return false;
+}
+
+/*! \reimp */
+bool Q3DockWindow::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::WindowDeactivate:
+ if (place() == OutsideDock && isWindow() && parentWidget()
+ && parentWidget()->isActiveWindow())
+ return true;
+ break;
+ case QEvent::HideToParent:
+ emit visibilityChanged(false);
+ break;
+ case QEvent::ShowToParent:
+ emit visibilityChanged(true);
+ break;
+ case QEvent::WindowTitleChange:
+ {
+ QString s = Q3Frame::windowTitle();
+ titleBar->setWindowTitle(s);
+#ifndef QT_NO_TOOLTIP
+ horHandle->setToolTip(s);
+ verHandle->setToolTip(s);
+#endif
+ break;
+ }
+ default:
+ break;
+ }
+ return Q3Frame::event(e);
+}
+
+/*!
+ Returns the dock window's title.
+*/
+QString Q3DockWindow::windowTitle() const
+{
+ return titleBar->windowTitle();
+}
+
+/*! \reimp */
+void Q3DockWindow::contextMenuEvent(QContextMenuEvent *e)
+{
+ QObject *o = this;
+ while (o) {
+ if (qobject_cast<Q3MainWindow*>(o))
+ break;
+ o = o->parent();
+ }
+ if (!o || ! ((Q3MainWindow*)o)->showDockMenu(e->globalPos()))
+ e->ignore();
+}
+
+QT_END_NAMESPACE
+
+#include "q3dockwindow.moc"
+
+#endif //QT_NO_MAINWINDOW
diff --git a/src/qt3support/widgets/q3dockwindow.h b/src/qt3support/widgets/q3dockwindow.h
new file mode 100644
index 0000000..a857a66
--- /dev/null
+++ b/src/qt3support/widgets/q3dockwindow.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3DOCKWINDOW_H
+#define Q3DOCKWINDOW_H
+
+#include <Qt3Support/q3frame.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_MAINWINDOW
+
+class Q3DockWindowHandle;
+class Q3DockWindowTitleBar;
+class QPainter;
+class Q3DockWindowResizeHandle;
+class QBoxLayout;
+class QHBoxLayout;
+class QVBoxLayout;
+class Q3DockArea;
+class QWidgetResizeHandler;
+class Q3MainWindow;
+class Q3DockAreaLayout;
+class Q3DockWindowPrivate;
+class Q3ToolBar;
+class QWindowsXPStyle;
+class QRubberBand;
+
+class Q_COMPAT_EXPORT Q3DockWindow : public Q3Frame
+{
+ Q_OBJECT
+ Q_ENUMS(CloseMode Place)
+ Q_PROPERTY(int closeMode READ closeMode WRITE setCloseMode)
+ Q_PROPERTY(bool resizeEnabled READ isResizeEnabled WRITE setResizeEnabled)
+ Q_PROPERTY(bool movingEnabled READ isMovingEnabled WRITE setMovingEnabled)
+ Q_PROPERTY(bool horizontallyStretchable READ isHorizontallyStretchable WRITE setHorizontallyStretchable)
+ Q_PROPERTY(bool verticallyStretchable READ isVerticallyStretchable WRITE setVerticallyStretchable)
+ Q_PROPERTY(bool stretchable READ isStretchable)
+ Q_PROPERTY(bool newLine READ newLine WRITE setNewLine)
+ Q_PROPERTY(bool opaqueMoving READ opaqueMoving WRITE setOpaqueMoving)
+ Q_PROPERTY(int offset READ offset WRITE setOffset)
+ Q_PROPERTY(Place place READ place)
+
+ friend class Q3DockWindowHandle;
+ friend class Q3DockWindowTitleBar;
+ friend class Q3DockArea;
+ friend class Q3DockAreaLayout;
+ friend class Q3MainWindow;
+ friend class QCEMainWindow;
+ friend class Q3ToolBar;
+ friend class QWindowsXPStyle;
+
+public:
+ enum Place { InDock, OutsideDock };
+ enum CloseMode { Never = 0, Docked = 1, Undocked = 2, Always = Docked | Undocked };
+
+ Q3DockWindow(Place p = InDock, QWidget* parent=0, const char* name=0, Qt::WindowFlags f = 0);
+ Q3DockWindow(QWidget* parent, const char* name=0, Qt::WindowFlags f = 0);
+ ~Q3DockWindow();
+
+ virtual void setWidget(QWidget *w);
+ QWidget *widget() const;
+
+ Place place() const { return curPlace; }
+
+ Q3DockArea *area() const;
+
+ virtual void setCloseMode(int m);
+ bool isCloseEnabled() const;
+ int closeMode() const;
+
+ virtual void setResizeEnabled(bool b);
+ virtual void setMovingEnabled(bool b);
+ bool isResizeEnabled() const;
+ bool isMovingEnabled() const;
+
+ virtual void setHorizontallyStretchable(bool b);
+ virtual void setVerticallyStretchable(bool b);
+ bool isHorizontallyStretchable() const;
+ bool isVerticallyStretchable() const;
+ void setHorizontalStretchable(bool b) { setHorizontallyStretchable(b); }
+ void setVerticalStretchable(bool b) { setVerticallyStretchable(b); }
+ bool isHorizontalStretchable() const { return isHorizontallyStretchable(); }
+ bool isVerticalStretchable() const { return isVerticallyStretchable(); }
+ bool isStretchable() const;
+
+ virtual void setOffset(int o);
+ int offset() const;
+
+ virtual void setFixedExtentWidth(int w);
+ virtual void setFixedExtentHeight(int h);
+ QSize fixedExtent() const;
+
+ virtual void setNewLine(bool b);
+ bool newLine() const;
+
+ Qt::Orientation orientation() const;
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize minimumSizeHint() const;
+
+ QBoxLayout *boxLayout();
+
+ virtual void setOpaqueMoving(bool b);
+ bool opaqueMoving() const;
+
+ bool eventFilter(QObject *o, QEvent *e);
+
+ QString windowTitle() const;
+
+Q_SIGNALS:
+ void orientationChanged(Qt::Orientation o);
+ void placeChanged(Q3DockWindow::Place p);
+ void visibilityChanged(bool);
+
+public Q_SLOTS:
+ virtual void undock(QWidget *w);
+ virtual void undock() { undock(0); }
+ virtual void dock();
+ virtual void setOrientation(Qt::Orientation o);
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+ void showEvent(QShowEvent *e);
+ void hideEvent(QHideEvent *e);
+ void contextMenuEvent(QContextMenuEvent *e);
+
+ void drawFrame(QPainter *);
+ void drawContents(QPainter *);
+
+ bool event(QEvent *e);
+
+private Q_SLOTS:
+ void toggleVisible() { setVisible(!isVisible()); }
+
+private:
+ Q3DockWindow(Place p, QWidget* parent, const char* name, Qt::WindowFlags f, bool toolbar);
+
+ void handleMove(const QPoint &pos, const QPoint &gp, bool drawRect);
+ void updateGui();
+ void updateSplitterVisibility(bool visible);
+
+ void startRectDraw(const QPoint &so, bool drawRect);
+ void endRectDraw(bool drawRect);
+ void updatePosition(const QPoint &globalPos );
+ QWidget *areaAt(const QPoint &gp);
+ void removeFromDock(bool fixNewLines = true);
+ void swapRect(QRect &r, Qt::Orientation o, const QPoint &offset, Q3DockArea *area);
+ void init();
+
+private:
+ Q3DockWindowHandle *horHandle, *verHandle;
+ Q3DockWindowTitleBar *titleBar;
+ QWidget *wid;
+ QRubberBand *rubberBand;
+ Q3DockArea *dockArea, *tmpDockArea;
+ QRect currRect;
+ Place curPlace;
+ Place state;
+ bool resizeEnabled : 1;
+ bool moveEnabled : 1;
+ bool nl : 1;
+ bool opaque : 1;
+ bool isToolbar : 1;
+ bool stretchable[3];
+ Qt::Orientation startOrientation;
+ int cMode;
+ QPoint startOffset;
+ int offs;
+ QSize fExtent;
+ Q3DockWindowResizeHandle *hHandleTop, *hHandleBottom, *vHandleLeft, *vHandleRight;
+ QVBoxLayout *hbox;
+ QHBoxLayout *vbox;
+ QBoxLayout *childBox;
+ void *dockWindowData;
+ QPoint lastPos;
+ QSize lastSize;
+ QWidgetResizeHandler *widgetResizeHandler;
+ Q3DockWindowPrivate *d;
+
+private:
+ Q_DISABLE_COPY(Q3DockWindow)
+};
+
+inline Q3DockArea *Q3DockWindow::area() const
+{
+ return dockArea;
+}
+
+#endif // QT_NO_MAINWINDOW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3DOCKWINDOW_H
diff --git a/src/qt3support/widgets/q3frame.cpp b/src/qt3support/widgets/q3frame.cpp
new file mode 100644
index 0000000..49a8e28
--- /dev/null
+++ b/src/qt3support/widgets/q3frame.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3frame.h"
+#include "qevent.h"
+#include "qpainter.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class Q3Frame
+
+ \compat
+*/
+
+/*!
+ Creates a new frame with the given \a parent, object \a name, and
+ with widget flags \a f.
+*/
+Q3Frame::Q3Frame(QWidget* parent, const char* name, Qt::WindowFlags f)
+ :QFrame(parent, f), marg(0)
+{
+ if (name)
+ setObjectName(QLatin1String(name));
+ setAttribute(Qt::WA_LayoutOnEntireRect);
+}
+
+/*!
+ Destructs the frame.
+*/
+Q3Frame::~Q3Frame()
+{
+}
+
+/*!
+ Paints the frame (or part of the frame) that's necessary,
+ depending on the \a event.
+*/
+void Q3Frame::paintEvent(QPaintEvent * event)
+{
+ QPainter paint(this);
+ if (!contentsRect().contains(event->rect())) {
+ paint.save();
+ paint.setClipRegion(event->region().intersected(frameRect()));
+ drawFrame(&paint);
+ paint.restore();
+ }
+ if (event->rect().intersects(contentsRect())) {
+ paint.setClipRegion(event->region().intersected(contentsRect()));
+ drawContents(&paint);
+ }
+}
+
+/*!
+ \fn void Q3Frame::drawContents(QPainter *painter)
+
+ Virtual function that draws the contents of the frame on the given
+ \a painter.
+
+ The QPainter is already open when you get it, and you must leave
+ it open. Painter \link QPainter::setWorldMatrix()
+ transformations\endlink are switched off on entry. If you
+ transform the painter, remember to take the frame into account and
+ \link QPainter::resetXForm() reset transformation\endlink before
+ returning.
+
+ This function is reimplemented by subclasses that draw something
+ inside the frame. It should only draw inside contentsRect(). The
+ default function does nothing.
+
+ \sa contentsRect(), QPainter::setClipRect()
+*/
+
+void Q3Frame::drawContents(QPainter *)
+{
+}
+
+/*!
+ Draws the frame using the painter \a p and the current frame
+ attributes and color group. The rectangle inside the frame is not
+ affected.
+
+ This function is virtual, but in general you do not need to
+ reimplement it. If you do, note that the QPainter is already open
+ and must remain open.
+
+ \sa frameRect(), contentsRect(), drawContents(), frameStyle(), setPalette()
+*/
+
+void Q3Frame::drawFrame(QPainter *p)
+{
+ QFrame::drawFrame(p);
+}
+
+/*!
+ \fn void Q3Frame::resizeEvent(QResizeEvent *event)
+
+ This just calls frameChanged(); it does not make use of the \a
+ event itself.
+*/
+void Q3Frame::resizeEvent(QResizeEvent *e)
+{
+ if (e->size() == e->oldSize())
+ frameChanged();
+}
+
+/*!
+ Virtual function that is called when the frame style, line width
+ or mid-line width changes.
+
+ This function can be reimplemented by subclasses that need to know
+ when the frame attributes change.
+*/
+
+void Q3Frame::frameChanged()
+{
+}
+
+
+/*!
+ \property Q3Frame::margin
+ \brief the width of the margin
+
+ The margin is the distance between the innermost pixel of the
+ frame and the outermost pixel of contentsRect(). It is included in
+ frameWidth().
+
+ The margin is filled according to backgroundMode().
+
+ The default value is 0.
+
+ \sa lineWidth(), frameWidth()
+*/
+
+void Q3Frame::setMargin(int w)
+{
+ if (marg == w)
+ return;
+ marg = w;
+ update();
+ frameChanged();
+}
+
+/*!
+ \property Q3Frame::contentsRect
+ \brief the frame's contents rectangle (including the margins)
+*/
+QRect Q3Frame::contentsRect() const
+{
+ QRect cr(QFrame::contentsRect());
+ cr.adjust(marg, marg, -marg, -marg);
+ return cr;
+}
+
+/*!
+ Returns the width of the frame (including the margin).
+*/
+int Q3Frame::frameWidth() const
+{
+ return QFrame::frameWidth() + marg;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3frame.h b/src/qt3support/widgets/q3frame.h
new file mode 100644
index 0000000..b94dd4c
--- /dev/null
+++ b/src/qt3support/widgets/q3frame.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 Qt3Support module 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 Q3FRAME_H
+#define Q3FRAME_H
+
+#include <QtGui/qframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3Frame : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+ Q_PROPERTY(QRect contentsRect READ contentsRect)
+
+public:
+ Q3Frame(QWidget* parent, const char* name = 0, Qt::WindowFlags f = 0);
+ ~Q3Frame();
+#ifndef qdoc
+ bool lineShapesOk() const { return true; }
+#endif
+
+ int margin() const { return marg; }
+ void setMargin(int);
+
+ QRect contentsRect() const;
+ int frameWidth() const;
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+
+ virtual void frameChanged();
+ virtual void drawFrame(QPainter *);
+ virtual void drawContents(QPainter *);
+
+private:
+ Q_DISABLE_COPY(Q3Frame)
+
+ int marg;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3FRAME_H
diff --git a/src/qt3support/widgets/q3grid.cpp b/src/qt3support/widgets/q3grid.cpp
new file mode 100644
index 0000000..169e01e
--- /dev/null
+++ b/src/qt3support/widgets/q3grid.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3grid.h"
+#include "qlayout.h"
+#include "qapplication.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3Grid
+ \brief The Q3Grid widget provides simple geometry management of its children.
+
+ \compat
+
+ The grid places its widgets either in columns or in rows depending
+ on its orientation.
+
+ The number of rows \e or columns is defined in the constructor.
+ All the grid's children will be placed and sized in accordance
+ with their sizeHint() and sizePolicy().
+
+ Use setMargin() to add space around the grid itself, and
+ setSpacing() to add space between the widgets.
+
+ \sa Q3VBox Q3HBox QGridLayout
+*/
+
+/*!
+ \typedef Q3Grid::Direction
+ \internal
+*/
+
+/*!
+ Constructs a grid widget with parent \a parent, called \a name.
+ If \a orient is \c Horizontal, \a n specifies the number of
+ columns. If \a orient is \c Vertical, \a n specifies the number of
+ rows. The widget flags \a f are passed to the Q3Frame constructor.
+*/
+Q3Grid::Q3Grid(int n, Qt::Orientation orient, QWidget *parent, const char *name,
+ Qt::WindowFlags f)
+ : Q3Frame(parent, name, f)
+{
+ int nCols, nRows;
+ if (orient == Qt::Horizontal) {
+ nCols = n;
+ nRows = -1;
+ } else {
+ nCols = -1;
+ nRows = n;
+ }
+ (new QGridLayout(this, nRows, nCols, 0, 0, name))->setAutoAdd(true);
+}
+
+
+
+/*!
+ Constructs a grid widget with parent \a parent, called \a name.
+ \a n specifies the number of columns. The widget flags \a f are
+ passed to the Q3Frame constructor.
+ */
+Q3Grid::Q3Grid(int n, QWidget *parent, const char *name, Qt::WindowFlags f)
+ : Q3Frame(parent, name, f)
+{
+ (new QGridLayout(this, -1, n, 0, 0, name))->setAutoAdd(true);
+}
+
+
+/*!
+ Sets the spacing between the child widgets to \a space.
+*/
+
+void Q3Grid::setSpacing(int space)
+{
+ if (layout())
+ layout()->setSpacing(space);
+}
+
+
+/*!\reimp
+ */
+void Q3Grid::frameChanged()
+{
+ if (layout())
+ layout()->setMargin(frameWidth());
+}
+
+
+/*!
+ \reimp
+*/
+
+QSize Q3Grid::sizeHint() const
+{
+ QWidget *mThis = (QWidget*)this;
+ QApplication::sendPostedEvents(mThis, QEvent::ChildInserted);
+ return Q3Frame::sizeHint();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3grid.h b/src/qt3support/widgets/q3grid.h
new file mode 100644
index 0000000..365889d
--- /dev/null
+++ b/src/qt3support/widgets/q3grid.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3GRID_H
+#define Q3GRID_H
+
+#include <Qt3Support/q3frame.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class QGridLayout;
+
+class Q_COMPAT_EXPORT Q3Grid : public Q3Frame
+{
+ Q_OBJECT
+public:
+ Q3Grid(int n, QWidget* parent=0, const char* name=0, Qt::WindowFlags f = 0);
+ Q3Grid(int n, Qt::Orientation orient, QWidget* parent=0, const char* name=0,
+ Qt::WindowFlags f = 0);
+
+ void setSpacing(int);
+ QSize sizeHint() const;
+
+ typedef Qt::Orientation Direction;
+
+protected:
+ void frameChanged();
+
+private:
+ Q_DISABLE_COPY(Q3Grid)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3GRID_H
diff --git a/src/qt3support/widgets/q3gridview.cpp b/src/qt3support/widgets/q3gridview.cpp
new file mode 100644
index 0000000..af6f9aa
--- /dev/null
+++ b/src/qt3support/widgets/q3gridview.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3gridview.h"
+#include "qpainter.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt;
+
+/*!
+ \class Q3GridView
+ \brief The Q3GridView class provides an abstract base for
+ fixed-size grids.
+
+ \compat
+
+ A grid view consists of a number of abstract cells organized in
+ rows and columns. The cells have a fixed size and are identified
+ with a row index and a column index. The top-left cell is in row
+ 0, column 0. The bottom-right cell is in row numRows()-1, column
+ numCols()-1.
+
+ You can define \l{Q3GridView::numRows} {numRows},
+ \l{Q3GridView::numCols} {numCols}, \l{Q3GridView::cellWidth}
+ {cellWidth} and \l{Q3GridView::cellHeight} {cellHeight}. Reimplement
+ the pure virtual function paintCell() to draw the contents of a
+ cell.
+
+ With ensureCellVisible(), you can ensure a certain cell is
+ visible. With rowAt() and columnAt() you can find a cell based on
+ the given x- and y-coordinates.
+
+ If you need to monitor changes to the grid's dimensions (i.e. when
+ numRows or numCols is changed), reimplement the dimensionChange()
+ change handler.
+
+ Note: the row and column indices are always given in the order,
+ row (vertical offset) then column (horizontal offset). This order
+ is the opposite of all pixel operations, which are given in the
+ order x (horizontal offset), y (vertical offset).
+
+ Q3GridView is a very simple abstract class based on Q3ScrollView. It
+ is designed to simplify the task of drawing many cells of the same
+ size in a potentially scrollable canvas. If you need rows and
+ columns with different sizes, use a Q3Table instead. If you need a
+ simple list of items, use a Q3ListBox. If you need to present
+ hierachical data use a Q3ListView, and if you need random objects
+ at random positions, consider using either a Q3IconView or a
+ Q3Canvas.
+*/
+
+
+/*!
+ Constructs a grid view.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the Q3ScrollView constructor.
+*/
+Q3GridView::Q3GridView(QWidget *parent, const char *name, Qt::WindowFlags f)
+ : Q3ScrollView(parent, name, f | WStaticContents),
+ nrows(5), ncols(5), cellw(12), cellh(12)
+{
+ viewport()->setBackgroundMode(PaletteBase);
+ setBackgroundMode(PaletteBackground, PaletteBase);
+ viewport()->setFocusProxy(this);
+}
+
+/*!
+ Destroys the grid view.
+*/
+Q3GridView::~Q3GridView()
+{
+}
+
+void Q3GridView::updateGrid()
+{
+ resizeContents(ncols * cellw, nrows * cellh);
+}
+
+/*!
+ \property Q3GridView::numRows
+ \brief The number of rows in the grid
+
+ \sa numCols
+*/
+void Q3GridView::setNumRows(int numRows)
+{
+ int oldnrows = nrows;
+ nrows = numRows;
+ dimensionChange(oldnrows, ncols);
+ updateGrid();
+}
+
+/*!
+ \property Q3GridView::numCols
+ \brief The number of columns in the grid
+
+ \sa numRows
+*/
+void Q3GridView::setNumCols(int numCols)
+{
+ int oldncols = ncols;
+ ncols = numCols;
+ dimensionChange(nrows, oldncols);
+ updateGrid();
+}
+
+/*!
+ \property Q3GridView::cellWidth
+ \brief The width of a grid column
+
+ All columns in a grid view have the same width.
+
+ \sa cellHeight
+*/
+void Q3GridView::setCellWidth(int cellWidth)
+{
+ cellw = cellWidth;
+ updateGrid();
+ updateContents();
+}
+
+/*!
+ \property Q3GridView::cellHeight
+ \brief The height of a grid row
+
+ All rows in a grid view have the same height.
+
+ \sa cellWidth
+*/
+void Q3GridView::setCellHeight(int cellHeight)
+{
+ cellh = cellHeight;
+ updateGrid();
+ updateContents();
+}
+
+/*!
+ Returns the geometry of cell (\a row, \a column) in the content
+ coordinate system.
+
+ \sa cellRect()
+*/
+QRect Q3GridView::cellGeometry(int row, int column)
+{
+ QRect r;
+ if (row >= 0 && row < nrows && column >= 0 && column < ncols)
+ r.setRect(cellw * column, cellh * row, cellw, cellh);
+ return r;
+}
+
+/*!
+ Repaints cell (\a row, \a column).
+
+ If \a erase is true, Qt erases the area of the cell before the
+ paintCell() call; otherwise no erasing takes place.
+
+ \sa QWidget::repaint()
+*/
+void Q3GridView::repaintCell(int row, int column, bool erase)
+{
+ repaintContents(cellGeometry(row, column), erase);
+}
+
+/*!
+ Updates cell (\a row, \a column).
+
+ \sa QWidget::update()
+*/
+void Q3GridView::updateCell(int row, int column)
+{
+ updateContents(cellGeometry(row, column));
+}
+
+/*!
+ Ensures cell (\a row, \a column) is visible, scrolling the grid
+ view if necessary.
+*/
+void Q3GridView::ensureCellVisible(int row, int column)
+{
+ QRect r = cellGeometry(row, column);
+ ensureVisible(r.x(), r.y(), r.width(), r.height());
+}
+
+/*!
+ This function fills the \a cw pixels wide and \a ch pixels high
+ rectangle starting at position (\a cx, \a cy) with the background
+ color using the painter \a p.
+
+ paintEmptyArea() is invoked by drawContents() to erase or fill
+ unused areas.
+*/
+
+void Q3GridView::paintEmptyArea(QPainter *p, int cx ,int cy, int cw, int ch)
+{
+ if (gridSize().width() >= contentsWidth() && gridSize().height() >= contentsHeight())
+ return;
+ // Region of the rect we should draw
+ contentsToViewport(cx, cy, cx, cy);
+ QRegion reg(QRect(cx, cy, cw, ch));
+ // Subtract the table from it
+ reg = reg.subtracted(QRect(contentsToViewport(QPoint(0, 0)), gridSize()));
+
+ // And draw the rectangles (transformed as needed)
+ QVector<QRect> r = reg.rects();
+ const QBrush &brush = backgroundBrush();
+ for (int i = 0; i < (int)r.count(); ++i)
+ p->fillRect(r[ i ], brush);
+}
+
+/*!\reimp
+ */
+void Q3GridView::drawContents(QPainter *p, int cx, int cy, int cw, int ch)
+{
+ int colfirst = columnAt(cx);
+ int collast = columnAt(cx + cw);
+ int rowfirst = rowAt(cy);
+ int rowlast = rowAt(cy + ch);
+
+ if (rowfirst == -1 || colfirst == -1) {
+ paintEmptyArea(p, cx, cy, cw, ch);
+ return;
+ }
+
+ if (collast < 0 || collast >= ncols)
+ collast = ncols-1;
+ if (rowlast < 0 || rowlast >= nrows)
+ rowlast = nrows-1;
+
+ // Go through the rows
+ for (int r = rowfirst; r <= rowlast; ++r) {
+ // get row position and height
+ int rowp = r * cellh;
+
+ // Go through the columns in the row r
+ // if we know from where to where, go through [colfirst, collast],
+ // else go through all of them
+ for (int c = colfirst; c <= collast; ++c) {
+ // get position and width of column c
+ int colp = c * cellw;
+ // Translate painter and draw the cell
+ p->translate(colp, rowp);
+ paintCell(p, r, c);
+ p->translate(-colp, -rowp);
+ }
+ }
+
+ // Paint empty rects
+ paintEmptyArea(p, cx, cy, cw, ch);
+}
+
+/*!
+ \reimp
+
+ (Implemented to get rid of a compiler warning.)
+*/
+void Q3GridView::drawContents(QPainter *)
+{
+}
+
+/*!
+ \fn void Q3GridView::dimensionChange(int oldNumRows, int oldNumCols)
+
+ This change handler is called whenever any of the grid's
+ dimensions change. \a oldNumRows and \a oldNumCols contain the
+ old dimensions, numRows() and numCols() contain the new
+ dimensions.
+*/
+void Q3GridView::dimensionChange(int, int) {}
+
+
+
+/*!
+ \fn int Q3GridView::rowAt(int y) const
+
+ Returns the number of the row at position \a y. \a y must be given
+ in content coordinates.
+
+ \sa columnAt()
+*/
+
+/*!
+ \fn int Q3GridView::columnAt(int x) const
+
+ Returns the number of the column at position \a x. \a x must be
+ given in content coordinates.
+
+ \sa rowAt()
+*/
+
+/*!
+ \fn void Q3GridView::paintCell(QPainter *p, int row, int col)
+
+ This pure virtual function is called to paint the single cell at
+ (\a row, \a col) using painter \a p. The painter must be open when
+ paintCell() is called and must remain open.
+
+ The coordinate system is \link QPainter::translate() translated
+ \endlink so that the origin is at the top-left corner of the cell
+ to be painted, i.e. \e cell coordinates. Do not scale or shear
+ the coordinate system (or if you do, restore the transformation
+ matrix before you return).
+
+ The painter is not clipped by default in order to get maximum
+ efficiency. If you want clipping, use
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3gridview.cpp 0
+*/
+
+/*!
+ \fn QRect Q3GridView::cellRect() const
+
+ Returns the geometry of a cell in a cell's coordinate system. This
+ is a convenience function useful in paintCell(). It is equivalent
+ to QRect(0, 0, cellWidth(), cellHeight()).
+
+ \sa cellGeometry()
+
+*/
+
+/*!
+ \fn QSize Q3GridView::gridSize() const
+
+ Returns the size of the grid in pixels.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3gridview.h b/src/qt3support/widgets/q3gridview.h
new file mode 100644
index 0000000..2f4f4ae
--- /dev/null
+++ b/src/qt3support/widgets/q3gridview.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3GRIDVIEW_H
+#define Q3GRIDVIEW_H
+
+#include <Qt3Support/q3scrollview.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q3GridViewPrivate;
+
+class Q_COMPAT_EXPORT Q3GridView : public Q3ScrollView
+{
+ Q_OBJECT
+ Q_PROPERTY(int numRows READ numRows WRITE setNumRows)
+ Q_PROPERTY(int numCols READ numCols WRITE setNumCols)
+ Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth)
+ Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight)
+public:
+
+ Q3GridView(QWidget *parent=0, const char *name=0, Qt::WindowFlags f=0);
+ ~Q3GridView();
+
+ int numRows() const;
+ virtual void setNumRows(int);
+ int numCols() const;
+ virtual void setNumCols(int);
+
+ int cellWidth() const;
+ virtual void setCellWidth(int);
+ int cellHeight() const;
+ virtual void setCellHeight(int);
+
+ QRect cellRect() const;
+ QRect cellGeometry(int row, int column);
+ QSize gridSize() const;
+
+ int rowAt(int y) const;
+ int columnAt(int x) const;
+
+ void repaintCell(int row, int column, bool erase=true);
+ void updateCell(int row, int column);
+ void ensureCellVisible(int row, int column);
+
+protected:
+ virtual void paintCell(QPainter *, int row, int col) = 0;
+ virtual void paintEmptyArea(QPainter *p, int cx, int cy, int cw, int ch);
+
+ void drawContents(QPainter *p, int cx, int cy, int cw, int ch);
+
+ virtual void dimensionChange(int, int);
+
+private:
+ void drawContents(QPainter*);
+ void updateGrid();
+
+ int nrows;
+ int ncols;
+ int cellw;
+ int cellh;
+ Q3GridViewPrivate* d;
+
+ Q_DISABLE_COPY(Q3GridView)
+};
+
+inline int Q3GridView::cellWidth() const
+{ return cellw; }
+
+inline int Q3GridView::cellHeight() const
+{ return cellh; }
+
+inline int Q3GridView::rowAt(int y) const
+{ return y / cellh; }
+
+inline int Q3GridView::columnAt(int x) const
+{ return x / cellw; }
+
+inline int Q3GridView::numRows() const
+{ return nrows; }
+
+inline int Q3GridView::numCols() const
+{return ncols; }
+
+inline QRect Q3GridView::cellRect() const
+{ return QRect(0, 0, cellw, cellh); }
+
+inline QSize Q3GridView::gridSize() const
+{ return QSize(ncols * cellw, nrows * cellh); }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3GRIDVIEW_H
diff --git a/src/qt3support/widgets/q3groupbox.cpp b/src/qt3support/widgets/q3groupbox.cpp
new file mode 100644
index 0000000..1fa7e7c
--- /dev/null
+++ b/src/qt3support/widgets/q3groupbox.cpp
@@ -0,0 +1,964 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3groupbox.h"
+
+#include "qlayout.h"
+#include "qpainter.h"
+#include "qbitmap.h"
+#include "q3accel.h"
+#include "qradiobutton.h"
+#include "qdrawutil.h"
+#include "qapplication.h"
+#include "qstyle.h"
+#include "qcheckbox.h"
+#include "qaccessible.h"
+#include "qstyleoption.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3GroupBox
+ \brief The Q3GroupBox widget provides a group box frame with a title.
+
+ \compat
+
+ A group box provides a frame, a title and a keyboard shortcut, and
+ displays various other widgets inside itself. The title is on top,
+ the keyboard shortcut moves keyboard focus to one of the group
+ box's child widgets, and the child widgets are usually laid out
+ horizontally (or vertically) inside the frame.
+
+ The simplest way to use it is to create a group box with the
+ desired number of columns (or rows) and orientation, and then just
+ create widgets with the group box as parent.
+
+ It is also possible to change the orientation() and number of
+ columns() after construction, or to ignore all the automatic
+ layout support and manage the layout yourself. You can add 'empty'
+ spaces to the group box with addSpace().
+
+ Q3GroupBox also lets you set the title() (normally set in the
+ constructor) and the title's alignment().
+
+ You can change the spacing used by the group box with
+ setInsideMargin() and setInsideSpacing(). To minimize space
+ consumption, you can remove the right, left and bottom edges of
+ the frame with setFlat().
+
+ \sa QButtonGroup
+*/
+
+class QCheckBox;
+
+class Q3GroupBoxPrivate
+{
+public:
+ Q3GroupBoxPrivate(Q3GroupBox *w):
+ q(w), vbox(0), grid(0), row(0), col(0), nRows(0), nCols(0), dir(Qt::Horizontal),
+ spac(5), marg(11),
+ checkbox(0),
+ frameStyle(Q3GroupBox::GroupBoxPanel | Q3GroupBox::Sunken),
+ lineWidth(1), midLineWidth(0), frameWidth(0),
+ leftFrameWidth(0), rightFrameWidth(0),
+ topFrameWidth(0), bottomFrameWidth(0) {}
+
+ void updateFrameWidth();
+ void updateStyledFrameWidths();
+
+ Q3GroupBox *q;
+ QVBoxLayout *vbox;
+ QGridLayout *grid;
+ int row;
+ int col;
+ int nRows, nCols;
+ Qt::Orientation dir;
+ int spac, marg;
+
+ QCheckBox *checkbox;
+
+ int frameStyle;
+ int oldFrameStyle;
+ short lineWidth, //line width
+ midLineWidth; //midline width
+ int frameWidth;
+ short leftFrameWidth, rightFrameWidth,
+ topFrameWidth, bottomFrameWidth;
+};
+
+/*!
+ \internal
+ Updates the frame widths from the style.
+*/
+void Q3GroupBoxPrivate::updateStyledFrameWidths()
+{
+ QStyleOptionFrameV2 opt;
+ opt.initFrom(q);
+ QRect cr = q->style()->subElementRect(QStyle::SE_FrameContents, &opt, q);
+ leftFrameWidth = cr.left() - opt.rect.left();
+ topFrameWidth = cr.top() - opt.rect.top();
+ rightFrameWidth = opt.rect.right() - cr.right(),
+ bottomFrameWidth = opt.rect.bottom() - cr.bottom();
+ frameWidth = qMax(qMax(leftFrameWidth, rightFrameWidth),
+ qMax(topFrameWidth, bottomFrameWidth));
+}
+
+/*!
+ \internal
+ Updated the frameWidth parameter.
+*/
+
+void Q3GroupBoxPrivate::updateFrameWidth()
+{
+ QRect fr = q->frameRect();
+
+ int frameShape = frameStyle & QFrame::Shape_Mask;
+ int frameShadow = frameStyle & QFrame::Shadow_Mask;
+
+ frameWidth = -1;
+
+ switch (frameShape) {
+
+ case QFrame::NoFrame:
+ frameWidth = 0;
+ break;
+
+ case QFrame::Box:
+ case QFrame::HLine:
+ case QFrame::VLine:
+ switch (frameShadow) {
+ case QFrame::Plain:
+ frameWidth = lineWidth;
+ break;
+ case QFrame::Raised:
+ case QFrame::Sunken:
+ frameWidth = (short)(lineWidth*2 + midLineWidth);
+ break;
+ }
+ break;
+
+ case QFrame::StyledPanel:
+ updateStyledFrameWidths();
+ break;
+
+ case QFrame::WinPanel:
+ frameWidth = 2;
+ break;
+
+
+ case QFrame::Panel:
+ switch (frameShadow) {
+ case QFrame::Plain:
+ case QFrame::Raised:
+ case QFrame::Sunken:
+ frameWidth = lineWidth;
+ break;
+ }
+ break;
+ }
+
+ if (frameWidth == -1) // invalid style
+ frameWidth = 0;
+
+ q->setFrameRect(fr);
+}
+
+
+
+
+
+/*!
+ Constructs a group box widget with no title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+
+ This constructor does not do automatic layout.
+*/
+
+Q3GroupBox::Q3GroupBox(QWidget *parent, const char *name)
+ : QGroupBox(parent, name)
+{
+ init();
+}
+
+/*!
+ Constructs a group box with the title \a title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+
+ This constructor does not do automatic layout.
+*/
+
+Q3GroupBox::Q3GroupBox(const QString &title, QWidget *parent, const char *name)
+ : QGroupBox(parent, name)
+{
+ init();
+ setTitle(title);
+}
+
+/*!
+ Constructs a group box with no title. Child widgets will be
+ arranged in \a strips rows or columns (depending on \a
+ orientation).
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3GroupBox::Q3GroupBox(int strips, Qt::Orientation orientation,
+ QWidget *parent, const char *name)
+ : QGroupBox(parent, name)
+{
+ init();
+ setColumnLayout(strips, orientation);
+}
+
+/*!
+ Constructs a group box titled \a title. Child widgets will be
+ arranged in \a strips rows or columns (depending on \a
+ orientation).
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3GroupBox::Q3GroupBox(int strips, Qt::Orientation orientation,
+ const QString &title, QWidget *parent,
+ const char *name)
+ : QGroupBox(parent, name)
+{
+ init();
+ setTitle(title);
+ setColumnLayout(strips, orientation);
+}
+
+/*!
+ Destroys the group box.
+*/
+Q3GroupBox::~Q3GroupBox()
+{
+ delete d;
+}
+
+void Q3GroupBox::init()
+{
+ d = new Q3GroupBoxPrivate(this);
+}
+
+
+/*! \reimp
+*/
+void Q3GroupBox::resizeEvent(QResizeEvent *e)
+{
+ QGroupBox::resizeEvent(e);
+}
+
+
+/*!
+ Adds an empty cell at the next free position. If \a size is
+ greater than 0, the empty cell takes \a size to be its fixed width
+ (if orientation() is \c Horizontal) or height (if orientation() is
+ \c Vertical).
+
+ Use this method to separate the widgets in the group box or to
+ skip the next free cell. For performance reasons, call this method
+ after calling setColumnLayout() or by changing the \l
+ Q3GroupBox::columns or \l Q3GroupBox::orientation properties. It is
+ generally a good idea to call these methods first (if needed at
+ all), and insert the widgets and spaces afterwards.
+*/
+void Q3GroupBox::addSpace(int size)
+{
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+
+ if (d->nCols <= 0 || d->nRows <= 0)
+ return;
+
+ if (d->row >= d->nRows || d->col >= d->nCols)
+ d->grid->expand(d->row+1, d->col+1);
+
+ if (size > 0) {
+ QSpacerItem *spacer
+ = new QSpacerItem((d->dir == Qt::Horizontal) ? 0 : size,
+ (d->dir == Qt::Vertical) ? 0 : size,
+ QSizePolicy::Fixed, QSizePolicy::Fixed);
+ d->grid->addItem(spacer, d->row, d->col);
+ }
+
+ skip();
+}
+
+/*!
+ \property Q3GroupBox::columns
+ \brief the number of columns or rows (depending on \l Q3GroupBox::orientation) in the group box
+
+ Usually it is not a good idea to set this property because it is
+ slow (it does a complete layout). It is best to set the number
+ of columns directly in the constructor.
+*/
+int Q3GroupBox::columns() const
+{
+ if (d->dir == Qt::Horizontal)
+ return d->nCols;
+ return d->nRows;
+}
+
+void Q3GroupBox::setColumns(int c)
+{
+ setColumnLayout(c, d->dir);
+}
+
+/*!
+ Returns the width of the empty space between the items in the
+ group and the frame of the group.
+
+ Only applies if the group box has a defined orientation.
+
+ The default is usually 11, by may vary depending on the platform
+ and style.
+
+ \sa setInsideMargin(), orientation
+*/
+int Q3GroupBox::insideMargin() const
+{
+ return d->marg;
+}
+
+/*!
+ Returns the width of the empty space between each of the items
+ in the group.
+
+ Only applies if the group box has a defined orientation.
+
+ The default is usually 5, by may vary depending on the platform
+ and style.
+
+ \sa setInsideSpacing(), orientation
+*/
+int Q3GroupBox::insideSpacing() const
+{
+ return d->spac;
+}
+
+/*!
+ Sets the the width of the inside margin to \a m pixels.
+
+ \sa insideMargin()
+*/
+void Q3GroupBox::setInsideMargin(int m)
+{
+ d->marg = m;
+ setColumnLayout(columns(), d->dir);
+}
+
+/*!
+ Sets the width of the empty space between each of the items in
+ the group to \a s pixels.
+
+ \sa insideSpacing()
+*/
+void Q3GroupBox::setInsideSpacing(int s)
+{
+ d->spac = s;
+ setColumnLayout(columns(), d->dir);
+}
+
+/*!
+ \property Q3GroupBox::orientation
+ \brief the group box's orientation
+
+ A horizontal group box arranges its children in columns, while a
+ vertical group box arranges them in rows.
+
+ Usually it is not a good idea to set this property because it is
+ slow (it does a complete layout). It is better to set the
+ orientation directly in the constructor.
+*/
+void Q3GroupBox::setOrientation(Qt::Orientation o)
+{
+ setColumnLayout(columns(), o);
+}
+
+
+Qt::Orientation Q3GroupBox::orientation() const
+{
+ return d->dir;
+}
+
+/*!
+ Changes the layout of the group box. This function is only useful
+ in combination with the default constructor that does not take any
+ layout information. This function will put all existing children
+ in the new layout. It is not good Qt programming style to call
+ this function after children have been inserted. Sets the number
+ of columns or rows to be \a strips, depending on \a direction.
+
+ \sa orientation columns
+*/
+void Q3GroupBox::setColumnLayout(int strips, Qt::Orientation direction)
+{
+ if (layout())
+ delete layout();
+
+ d->vbox = 0;
+ d->grid = 0;
+
+ if (strips < 0) // if 0, we create the d->vbox but not the d->grid. See below.
+ return;
+
+ d->vbox = new QVBoxLayout(this, d->marg, 0);
+
+ d->nCols = 0;
+ d->nRows = 0;
+ d->dir = direction;
+
+ // Send all child events and ignore them. Otherwise we will end up
+ // with doubled insertion. This won't do anything because d->nCols ==
+ // d->nRows == 0.
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+
+ // if 0 or smaller , create a vbox-layout but no grid. This allows
+ // the designer to handle its own grid layout in a group box.
+ if (strips <= 0)
+ return;
+
+ d->dir = direction;
+ if (d->dir == Qt::Horizontal) {
+ d->nCols = strips;
+ d->nRows = 1;
+ } else {
+ d->nCols = 1;
+ d->nRows = strips;
+ }
+ d->grid = new QGridLayout(d->nRows, d->nCols, d->spac);
+ d->row = d->col = 0;
+ d->grid->setAlignment(Qt::AlignTop);
+ d->vbox->addLayout(d->grid);
+
+ // Add all children
+ QObjectList childList = children();
+ if (!childList.isEmpty()) {
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ if (o->isWidgetType() && o != d->checkbox)
+ insertWid(static_cast<QWidget *>(o));
+ }
+ }
+}
+
+/*!\reimp */
+void Q3GroupBox::childEvent(QChildEvent *c)
+{
+ QGroupBox::childEvent(c);
+ if (!c->inserted() || !c->child()->isWidgetType())
+ return;
+ if (d->grid) {
+ insertWid((QWidget*)c->child());
+ }
+}
+
+void Q3GroupBox::insertWid(QWidget* w)
+{
+ if (d->row >= d->nRows || d->col >= d->nCols)
+ d->grid->expand(d->row+1, d->col+1);
+ d->grid->addWidget(w, d->row, d->col);
+ skip();
+}
+
+
+void Q3GroupBox::skip()
+{
+ // Same as QGrid::skip()
+ if (d->dir == Qt::Horizontal) {
+ if (d->col+1 < d->nCols) {
+ d->col++;
+ } else {
+ d->col = 0;
+ d->row++;
+ }
+ } else { //Vertical
+ if (d->row+1 < d->nRows) {
+ d->row++;
+ } else {
+ d->row = 0;
+ d->col++;
+ }
+ }
+}
+
+
+/*! \reimp */
+void Q3GroupBox::changeEvent(QEvent *ev)
+{
+ QGroupBox::changeEvent(ev);
+}
+
+/*! \reimp */
+bool Q3GroupBox::event(QEvent *e)
+{
+ if (e->type()==QEvent::Paint)
+ {
+ QStyleOptionGroupBox opt;
+ initStyleOption(&opt);
+ opt.lineWidth=d->lineWidth;
+ opt.midLineWidth=d->midLineWidth;
+ QPainter p(this);
+ if (frameShape()==GroupBoxPanel)
+ {
+ style()->drawComplexControl(QStyle::CC_GroupBox, &opt, &p, this);
+ }
+ else {
+ //in case it is a Paint event with a frame shape different from the group box
+ const QRect textRect = style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, this);
+ const QRect checkBoxRect = style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, this);
+
+ // Draw title
+ if ((opt.subControls & QStyle::SC_GroupBoxLabel) && !opt.text.isEmpty()) {
+ QColor textColor = opt.textColor;
+ if (textColor.isValid())
+ p.setPen(textColor);
+ int alignment = int(opt.textAlignment);
+ if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
+ alignment |= Qt::TextHideMnemonic;
+
+ style()->drawItemText(&p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ opt.palette, opt.state & QStyle::State_Enabled, opt.text,
+ textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
+
+ if (opt.state & QStyle::State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(opt);
+ fropt.rect = textRect;
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this);
+ }
+ }
+
+ // Draw checkbox
+ if (opt.subControls & QStyle::SC_GroupBoxCheckBox) {
+ QStyleOptionButton box;
+ box.QStyleOption::operator=(opt);
+ box.rect = checkBoxRect;
+ style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &box, &p, this);
+ }
+
+ //sets clipping
+ QRegion region(rect());
+ if (!title().isEmpty()) {
+ bool ltr = layoutDirection() == Qt::LeftToRight;
+ QRect finalRect = checkBoxRect.united(textRect);
+ if (isCheckable())
+ finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
+ region -= finalRect;
+ }
+ p.setClipRegion(region);
+
+ drawFrame(&p);
+ }
+ return false;
+ }
+ return QGroupBox::event(e);
+}
+
+/*!
+ \fn void Q3GroupBox::drawFrame(QPainter *p)
+ \internal
+*/
+
+void Q3GroupBox::drawFrame(QPainter *p)
+{
+ QPoint p1, p2;
+ QStyleOptionFrame opt;
+ opt.init(this);
+
+ int frameShape = d->frameStyle & QFrame::Shape_Mask;
+ int frameShadow = d->frameStyle & QFrame::Shadow_Mask;
+
+ int lw = 0;
+ int mlw = 0;
+ opt.rect = frameRect();
+
+ switch (frameShape) {
+ case QFrame::Box:
+ case QFrame::HLine:
+ case QFrame::VLine:
+ case QFrame::StyledPanel:
+ lw = d->lineWidth;
+ mlw = d->midLineWidth;
+ break;
+ default:
+ // most frame styles do not handle customized line and midline widths
+ // (see updateFrameWidth()).
+ lw = d->frameWidth;
+ break;
+ }
+ opt.lineWidth = lw;
+ opt.midLineWidth = mlw;
+ if (frameShadow == Sunken)
+ opt.state |= QStyle::State_Sunken;
+ else if (frameShadow == Raised)
+ opt.state |= QStyle::State_Raised;
+
+ switch (frameShape) {
+ case Box:
+ if (frameShadow == Plain)
+ qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw);
+ else
+ qDrawShadeRect(p, opt.rect, opt.palette, frameShadow == Sunken, lw, mlw);
+ break;
+
+ case StyledPanel:
+ style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);
+ break;
+
+ case Panel:
+ if (frameShadow == Plain)
+ qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw);
+ else
+ qDrawShadePanel(p, opt.rect, opt.palette, frameShadow == Sunken, lw);
+ break;
+
+ case WinPanel:
+ if (frameShadow == Plain)
+ qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw);
+ else
+ qDrawWinPanel(p, opt.rect, opt.palette, frameShadow == Sunken);
+ break;
+ case HLine:
+ case VLine:
+ if (frameShape == HLine) {
+ p1 = QPoint(opt.rect.x(), opt.rect.height() / 2);
+ p2 = QPoint(opt.rect.x() + opt.rect.width(), p1.y());
+ } else {
+ p1 = QPoint(opt.rect.x()+opt.rect.width() / 2, 0);
+ p2 = QPoint(p1.x(), opt.rect.height());
+ }
+ if (frameShadow == Plain) {
+ QPen oldPen = p->pen();
+ p->setPen(QPen(opt.palette.foreground().color(), lw));
+ p->drawLine(p1, p2);
+ p->setPen(oldPen);
+ } else {
+ qDrawShadeLine(p, p1, p2, opt.palette, frameShadow == Sunken, lw, mlw);
+ }
+ break;
+ }
+
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled() && hasFocus()) {
+ QStyleOptionFocusRect fopt;
+ fopt.init(this);
+ fopt.state |= QStyle::State_KeyboardFocusChange;
+ fopt.rect = frameRect();
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fopt, p, this);
+ }
+#endif
+}
+
+/*!
+ \property Q3GroupBox::frameShadow
+ \brief the frame shadow value from the frame style
+
+ \sa frameStyle()
+*/
+
+/*
+ \enum Q3GroupBox::FrameShape
+
+ This enum defines the available frame shapes a group box can
+ have. All values have equivalents in QFrame.
+
+ \value Box QFrame::Box
+ \value Sunken QFrame::Sunken
+ \value Plain QFrame::Plain
+ \value Raised QFrame::Raised
+ \value MShadow QFrame::Shadow_Mask
+ \value NoFrame QFrame::NoFrame
+ \value Panel QFrame::Panel
+ \value StyledPanel QFrame::StyledPanel
+ \value HLine QFrame::HLine
+ \value VLine QFrame::VLine
+ \value WinPanel QFrame::WinPanel
+ \value ToolBarPanel QFrame::StyledPanel
+ \value MenuBarPanel = QFrame::StyledPanel
+ \value PopupPanel QFrame::StyledPanel
+ \value LineEditPanel QFrame::StyledPanel
+ \value TabWidgetPanel QFrame::StyledPanel
+ \value GroupBoxPanel 0x0007
+ \value MShape QFrame::Shape_Mask
+*/
+
+
+void Q3GroupBox::setFrameShadow(DummyFrame s)
+{
+ setFrameStyle((d->frameStyle & MShape) | s);
+}
+
+Q3GroupBox::DummyFrame Q3GroupBox::frameShadow() const
+{
+ return (DummyFrame) (d->frameStyle & MShadow);
+}
+
+/*!
+ \property Q3GroupBox::frameShape
+ \brief the frame shape value from the frame style
+
+ \sa frameStyle(), frameShadow()
+*/
+
+void Q3GroupBox::setFrameShape(DummyFrame s)
+{
+ setFrameStyle((d->frameStyle & MShadow) | s);
+}
+
+Q3GroupBox::DummyFrame Q3GroupBox::frameShape() const
+{
+ return (DummyFrame) (d->frameStyle & MShape);
+}
+
+/*!
+ \fn void Q3GroupBox::setFrameStyle(int style)
+
+ Sets the frame style to \a style. The style is the bitwise OR
+ between a frame shape and a frame shadow style.
+*/
+
+void Q3GroupBox::setFrameStyle(int style)
+{
+ if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
+ switch (style & MShape) {
+ case HLine:
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ break;
+ case VLine:
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ break;
+ default:
+ if ((d->frameStyle & MShape) == HLine || (d->frameStyle & MShape) == VLine)
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ }
+ setAttribute(Qt::WA_WState_OwnSizePolicy, false);
+ }
+ d->frameStyle = style;
+ update();
+ d->updateFrameWidth();
+ d->oldFrameStyle = style;
+}
+
+/*!
+ \fn int Q3GroupBox::frameStyle() const
+
+ Returns the frame style.
+*/
+
+int Q3GroupBox::frameStyle() const
+{
+ return d->frameStyle;
+}
+
+/*!
+ \property Q3GroupBox::lineWidth
+ \brief This property holds the width of the line.
+
+ \sa frameStyle(), frameShadow()
+*/
+
+void Q3GroupBox::setLineWidth(int w)
+{
+ if (short(w) == d->lineWidth)
+ return;
+ d->lineWidth = short(w);
+ d->updateFrameWidth();
+}
+
+int Q3GroupBox::lineWidth() const
+{
+ return d->lineWidth;
+}
+
+/*!
+ \property Q3GroupBox::midLineWidth
+ \brief This property holds the width of the mid-line.
+
+ \sa frameStyle(), frameShadow()
+*/
+
+void Q3GroupBox::setMidLineWidth(int w)
+{
+ if (short(w) == d->midLineWidth)
+ return;
+ d->midLineWidth = short(w);
+ d->updateFrameWidth();
+}
+
+int Q3GroupBox::midLineWidth() const
+{
+ return d->midLineWidth;
+}
+
+/*!
+ \property Q3GroupBox::frameRect
+ \brief the bounding rectangle of the frame of the group box.
+*/
+
+/*!
+ \fn QRect Q3GroupBox::frameRect() const
+ \internal
+*/
+
+QRect Q3GroupBox::frameRect() const
+{
+ QStyleOptionGroupBox opt;
+ initStyleOption(&opt);
+ QRect fr = style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxFrame, this);
+ return fr;
+}
+
+/*!
+ \fn void Q3GroupBox::setFrameRect(QRect)
+ \internal
+*/
+
+void Q3GroupBox::setFrameRect(QRect r)
+{
+ QRect cr = r.isValid() ? r : rect();
+ if ((d->frameStyle & QFrame::Shape_Mask) == StyledPanel) {
+ cr.adjust(d->leftFrameWidth, d->topFrameWidth, -d->rightFrameWidth, -d->bottomFrameWidth);
+ } else
+ cr.adjust(d->frameWidth, d->frameWidth, -d->frameWidth, -d->frameWidth);
+ setContentsMargins(cr.left(), cr.top(), rect().right() - cr.right(), rect().bottom() - cr.bottom());
+}
+
+/*!
+ \fn int Q3GroupBox::frameWidth() const
+ \internal
+*/
+
+int Q3GroupBox::frameWidth() const
+{
+ return d->frameWidth;
+}
+
+#if defined(Q_MOC_RUN)
+/*!
+ \enum Q3GroupBox::FrameShape
+ \internal
+
+ \value Box
+ \value Sunken
+ \value Plain
+ \value Raised
+ \value MShadow
+ \value NoFrame
+ \value Panel
+ \value StyledPanel
+ \value HLine
+ \value VLine
+ \value GroupBoxPanel
+ \value WinPanel
+ \value ToolBarPanel
+ \value MenuBarPanel
+ \value PopupPanel
+ \value LineEditPanel
+ \value TabWidgetPanel
+ \value MShape
+*/
+#else
+/*!
+ \enum Q3GroupBox::DummyFrame
+ \internal
+
+ \value Box
+ \value Sunken
+ \value Plain
+ \value Raised
+ \value MShadow
+ \value NoFrame
+ \value Panel
+ \value StyledPanel
+ \value HLine
+ \value VLine
+ \value GroupBoxPanel
+ \value WinPanel
+ \value ToolBarPanel
+ \value MenuBarPanel
+ \value PopupPanel
+ \value LineEditPanel
+ \value TabWidgetPanel
+ \value MShape
+*/
+#endif
+
+/*!
+ \typedef Q3GroupBox::FrameShape
+ \internal
+*/
+
+/*!
+ \property Q3GroupBox::margin
+ \brief the width of the margin around the contents of the
+ group box.
+*/
+
+/*!
+ \fn void Q3GroupBox::setMargin(int margin)
+ \since 4.2
+
+ Sets the width of the margin around the contents of the widget to \a margin.
+
+ This function uses QWidget::setContentsMargins() to set the margin.
+ \sa margin(), QWidget::setContentsMargins()
+*/
+
+/*!
+ \fn int Q3GroupBox::margin() const
+ \since 4.2
+
+ Returns the width of the the margin around the contents of the widget.
+
+ This function uses QWidget::getContentsMargins() to get the margin.
+
+ \sa setMargin(), QWidget::getContentsMargins()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3groupbox.h b/src/qt3support/widgets/q3groupbox.h
new file mode 100644
index 0000000..39dc7e3
--- /dev/null
+++ b/src/qt3support/widgets/q3groupbox.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3GROUPBOX_H
+#define Q3GROUPBOX_H
+
+#include <QtGui/qgroupbox.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q3GroupBoxPrivate;
+
+class Q_COMPAT_EXPORT Q3GroupBox : public QGroupBox
+{
+ Q_OBJECT
+public:
+ enum
+#if defined(Q_MOC_RUN)
+ FrameShape
+#else
+ DummyFrame
+#endif
+ { Box = QFrame::Box, Sunken = QFrame::Sunken, Plain = QFrame::Plain,
+ Raised = QFrame::Raised, MShadow=QFrame::Shadow_Mask, NoFrame = QFrame::NoFrame,
+ Panel = QFrame::Panel, StyledPanel = QFrame::StyledPanel, HLine = QFrame::HLine,
+ VLine = QFrame::VLine,
+ WinPanel = QFrame::WinPanel,ToolBarPanel = QFrame::StyledPanel,
+ MenuBarPanel = QFrame::StyledPanel, PopupPanel = QFrame::StyledPanel,
+ LineEditPanel = QFrame::StyledPanel,TabWidgetPanel = QFrame::StyledPanel,
+ GroupBoxPanel = 0x0007,
+ MShape = QFrame::Shape_Mask};
+
+ typedef DummyFrame FrameShape;
+ Q_ENUMS(FrameShape)
+
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation DESIGNABLE false)
+ Q_PROPERTY(int columns READ columns WRITE setColumns DESIGNABLE false)
+
+ Q_PROPERTY(QRect frameRect READ frameRect WRITE setFrameRect DESIGNABLE false)
+ Q_PROPERTY(FrameShape frameShape READ frameShape WRITE setFrameShape)
+ Q_PROPERTY(FrameShape frameShadow READ frameShadow WRITE setFrameShadow)
+ Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth)
+ Q_PROPERTY(int midLineWidth READ midLineWidth WRITE setMidLineWidth)
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+
+public:
+ explicit Q3GroupBox(QWidget* parent=0, const char* name=0);
+ explicit Q3GroupBox(const QString &title,
+ QWidget* parent=0, const char* name=0);
+ Q3GroupBox(int strips, Qt::Orientation o,
+ QWidget* parent=0, const char* name=0);
+ Q3GroupBox(int strips, Qt::Orientation o, const QString &title,
+ QWidget* parent=0, const char* name=0);
+ ~Q3GroupBox();
+
+ virtual void setColumnLayout(int strips, Qt::Orientation o);
+
+ int columns() const;
+ void setColumns(int);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation);
+
+ int insideMargin() const;
+ int insideSpacing() const;
+ void setInsideMargin(int m);
+ void setInsideSpacing(int s);
+
+ void addSpace(int);
+
+ void setFrameRect(QRect);
+ QRect frameRect() const;
+#ifdef qdoc
+ void setFrameShadow(FrameShape);
+ FrameShape frameShadow() const;
+ void setFrameShape(FrameShape);
+ FrameShape frameShape() const;
+#else
+ void setFrameShadow(DummyFrame);
+ DummyFrame frameShadow() const;
+ void setFrameShape(DummyFrame);
+ DummyFrame frameShape() const;
+#endif
+ void setFrameStyle(int);
+ int frameStyle() const;
+ int frameWidth() const;
+ void setLineWidth(int);
+ int lineWidth() const;
+ void setMargin(int margin) { setContentsMargins(margin, margin, margin, margin); }
+ int margin() const
+ { int margin; int dummy; getContentsMargins(&margin, &dummy, &dummy, &dummy); return margin; }
+ void setMidLineWidth(int);
+ int midLineWidth() const;
+
+protected:
+ void childEvent(QChildEvent *);
+ void resizeEvent(QResizeEvent *);
+ void changeEvent(QEvent *);
+ bool event(QEvent *);
+
+private:
+ void skip();
+ void init();
+ void calculateFrame();
+ void insertWid(QWidget*);
+ void drawFrame(QPainter *p);
+
+ Q3GroupBoxPrivate * d;
+
+ Q_DISABLE_COPY(Q3GroupBox)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3GROUPBOX_H
diff --git a/src/qt3support/widgets/q3hbox.cpp b/src/qt3support/widgets/q3hbox.cpp
new file mode 100644
index 0000000..87fe2fa
--- /dev/null
+++ b/src/qt3support/widgets/q3hbox.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3hbox.h"
+#include "qlayout.h"
+#include "qapplication.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3HBox
+ \brief The Q3HBox widget provides horizontal geometry management
+ for its child widgets.
+
+ \compat
+
+ All the horizontal box's child widgets will be placed alongside
+ each other and sized according to their sizeHint()s.
+
+ Use setMargin() to add space around the edges, and use
+ setSpacing() to add space between the widgets. Use
+ setStretchFactor() if you want the widgets to be different sizes
+ in proportion to one another. (See \link layout.html
+ Layouts\endlink for more information on stretch factors.)
+
+ \img qhbox-m.png Q3HBox
+
+ \sa QHBoxLayout Q3VBox Q3Grid
+*/
+
+
+/*!
+ Constructs an hbox widget with parent \a parent, called \a name.
+ The parent, name and widget flags, \a f, are passed to the Q3Frame
+ constructor.
+*/
+Q3HBox::Q3HBox(QWidget *parent, const char *name, Qt::WindowFlags f)
+ :Q3Frame(parent, name, f)
+{
+ (new QHBoxLayout(this, frameWidth(), frameWidth(), name))->setAutoAdd(true);
+}
+
+
+/*!
+ Constructs a horizontal hbox if \a horizontal is TRUE, otherwise
+ constructs a vertical hbox (also known as a vbox).
+
+ This constructor is provided for the QVBox class. You should never
+ need to use it directly.
+
+ The \a parent, \a name and widget flags, \a f, are passed to the
+ Q3Frame constructor.
+*/
+
+Q3HBox::Q3HBox(bool horizontal, QWidget *parent , const char *name, Qt::WindowFlags f)
+ :Q3Frame(parent, name, f)
+{
+ (new QBoxLayout(this, horizontal ? QBoxLayout::LeftToRight : QBoxLayout::Down,
+ frameWidth(), frameWidth(), name))->setAutoAdd(true);
+}
+
+/*!\reimp
+ */
+void Q3HBox::frameChanged()
+{
+ if (layout())
+ layout()->setMargin(frameWidth());
+}
+
+
+/*!
+ Sets the spacing between the child widgets to \a space.
+*/
+
+void Q3HBox::setSpacing(int space)
+{
+ if (layout())
+ layout()->setSpacing(space);
+}
+
+
+/*!
+ \reimp
+*/
+
+QSize Q3HBox::sizeHint() const
+{
+ QWidget *mThis = (QWidget*)this;
+ QApplication::sendPostedEvents(mThis, QEvent::ChildInserted);
+ return Q3Frame::sizeHint();
+}
+
+/*!
+ Sets the stretch factor of widget \a w to \a stretch. Returns true if
+ \a w is found. Otherwise returns false.
+
+ \sa QBoxLayout::setStretchFactor() \link layout.html Layouts\endlink
+*/
+bool Q3HBox::setStretchFactor(QWidget* w, int stretch)
+{
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+ if (QBoxLayout *lay = qobject_cast<QBoxLayout *>(layout()))
+ return lay->setStretchFactor(w, stretch);
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3hbox.h b/src/qt3support/widgets/q3hbox.h
new file mode 100644
index 0000000..71a6d04
--- /dev/null
+++ b/src/qt3support/widgets/q3hbox.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3HBOX_H
+#define Q3HBOX_H
+
+#include <Qt3Support/q3frame.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class QBoxLayout;
+
+class Q_COMPAT_EXPORT Q3HBox : public Q3Frame
+{
+ Q_OBJECT
+public:
+ Q3HBox(QWidget* parent=0, const char* name=0, Qt::WindowFlags f=0);
+
+ void setSpacing(int);
+ bool setStretchFactor(QWidget*, int stretch);
+ QSize sizeHint() const;
+
+protected:
+ Q3HBox(bool horizontal, QWidget* parent, const char* name, Qt::WindowFlags f = 0);
+ void frameChanged();
+
+private:
+ Q_DISABLE_COPY(Q3HBox)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3HBOX_H
diff --git a/src/qt3support/widgets/q3header.cpp b/src/qt3support/widgets/q3header.cpp
new file mode 100644
index 0000000..69c5e8b
--- /dev/null
+++ b/src/qt3support/widgets/q3header.cpp
@@ -0,0 +1,2040 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3header.h"
+#ifndef QT_NO_HEADER
+#include "qapplication.h"
+#include "qbitarray.h"
+#include "qcursor.h"
+#include "qdrawutil.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qpixmap.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qvector.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3HeaderData
+{
+public:
+ Q3HeaderData(int n)
+ {
+ count = n;
+ sizes.resize(n);
+ positions.resize(n);
+ labels.resize(n);
+ nullStringLabels.resize(n);
+ icons.resize(n);
+ i2s.resize(n);
+ s2i.resize(n);
+ clicks.resize(n);
+ resize.resize(n);
+ int p =0;
+ for (int i = 0; i < n; i ++) {
+ sizes[i] = 88;
+ i2s[i] = i;
+ s2i[i] = i;
+ positions[i] = p;
+ p += sizes[i];
+ }
+ clicks_default = true;
+ resize_default = true;
+ clicks.fill(clicks_default);
+ resize.fill(resize_default);
+ move = true;
+ sortSection = -1;
+ sortDirection = true;
+ positionsDirty = true;
+ lastPos = 0;
+ fullSize = -2;
+ pos_dirty = false;
+ is_a_table_header = false;
+ focusIdx = 0;
+ }
+ ~Q3HeaderData()
+ {
+ for (int i = 0; i < icons.size(); ++i)
+ delete icons.at(i);
+ }
+
+
+ QVector<int> sizes;
+ int height; // we abuse the heights as widths for vertical layout
+ bool heightDirty;
+ QVector<int> positions; // sorted by index
+ QVector<QString> labels;
+ QVector<QIcon *> icons;
+ QVector<int> i2s;
+ QVector<int> s2i;
+
+ QBitArray clicks;
+ QBitArray resize;
+ QBitArray nullStringLabels;
+ uint move : 1;
+ uint clicks_default : 1; // default value for new clicks bits
+ uint resize_default : 1; // default value for new resize bits
+ uint pos_dirty : 1;
+ uint is_a_table_header : 1;
+ bool sortDirection;
+ bool positionsDirty;
+ int sortSection;
+ int count;
+ int lastPos;
+ int fullSize;
+ int focusIdx;
+ int pressDelta;
+
+ int sectionAt(int pos) {
+ // positions is sorted by index, not by section
+ if (!count)
+ return -1;
+ int l = 0;
+ int r = count - 1;
+ int i = ((l+r+1) / 2);
+ while (r - l) {
+ if (positions[i] > pos)
+ r = i -1;
+ else
+ l = i;
+ i = ((l+r+1) / 2);
+ }
+ if (positions[i] <= pos && pos <= positions[i] + sizes[i2s[i]])
+ return i2s[i];
+ return -1;
+ }
+};
+
+static QStyleOptionHeader getStyleOption(const Q3Header *header, int section)
+{
+ QStyleOptionHeader opt;
+ opt.init(header);
+ opt.section = section;
+ opt.textAlignment = Qt::AlignVCenter;
+ opt.iconAlignment = Qt::AlignVCenter;
+ if (header->iconSet(section))
+ opt.icon = *header->iconSet(section);
+ opt.text = header->label(section);
+ if (header->orientation() == Qt::Horizontal)
+ opt.state = QStyle::State_Horizontal;
+ return opt;
+}
+
+bool qt_get_null_label_bit(Q3HeaderData *data, int section)
+{
+ return data->nullStringLabels.testBit(section);
+}
+
+void qt_set_null_label_bit(Q3HeaderData *data, int section, bool b)
+{
+ data->nullStringLabels.setBit(section, b);
+}
+
+/*!
+ \class Q3Header
+ \brief The Q3Header class provides a header row or column, e.g. for
+ tables and listviews.
+
+ \compat
+
+ This class provides a header, e.g. a vertical header to display
+ row labels, or a horizontal header to display column labels. It is
+ used by Q3Table and Q3ListView for example.
+
+ A header is composed of one or more \e sections, each of which can
+ display a text label and an \link QIcon icon\endlink. A sort
+ indicator (an arrow) can also be displayed using
+ setSortIndicator().
+
+ Sections are added with addLabel() and removed with removeLabel().
+ The label and icon are set in addLabel() and can be changed
+ later with setLabel(). Use count() to retrieve the number of
+ sections in the header.
+
+ The orientation of the header is set with setOrientation(). If
+ setStretchEnabled() is true, the sections will expand to take up
+ the full width (height for vertical headers) of the header. The
+ user can resize the sections manually if setResizeEnabled() is
+ true. Call adjustHeaderSize() to have the sections resize to
+ occupy the full width (or height).
+
+ A section can be moved with moveSection(). If setMovingEnabled()
+ is true (the default)the user may drag a section from one position
+ to another. If a section is moved, the index positions at which
+ sections were added (with addLabel()), may not be the same after the
+ move. You don't have to worry about this in practice because the
+ Q3Header API works in terms of section numbers, so it doesn't matter
+ where a particular section has been moved to.
+
+ If you want the current index position of a section call
+ mapToIndex() giving it the section number. (This is the number
+ returned by the addLabel() call which created the section.) If you
+ want to get the section number of a section at a particular index
+ position call mapToSection() giving it the index number.
+
+ Here's an example to clarify mapToSection() and mapToIndex():
+
+ \table
+ \header \i41 Index positions
+ \row \i 0 \i 1 \i 2 \i 3
+ \header \i41 Original section ordering
+ \row \i Sect 0 \i Sect 1 \i Sect 2 \i Sect 3
+ \header \i41 Ordering after the user moves a section
+ \row \i Sect 0 \i Sect 2 \i Sect 3 \i Sect 1
+ \endtable
+
+ \table
+ \header \i \e k \i mapToSection(\e k) \i mapToIndex(\e k)
+ \row \i 0 \i 0 \i 0
+ \row \i 1 \i 2 \i 3
+ \row \i 2 \i 3 \i 1
+ \row \i 3 \i 1 \i 2
+ \endtable
+
+ In the example above, if we wanted to find out which section is at
+ index position 3 we'd call mapToSection(3) and get a section
+ number of 1 since section 1 was moved. Similarly, if we wanted to
+ know which index position section 2 occupied we'd call
+ mapToIndex(2) and get an index of 1.
+
+ Q3Header provides the clicked(), pressed() and released() signals.
+ If the user changes the size of a section, the sizeChange() signal
+ is emitted. If you want to have a sizeChange() signal emitted
+ continuously whilst the user is resizing (rather than just after
+ the resizing is finished), use setTracking(). If the user moves a
+ section the indexChange() signal is emitted.
+
+ \sa Q3ListView Q3Table
+*/
+
+
+
+/*!
+ Constructs a horizontal header called \a name, with parent \a
+ parent.
+*/
+
+Q3Header::Q3Header(QWidget *parent, const char *name)
+ : QWidget(parent, name, Qt::WStaticContents)
+{
+ orient = Qt::Horizontal;
+ init(0);
+}
+
+/*!
+ Constructs a horizontal header called \a name, with \a n sections
+ and parent \a parent.
+*/
+
+Q3Header::Q3Header(int n, QWidget *parent, const char *name)
+ : QWidget(parent, name, Qt::WStaticContents)
+{
+ orient = Qt::Horizontal;
+ init(n);
+}
+
+/*!
+ Destroys the header and all its sections.
+*/
+
+Q3Header::~Q3Header()
+{
+ delete d;
+ d = 0;
+}
+
+/*! \reimp
+ */
+
+void Q3Header::showEvent(QShowEvent *e)
+{
+ calculatePositions();
+ QWidget::showEvent(e);
+}
+
+/*!
+ \fn void Q3Header::sizeChange(int section, int oldSize, int newSize)
+
+ This signal is emitted when the user has changed the size of a \a
+ section from \a oldSize to \a newSize. This signal is typically
+ connected to a slot that repaints the table or list that contains
+ the header.
+*/
+
+/*!
+ \fn void Q3Header::clicked(int section)
+
+ If isClickEnabled() is true, this signal is emitted when the user
+ clicks section \a section.
+
+ \sa pressed(), released()
+*/
+
+/*!
+ \fn void Q3Header::pressed(int section)
+
+ This signal is emitted when the user presses section \a section
+ down.
+
+ \sa released()
+*/
+
+/*!
+ \fn void Q3Header::released(int section)
+
+ This signal is emitted when section \a section is released.
+
+ \sa pressed()
+*/
+
+
+/*!
+ \fn void Q3Header::indexChange(int section, int fromIndex, int toIndex)
+
+ This signal is emitted when the user moves section \a section from
+ index position \a fromIndex, to index position \a toIndex.
+*/
+
+/*!
+ \fn void Q3Header::moved(int fromIndex, int toIndex)
+
+ Use indexChange() instead.
+
+ This signal is emitted when the user has moved the section which
+ is displayed at the index \a fromIndex to the index \a toIndex.
+*/
+
+/*!
+ \fn void Q3Header::sectionClicked(int index)
+
+ Use clicked() instead.
+
+ This signal is emitted when a part of the header is clicked. \a
+ index is the index at which the section is displayed.
+
+ In a list view this signal would typically be connected to a slot
+ that sorts the specified column (or row).
+*/
+
+/*! \fn int Q3Header::cellSize(int) const
+
+ Use sectionSize() instead.
+
+ Returns the size in pixels of the section that is displayed at
+ the index \a i.
+*/
+
+/*!
+ \fn void Q3Header::sectionHandleDoubleClicked(int section)
+
+ This signal is emitted when the user doubleclicks on the edge
+ (handle) of section \a section.
+*/
+
+/*!
+
+ Use sectionPos() instead.
+
+ Returns the position in pixels of the section that is displayed at the
+ index \a i. The position is measured from the start of the header.
+*/
+
+int Q3Header::cellPos(int i) const
+{
+ if (i == count() && i > 0)
+ return d->positions[i-1] + d->sizes[d->i2s[i-1]]; // compatibility
+ return sectionPos(mapToSection(i));
+}
+
+
+/*!
+ \property Q3Header::count
+ \brief the number of sections in the header
+*/
+
+int Q3Header::count() const
+{
+ return d->count;
+}
+
+
+/*!
+ \property Q3Header::tracking
+ \brief whether the sizeChange() signal is emitted continuously
+
+ If tracking is on, the sizeChange() signal is emitted continuously
+ while the mouse is moved (i.e. when the header is resized),
+ otherwise it is only emitted when the mouse button is released at
+ the end of resizing.
+
+ Tracking defaults to false.
+*/
+
+
+/*
+ Initializes with \a n columns.
+*/
+void Q3Header::init(int n)
+{
+ state = Idle;
+ cachedPos = 0; // unused
+ d = new Q3HeaderData(n);
+ d->height = 0;
+ d->heightDirty = true;
+ offs = 0;
+ if(reverse())
+ offs = d->lastPos - width();
+ oldHandleIdx = oldHIdxSize = handleIdx = 0;
+
+ setMouseTracking(true);
+ trackingIsOn = false;
+ setBackgroundRole(QPalette::Button);
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ setAttribute(Qt::WA_PaintOutsidePaintEvent);
+}
+
+/*!
+ \property Q3Header::orientation
+ \brief the header's orientation
+
+ The orientation is either Qt::Vertical or Qt::Horizontal (the
+ default).
+
+ Call setOrientation() before adding labels if you don't provide a
+ size parameter otherwise the sizes will be incorrect.
+*/
+
+void Q3Header::setOrientation(Qt::Orientation orientation)
+{
+ if (orient == orientation)
+ return;
+ orient = orientation;
+ if (orient == Qt::Horizontal)
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ else
+ setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
+ update();
+ updateGeometry();
+}
+
+
+/*
+ Paints a rectangle starting at \a p, with length \s.
+*/
+void Q3Header::paintRect(int p, int s)
+{
+ QPainter paint(this);
+ paint.setPen(QPen(Qt::black, 1, Qt::DotLine));
+ if (reverse())
+ paint.drawRect(p - s, 3, s, height() - 5);
+ else if (orient == Qt::Horizontal)
+ paint.drawRect(p, 3, s, height() - 5);
+ else
+ paint.drawRect(3, p, height() - 5, s);
+}
+
+/*
+ Marks the division line at \a idx.
+*/
+void Q3Header::markLine(int idx)
+{
+ QPainter paint(this);
+ paint.setPen(QPen(Qt::black, 1, Qt::DotLine));
+ int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
+ int p = pPos(idx);
+ int x = p - MARKSIZE/2;
+ int y = 2;
+ int x2 = p + MARKSIZE/2;
+ int y2 = height() - 3;
+ if (orient == Qt::Vertical) {
+ int t = x; x = y; y = t;
+ t = x2; x2 = y2; y2 = t;
+ }
+
+ paint.drawLine(x, y, x2, y);
+ paint.drawLine(x, y+1, x2, y+1);
+
+ paint.drawLine(x, y2, x2, y2);
+ paint.drawLine(x, y2-1, x2, y2-1);
+
+ paint.drawLine(x, y, x, y2);
+ paint.drawLine(x+1, y, x+1, y2);
+
+ paint.drawLine(x2, y, x2, y2);
+ paint.drawLine(x2-1, y, x2-1, y2);
+}
+
+/*
+ Removes the mark at the division line at \a idx.
+*/
+void Q3Header::unMarkLine(int idx)
+{
+ if (idx < 0)
+ return;
+ int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
+ int p = pPos(idx);
+ int x = p - MARKSIZE/2;
+ int y = 2;
+ int x2 = p + MARKSIZE/2;
+ int y2 = height() - 3;
+ if (orient == Qt::Vertical) {
+ int t = x; x = y; y = t;
+ t = x2; x2 = y2; y2 = t;
+ }
+ repaint(x, y, x2-x+1, y2-y+1);
+}
+
+/*! \fn int Q3Header::cellAt(int) const
+
+ Use sectionAt() instead.
+
+ Returns the index at which the section is displayed, which contains
+ \a pos in widget coordinates, or -1 if \a pos is outside the header
+ sections.
+*/
+
+/*
+ Tries to find a line that is not a neighbor of \c handleIdx.
+*/
+int Q3Header::findLine(int c)
+{
+ int i = 0;
+ if (c > d->lastPos || (reverse() && c < 0)) {
+ return d->count;
+ } else {
+ int section = sectionAt(c);
+ if (section < 0)
+ return handleIdx;
+ i = d->s2i[section];
+ }
+ int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
+ if (i == handleIdx)
+ return i;
+ if (i == handleIdx - 1 && pPos(handleIdx) - c > MARKSIZE/2)
+ return i;
+ if (i == handleIdx + 1 && c - pPos(i) > MARKSIZE/2)
+ return i + 1;
+ if (c - pPos(i) > pSize(i) / 2)
+ return i + 1;
+ else
+ return i;
+}
+
+/*!
+ Returns the handle at position \a p, or -1 if there is no handle at \a p.
+*/
+int Q3Header::handleAt(int p)
+{
+ int section = d->sectionAt(p);
+ if (section >= 0) {
+ int GripMargin = (bool)d->resize[section] ?
+ style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
+ int index = d->s2i[section];
+ if ((index > 0 && p < d->positions[index] + GripMargin) ||
+ (p > d->positions[index] + d->sizes[section] - GripMargin)) {
+ if (index > 0 && p < d->positions[index] + GripMargin)
+ section = d->i2s[--index];
+ // don't show icon if streaching is enabled it is at the end of the last section
+ if (d->resize.testBit(section) && (d->fullSize == -2 || index != count() - 1)) {
+ return section;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/*!
+ Use moveSection() instead.
+
+ Moves the section that is currently displayed at index \a fromIdx
+ to index \a toIdx.
+*/
+
+void Q3Header::moveCell(int fromIdx, int toIdx)
+{
+ moveSection(mapToSection(fromIdx), toIdx);
+}
+
+
+
+/*!
+ Move and signal and repaint.
+ */
+
+void Q3Header::handleColumnMove(int fromIdx, int toIdx)
+{
+ int s = d->i2s[fromIdx];
+ if (fromIdx < toIdx)
+ toIdx++; //Convert to
+ QRect r = sRect(fromIdx);
+ r |= sRect(toIdx);
+ moveSection(s, toIdx);
+ update(r);
+ emit moved(fromIdx, toIdx);
+ emit indexChange(s, fromIdx, toIdx);
+}
+
+/*!
+ \reimp
+*/
+void Q3Header::keyPressEvent(QKeyEvent *e)
+{
+ int i = d->focusIdx;
+ if (e->key() == Qt::Key_Space) {
+ //don't do it if we're doing something with the mouse
+ if (state == Idle && d->clicks[d->i2s[d->focusIdx] ]) {
+ handleIdx = i;
+ state = Pressed;
+ repaint(sRect(handleIdx));
+ emit pressed(d->i2s[i]);
+ }
+ } else if ((orientation() == Qt::Horizontal && (e->key() == Qt::Key_Right || e->key() == Qt::Key_Left))
+ || (orientation() == Qt::Vertical && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
+ int dir = e->key() == Qt::Key_Right || e->key() == Qt::Key_Down ? 1 : -1;
+ int s = d->i2s[i];
+ if (e->state() & Qt::ControlButton && d->resize[s]) {
+ //resize
+ int step = e->state() & Qt::ShiftButton ? dir : 10*dir;
+ int c = d->positions[i] + d->sizes[s] + step;
+ handleColumnResize(i, c, true);
+ } else if (e->state() & (Qt::AltButton|Qt::MetaButton) && d->move) {
+ //move section
+ int i2 = (i + count() + dir) % count();
+ d->focusIdx = i2;
+ handleColumnMove(i, i2);
+ } else {
+ //focus on different section
+ QRect r = sRect(d->focusIdx);
+ d->focusIdx = (d->focusIdx + count() + dir) % count();
+ r |= sRect(d->focusIdx);
+ update(r);
+ }
+ } else {
+ e->ignore();
+ }
+}
+
+/*!
+ \reimp
+*/
+void Q3Header::keyReleaseEvent(QKeyEvent *e)
+{
+ switch (e->key()) {
+ case Qt::Key_Space:
+ //double check that this wasn't started with the mouse
+ if (state == Pressed && handleIdx == d->focusIdx) {
+ repaint(sRect(handleIdx));
+ int section = d->i2s[d->focusIdx];
+ emit released(section);
+ emit sectionClicked(handleIdx);
+ emit clicked(section);
+ state = Idle;
+ handleIdx = -1;
+ }
+ break;
+ default:
+ e->ignore();
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void Q3Header::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton || state != Idle)
+ return;
+ oldHIdxSize = handleIdx;
+ handleIdx = 0;
+ int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
+ c += offset();
+ if (reverse())
+ c = d->lastPos - c;
+
+ int section = d->sectionAt(c);
+ if (section < 0)
+ return;
+ int GripMargin = (bool)d->resize[section] ?
+ style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
+ int index = d->s2i[section];
+
+ if ((index > 0 && c < d->positions[index] + GripMargin) ||
+ (c > d->positions[index] + d->sizes[section] - GripMargin)) {
+ if (c < d->positions[index] + GripMargin)
+ handleIdx = index-1;
+ else
+ handleIdx = index;
+ if (d->lastPos <= (orient == Qt::Horizontal ? width() :
+ height()) && d->fullSize != -2 && handleIdx == count() - 1) {
+ handleIdx = -1;
+ return;
+ }
+ oldHIdxSize = d->sizes[d->i2s[handleIdx]];
+ state = d->resize[d->i2s[handleIdx] ] ? Sliding : Blocked;
+ } else if (index >= 0) {
+ oldHandleIdx = handleIdx = index;
+ moveToIdx = -1;
+ state = d->clicks[d->i2s[handleIdx] ] ? Pressed : Blocked;
+ clickPos = c;
+ repaint(sRect(handleIdx));
+ if(oldHandleIdx != handleIdx)
+ repaint(sRect(oldHandleIdx));
+ emit pressed(section);
+ }
+
+ d->pressDelta = c - (d->positions[handleIdx] + d->sizes[d->i2s[handleIdx]]);
+}
+
+/*!
+ \reimp
+*/
+void Q3Header::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+ int oldOldHandleIdx = oldHandleIdx;
+ State oldState = state;
+ state = Idle;
+ switch (oldState) {
+ case Pressed: {
+ int section = d->i2s[handleIdx];
+ emit released(section);
+ if (sRect(handleIdx).contains(e->pos())) {
+ oldHandleIdx = handleIdx;
+ emit sectionClicked(handleIdx);
+ emit clicked(section);
+ } else {
+ handleIdx = oldHandleIdx;
+ }
+ repaint(sRect(handleIdx));
+ if (oldOldHandleIdx != handleIdx)
+ repaint(sRect(oldOldHandleIdx));
+ } break;
+ case Sliding: {
+ int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
+ c += offset();
+ if (reverse())
+ c = d->lastPos - c;
+ handleColumnResize(handleIdx, c - d->pressDelta, true);
+ } break;
+ case Moving: {
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ int section = d->i2s[handleIdx];
+ if (handleIdx != moveToIdx && moveToIdx != -1) {
+ moveSection(section, moveToIdx);
+ handleIdx = oldHandleIdx;
+ emit moved(handleIdx, moveToIdx);
+ emit indexChange(section, handleIdx, moveToIdx);
+ emit released(section);
+ repaint(); // a bit overkill, but removes the handle as well
+ } else {
+ if (sRect(handleIdx).contains(e->pos())) {
+ oldHandleIdx = handleIdx;
+ emit released(section);
+ emit sectionClicked(handleIdx);
+ emit clicked(section);
+ } else {
+ handleIdx = oldHandleIdx;
+ }
+ repaint(sRect(handleIdx));
+ if(oldOldHandleIdx != handleIdx)
+ repaint(sRect(oldOldHandleIdx));
+ }
+ break;
+ }
+ case Blocked:
+ //nothing
+ break;
+ default:
+ // empty, probably. Idle, at any rate.
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void Q3Header::mouseMoveEvent(QMouseEvent *e)
+{
+ int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
+ c += offset();
+
+ int pos = c;
+ if(reverse())
+ c = d->lastPos - c;
+
+ switch(state) {
+ case Idle:
+#ifndef QT_NO_CURSOR
+ if (handleAt(c) < 0)
+ unsetCursor();
+ else if (orient == Qt::Horizontal)
+ setCursor(Qt::splitHCursor);
+ else
+ setCursor(Qt::splitVCursor);
+#endif
+ break;
+ case Blocked:
+ break;
+ case Pressed:
+ if (QABS(c - clickPos) > 4 && d->move) {
+ state = Moving;
+ moveToIdx = -1;
+#ifndef QT_NO_CURSOR
+ if (orient == Qt::Horizontal)
+ setCursor(Qt::SizeHorCursor);
+ else
+ setCursor(Qt::SizeVerCursor);
+#endif
+ }
+ break;
+ case Sliding:
+ handleColumnResize(handleIdx, c, false, false);
+ break;
+ case Moving: {
+ int newPos = findLine(pos);
+ if (newPos != moveToIdx) {
+ if (moveToIdx == handleIdx || moveToIdx == handleIdx + 1)
+ repaint(sRect(handleIdx));
+ else
+ unMarkLine(moveToIdx);
+ moveToIdx = newPos;
+ if (moveToIdx == handleIdx || moveToIdx == handleIdx + 1)
+ paintRect(pPos(handleIdx), pSize(handleIdx));
+ else
+ markLine(moveToIdx);
+ }
+ break;
+ }
+ default:
+ qWarning("Q3Header::mouseMoveEvent: (%s) unknown state", objectName().toLocal8Bit().data());
+ break;
+ }
+}
+
+/*! \reimp */
+
+void Q3Header::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ int p = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
+ p += offset();
+ if(reverse())
+ p = d->lastPos - p;
+
+ int header = handleAt(p);
+ if (header >= 0)
+ emit sectionHandleDoubleClicked(header);
+}
+
+/*
+ Handles resizing of sections. This means it redraws the relevant parts
+ of the header.
+*/
+
+void Q3Header::handleColumnResize(int index, int c, bool final, bool recalcAll)
+{
+ int section = d->i2s[index];
+ int GripMargin = (bool)d->resize[section] ?
+ style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
+ int lim = d->positions[index] + 2*GripMargin;
+ if (c == lim)
+ return;
+ if (c < lim)
+ c = lim;
+ int oldSize = d->sizes[section];
+ int newSize = c - d->positions[index];
+ d->sizes[section] = newSize;
+
+ calculatePositions(!recalcAll, !recalcAll ? section : 0);
+
+ int pos = d->positions[index]-offset();
+ if(reverse()) // repaint the whole thing. Could be optimized (lars)
+ repaint(0, 0, width(), height());
+ else if (orient == Qt::Horizontal)
+ repaint(pos, 0, width() - pos, height());
+ else
+ repaint(0, pos, width(), height() - pos);
+
+ int os = 0, ns = 0;
+ if (tracking() && oldSize != newSize) {
+ os = oldSize;
+ ns = newSize;
+ emit sizeChange(section, oldSize, newSize);
+ } else if (!tracking() && final && oldHIdxSize != newSize) {
+ os = oldHIdxSize;
+ ns = newSize;
+ emit sizeChange(section, oldHIdxSize, newSize);
+ }
+
+ if (os != ns) {
+ if (d->fullSize == -1) {
+ d->fullSize = count() - 1;
+ adjustHeaderSize();
+ d->fullSize = -1;
+ } else if (d->fullSize >= 0) {
+ int old = d->fullSize;
+ d->fullSize = count() - 1;
+ adjustHeaderSize();
+ d->fullSize = old;
+ }
+ }
+}
+
+/*!
+ Returns the rectangle covered by the section at index \a index.
+*/
+
+QRect Q3Header::sRect(int index)
+{
+
+ int section = mapToSection(index);
+ if (count() > 0 && index >= count()) {
+ int s = d->positions[count() - 1] - offset() +
+ d->sizes[mapToSection(count() - 1)];
+ if (orient == Qt::Horizontal)
+ return QRect(s, 0, width() - s + 10, height());
+ else
+ return QRect(0, s, width(), height() - s + 10);
+ }
+ if (section < 0)
+ return rect(); // ### eeeeevil
+
+ if (reverse())
+ return QRect( d->lastPos - d->positions[index] - d->sizes[section] -offset(),
+ 0, d->sizes[section], height());
+ else if (orient == Qt::Horizontal)
+ return QRect( d->positions[index]-offset(), 0, d->sizes[section], height());
+ else
+ return QRect(0, d->positions[index]-offset(), width(), d->sizes[section]);
+}
+
+/*!
+ Returns the rectangle covered by section \a section.
+*/
+
+QRect Q3Header::sectionRect(int section) const
+{
+ int index = mapToIndex(section);
+ if (section < 0)
+ return rect(); // ### eeeeevil
+
+ if (reverse())
+ return QRect( d->lastPos - d->positions[index] - d->sizes[section] -offset(),
+ 0, d->sizes[section], height());
+ else if (orient == Qt::Horizontal)
+ return QRect( d->positions[index]-offset(), 0, d->sizes[section], height());
+ else
+ return QRect(0, d->positions[index]-offset(), width(), d->sizes[section]);
+}
+
+/*!
+ \overload
+
+ Sets the icon for section \a section to \a icon and the text to
+ \a s. The section's width is set to \a size if \a size \>= 0;
+ otherwise it is left unchanged.
+
+ If the section does not exist, nothing happens.
+*/
+
+void Q3Header::setLabel(int section, const QIcon& icon,
+ const QString &s, int size)
+{
+ if (section < 0 || section >= count())
+ return;
+ delete d->icons[section];
+ d->icons[section] = new QIcon(icon);
+ setLabel(section, s, size);
+}
+
+/*!
+ Sets the text of section \a section to \a s. The section's width
+ is set to \a size if \a size \>= 0; otherwise it is left
+ unchanged. Any icon set that has been set for this section remains
+ unchanged.
+
+ If the section does not exist, nothing happens.
+*/
+void Q3Header::setLabel(int section, const QString &s, int size)
+{
+ if (section < 0 || section >= count())
+ return;
+ d->labels[section] = s;
+ d->nullStringLabels.setBit(section, s.isNull());
+
+ setSectionSizeAndHeight(section, size);
+
+ if (updatesEnabled()) {
+ updateGeometry();
+ calculatePositions();
+ update();
+ }
+}
+
+
+bool qt_qheader_label_return_null_strings = false;
+/*!
+ Returns the text for section \a section. If the section does not
+ exist, returns an empty string.
+*/
+QString Q3Header::label(int section) const
+{
+ if (section < 0 || section >= count())
+ return QString();
+ QString l = d->labels.value(section);
+ if (!l.isNull())
+ return l;
+ if (d->nullStringLabels.testBit(section) || qt_qheader_label_return_null_strings)
+ return l;
+ else
+ return QString::number(section + 1);
+}
+
+/*!
+ Returns the icon set for section \a section. If the section does
+ not exist, 0 is returned.
+*/
+
+QIcon *Q3Header::iconSet(int section) const
+{
+ if (section < 0 || section >= count())
+ return 0;
+ return d->icons[section];
+}
+
+
+/*!
+ \overload
+
+ Adds a new section with icon \a icon and label text \a s.
+ Returns the index position where the section was added (at the
+ right for horizontal headers, at the bottom for vertical headers).
+ The section's width is set to \a size, unless size is negative in
+ which case the size is calculated taking account of the size of
+ the text.
+*/
+int Q3Header::addLabel(const QIcon& icon, const QString &s, int size)
+{
+ int n = count() + 1;
+ d->icons.resize(n + 1);
+ d->icons.insert(n - 1, new QIcon(icon));
+ return addLabel(s, size);
+}
+
+/*!
+ Removes section \a section. If the section does not exist, nothing
+ happens.
+*/
+void Q3Header::removeLabel(int section)
+{
+ if (section < 0 || section > count() - 1)
+ return;
+
+ int index = d->s2i[section];
+ int n = --d->count;
+ int i;
+ for (i = section; i < n; ++i) {
+ d->sizes[i] = d->sizes[i+1];
+ d->labels[i] = d->labels[i+1];
+ d->labels[i+1] = QString();
+ d->nullStringLabels[i] = d->nullStringLabels[i+1];
+ d->nullStringLabels[i+1] = 0;
+ d->icons[i] = d->icons[i+1];
+ d->icons[i+1] = 0;
+ }
+
+ d->sizes.resize(n);
+ d->positions.resize(n);
+ d->labels.resize(n);
+ d->nullStringLabels.resize(n);
+ d->icons.resize(n);
+
+ for (i = section; i < n; ++i)
+ d->s2i[i] = d->s2i[i+1];
+ d->s2i.resize(n);
+
+ if (updatesEnabled()) {
+ for (i = 0; i < n; ++i)
+ if (d->s2i[i] > index)
+ --d->s2i[i];
+ }
+
+ for (i = index; i < n; ++i)
+ d->i2s[i] = d->i2s[i+1];
+ d->i2s.resize(n);
+
+ if (updatesEnabled()) {
+ for (i = 0; i < n; ++i)
+ if (d->i2s[i] > section)
+ --d->i2s[i];
+ }
+
+ if (updatesEnabled()) {
+ updateGeometry();
+ calculatePositions();
+ update();
+ }
+}
+
+QSize Q3Header::sectionSizeHint(int section, const QFontMetrics& fm) const
+{
+ int iw = 0;
+ int ih = 0;
+ if (d->icons[section] != 0) {
+ QSize isize = d->icons[section]->pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize),
+ QIcon::Normal).size();
+ iw = isize.width() + 2;
+ ih = isize.height();
+ }
+
+ QRect bound;
+ QString label = d->labels[section];
+ if (!label.isNull() || d->nullStringLabels.testBit(section)) {
+ int lines = label.count(QLatin1Char('\n')) + 1;
+ int w = 0;
+ if (lines > 1) {
+ bound.setHeight(fm.height() + fm.lineSpacing() * (lines - 1));
+ QStringList list = label.split(QLatin1Char('\n'));
+ for (int i=0; i < list.count(); ++i) {
+ int tmpw = fm.width(list.at(i));
+ w = QMAX(w, tmpw);
+ }
+ } else {
+ bound.setHeight(fm.height());
+ w = fm.width(label);
+ }
+ bound.setWidth(w);
+ }
+ int arrowWidth = 0;
+ if (d->sortSection == section)
+ arrowWidth = ((orient == Qt::Horizontal ? height() : width()) / 2) + 8;
+ int height = qMax(bound.height() + 2, ih) + 4;
+ int width = bound.width() + style()->pixelMetric(QStyle::PM_HeaderMargin) * 4
+ + iw + arrowWidth;
+ return QSize(width, height);
+}
+
+/*
+ Sets d->sizes[\a section] to a bounding rect based on its size
+ hint and font metrics, but constrained by \a size. It also updates
+ d->height.
+*/
+void Q3Header::setSectionSizeAndHeight(int section, int size)
+{
+ QSize sz = sectionSizeHint(section, fontMetrics());
+
+ if (size < 0) {
+ if (d->sizes[section] < 0)
+ d->sizes[section] = (orient == Qt::Horizontal) ? sz.width()
+ : sz.height();
+ } else {
+ d->sizes[section] = size;
+ }
+
+ int newHeight = (orient == Qt::Horizontal) ? sz.height() : sz.width();
+ if (newHeight > d->height) {
+ d->height = newHeight;
+ } else if (newHeight < d->height) {
+ /*
+ We could be smarter, but we aren't. This makes a difference
+ only for users with many columns and '\n's in their headers
+ at the same time.
+ */
+ d->heightDirty = true;
+ }
+}
+
+/*!
+ Adds a new section with label text \a s. Returns the index
+ position where the section was added (at the right for horizontal
+ headers, at the bottom for vertical headers). The section's width
+ is set to \a size. If \a size \< 0, an appropriate size for the
+ text \a s is chosen.
+*/
+int Q3Header::addLabel(const QString &s, int size)
+{
+ int n = ++d->count;
+ if ((int)d->icons.size() < n )
+ d->icons.resize(n);
+ if ((int)d->sizes.size() < n ) {
+ d->labels.resize(n);
+ d->nullStringLabels.resize(n);
+ d->sizes.resize(n);
+ d->positions.resize(n);
+ d->i2s.resize(n);
+ d->s2i.resize(n);
+ d->clicks.resize(n);
+ d->resize.resize(n);
+ }
+ int section = d->count - 1;
+ if (!d->is_a_table_header || !s.isNull()) {
+ d->labels.insert(section, s);
+ d->nullStringLabels.setBit(section, s.isNull());
+ }
+
+ if (size >= 0 && s.isNull() && d->is_a_table_header) {
+ d->sizes[section] = size;
+ } else {
+ d->sizes[section] = -1;
+ setSectionSizeAndHeight(section, size);
+ }
+
+ int index = section;
+ d->positions[index] = d->lastPos;
+
+ d->s2i[section] = index;
+ d->i2s[index] = section;
+ d->clicks.setBit(section, d->clicks_default);
+ d->resize.setBit(section, d->resize_default);
+
+ if (updatesEnabled()) {
+ updateGeometry();
+ calculatePositions();
+ update();
+ }
+ return index;
+}
+
+void Q3Header::resizeArrays(int size)
+{
+ d->icons.resize(size);
+ d->labels.resize(size);
+ d->nullStringLabels.resize(size);
+ d->sizes.resize(size);
+ d->positions.resize(size);
+ d->i2s.resize(size);
+ d->s2i.resize(size);
+ d->clicks.resize(size);
+ d->resize.resize(size);
+}
+
+void Q3Header::setIsATableHeader(bool b)
+{
+ d->is_a_table_header = b;
+}
+
+/*! \reimp */
+QSize Q3Header::sizeHint() const
+{
+ int width;
+ int height;
+
+ ensurePolished();
+ QFontMetrics fm = fontMetrics();
+
+ if (d->heightDirty) {
+ d->height = fm.lineSpacing() + 6;
+ for (int i = 0; i < count(); i++) {
+ int h = orient == Qt::Horizontal ?
+ sectionSizeHint(i, fm).height() : sectionSizeHint(i, fm).width();
+ d->height = qMax(d->height, h);
+ }
+ d->heightDirty = false;
+ }
+
+ if (orient == Qt::Horizontal) {
+ height = fm.lineSpacing() + 6;
+ width = 0;
+ height = qMax(height, d->height);
+ for (int i = 0; i < count(); i++)
+ width += d->sizes[i];
+ } else {
+ width = fm.width(QLatin1Char(' '));
+ height = 0;
+ width = qMax(width, d->height);
+ for (int i = 0; i < count(); i++)
+ height += d->sizes[i];
+ }
+ QStyleOptionHeader opt = getStyleOption(this, 0);
+ return style()->sizeFromContents(QStyle::CT_Q3Header, &opt, QSize(width, height),
+ this).expandedTo(QApplication::globalStrut());
+}
+
+/*!
+ \property Q3Header::offset
+ \brief the header's left-most (or top-most) visible pixel
+
+ Setting this property will scroll the header so that \e offset
+ becomes the left-most (or top-most for vertical headers) visible
+ pixel.
+*/
+int Q3Header::offset() const
+{
+ if (reverse())
+ return d->lastPos - width() - offs;
+ return offs;
+}
+
+void Q3Header::setOffset(int x)
+{
+ int oldOff = offset();
+ offs = x;
+ if(d->lastPos < (orient == Qt::Horizontal ? width() : height()))
+ offs = 0;
+ else if (reverse())
+ offs = d->lastPos - width() - x;
+ if (orient == Qt::Horizontal)
+ scroll(oldOff-offset(), 0);
+ else
+ scroll(0, oldOff-offset());
+}
+
+
+
+/*
+ Returns the position of actual division line \a i in widget
+ coordinates. May return a position outside the widget.
+
+ Note that the last division line is numbered count(). (There is one
+ more line than the number of sections).
+*/
+int Q3Header::pPos(int i) const
+{
+ int pos;
+ if (i == count())
+ pos = d->lastPos;
+ else
+ pos = d->positions[i];
+ if (reverse())
+ pos = d->lastPos - pos;
+ return pos - offset();
+}
+
+
+/*
+ Returns the size of the section at index position \a i.
+*/
+int Q3Header::pSize(int i) const
+{
+ return d->sizes[d->i2s[i]];
+}
+
+/*!
+ Use mapToSection() instead.
+
+ Translates from actual index \a a (index at which the section is displayed) to
+ logical index of the section. Returns -1 if \a a is outside the legal range.
+
+ \sa mapToActual()
+*/
+
+int Q3Header::mapToLogical(int a) const
+{
+ return mapToSection(a);
+}
+
+
+/*!
+ Use mapToIndex() instead.
+
+ Translates from logical index \a l to actual index (index at which the section \a l is displayed) .
+ Returns -1 if \a l is outside the legal range.
+
+ \sa mapToLogical()
+*/
+
+int Q3Header::mapToActual(int l) const
+{
+ return mapToIndex(l);
+}
+
+
+/*!
+ Use resizeSection() instead.
+
+ Sets the size of the section \a section to \a s pixels.
+
+ \warning does not repaint or send out signals
+*/
+
+void Q3Header::setCellSize(int section, int s)
+{
+ if (section < 0 || section >= count())
+ return;
+ d->sizes[section] = s;
+ if (updatesEnabled())
+ calculatePositions();
+ else
+ d->positionsDirty = true;
+}
+
+
+/*!
+ If \a enable is true the user may resize section \a section;
+ otherwise the section may not be manually resized.
+
+ If \a section is negative (the default) then the \a enable value
+ is set for all existing sections and will be applied to any new
+ sections that are added.
+ Example:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3header.cpp 0
+
+ If the user resizes a section, a sizeChange() signal is emitted.
+
+ \sa setMovingEnabled() setClickEnabled() setTracking()
+*/
+
+void Q3Header::setResizeEnabled(bool enable, int section)
+{
+ if (section < 0) {
+ d->resize.fill(enable);
+ // and future ones...
+ d->resize_default = enable;
+ } else if (section < count()) {
+ d->resize[section] = enable;
+ }
+}
+
+
+/*!
+ \property Q3Header::moving
+ \brief whether the header sections can be moved
+
+ If this property is true (the default) the user can move sections.
+ If the user moves a section the indexChange() signal is emitted.
+
+ \sa setClickEnabled(), setResizeEnabled()
+*/
+
+void Q3Header::setMovingEnabled(bool enable)
+{
+ d->move = enable;
+}
+
+
+/*!
+ If \a enable is true, any clicks on section \a section will result
+ in clicked() signals being emitted; otherwise the section will
+ ignore clicks.
+
+ If \a section is -1 (the default) then the \a enable value is set
+ for all existing sections and will be applied to any new sections
+ that are added.
+
+ \sa setMovingEnabled(), setResizeEnabled()
+*/
+
+void Q3Header::setClickEnabled(bool enable, int section)
+{
+ if (section < 0) {
+ d->clicks.fill(enable);
+ // and future ones...
+ d->clicks_default = enable;
+ } else if (section < count()) {
+ d->clicks[section] = enable;
+ }
+}
+
+
+/*!
+ Paints the section at position \a index, inside rectangle \a fr
+ (which uses widget coordinates) using painter \a p.
+
+ Calls paintSectionLabel().
+*/
+
+void Q3Header::paintSection(QPainter *p, int index, const QRect& fr)
+{
+ int section = mapToSection(index);
+ QStyleOptionHeader opt = getStyleOption(this, section);
+ opt.state |= QStyle::State_Raised;
+ opt.rect = fr;
+
+ if (section < 0) {
+ style()->drawControl(QStyle::CE_Header, &opt, p, this);
+ return;
+ }
+
+ if (sectionSize(section) <= 0)
+ return;
+
+ opt.state = (orient == Qt::Horizontal ? QStyle::State_Horizontal : QStyle::State_None);
+ if (d->sortSection == section)
+ opt.sortIndicator = d->sortDirection ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
+
+ if (isEnabled())
+ opt.state |= QStyle::State_Enabled;
+ if (isClickEnabled(section) && (state == Pressed || state == Moving) && index == handleIdx)
+ opt.state |= QStyle::State_Sunken; //currently pressed
+ if (!(opt.state & QStyle::State_Sunken))
+ opt.state |= QStyle::State_Raised;
+ p->setBrushOrigin(fr.topLeft());
+ if (d->clicks[section]) {
+ style()->drawControl(QStyle::CE_Header, &opt, p, this);
+ } else {
+ p->save();
+ p->setClipRect(fr); // hack to keep styles working
+ opt.rect.setRect(fr.x() + 1, fr.y(), fr.width(), fr.height());
+ style()->drawControl(QStyle::CE_Header, &opt, p, this);
+ if (orient == Qt::Horizontal) {
+ p->setPen(palette().color(QPalette::Mid));
+ p->drawLine(fr.x() - 1, fr.y() + fr.height() - 1,
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
+ p->drawLine(fr.x() + fr.width() - 1, fr.y(),
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
+ } else {
+ p->setPen(palette().color(QPalette::Mid));
+ p->drawLine(fr.x() + width() - 1, fr.y(),
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
+ p->drawLine(fr.x(), fr.y() + fr.height() - 1,
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
+ p->setPen(palette().color(QPalette::Light));
+ if (index > 0)
+ p->drawLine(fr.x(), fr.y(), fr.x() + fr.width() - 1, fr.y());
+ if (index == count() - 1) {
+ p->drawLine(fr.x(), fr.y() + fr.height() - 1,
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
+ p->setPen(palette().color(QPalette::Mid));
+ p->drawLine(fr.x(), fr.y() + fr.height() - 2,
+ fr.x() + fr.width() - 1, fr.y() + fr.height() - 2);
+ }
+ }
+ p->restore();
+ }
+}
+
+/*!
+ Paints the label of the section at position \a index, inside
+ rectangle \a fr (which uses widget coordinates) using painter \a
+ p.
+
+ Called by paintSection()
+*/
+void Q3Header::paintSectionLabel(QPainter *p, int index, const QRect& fr)
+{
+ int section = mapToSection(index);
+ if (section < 0)
+ return;
+
+ int dx = 0, dy = 0;
+ QStyleOptionHeader opt = getStyleOption(this, section);
+ if (d->sortSection == section)
+ opt.sortIndicator = d->sortDirection ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
+ if (index == handleIdx && (state == Pressed || state == Moving)) {
+ dx = style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &opt, this);
+ dy = style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &opt, this);
+ opt.state |= QStyle::State_Sunken;
+ }
+ if (isEnabled())
+ opt.state |= QStyle::State_Enabled;
+
+
+ opt.rect.setRect(fr.x() + style()->pixelMetric(QStyle::PM_HeaderMargin) + dx, fr.y() + 2 + dy,
+ fr.width() - 6, fr.height() - 4);
+
+ style()->drawControl(QStyle::CE_HeaderLabel, &opt, p, this);
+
+ int arrowWidth = (orient == Qt::Horizontal ? height() : width()) / 2;
+ int arrowHeight = fr.height() - 6;
+ QSize ssh = sectionSizeHint(section, p->fontMetrics());
+ int tw = (orient == Qt::Horizontal ? ssh.width() : ssh.height());
+ int ew = 0;
+
+ if (style()->styleHint(QStyle::SH_Header_ArrowAlignment, 0, this) & Qt::AlignRight)
+ ew = fr.width() - tw - 8;
+ if (d->sortSection == section && tw <= fr.width()) {
+ if (reverse()) {
+ tw = fr.width() - tw;
+ ew = fr.width() - ew - tw;
+ }
+ opt.state = QStyle::State_None;
+ if (isEnabled())
+ opt.state |= QStyle::State_Enabled;
+ if (d->sortDirection)
+ opt.state |= QStyle::State_DownArrow;
+ else
+ opt.state |= QStyle::State_UpArrow;
+ QRect ar(fr.x() + tw - arrowWidth - 6 + ew, 4, arrowWidth, arrowHeight);
+ if (label(section).isRightToLeft())
+ ar.moveBy( 2*(fr.right() - ar.right()) + ar.width() - fr.width(), 0 );
+ opt.rect = ar;
+ style()->drawPrimitive(QStyle::PE_IndicatorHeaderArrow, &opt, p, this);
+ }
+}
+
+
+/*! \reimp */
+void Q3Header::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ p.setPen(palette().buttonText().color());
+ int pos = orient == Qt::Horizontal ? e->rect().left() : e->rect().top();
+ int id = mapToIndex(sectionAt(pos + offset()));
+ if (id < 0) {
+ if (pos > 0)
+ id = d->count;
+ else if (reverse())
+ id = d->count - 1;
+ else
+ id = 0;
+ }
+ if (reverse()) {
+ for (int i = id; i >= 0; i--) {
+ QRect r = sRect(i);
+ paintSection(&p, i, r);
+ if (r.right() >= e->rect().right())
+ return;
+ }
+ } else {
+ if (count() > 0) {
+ for (int i = id; i <= count(); i++) {
+ QRect r = sRect(i);
+ /*
+ If the last section is clickable (and thus is
+ painted raised), draw the virtual section count()
+ as well. Otherwise it looks ugly.
+ */
+ if (i < count() || d->clicks[mapToSection(count() - 1)])
+ paintSection(&p, i, r);
+ if (hasFocus() && d->focusIdx == i) {
+ QStyleOptionFocusRect opt;
+ opt.rect.setRect(r.x()+2, r.y()+2, r.width()-4, r.height()-4);
+ opt.palette = palette();
+ opt.state = QStyle::State_None;
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, &p, this);
+ }
+ if ((orient == Qt::Horizontal && r. right() >= e->rect().right())
+ || (orient == Qt::Vertical && r. bottom() >= e->rect().bottom()))
+ return;
+ }
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Sets the sort indicator to \a ascending. Use the other overload instead.
+*/
+
+void Q3Header::setSortIndicator(int section, bool ascending)
+{
+ d->sortSection = section;
+ if (section != -1)
+ oldHandleIdx = section;
+ d->sortDirection = ascending;
+ update();
+ updateGeometry();
+}
+
+/*!
+ \fn void Q3Header::setSortIndicator(int section, Qt::SortOrder order)
+
+ Sets a sort indicator onto the specified \a section. The indicator's
+ \a order is either Ascending or Descending.
+
+ Only one section can show a sort indicator at any one time. If you
+ don't want any section to show a sort indicator pass a \a section
+ number of -1.
+
+ \sa sortIndicatorSection(), sortIndicatorOrder()
+*/
+
+/*!
+ Returns the section showing the sort indicator or -1 if there is no sort indicator.
+
+ \sa setSortIndicator(), sortIndicatorOrder()
+*/
+
+int Q3Header::sortIndicatorSection() const
+{
+ return d->sortSection;
+}
+
+/*!
+ Returns the implied sort order of the Q3Headers sort indicator.
+
+ \sa setSortIndicator(), sortIndicatorSection()
+*/
+
+Qt::SortOrder Q3Header::sortIndicatorOrder() const
+{
+ return d->sortDirection ? Qt::AscendingOrder : Qt::DescendingOrder;
+}
+
+/*!
+ Resizes section \a section to \a s pixels wide (or high).
+*/
+
+void Q3Header::resizeSection(int section, int s)
+{
+ setCellSize(section, s);
+ update();
+}
+
+/*!
+ Returns the width (or height) of the \a section in pixels.
+*/
+
+int Q3Header::sectionSize(int section) const
+{
+ if (section < 0 || section >= count())
+ return 0;
+ return d->sizes[section];
+}
+
+/*!
+ Returns the position (in pixels) at which the \a section starts.
+
+ \sa offset()
+*/
+
+int Q3Header::sectionPos(int section) const
+{
+ if (d->positionsDirty)
+ ((Q3Header *)this)->calculatePositions();
+ if (section < 0 || section >= count() )
+ return 0;
+ return d->positions[d->s2i[section]];
+}
+
+/*!
+ Returns the index of the section which contains the position \a
+ pos given in pixels from the left (or top).
+
+ \sa offset()
+*/
+
+int Q3Header::sectionAt(int pos) const
+{
+ if (reverse())
+ pos = d->lastPos - pos;
+ return d->sectionAt(pos);
+}
+
+/*!
+ Returns the number of the section that is displayed at index
+ position \a index.
+*/
+
+int Q3Header::mapToSection(int index) const
+{
+ return (index >= 0 && index < count()) ? d->i2s[index] : -1;
+}
+
+/*!
+ Returns the index position at which section \a section is
+ displayed.
+*/
+
+int Q3Header::mapToIndex(int section) const
+{
+ return (section >= 0 && section < count()) ? d->s2i[section] : -1;
+}
+
+/*!
+ Moves section \a section to index position \a toIndex.
+*/
+
+void Q3Header::moveSection(int section, int toIndex)
+{
+ int fromIndex = mapToIndex(section);
+ if (fromIndex == toIndex ||
+ fromIndex < 0 || fromIndex > count() ||
+ toIndex < 0 || toIndex > count())
+ return;
+ int i;
+ int idx = d->i2s[fromIndex];
+ if (fromIndex < toIndex) {
+ for (i = fromIndex; i < toIndex - 1; i++) {
+ int t;
+ d->i2s[i] = t = d->i2s[i+1];
+ d->s2i[t] = i;
+ }
+ d->i2s[toIndex-1] = idx;
+ d->s2i[idx] = toIndex-1;
+ } else {
+ for (i = fromIndex; i > toIndex; i--) {
+ int t;
+ d->i2s[i] = t = d->i2s[i-1];
+ d->s2i[t] = i;
+ }
+ d->i2s[toIndex] = idx;
+ d->s2i[idx] = toIndex;
+ }
+ calculatePositions();
+}
+
+/*!
+ Returns true if section \a section is clickable; otherwise returns
+ false.
+
+ If \a section is out of range (negative or larger than count() -
+ 1): returns true if all sections are clickable; otherwise returns
+ false.
+
+ \sa setClickEnabled()
+*/
+
+bool Q3Header::isClickEnabled(int section) const
+{
+ if (section >= 0 && section < count()) {
+ return (bool)d->clicks[section];
+ }
+
+ for (int i = 0; i < count(); ++i) {
+ if (!d->clicks[i])
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Returns true if section \a section is resizeable; otherwise
+ returns false.
+
+ If \a section is -1 then this function applies to all sections,
+ i.e. returns true if all sections are resizeable; otherwise
+ returns false.
+
+ \sa setResizeEnabled()
+*/
+
+bool Q3Header::isResizeEnabled(int section) const
+{
+ if (section >= 0 && section < count()) {
+ return (bool)d->resize[section];
+ }
+
+ for (int i = 0; i < count();++i) {
+ if (!d->resize[i])
+ return false;
+ }
+ return true;
+}
+
+bool Q3Header::isMovingEnabled() const
+{
+ return d->move;
+}
+
+/*! \internal */
+
+void Q3Header::setUpdatesEnabled(bool enable)
+{
+ if (enable)
+ calculatePositions();
+ QWidget::setUpdatesEnabled(enable);
+}
+
+
+bool Q3Header::reverse () const
+{
+#if 0
+ return (orient == Qt::Horizontal && QApplication::reverseLayout());
+#else
+ return false;
+#endif
+}
+
+/*! \reimp */
+void Q3Header::resizeEvent(QResizeEvent *e)
+{
+ if (e)
+ QWidget::resizeEvent(e);
+
+ if(d->lastPos < width()) {
+ offs = 0;
+ }
+
+ if (e) {
+ adjustHeaderSize(orientation() == Qt::Horizontal ?
+ width() - e->oldSize().width() : height() - e->oldSize().height());
+ if ((orientation() == Qt::Horizontal && height() != e->oldSize().height())
+ || (orientation() == Qt::Vertical && width() != e->oldSize().width()))
+ update();
+ } else
+ adjustHeaderSize();
+}
+
+/*!
+ \fn void Q3Header::adjustHeaderSize()
+
+ Adjusts the size of the sections to fit the size of the header as
+ completely as possible. Only sections for which isStretchEnabled()
+ is true will be resized.
+*/
+
+void Q3Header::adjustHeaderSize(int diff)
+{
+ if (!count())
+ return;
+
+ // we skip the adjustHeaderSize when trying to resize the last column which is set to stretchable
+ if (d->fullSize == (count() -1) &&
+ (d->lastPos - d->sizes[count() -1]) > (orient == Qt::Horizontal ? width() : height()))
+ return;
+
+ if (d->fullSize >= 0) {
+ int sec = mapToSection(d->fullSize);
+ int lsec = mapToSection(count() - 1);
+ int ns = sectionSize(sec) +
+ (orientation() == Qt::Horizontal ?
+ width() : height()) - (sectionPos(lsec) + sectionSize(lsec));
+ int os = sectionSize(sec);
+ if (ns < 20)
+ ns = 20;
+ setCellSize(sec, ns);
+ repaint();
+ emit sizeChange(sec, os, ns);
+ } else if (d->fullSize == -1) {
+ int df = diff / count();
+ int part = orientation() == Qt::Horizontal ? width() / count() : height() / count();
+ for (int i = 0; i < count() - 1; ++i) {
+ int sec = mapToIndex(i);
+ int os = sectionSize(sec);
+ int ns = diff != -1 ? os + df : part;
+ if (ns < 20)
+ ns = 20;
+ setCellSize(sec, ns);
+ emit sizeChange(sec, os, ns);
+ }
+ int sec = mapToIndex(count() - 1);
+ int ns = (orientation() == Qt::Horizontal ? width() : height()) - sectionPos(sec);
+ int os = sectionSize(sec);
+ if (ns < 20)
+ ns = 20;
+ setCellSize(sec, ns);
+ repaint();
+ emit sizeChange(sec, os, ns);
+ }
+}
+
+/*!
+ Returns the total width of all the header columns.
+*/
+int Q3Header::headerWidth() const
+{
+ if (d->pos_dirty) {
+ ((Q3Header*)this)->calculatePositions();
+ d->pos_dirty = false;
+ }
+ return d->lastPos;
+}
+
+void Q3Header::calculatePositions(bool onlyVisible, int start)
+{
+ d->positionsDirty = false;
+ d->lastPos = count() > 0 ? d->positions[start] : 0;
+ for (int i = start; i < count(); i++) {
+ d->positions[i] = d->lastPos;
+ d->lastPos += d->sizes[d->i2s[i]];
+ if (onlyVisible && d->lastPos > offset() +
+ (orientation() == Qt::Horizontal ? width() : height()))
+ break;
+ }
+ d->pos_dirty = onlyVisible;
+}
+
+
+/*!
+ \property Q3Header::stretching
+ \brief whether the header sections always take up the full width
+ (or height) of the header
+*/
+
+
+/*!
+ If \a b is true, section \a section will be resized when the
+ header is resized, so that the sections take up the full width (or
+ height for vertical headers) of the header; otherwise section \a
+ section will be set to be unstretchable and will not resize when
+ the header is resized.
+
+ If \a section is -1, and if \a b is true, then all sections will
+ be resized equally when the header is resized so that they take up
+ the full width (or height for vertical headers) of the header;
+ otherwise all the sections will be set to be unstretchable and
+ will not resize when the header is resized.
+
+ \sa adjustHeaderSize()
+*/
+
+void Q3Header::setStretchEnabled(bool b, int section)
+{
+ if (b)
+ d->fullSize = section;
+ else
+ d->fullSize = -2;
+ adjustHeaderSize();
+}
+
+bool Q3Header::isStretchEnabled() const
+{
+ return d->fullSize == -1;
+}
+
+/*!
+ \overload
+
+ Returns true if section \a section will resize to take up the full
+ width (or height) of the header; otherwise returns false. If at
+ least one section has stretch enabled the sections will always
+ take up the full width of the header.
+
+ \sa setStretchEnabled()
+*/
+
+bool Q3Header::isStretchEnabled(int section) const
+{
+ return d->fullSize == section;
+}
+
+/*!
+ \reimp
+*/
+void Q3Header::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::FontChange) {
+ QFontMetrics fm = fontMetrics();
+ d->height = (orient == Qt::Horizontal) ? fm.lineSpacing() + 6 : fm.width(QLatin1Char(' '));
+ }
+ QWidget::changeEvent(ev);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_HEADER
diff --git a/src/qt3support/widgets/q3header.h b/src/qt3support/widgets/q3header.h
new file mode 100644
index 0000000..3768aa0
--- /dev/null
+++ b/src/qt3support/widgets/q3header.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3HEADER_H
+#define Q3HEADER_H
+
+#include <QtGui/qicon.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_HEADER
+
+class QShowEvent;
+class Q3HeaderData;
+class Q3Table;
+class Q3ListView;
+
+class Q_COMPAT_EXPORT Q3Header : public QWidget
+{
+ friend class Q3Table;
+ friend class Q3TableHeader;
+ friend class Q3ListView;
+
+ Q_OBJECT
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(bool tracking READ tracking WRITE setTracking)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(int offset READ offset WRITE setOffset)
+ Q_PROPERTY(bool moving READ isMovingEnabled WRITE setMovingEnabled)
+ Q_PROPERTY(bool stretching READ isStretchEnabled WRITE setStretchEnabled)
+
+public:
+ Q3Header(QWidget* parent=0, const char* name=0);
+ Q3Header(int, QWidget* parent=0, const char* name=0);
+ ~Q3Header();
+
+ int addLabel(const QString &, int size = -1);
+ int addLabel(const QIcon&, const QString &, int size = -1);
+ void removeLabel(int section);
+ virtual void setLabel(int, const QString &, int size = -1);
+ virtual void setLabel(int, const QIcon&, const QString &, int size = -1);
+ QString label(int section) const;
+ QIcon* iconSet(int section) const;
+
+ virtual void setOrientation(Qt::Orientation);
+ Qt::Orientation orientation() const;
+ virtual void setTracking(bool enable);
+ bool tracking() const;
+
+ virtual void setClickEnabled(bool, int section = -1);
+ virtual void setResizeEnabled(bool, int section = -1);
+ virtual void setMovingEnabled(bool);
+ virtual void setStretchEnabled(bool b, int section);
+ void setStretchEnabled(bool b) { setStretchEnabled(b, -1); }
+ bool isClickEnabled(int section = -1) const;
+ bool isResizeEnabled(int section = -1) const;
+ bool isMovingEnabled() const;
+ bool isStretchEnabled() const;
+ bool isStretchEnabled(int section) const;
+
+ void resizeSection(int section, int s);
+ int sectionSize(int section) const;
+ int sectionPos(int section) const;
+ int sectionAt(int pos) const;
+ int count() const;
+ int headerWidth() const;
+ QRect sectionRect(int section) const;
+
+ virtual void setCellSize(int , int); // obsolete, do not use
+ int cellSize(int i) const { return sectionSize(mapToSection(i)); } // obsolete, do not use
+ int cellPos(int) const; // obsolete, do not use
+ int cellAt(int pos) const { return mapToIndex(sectionAt(pos + offset())); } // obsolete, do not use
+
+ int offset() const;
+
+ QSize sizeHint() const;
+
+ int mapToSection(int index) const;
+ int mapToIndex(int section) const;
+ int mapToLogical(int) const; // obsolete, do not use
+ int mapToActual(int) const; // obsolete, do not use
+
+ void moveSection(int section, int toIndex);
+ virtual void moveCell(int, int); // obsolete, do not use
+
+ void setSortIndicator(int section, bool ascending = true); // obsolete, do not use
+ inline void setSortIndicator(int section, Qt::SortOrder order)
+ { setSortIndicator(section, (order == Qt::AscendingOrder)); }
+ int sortIndicatorSection() const;
+ Qt::SortOrder sortIndicatorOrder() const;
+
+ void adjustHeaderSize() { adjustHeaderSize(-1); }
+
+public Q_SLOTS:
+ void setUpdatesEnabled(bool enable);
+ virtual void setOffset(int pos);
+
+Q_SIGNALS:
+ void clicked(int section);
+ void pressed(int section);
+ void released(int section);
+ void sizeChange(int section, int oldSize, int newSize);
+ void indexChange(int section, int fromIndex, int toIndex);
+ void sectionClicked(int); // obsolete, do not use
+ void moved(int, int); // obsolete, do not use
+ void sectionHandleDoubleClicked(int section);
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void showEvent(QShowEvent *e);
+ void resizeEvent(QResizeEvent *e);
+ QRect sRect(int index);
+
+ virtual void paintSection(QPainter *p, int index, const QRect& fr);
+ virtual void paintSectionLabel(QPainter* p, int index, const QRect& fr);
+
+ void changeEvent(QEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void mouseDoubleClickEvent(QMouseEvent *);
+
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+private:
+ void handleColumnMove(int fromIdx, int toIdx);
+ void adjustHeaderSize(int diff);
+ void init(int);
+
+ void paintRect(int p, int s);
+ void markLine(int idx);
+ void unMarkLine(int idx);
+ int pPos(int i) const;
+ int pSize(int i) const;
+ int findLine(int);
+ int handleAt(int p);
+ bool reverse() const;
+ void calculatePositions(bool onlyVisible = false, int start = 0);
+ void handleColumnResize(int, int, bool, bool = true);
+ QSize sectionSizeHint(int section, const QFontMetrics& fm) const;
+ void setSectionSizeAndHeight(int section, int size);
+
+ void resizeArrays(int size);
+ void setIsATableHeader(bool b);
+ int offs;
+ int handleIdx;
+ int oldHIdxSize;
+ int moveToIdx;
+ enum State { Idle, Sliding, Pressed, Moving, Blocked };
+ State state;
+ int clickPos;
+ bool trackingIsOn;
+ int oldHandleIdx;
+ int cachedPos; // not used
+ Qt::Orientation orient;
+
+ Q3HeaderData *d;
+
+private:
+ Q_DISABLE_COPY(Q3Header)
+};
+
+
+inline Qt::Orientation Q3Header::orientation() const
+{
+ return orient;
+}
+
+inline void Q3Header::setTracking(bool enable) { trackingIsOn = enable; }
+inline bool Q3Header::tracking() const { return trackingIsOn; }
+
+extern Q_COMPAT_EXPORT bool qt_qheader_label_return_null_strings; // needed for professional edition
+
+#endif // QT_NO_HEADER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3HEADER_H
diff --git a/src/qt3support/widgets/q3hgroupbox.cpp b/src/qt3support/widgets/q3hgroupbox.cpp
new file mode 100644
index 0000000..cf08389
--- /dev/null
+++ b/src/qt3support/widgets/q3hgroupbox.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3hgroupbox.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3HGroupBox
+
+ \brief The Q3HGroupBox widget organizes widgets in a group with one
+ horizontal row.
+
+ \compat
+
+ Q3HGroupBox is a convenience class that offers a thin layer on top
+ of Q3GroupBox. Think of it as a Q3HBox that offers a frame with a
+ title.
+
+ \sa Q3VGroupBox
+*/
+
+/*!
+ Constructs a horizontal group box with no title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+Q3HGroupBox::Q3HGroupBox( QWidget *parent, const char *name )
+ : Q3GroupBox( 1, Qt::Vertical /* sic! */, parent, name )
+{
+}
+
+/*!
+ Constructs a horizontal group box with the title \a title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3HGroupBox::Q3HGroupBox( const QString &title, QWidget *parent,
+ const char *name )
+ : Q3GroupBox( 1, Qt::Vertical /* sic! */, title, parent, name )
+{
+}
+
+/*!
+ Destroys the horizontal group box, deleting its child widgets.
+*/
+Q3HGroupBox::~Q3HGroupBox()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3hgroupbox.h b/src/qt3support/widgets/q3hgroupbox.h
new file mode 100644
index 0000000..71baf08
--- /dev/null
+++ b/src/qt3support/widgets/q3hgroupbox.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3HGROUPBOX_H
+#define Q3HGROUPBOX_H
+
+#include <Qt3Support/q3groupbox.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3HGroupBox : public Q3GroupBox
+{
+ Q_OBJECT
+public:
+ Q3HGroupBox( QWidget* parent=0, const char* name=0 );
+ Q3HGroupBox( const QString &title, QWidget* parent=0, const char* name=0 );
+ ~Q3HGroupBox();
+
+private:
+ Q_DISABLE_COPY(Q3HGroupBox)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3HGROUPBOX_H
diff --git a/src/qt3support/widgets/q3mainwindow.cpp b/src/qt3support/widgets/q3mainwindow.cpp
new file mode 100644
index 0000000..2ee3bdc
--- /dev/null
+++ b/src/qt3support/widgets/q3mainwindow.cpp
@@ -0,0 +1,2427 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3mainwindow.h"
+#ifndef QT_NO_MAINWINDOW
+
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qdatetime.h"
+#include "q3dockarea.h"
+#include "qevent.h"
+#include "qlayout.h"
+#include "qmap.h"
+#include "qmenubar.h"
+#include "qpainter.h"
+#include "q3popupmenu.h"
+#include "q3scrollview.h"
+#include "qstatusbar.h"
+#include "qstringlist.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+#include "q3toolbar.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#ifdef Q_WS_MAC
+# include <private/qt_mac_p.h>
+#endif
+
+#include <private/q3mainwindow_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHideDock;
+
+/* Q3MainWindowLayout, respects widthForHeight layouts (like the left
+ and right docks are)
+*/
+
+class Q3MainWindowLayout : public QLayout
+{
+ Q_OBJECT
+
+public:
+ Q3MainWindowLayout(Q3MainWindow *mw);
+ ~Q3MainWindowLayout() {}
+
+ void addItem(QLayoutItem *);
+ void setLeftDock(Q3DockArea *l);
+ void setRightDock(Q3DockArea *r);
+ void setCentralWidget(QWidget *w);
+ bool hasHeightForWidth() const { return false; }
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QLayoutItem *itemAt(int) const { return 0; } //###
+ QLayoutItem *takeAt(int) { return 0; } //###
+ int count() const { return 0; } //###
+
+protected:
+ void setGeometry(const QRect &r) {
+ QLayout::setGeometry(r);
+ layoutItems(r);
+ }
+
+private:
+ int layoutItems(const QRect&, bool testonly = false);
+ int extraPixels() const;
+
+ Q3DockArea *left, *right;
+ QWidget *central;
+ Q3MainWindow *mainWindow;
+
+};
+
+QSize Q3MainWindowLayout::sizeHint() const
+{
+ int w = 0;
+ int h = 0;
+
+ if (left) {
+ w += left->sizeHint().width();
+ h = qMax(h, left->sizeHint().height());
+ }
+ if (right) {
+ w += right->sizeHint().width();
+ h = qMax(h, right->sizeHint().height());
+ }
+ if (central) {
+ w += central->sizeHint().width();
+ int diff = extraPixels();
+ h = qMax(h, central->sizeHint().height() + diff);
+ }
+ return QSize(w, h);
+}
+
+QSize Q3MainWindowLayout::minimumSize() const
+{
+ int w = 0;
+ int h = 0;
+
+ if (left) {
+ QSize ms = left->minimumSizeHint().expandedTo(left->minimumSize());
+ w += ms.width();
+ h = qMax(h, ms.height());
+ }
+ if (right) {
+ QSize ms = right->minimumSizeHint().expandedTo(right->minimumSize());
+ w += ms.width();
+ h = qMax(h, ms.height());
+ }
+ if (central) {
+ QSize min = central->minimumSize().isNull() ?
+ central->minimumSizeHint() : central->minimumSize();
+ w += min.width();
+ int diff = extraPixels();
+ h = qMax(h, min.height() + diff);
+ }
+ return QSize(w, h);
+}
+
+Q3MainWindowLayout::Q3MainWindowLayout(Q3MainWindow *mw)
+ : left(0), right(0), central(0)
+{
+ mainWindow = mw;
+}
+
+void Q3MainWindowLayout::setLeftDock(Q3DockArea *l)
+{
+ left = l;
+}
+
+void Q3MainWindowLayout::setRightDock(Q3DockArea *r)
+{
+ right = r;
+}
+
+void Q3MainWindowLayout::setCentralWidget(QWidget *w)
+{
+ central = w;
+}
+
+int Q3MainWindowLayout::layoutItems(const QRect &r, bool testonly)
+{
+ if (!left && !central && !right)
+ return 0;
+
+ int wl = 0, wr = 0;
+ if (left)
+ wl = ((Q3DockAreaLayout*)left->QWidget::layout())->widthForHeight(r.height());
+ if (right)
+ wr = ((Q3DockAreaLayout*)right->QWidget::layout())->widthForHeight(r.height());
+ int w = r.width() - wr - wl;
+ if (w < 0)
+ w = 0;
+
+ int diff = extraPixels();
+ if (!testonly) {
+ QRect g(geometry());
+ if (left)
+ left->setGeometry(QRect(g.x(), g.y() + diff, wl, r.height() - diff));
+ if (right)
+ right->setGeometry(QRect(g.x() + g.width() - wr, g.y() + diff, wr, r.height() - diff));
+ if (central)
+ central->setGeometry(g.x() + wl, g.y() + diff, w, r.height() - diff);
+ }
+
+ w = wl + wr;
+ if (central)
+ w += central->minimumSize().width();
+ return w;
+}
+
+int Q3MainWindowLayout::extraPixels() const
+{
+ if (mainWindow->d_func()->topDock->isEmpty() &&
+ !(mainWindow->d_func()->leftDock->isEmpty() &&
+ mainWindow->d_func()->rightDock->isEmpty())) {
+ return 2;
+ } else {
+ return 0;
+ }
+}
+
+void Q3MainWindowLayout::addItem(QLayoutItem * /* item */)
+{
+}
+
+/*
+ QHideToolTip and QHideDock - minimized dock
+*/
+
+#if 0
+class QHideToolTip : public QToolTip
+{
+public:
+ QHideToolTip(QWidget *parent) : QToolTip(parent) {}
+
+ void maybeTip(const QPoint &pos);
+};
+#endif
+
+
+class QHideDock : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QHideDock(Q3MainWindow *parent) : QWidget(parent, "qt_hide_dock") {
+ hide();
+ setFixedHeight(style()->pixelMetric(QStyle::PM_DockWidgetHandleExtent, 0, this) + 3);
+ pressedHandle = -1;
+ pressed = false;
+ setMouseTracking(true);
+ win = parent;
+#if 0
+ tip = new QHideToolTip(this);
+#endif
+ }
+ ~QHideDock()
+ {
+#if 0
+ delete tip;
+#endif
+ }
+
+protected:
+ void paintEvent(QPaintEvent *e) {
+ QObjectList childList = children();
+ if (childList.isEmpty())
+ return;
+ QPainter p(this);
+ p.setClipRegion(e->rect());
+ p.fillRect(e->rect(), palette().brush(QPalette::Window));
+ int x = 0;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(o);
+ if (!dw || !dw->isVisible())
+ continue;
+ QStyleOptionQ3DockWindow opt;
+ opt.rect.setRect(x, 0, 30, 10);
+ opt.palette = palette();
+ opt.docked = dw->area();
+ opt.closeEnabled = dw->isCloseEnabled();
+ opt.state = QStyle::State_None;
+ if (i == pressedHandle)
+ opt.state |= QStyle::State_On;
+
+ style()->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
+ x += 30;
+ }
+ }
+
+ void mousePressEvent(QMouseEvent *e) {
+ pressed = true;
+ QObjectList childList = children();
+ if (childList.isEmpty())
+ return;
+ mouseMoveEvent(e);
+ pressedHandle = -1;
+
+ if (e->button() == Qt::RightButton && win->isDockMenuEnabled()) {
+ // ### TODO: HideDock menu
+ } else {
+ mouseMoveEvent(e);
+ }
+ }
+
+ void mouseMoveEvent(QMouseEvent *e) {
+ QObjectList childList = children();
+ if (childList.isEmpty())
+ return;
+ if (!pressed)
+ return;
+ int x = 0;
+ if (e->y() >= 0 && e->y() <= height()) {
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(o);
+ if (!dw || !dw->isVisible())
+ continue;
+ if (e->x() >= x && e->x() <= x + 30) {
+ int old = pressedHandle;
+ pressedHandle = i;
+ if (pressedHandle != old)
+ repaint();
+ return;
+ }
+ x += 30;
+ }
+ }
+ int old = pressedHandle;
+ pressedHandle = -1;
+ if (old != -1)
+ repaint();
+ }
+
+ void mouseReleaseEvent(QMouseEvent *e) {
+ pressed = false;
+ if (pressedHandle == -1)
+ return;
+ QObjectList childList = children();
+ if (childList.isEmpty())
+ return;
+ if (e->button() == Qt::LeftButton) {
+ if (e->y() >= 0 && e->y() <= height()) {
+ QObject *o = childList.at(pressedHandle);
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(o);
+ if (dw) {
+ dw->show();
+ dw->dock();
+ }
+ }
+ }
+ pressedHandle = -1;
+ repaint();
+ }
+
+ bool eventFilter(QObject *o, QEvent *e) {
+ if (o == this || !o->isWidgetType())
+ return QWidget::eventFilter(o, e);
+ if (e->type() == QEvent::HideToParent ||
+ e->type() == QEvent::ShowToParent)
+ updateState();
+ return QWidget::eventFilter(o, e);
+ }
+
+ void updateState() {
+ bool visible = true;
+ QObjectList childList = children();
+ if (childList.isEmpty())
+ return;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(o);
+ if (!dw)
+ continue;
+ if (dw->isHidden()) {
+ visible = false;
+ continue;
+ }
+ if (!dw->isVisible())
+ continue;
+ visible = true;
+ break;
+ }
+
+ if (visible)
+ show();
+ else
+ hide();
+ win->triggerLayout(false);
+ update();
+ }
+
+ void childEvent(QChildEvent *e) {
+ QWidget::childEvent(e);
+ if (e->type() == QEvent::ChildInserted)
+ e->child()->installEventFilter(this);
+ else
+ e->child()->removeEventFilter(this);
+ updateState();
+ }
+
+private:
+ Q3MainWindow *win;
+ int pressedHandle;
+ bool pressed;
+#if 0
+ QHideToolTip *tip;
+ friend class QHideToolTip;
+#endif
+};
+
+#if 0
+void QHideToolTip::maybeTip(const QPoint &pos)
+{
+ if (!parentWidget())
+ return;
+ QHideDock *dock = (QHideDock*)parentWidget();
+
+ QObjectList dchilds = dock->children();
+ if (dchilds.isEmpty())
+ return;
+ int x = 0;
+ for (int i = 0; i < dchilds.size(); ++i) {
+ QObject *o = dchilds.at(i);
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(o);
+ if (!dw || !dw->isVisible())
+ continue;
+ if (pos.x() >= x && pos.x() <= x + 30) {
+ Q3DockWindow *dw = (Q3DockWindow*)o;
+ if (!dw->windowTitle().isEmpty())
+ tip(QRect(x, 0, 30, dock->height()), dw->windowTitle());
+ return;
+ }
+ x += 30;
+ }
+}
+#endif
+
+/*!
+ \class Q3MainWindow
+ \brief The Q3MainWindow class provides a main application window,
+ with a menu bar, dock windows (e.g. for toolbars), and a status
+ bar.
+
+ \compat
+
+ Main windows are most often used to provide menus, toolbars and a
+ status bar around a large central widget, such as a text edit,
+ drawing canvas or QWorkspace (for MDI applications). Q3MainWindow
+ is usually subclassed since this makes it easier to encapsulate
+ the central widget, menus and toolbars as well as the window's
+ state. Subclassing makes it possible to create the slots that are
+ called when the user clicks menu items or toolbar buttons.
+
+ We'll briefly review adding menu items and
+ toolbar buttons then describe the facilities of Q3MainWindow
+ itself.
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3mainwindow.cpp 0
+
+ Q3MainWindows may be created in their own right as shown above.
+ The central widget is set with setCentralWidget(). Popup menus can
+ be added to the default menu bar, widgets can be added to the
+ status bar, toolbars and dock windows can be added to any of the
+ dock areas.
+
+ The main window will take care of the dock areas, and the geometry
+ of the central widget, but all other aspects of the central widget
+ are left to you. Q3MainWindow automatically detects the creation of
+ a menu bar or status bar if you specify the Q3MainWindow as parent,
+ or you can use the provided menuBar() and statusBar() functions.
+ The functions menuBar() and statusBar() create a suitable widget
+ if one doesn't exist, and update the window's layout to make
+ space.
+
+ New dock windows and toolbars can be added to a Q3MainWindow using
+ addDockWindow(). Qt::Dock windows can be moved using moveDockWindow()
+ and removed with removeDockWindow(). Q3MainWindow allows default
+ dock window (toolbar) docking in all its dock areas (\c Top, \c
+ Left, \c Right, \c Bottom). You can use setDockEnabled() to
+ enable and disable docking areas for dock windows. When adding or
+ moving dock windows you can specify their 'edge' (dock area). The
+ currently available edges are: \c Top, \c Left, \c Right, \c
+ Bottom, \c Minimized (effectively a 'hidden' dock area) and \c
+ TornOff (floating). See \l Qt::Dock for an explanation of these
+ areas. Note that the *ToolBar functions are included for backward
+ compatibility; all new code should use the *DockWindow functions.
+ QToolbar is a subclass of Q3DockWindow so all functions that work
+ with dock windows work on toolbars in the same way.
+
+ \target dwm
+ If the user clicks the close button, then the dock window is
+ hidden. A dock window can be hidden or unhidden by the user by
+ right clicking a dock area and clicking the name of the relevant
+ dock window on the pop up dock window menu. This menu lists the
+ names of every dock window; visible dock windows have a tick
+ beside their names. The dock window menu is created automatically
+ as required by createDockWindowMenu(). Since it may not always be
+ appropriate for a dock window to appear on this menu the
+ setAppropriate() function is used to inform the main window
+ whether or not the dock window menu should include a particular
+ dock window. Double clicking a dock window handle (usually on the
+ left-hand side of the dock window) undocks (floats) the dock
+ window. Double clicking a floating dock window's title bar will
+ dock the floating dock window. (See also
+ \l{Q3MainWindow::DockWindows}.)
+
+ Some functions change the appearance of a Q3MainWindow globally:
+ \list
+ \i Q3DockWindow::setHorizontalStretchable() and
+ Q3DockWindow::setVerticalStretchable() are used to make specific dock
+ windows or toolbars stretchable.
+ \i setUsesBigPixmaps() is used to set whether tool buttons should
+ draw small or large pixmaps (see QIcon for more information).
+ \i setUsesTextLabel() is used to set whether tool buttons
+ should display a textual label in addition to pixmaps
+ (see QToolButton for more information).
+ \endlist
+
+ The user can drag dock windows into any enabled docking area. Qt::Dock
+ windows can also be dragged \e within a docking area, for example
+ to rearrange the order of some toolbars. Qt::Dock windows can also be
+ dragged outside any docking area (undocked or 'floated'). Being
+ able to drag dock windows can be enabled (the default) and
+ disabled using setDockWindowsMovable().
+
+ The \c Minimized edge is a hidden dock area. If this dock area is
+ enabled the user can hide (minimize) a dock window or show (restore)
+ a minimized dock window by clicking the dock window handle. If the
+ user hovers the mouse cursor over one of the handles, the caption of
+ the dock window is displayed in a tool tip (see
+ Q3DockWindow::windowTitle() or Q3ToolBar::label()), so if you enable the
+ \c Minimized dock area, it is best to specify a meaningful caption
+ or label for each dock window. To minimize a dock window
+ programmatically use moveDockWindow() with an edge of \c Minimized.
+
+ Qt::Dock windows are moved transparently by default, i.e. during the
+ drag an outline rectangle is drawn on the screen representing the
+ position of the dock window as it moves. If you want the dock
+ window to be shown normally whilst it is moved use
+ setOpaqueMoving().
+
+ The location of a dock window, i.e. its dock area and position
+ within the dock area, can be determined by calling getLocation().
+ Movable dock windows can be lined up to minimize wasted space with
+ lineUpDockWindows(). Pointers to the dock areas are available from
+ topDock(), leftDock(), rightDock() and bottomDock(). A customize
+ menu item is added to the pop up dock window menu if
+ isCustomizable() returns true; it returns false by default.
+ Reimplement isCustomizable() and customize() if you want to offer
+ this extra menu item, for example, to allow the user to change
+ settings relating to the main window and its toolbars and dock
+ windows.
+
+ The main window's menu bar is fixed (at the top) by default. If
+ you want a movable menu bar, create a QMenuBar as a stretchable
+ widget inside its own movable dock window and restrict this dock
+ window to only live within the \c Top or \c Bottom dock:
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3mainwindow.cpp 1
+
+ An application with multiple dock windows can choose to save the
+ current dock window layout in order to restore it later, e.g. in
+ the next session. You can do this by using the streaming operators
+ for Q3MainWindow.
+
+ To save the layout and positions of all the dock windows do this:
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3mainwindow.cpp 2
+
+ To restore the dock window positions and sizes (normally when the
+ application is next started), do the following:
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3mainwindow.cpp 3
+
+ The QSettings class can be used in conjunction with the streaming
+ operators to store the application's settings.
+
+ Q3MainWindow's management of dock windows and toolbars is done
+ transparently behind-the-scenes by Q3DockArea.
+
+ For multi-document interfaces (MDI), use a QWorkspace as the
+ central widget.
+
+ Adding dock windows, e.g. toolbars, to Q3MainWindow's dock areas is
+ straightforward. If the supplied dock areas are not sufficient for
+ your application we suggest that you create a QWidget subclass and
+ add your own dock areas (see \l Q3DockArea) to the subclass since
+ Q3MainWindow provides functionality specific to the standard dock
+ areas it provides.
+
+ \sa Q3ToolBar Q3DockWindow QStatusBar QAction QMenuBar Q3PopupMenu QDialog
+*/
+
+/*!
+ \enum Q3MainWindow::DockWindows
+
+ Right-clicking a dock area will pop-up the dock window menu
+ (createDockWindowMenu() is called automatically). When called in
+ code you can specify what items should appear on the menu with
+ this enum.
+
+ \value OnlyToolBars The menu will list all the toolbars, but not
+ any other dock windows.
+
+ \value NoToolBars The menu will list dock windows but not
+ toolbars.
+
+ \value AllDockWindows The menu will list all toolbars and other
+ dock windows. (This is the default.)
+*/
+
+/*!
+ \fn void Q3MainWindow::addToolBar(Q3DockWindow *dockWindow,
+ Qt::Dock position, bool newLine);
+
+ Adds a new toolbar to the \a dockWindow. The toolbar is placed in
+ the given \a position. If \a newLine is true the toolbar is put on
+ a new line.
+*/
+
+/*!
+ \fn void Q3MainWindow::addToolBar(Q3DockWindow *dockWindow, const
+ QString &label, Qt::Dock position, bool newLine)
+ \overload
+
+ The toolbar has the caption \a label and is placed in the given \a
+ position.
+*/
+
+/*!
+ \fn void Q3MainWindow::moveToolBar(Q3DockWindow *dockWindow, Qt::Dock position);
+
+ Moves the given \a dockWindow into the given \a position.
+*/
+
+/*!
+ \fn void Q3MainWindow::moveToolBar(Q3DockWindow *dockWindow,
+ Qt::Dock position, bool nl, int index, int extraOffset)
+ \overload
+
+ The \a dockWindow is made the \a{index}-th item in the toolbar,
+ moved over by \a extraOffset. If \a nl is true, the dock window is
+ put on a new line.
+*/
+
+/*!
+ \fn void Q3MainWindow::removeToolBar(Q3DockWindow *dockWindow);
+
+ Removes the toolbar from the given \a dockWindow.
+*/
+
+/*!
+ \fn void Q3MainWindow::lineUpToolBars(bool keepNewLines);
+
+ Lines up the toolbars. Line breaks are preserved if \a
+ keepNewLines is true.
+*/
+
+/*!
+ \fn void Q3MainWindow::toolBarPositionChanged(Q3ToolBar *toolbar);
+
+ This signal is emitted when a \a toolbar is moved.
+*/
+
+/*!
+ \fn bool Q3MainWindow::toolBarsMovable() const
+
+ Returns true if the window allows its toolbars to be moved; otherwise
+ returns false.
+*/
+
+/*!
+ \fn void Q3MainWindow::setToolBarsMovable(bool b)
+ If \a b is true the tool bars can be moved.
+*/
+
+/*!
+ Constructs an empty main window. The \a parent, \a name and widget
+ flags \a f, are passed on to the QWidget constructor.
+
+ By default, the widget flags are set to Qt::WType_TopLevel rather
+ than 0 as they are with QWidget. If you don't want your
+ Q3MainWindow to be a top level widget then you will need to set \a
+ f to 0.
+*/
+
+Q3MainWindow::Q3MainWindow(QWidget * parent, const char * name, Qt::WindowFlags f)
+ : QWidget(*new Q3MainWindowPrivate, parent, f)
+{
+ Q_D(Q3MainWindow);
+ setObjectName(QLatin1String(name));
+#ifdef Q_WS_MAC
+ d->opaque = true;
+#else
+ d->opaque = false;
+#endif
+ installEventFilter(this);
+ d->topDock = new Q3DockArea(Qt::Horizontal, Q3DockArea::Normal, this, "qt_top_dock");
+ d->topDock->installEventFilter(this);
+ d->bottomDock = new Q3DockArea(Qt::Horizontal, Q3DockArea::Reverse, this, "qt_bottom_dock");
+ d->bottomDock->installEventFilter(this);
+ d->leftDock = new Q3DockArea(Qt::Vertical, Q3DockArea::Normal, this, "qt_left_dock");
+ d->leftDock->installEventFilter(this);
+ d->rightDock = new Q3DockArea(Qt::Vertical, Q3DockArea::Reverse, this, "qt_right_dock");
+ d->rightDock->installEventFilter(this);
+ d->hideDock = new QHideDock(this);
+}
+
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3MainWindow::~Q3MainWindow()
+{
+ delete layout();
+}
+
+#ifndef QT_NO_MENUBAR
+/*!
+ Sets this main window to use the menu bar \a newMenuBar.
+
+ The existing menu bar (if any) is deleted along with its contents.
+
+ \sa menuBar()
+*/
+
+void Q3MainWindow::setMenuBar(QMenuBar * newMenuBar)
+{
+ Q_D(Q3MainWindow);
+ if (!newMenuBar)
+ return;
+ if (d->mb)
+ delete d->mb;
+ d->mb = newMenuBar;
+ d->mb->installEventFilter(this);
+ triggerLayout();
+}
+
+
+/*!
+ Returns the menu bar for this window.
+
+ If there isn't one, then menuBar() creates an empty menu bar.
+
+ \sa statusBar()
+*/
+
+QMenuBar * Q3MainWindow::menuBar() const
+{
+ Q_D(const Q3MainWindow);
+ if (d->mb)
+ return d->mb;
+
+ QObjectList l = queryList("QMenuBar", 0, false, false);
+ QMenuBar * b;
+ if (l.size()) {
+ b = static_cast<QMenuBar *>(l.at(0));
+ } else {
+ b = new QMenuBar((Q3MainWindow *)this);
+ b->setObjectName(QLatin1String("automatic menu bar"));
+ b->show();
+ }
+ d->mb = b;
+ d->mb->installEventFilter(const_cast<Q3MainWindow *>(this));
+ ((Q3MainWindow *)this)->triggerLayout();
+ return b;
+}
+#endif // QT_NO_MENUBAR
+
+/*!
+ Sets this main window to use the status bar \a newStatusBar.
+
+ The existing status bar (if any) is deleted along with its
+ contents.
+
+ Note that \a newStatusBar \e must be a child of this main window,
+ and that it is not automatically displayed. If you call this
+ function after show(), you will probably also need to call
+ newStatusBar->show().
+
+ \sa setMenuBar() statusBar()
+*/
+
+void Q3MainWindow::setStatusBar(QStatusBar * newStatusBar)
+{
+ Q_D(Q3MainWindow);
+ if (!newStatusBar || newStatusBar == d->sb)
+ return;
+ if (d->sb)
+ delete d->sb;
+ d->sb = newStatusBar;
+#if 0
+ // ### this code can cause unnecessary creation of a tool tip group
+ connect(toolTipGroup(), SIGNAL(showTip(QString)),
+ d->sb, SLOT(showMessage(QString)));
+ connect(toolTipGroup(), SIGNAL(removeTip()),
+ d->sb, SLOT(clearMessage()));
+#endif
+ d->sb->installEventFilter(this);
+ triggerLayout();
+}
+
+
+/*!
+ Returns this main window's status bar. If there isn't one,
+ statusBar() creates an empty status bar, and if necessary a tool
+ tip group too.
+
+ \sa menuBar()
+*/
+
+QStatusBar * Q3MainWindow::statusBar() const
+{
+ Q_D(const Q3MainWindow);
+ if (d->sb)
+ return d->sb;
+
+ QObjectList l = queryList("QStatusBar", 0, false, false);
+ QStatusBar * s;
+ if (l.size()) {
+ s = (QStatusBar *)l.at(0);
+ } else {
+ s = new QStatusBar((Q3MainWindow *)this, "automatic status bar");
+ s->show();
+ }
+ ((Q3MainWindow *)this)->setStatusBar(s);
+ ((Q3MainWindow *)this)->triggerLayout(true);
+ return s;
+}
+
+
+#if 0
+/*!
+ Sets this main window to use the tool tip group \a
+ newToolTipGroup.
+
+ The existing tool tip group (if any) is deleted along with its
+ contents. All the tool tips connected to it lose the ability to
+ display the group texts.
+
+ \sa menuBar()
+*/
+
+void Q3MainWindow::setToolTipGroup(QToolTipGroup * newToolTipGroup)
+{
+ Q_D(Q3MainWindow);
+ if (!newToolTipGroup || newToolTipGroup == d->ttg)
+ return;
+ if (d->ttg)
+ delete d->ttg;
+ d->ttg = newToolTipGroup;
+
+ connect(toolTipGroup(), SIGNAL(showTip(QString)),
+ statusBar(), SLOT(showMessage(QString)));
+ connect(toolTipGroup(), SIGNAL(removeTip()),
+ statusBar(), SLOT(clearMessage()));
+}
+
+
+/*!
+ Returns this main window's tool tip group. If there isn't one,
+ toolTipGroup() creates an empty tool tip group.
+
+ \sa menuBar() statusBar()
+*/
+QToolTipGroup * Q3MainWindow::toolTipGroup() const
+{
+ Q_D(const Q3MainWindow);
+ if (d->ttg)
+ return d->ttg;
+
+ QToolTipGroup * t = new QToolTipGroup((Q3MainWindow*)this,
+ "automatic tool tip group");
+ ((Q3MainWindowPrivate*)d)->ttg = t;
+ return t;
+}
+#endif
+
+
+/*!
+ If \a enable is true then users can dock windows in the \a dock
+ area. If \a enable is false users cannot dock windows in the \a
+ dock dock area.
+
+ Users can dock (drag) dock windows into any enabled dock area.
+*/
+
+void Q3MainWindow::setDockEnabled(Qt::Dock dock, bool enable)
+{
+ d_func()->docks.insert(dock, enable);
+}
+
+
+/*!
+ Returns true if the \a dock dock area is enabled, i.e. it can
+ accept user dragged dock windows; otherwise returns false.
+
+ \sa setDockEnabled()
+*/
+
+bool Q3MainWindow::isDockEnabled(Qt::Dock dock) const
+{
+ return d_func()->docks[dock];
+}
+
+/*!
+ \overload
+
+ Returns true if dock area \a area is enabled, i.e. it can accept
+ user dragged dock windows; otherwise returns false.
+
+ \sa setDockEnabled()
+*/
+
+bool Q3MainWindow::isDockEnabled(Q3DockArea *area) const
+{
+ Q_D(const Q3MainWindow);
+ if (area == d->leftDock)
+ return d->docks[Qt::DockLeft];
+ if (area == d->rightDock)
+ return d->docks[Qt::DockRight];
+ if (area == d->topDock)
+ return d->docks[Qt::DockTop];
+ if (area == d->bottomDock)
+ return d->docks[Qt::DockBottom];
+ return false;
+}
+
+/*!
+ \overload
+
+ If \a enable is true then users can dock the \a dw dock window in
+ the \a dock area. If \a enable is false users cannot dock the \a
+ dw dock window in the \a dock area.
+
+ In general users can dock (drag) dock windows into any enabled
+ dock area. Using this function particular dock areas can be
+ enabled (or disabled) as docking points for particular dock
+ windows.
+*/
+
+
+void Q3MainWindow::setDockEnabled(Q3DockWindow *dw, Qt::Dock dock, bool enable)
+{
+ Q_D(Q3MainWindow);
+ if (!d->dockWindows.contains(dw)) {
+ d->dockWindows.append(dw);
+ connect(dw, SIGNAL(placeChanged(Q3DockWindow::Place)),
+ this, SLOT(slotPlaceChanged()));
+ }
+ QString s;
+ s.sprintf("%p_%d", (void*)dw, (int)dock);
+ if (enable)
+ d->disabledDocks.removeAll(s);
+ else if (!d->disabledDocks.contains(s))
+ d->disabledDocks << s;
+ switch (dock) {
+ case Qt::DockTop:
+ topDock()->setAcceptDockWindow(dw, enable);
+ break;
+ case Qt::DockLeft:
+ leftDock()->setAcceptDockWindow(dw, enable);
+ break;
+ case Qt::DockRight:
+ rightDock()->setAcceptDockWindow(dw, enable);
+ break;
+ case Qt::DockBottom:
+ bottomDock()->setAcceptDockWindow(dw, enable);
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ \overload
+
+ Returns true if dock area \a area is enabled for the dock window
+ \a dw; otherwise returns false.
+
+ \sa setDockEnabled()
+*/
+
+bool Q3MainWindow::isDockEnabled(Q3DockWindow *dw, Q3DockArea *area) const
+{
+ Q_D(const Q3MainWindow);
+ if (!isDockEnabled(area))
+ return false;
+ Qt::Dock dock;
+ if (area == d->leftDock)
+ dock = Qt::DockLeft;
+ else if (area == d->rightDock)
+ dock = Qt::DockRight;
+ else if (area == d->topDock)
+ dock = Qt::DockTop;
+ else if (area == d->bottomDock)
+ dock = Qt::DockBottom;
+ else
+ return false;
+ return isDockEnabled(dw, dock);
+}
+
+/*!
+ \overload
+
+ Returns true if dock area \a dock is enabled for the dock window
+ \a tb; otherwise returns false.
+
+ \sa setDockEnabled()
+*/
+
+bool Q3MainWindow::isDockEnabled(Q3DockWindow *tb, Qt::Dock dock) const
+{
+ if (!isDockEnabled(dock))
+ return false;
+ QString s;
+ s.sprintf("%p_%d", (void*)tb, (int)dock);
+ return !d_func()->disabledDocks.contains(s);
+}
+
+
+
+/*!
+ Adds \a dockWindow to the \a edge dock area.
+
+ If \a newLine is false (the default) then the \a dockWindow is
+ added at the end of the \a edge. For vertical edges the end is at
+ the bottom, for horizontal edges (including \c Minimized) the end
+ is at the right. If \a newLine is true a new line of dock windows
+ is started with \a dockWindow as the first (left-most and
+ top-most) dock window.
+
+ If \a dockWindow is managed by another main window, it is first
+ removed from that window.
+*/
+
+void Q3MainWindow::addDockWindow(Q3DockWindow *dockWindow,
+ Qt::Dock edge, bool newLine)
+{
+ Q_D(Q3MainWindow);
+#ifdef Q_WS_MAC
+ extern WindowPtr qt_mac_window_for(const QWidget*); //qwidget_mac.cpp
+ if(isWindow() && edge == Qt::DockTop) {
+ d->createWinId();
+ ChangeWindowAttributes(qt_mac_window_for(this), kWindowToolbarButtonAttribute, 0);
+ }
+#endif
+ moveDockWindow(dockWindow, edge);
+ dockWindow->setNewLine(newLine);
+ if (!d->dockWindows.contains(dockWindow)) {
+ d->dockWindows.append(dockWindow);
+ connect(dockWindow, SIGNAL(placeChanged(Q3DockWindow::Place)),
+ this, SLOT(slotPlaceChanged()));
+ dockWindow->installEventFilter(this);
+ }
+ dockWindow->setOpaqueMoving(d->opaque);
+}
+
+
+/*!
+ \overload
+
+ Adds \a dockWindow to the dock area with label \a label.
+
+ If \a newLine is false (the default) the \a dockWindow is added at
+ the end of the \a edge. For vertical edges the end is at the
+ bottom, for horizontal edges (including \c Minimized) the end is
+ at the right. If \a newLine is true a new line of dock windows is
+ started with \a dockWindow as the first (left-most and top-most)
+ dock window.
+
+ If \a dockWindow is managed by another main window, it is first
+ removed from that window.
+*/
+
+void Q3MainWindow::addDockWindow(Q3DockWindow * dockWindow, const QString &label,
+ Qt::Dock edge, bool newLine)
+{
+ addDockWindow(dockWindow, edge, newLine);
+#ifndef QT_NO_TOOLBAR
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(dockWindow);
+ if (tb)
+ tb->setLabel(label);
+#endif
+}
+
+/*!
+ Moves \a dockWindow to the end of the \a edge.
+
+ For vertical edges the end is at the bottom, for horizontal edges
+ (including \c Minimized) the end is at the right.
+
+ If \a dockWindow is managed by another main window, it is first
+ removed from that window.
+*/
+
+void Q3MainWindow::moveDockWindow(Q3DockWindow * dockWindow, Qt::Dock edge)
+{
+ Q_D(Q3MainWindow);
+ Qt::Orientation oo = dockWindow->orientation();
+ switch (edge) {
+ case Qt::DockTop:
+ if (dockWindow->area() != d->topDock)
+ dockWindow->removeFromDock(false);
+ d->topDock->moveDockWindow(dockWindow);
+ emit dockWindowPositionChanged(dockWindow);
+ break;
+ case Qt::DockBottom:
+ if (dockWindow->area() != d->bottomDock)
+ dockWindow->removeFromDock(false);
+ d->bottomDock->moveDockWindow(dockWindow);
+ emit dockWindowPositionChanged(dockWindow);
+ break;
+ case Qt::DockRight:
+ if (dockWindow->area() != d->rightDock)
+ dockWindow->removeFromDock(false);
+ d->rightDock->moveDockWindow(dockWindow);
+ emit dockWindowPositionChanged(dockWindow);
+ break;
+ case Qt::DockLeft:
+ if (dockWindow->area() != d->leftDock)
+ dockWindow->removeFromDock(false);
+ d->leftDock->moveDockWindow(dockWindow);
+ emit dockWindowPositionChanged(dockWindow);
+ break;
+ case Qt::DockTornOff:
+ dockWindow->undock();
+ break;
+ case Qt::DockMinimized:
+ dockWindow->undock(d->hideDock);
+ break;
+ case Qt::DockUnmanaged:
+ break;
+ }
+
+ if (oo != dockWindow->orientation())
+ dockWindow->setOrientation(dockWindow->orientation());
+}
+
+/*!
+ \overload
+
+ Moves \a dockWindow to position \a index within the \a edge dock
+ area.
+
+ Any dock windows with positions \a index or higher have their
+ position number incremented and any of these on the same line are
+ moved right (down for vertical dock areas) to make room.
+
+ If \a nl is true, a new dock window line is created below the line
+ in which the moved dock window appears and the moved dock window,
+ with any others with higher positions on the same line, is moved
+ to this new line.
+
+ The \a extraOffset is the space to put between the left side of
+ the dock area (top side for vertical dock areas) and the dock
+ window. (This is mostly used for restoring dock windows to the
+ positions the user has dragged them to.)
+
+ If \a dockWindow is managed by another main window, it is first
+ removed from that window.
+*/
+
+void Q3MainWindow::moveDockWindow(Q3DockWindow * dockWindow, Qt::Dock edge, bool nl, int index, int extraOffset)
+{
+ Q_D(Q3MainWindow);
+ Qt::Orientation oo = dockWindow->orientation();
+
+ dockWindow->setNewLine(nl);
+ dockWindow->setOffset(extraOffset);
+ switch (edge) {
+ case Qt::DockTop:
+ if (dockWindow->area() != d->topDock)
+ dockWindow->removeFromDock(false);
+ d->topDock->moveDockWindow(dockWindow, index);
+ break;
+ case Qt::DockBottom:
+ if (dockWindow->area() != d->bottomDock)
+ dockWindow->removeFromDock(false);
+ d->bottomDock->moveDockWindow(dockWindow, index);
+ break;
+ case Qt::DockRight:
+ if (dockWindow->area() != d->rightDock)
+ dockWindow->removeFromDock(false);
+ d->rightDock->moveDockWindow(dockWindow, index);
+ break;
+ case Qt::DockLeft:
+ if (dockWindow->area() != d->leftDock)
+ dockWindow->removeFromDock(false);
+ d->leftDock->moveDockWindow(dockWindow, index);
+ break;
+ case Qt::DockTornOff:
+ dockWindow->undock();
+ break;
+ case Qt::DockMinimized:
+ dockWindow->undock(d->hideDock);
+ break;
+ case Qt::DockUnmanaged:
+ break;
+ }
+
+ if (oo != dockWindow->orientation())
+ dockWindow->setOrientation(dockWindow->orientation());
+}
+
+/*!
+ Removes \a dockWindow from the main window's docking area,
+ provided \a dockWindow is non-null and managed by this main
+ window.
+*/
+
+void Q3MainWindow::removeDockWindow(Q3DockWindow * dockWindow)
+{
+ Q_D(Q3MainWindow);
+
+#ifdef Q_WS_MAC
+ extern WindowPtr qt_mac_window_for(const QWidget*); //qwidget_mac.cpp
+ if(isWindow() && dockWindow->area() == topDock() && !dockWindows(Qt::DockTop).count())
+ ChangeWindowAttributes(qt_mac_window_for(this), 0, kWindowToolbarButtonAttribute);
+#endif
+
+ dockWindow->hide();
+ d->dockWindows.removeAll(dockWindow);
+ disconnect(dockWindow, SIGNAL(placeChanged(Q3DockWindow::Place)),
+ this, SLOT(slotPlaceChanged()));
+ dockWindow->removeEventFilter(this);
+}
+
+/*!
+ Sets up the geometry management of the window. It is called
+ automatically when needed, so you shouldn't need to call it.
+*/
+
+void Q3MainWindow::setUpLayout()
+{
+ Q_D(Q3MainWindow);
+#ifndef QT_NO_MENUBAR
+ if (!d->mb) {
+ // slightly evil hack here. reconsider this
+ QObjectList l = queryList("QMenuBar", 0, false, false);
+ if (l.size())
+ d->mb = menuBar();
+ }
+#endif
+ if (!d->sb) {
+ // as above.
+ QObjectList l = queryList("QStatusBar", 0, false, false);
+ if (l.size())
+ d->sb = statusBar();
+ }
+
+ if (!d->tll) {
+ d->tll = new QBoxLayout(this, QBoxLayout::Down);
+ d->tll->setResizeMode(minimumSize().isNull() ? QLayout::Minimum : QLayout::FreeResize);
+ d->mwl = new Q3MainWindowLayout(this);
+ } else {
+ d->tll->setMenuBar(0);
+ QLayoutItem *item;
+ while ((item = d->tll->takeAt(0))) {
+ if (item != d->mwl)
+ delete item;
+ }
+ }
+
+#ifndef QT_NO_MENUBAR
+ if (d->mb && d->mb->isVisibleTo(this)) {
+ d->tll->setMenuBar(d->mb);
+ if (style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this))
+ d->tll->addSpacing(d->movable ? 1 : 2);
+ }
+#endif
+
+ d->tll->addWidget(d->hideDock);
+ if(d->topDock->parentWidget() == this)
+ d->tll->addWidget(d->topDock);
+
+ Q3MainWindowLayout *mwl = d->mwl;
+ d->tll->addItem(mwl);
+ d->tll->setStretchFactor(mwl, 1);
+
+ if(d->leftDock->parentWidget() == this)
+ mwl->setLeftDock(d->leftDock);
+ if (centralWidget())
+ mwl->setCentralWidget(centralWidget());
+ if(d->rightDock->parentWidget() == this)
+ mwl->setRightDock(d->rightDock);
+
+ if(d->bottomDock->parentWidget() == this)
+ d->tll->addWidget(d->bottomDock);
+
+ if (d->sb && d->sb->parentWidget() == this) {
+ d->tll->addWidget(d->sb, 0);
+ // make the sb stay on top of tool bars if there isn't enough space
+ d->sb->raise();
+ }
+}
+
+/*! \reimp */
+void Q3MainWindow::setVisible(bool visible)
+{
+ Q_D(Q3MainWindow);
+ if (visible) {
+ if (!d->tll)
+ setUpLayout();
+
+ // show all floating dock windows not explicitly hidden
+ if (!isVisible()) {
+ for (int i = 0; i < d->dockWindows.size(); ++i) {
+ Q3DockWindow *dw = d->dockWindows.at(i);
+ if (dw->isWindow() && !dw->isVisible() && !dw->testAttribute(Qt::WA_WState_Hidden)) {
+ reinterpret_cast<Q3MainWindow *>(dw)->setAttribute(Qt::WA_WState_Hidden);
+ dw->show();
+ }
+ }
+ }
+ } else if (isVisible()) {
+ for (int i = 0; i < d->dockWindows.size(); ++i) {
+ Q3DockWindow *dw = d->dockWindows.at(i);
+ if (dw->isWindow() && dw->isVisible()) {
+ dw->hide(); // implicit hide, so clear forcehide
+ reinterpret_cast<Q3MainWindow *>(dw)->setAttribute(Qt::WA_WState_Hidden, false);
+ }
+ }
+ }
+ QWidget::setVisible(visible);
+}
+
+
+/*! \reimp */
+QSize Q3MainWindow::sizeHint() const
+{
+ Q3MainWindow* that = (Q3MainWindow*) this;
+ // Workaround: because d->tll get's deleted in
+ // totalSizeHint->polish->sendPostedEvents->childEvent->triggerLayout
+ QApplication::sendPostedEvents(that, QEvent::ChildInserted);
+ if (!that->d_func()->tll)
+ that->setUpLayout();
+ return that->d_func()->tll->totalSizeHint();
+}
+
+/*! \reimp */
+QSize Q3MainWindow::minimumSizeHint() const
+{
+ Q_D(const Q3MainWindow);
+ if (!d->tll) {
+ Q3MainWindow* that = (Q3MainWindow*) this;
+ that->setUpLayout();
+ }
+ return d->tll->totalMinimumSize();
+}
+
+/*!
+ Sets the central widget for this main window to \a w.
+
+ The central widget is surrounded by the left, top, right and
+ bottom dock areas. The menu bar is above the top dock area.
+
+ \sa centralWidget()
+*/
+
+void Q3MainWindow::setCentralWidget(QWidget * w)
+{
+ Q_D(Q3MainWindow);
+ if (d->mc)
+ d->mc->removeEventFilter(this);
+ d->mc = w;
+ if (d->mc)
+ d->mc->installEventFilter(this);
+ triggerLayout();
+}
+
+
+/*!
+ Returns a pointer to the main window's central widget.
+
+ The central widget is surrounded by the left, top, right and
+ bottom dock areas. The menu bar is above the top dock area.
+
+ \sa setCentralWidget()
+*/
+
+QWidget * Q3MainWindow::centralWidget() const
+{
+ return d_func()->mc;
+}
+
+
+/*! \reimp */
+
+void Q3MainWindow::paintEvent(QPaintEvent *)
+{
+ Q_D(Q3MainWindow);
+ if (d->mb &&
+ style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this)) {
+ QPainter p(this);
+ int y = d->mb->height() + 1;
+ QStyleOption opt(0, QStyleOption::SO_Default);
+ opt.rect.setRect(0, y, width(), 1);
+ opt.palette = palette();
+ opt.state = QStyle::State_Sunken;
+ style()->drawPrimitive(QStyle::PE_Q3Separator, &opt, &p, this);
+ }
+}
+
+
+bool Q3MainWindow::dockMainWindow(QObject *dock) const
+{
+ while (dock) {
+ if (dock->parent() &&
+ dock->parent() == const_cast<Q3MainWindow*>(this))
+ return true;
+ if (qobject_cast<Q3MainWindow*>(dock->parent()))
+ return false;
+ dock = dock->parent();
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+
+bool Q3MainWindow::eventFilter(QObject* o, QEvent *e)
+{
+ Q_D(Q3MainWindow);
+ if (e->type() == QEvent::Show && o == this) {
+ if (!d->tll)
+ setUpLayout();
+ d->tll->activate();
+ } else if (e->type() == QEvent::ContextMenu && d->dockMenu &&
+ ((qobject_cast<Q3DockArea*>(o) && dockMainWindow(o)) || o == d->hideDock || o == d->mb)) {
+ if (showDockMenu(((QMouseEvent*)e)->globalPos())) {
+ ((QContextMenuEvent*)e)->accept();
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+
+/*!
+ Monitors events, received in \a e, to ensure the layout is updated.
+*/
+void Q3MainWindow::childEvent(QChildEvent* e)
+{
+ Q_D(Q3MainWindow);
+ if (e->type() == QEvent::ChildRemoved) {
+ if (e->child() == 0 ||
+ !e->child()->isWidgetType() ||
+ ((QWidget*)e->child())->isWindow()) {
+ // nothing
+ } else if (e->child() == d->sb) {
+ d->sb = 0;
+ triggerLayout();
+ } else if (e->child() == d->mb) {
+ d->mb = 0;
+ triggerLayout();
+ } else if (e->child() == d->mc) {
+ d->mc = 0;
+ d->mwl->setCentralWidget(0);
+ triggerLayout();
+ } else if (qobject_cast<Q3DockWindow*>(e->child())) {
+ removeDockWindow((Q3DockWindow *)(e->child()));
+ d->appropriate.remove((Q3DockWindow*)e->child());
+ triggerLayout();
+ }
+ } else if (e->type() == QEvent::ChildInserted && !d->sb) {
+ d->sb = qobject_cast<QStatusBar*>(e->child());
+ if (d->sb) {
+ if (d->tll) {
+ if (!d->tll->findWidget(d->sb))
+ d->tll->addWidget(d->sb);
+ } else {
+ triggerLayout();
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+
+bool Q3MainWindow::event(QEvent * e)
+{
+ Q_D(Q3MainWindow);
+#ifndef QT_NO_STATUSTIP
+ if (e->type() == QEvent::StatusTip) {
+ if (d->sb) {
+ d->sb->showMessage(static_cast<QStatusTipEvent*>(e)->tip());
+ return true;
+ }
+ }
+#endif
+ if (e->type() == QEvent::ToolBarChange) {
+ // Keep compatibility with the Qt 3 main window, use the real main window
+ // or reimplement if you want proper handling.
+ int deltaH = 0;
+ Q3DockArea *area = topDock();
+ if (area->width() >= area->height()) {
+ deltaH = area->sizeHint().height();
+ if (!area->isVisible()) {
+ area->show();
+ } else {
+ area->hide();
+ deltaH = -deltaH;
+ }
+ }
+
+ if (deltaH) {
+ QApplication::sendPostedEvents(this, QEvent::LayoutRequest);
+ resize(width(), height() + deltaH);
+ }
+ return true;
+ }
+ if (e->type() == QEvent::ChildRemoved && ((QChildEvent*)e)->child() == d->mc) {
+ d->mc->removeEventFilter(this);
+ d->mc = 0;
+ d->mwl->setCentralWidget(0);
+ }
+
+ if (e->type() == QEvent::MenubarUpdated) {
+ QMenubarUpdatedEvent * const event = static_cast<QMenubarUpdatedEvent *>(e);
+ if (event->menuBar() && event->menuBar()->parent() == this) {
+ triggerLayout();
+ update();
+ }
+ }
+ return QWidget::event(e);
+}
+
+
+/*!
+ \property Q3MainWindow::usesBigPixmaps
+ \brief whether big pixmaps are enabled
+
+ If false (the default), the tool buttons will use small pixmaps;
+ otherwise big pixmaps will be used.
+
+ Tool buttons and other widgets that wish to respond to this
+ setting are responsible for reading the correct state on startup,
+ and for connecting to the main window's widget's
+ pixmapSizeChanged() signal.
+*/
+
+bool Q3MainWindow::usesBigPixmaps() const
+{
+ return d_func()->ubp;
+}
+
+void Q3MainWindow::setUsesBigPixmaps(bool enable)
+{
+ Q_D(Q3MainWindow);
+ if (enable == (bool)d->ubp)
+ return;
+
+ d->ubp = enable;
+ emit pixmapSizeChanged(enable);
+
+ QObjectList l = queryList("QLayout");
+ for (int i = 0; i < l.size(); ++i)
+ static_cast<QLayout *>(l.at(i))->activate();
+}
+
+/*!
+ \property Q3MainWindow::usesTextLabel
+ \brief whether text labels for toolbar buttons are enabled
+
+ If disabled (the default), the tool buttons will not use text
+ labels. If enabled, text labels will be used.
+
+ Tool buttons and other widgets that wish to respond to this
+ setting are responsible for reading the correct state on startup,
+ and for connecting to the main window's widget's
+ usesTextLabelChanged() signal.
+
+ \sa QToolButton::setUsesTextLabel()
+*/
+
+bool Q3MainWindow::usesTextLabel() const
+{
+ return d_func()->utl;
+}
+
+
+void Q3MainWindow::setUsesTextLabel(bool enable)
+{
+ Q_D(Q3MainWindow);
+ if (enable == (bool)d->utl)
+ return;
+
+ d->utl = enable;
+ emit usesTextLabelChanged(enable);
+
+ QObjectList l = queryList("QLayout");
+ for (int i = 0; i < l.size(); ++i)
+ static_cast<QLayout *>(l.at(i))->activate();
+ triggerLayout(false);
+}
+
+
+/*!
+ \fn void Q3MainWindow::pixmapSizeChanged(bool b)
+
+ This signal is emitted whenever the setUsesBigPixmaps() is called
+ with a value different to the current setting. The new value is
+ passed in \a b. All widgets that should respond to such changes,
+ e.g. toolbar buttons, must connect to this signal.
+*/
+
+/*!
+ \fn void Q3MainWindow::usesTextLabelChanged(bool b)
+
+ This signal is emitted whenever the setUsesTextLabel() is called
+ with a value different to the current setting. The new value is
+ passed in \a b. All widgets that should respond to such changes,
+ e.g. toolbar buttons, must connect to this signal.
+*/
+
+/*!
+ \fn void Q3MainWindow::dockWindowPositionChanged(Q3DockWindow *dockWindow)
+
+ This signal is emitted when the \a dockWindow has changed its
+ position. A change in position occurs when a dock window is moved
+ within its dock area or moved to another dock area (including the
+ \c Minimized and \c TearOff dock areas).
+
+ \sa getLocation()
+*/
+
+void Q3MainWindow::setRightJustification(bool enable)
+{
+ Q_D(Q3MainWindow);
+ if (enable == (bool)d->justify)
+ return;
+ d->justify = enable;
+ triggerLayout(true);
+}
+
+
+/*!
+ \property Q3MainWindow::rightJustification
+ \brief whether the main window right-justifies its dock windows
+
+ If disabled (the default), stretchable dock windows are expanded,
+ and non-stretchable dock windows are given the minimum space they
+ need. Since most dock windows are not stretchable, this usually
+ results in an unjustified right edge (or unjustified bottom edge
+ for a vertical dock area). If enabled, the main window will
+ right-justify its dock windows.
+
+ \sa Q3DockWindow::setVerticalStretchable(), Q3DockWindow::setHorizontalStretchable()
+*/
+
+bool Q3MainWindow::rightJustification() const
+{
+ return d_func()->justify;
+}
+
+/*! \internal
+ */
+
+void Q3MainWindow::triggerLayout(bool deleteLayout)
+{
+ Q_D(Q3MainWindow);
+ if (deleteLayout || !d->tll)
+ setUpLayout();
+ QApplication::postEvent(this, new QEvent(QEvent::LayoutHint));
+}
+
+/*!
+ Enters 'What's This?' mode and returns immediately.
+
+ This is the same as QWhatsThis::enterWhatsThisMode(), but
+ implemented as a main window object's slot. This way it can easily
+ be used for popup menus, for example:
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3mainwindow.cpp 4
+
+ \sa Q3WhatsThis::enterWhatsThisMode()
+*/
+void Q3MainWindow::whatsThis()
+{
+#ifndef QT_NO_WHATSTHIS
+ QWhatsThis::enterWhatsThisMode();
+#endif
+}
+
+/*!
+ Finds the location of the dock window \a dw.
+
+ If the \a dw dock window is found in the main window the function
+ returns true and populates the \a dock variable with the dw's dock
+ area and the \a index with the dw's position within the dock area.
+ It also sets \a nl to true if the \a dw begins a new line
+ (otherwise false), and \a extraOffset with the dock window's offset.
+
+ If the \a dw dock window is not found then the function returns
+ false and the state of \a dock, \a index, \a nl and \a extraOffset
+ is undefined.
+
+ If you want to save and restore dock window positions then use
+ operator>>() and operator<<().
+*/
+
+bool Q3MainWindow::getLocation(Q3DockWindow *dw, Qt::Dock &dock, int &index, bool &nl, int &extraOffset) const
+{
+ Q_D(const Q3MainWindow);
+ dock = Qt::DockTornOff;
+ if (d->topDock->hasDockWindow(dw, &index))
+ dock = Qt::DockTop;
+ else if (d->bottomDock->hasDockWindow(dw, &index))
+ dock = Qt::DockBottom;
+ else if (d->leftDock->hasDockWindow(dw, &index))
+ dock = Qt::DockLeft;
+ else if (d->rightDock->hasDockWindow(dw, &index))
+ dock = Qt::DockRight;
+ else if (dw->parentWidget() == d->hideDock) {
+ index = 0;
+ dock = Qt::DockMinimized;
+ } else {
+ index = 0;
+ }
+ nl = dw->newLine();
+ extraOffset = dw->offset();
+ return true;
+}
+
+#ifndef QT_NO_TOOLBAR
+/*!
+ Returns a list of all the toolbars which are in the \a dock dock
+ area, regardless of their state.
+
+ For example, the \c TornOff dock area may contain closed toolbars
+ but these are returned along with the visible toolbars.
+
+ \sa dockWindows()
+*/
+
+QList<Q3ToolBar *> Q3MainWindow::toolBars(Qt::Dock dock) const
+{
+ QList<Q3DockWindow *> lst = dockWindows(dock);
+ QList<Q3ToolBar *> tbl;
+ for (int i = 0; i < lst.size(); ++i) {
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar *>(lst.at(i));
+ if (tb)
+ tbl.append(tb);
+ }
+ return tbl;
+}
+#endif
+
+/*!
+ Returns a list of all the dock windows which are in the \a dock
+ dock area, regardless of their state.
+
+ For example, the Qt::DockTornOff dock area may contain closed dock
+ windows but these are returned along with the visible dock
+ windows.
+*/
+
+QList<Q3DockWindow *> Q3MainWindow::dockWindows(Qt::Dock dock) const
+{
+ Q_D(const Q3MainWindow);
+ QList<Q3DockWindow *> lst;
+ switch (dock) {
+ case Qt::DockTop:
+ return d->topDock->dockWindowList();
+ case Qt::DockBottom:
+ return d->bottomDock->dockWindowList();
+ case Qt::DockLeft:
+ return d->leftDock->dockWindowList();
+ case Qt::DockRight:
+ return d->rightDock->dockWindowList();
+ case Qt::DockTornOff: {
+ for (int i = 0; i < d->dockWindows.size(); ++i) {
+ Q3DockWindow *w = d->dockWindows.at(i);
+ if (!w->area() && w->place() == Q3DockWindow::OutsideDock)
+ lst.append(w);
+ }
+ }
+ return lst;
+ case Qt::DockMinimized: {
+ QObjectList childList = d->hideDock->children();
+ for (int i = 0; i < childList.size(); ++i) {
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(childList.at(i));
+ if (dw)
+ lst.append(dw);
+ }
+ }
+ return lst;
+ default:
+ break;
+ }
+ return lst;
+}
+
+/*!
+ \overload
+
+ Returns the list of dock windows which belong to this main window,
+ regardless of which dock area they are in or what their state is,
+ (e.g. irrespective of whether they are visible or not).
+*/
+
+QList<Q3DockWindow *> Q3MainWindow::dockWindows() const
+{
+ return d_func()->dockWindows;
+}
+
+void Q3MainWindow::setDockWindowsMovable(bool enable)
+{
+ Q_D(Q3MainWindow);
+ d->movable = enable;
+ QObjectList l = queryList("Q3DockWindow");
+ for (int i = 0; i < l.size(); ++i)
+ static_cast<Q3DockWindow*>(l.at(i))->setMovingEnabled(enable);
+}
+
+/*!
+ \property Q3MainWindow::dockWindowsMovable
+ \brief whether the dock windows are movable
+
+ If true (the default), the user will be able to move movable dock
+ windows from one Q3MainWindow dock area to another, including the
+ \c TearOff area (i.e. where the dock window floats freely as a
+ window in its own right), and the \c Minimized area (where only
+ the dock window's handle is shown below the menu bar). Movable
+ dock windows can also be moved within Q3MainWindow dock areas, i.e.
+ to rearrange them within a dock area.
+
+ If false the user will not be able to move any dock windows.
+
+ By default dock windows are moved transparently (i.e. only an
+ outline rectangle is shown during the drag), but this setting can
+ be changed with setOpaqueMoving().
+
+ \sa setDockEnabled(), setOpaqueMoving()
+*/
+
+bool Q3MainWindow::dockWindowsMovable() const
+{
+ return d_func()->movable;
+}
+
+void Q3MainWindow::setOpaqueMoving(bool b)
+{
+ Q_D(Q3MainWindow);
+ d->opaque = b;
+ QObjectList l = queryList("Q3DockWindow");
+ for (int i = 0; i < l.size(); ++i)
+ static_cast<Q3DockWindow*>(l.at(i))->setOpaqueMoving(b);
+}
+
+/*!
+ \property Q3MainWindow::opaqueMoving
+ \brief whether dock windows are moved opaquely
+
+ If true the dock windows of the main window are shown opaquely
+ (i.e. it shows the toolbar as it looks when docked) whilst it is
+ being moved. If false (the default) they are shown transparently,
+ (i.e. as an outline rectangle).
+
+ \warning Opaque moving of toolbars and dockwindows is known to
+ have several problems. We recommend avoiding the use of this
+ feature for the time being. We intend fixing the problems in a
+ future release.
+*/
+
+bool Q3MainWindow::opaqueMoving() const
+{
+ return d_func()->opaque;
+}
+
+/*!
+ This function will line up dock windows within the visible dock
+ areas (\c Top, \c Left, \c Right and \c Bottom) as compactly as
+ possible.
+
+ If \a keepNewLines is true, all dock windows stay on their
+ original lines. If \a keepNewLines is false then newlines may be
+ removed to achieve the most compact layout possible.
+
+ The method only works if dockWindowsMovable() returns true.
+*/
+
+void Q3MainWindow::lineUpDockWindows(bool keepNewLines)
+{
+ Q_D(const Q3MainWindow);
+ if (!dockWindowsMovable())
+ return;
+ d->topDock->lineUp(keepNewLines);
+ d->leftDock->lineUp(keepNewLines);
+ d->rightDock->lineUp(keepNewLines);
+ d->bottomDock->lineUp(keepNewLines);
+}
+
+/*!
+ Returns true, if the dock window menu is enabled; otherwise
+ returns false.
+
+ The menu lists the (appropriate()) dock windows (which may be
+ shown or hidden), and has a "Line Up Dock Windows" menu item. It
+ will also have a "Customize" menu item if isCustomizable() returns
+ true.
+
+ \sa setDockEnabled(), lineUpDockWindows() appropriate()
+ setAppropriate()
+*/
+
+bool Q3MainWindow::isDockMenuEnabled() const
+{
+ return d_func()->dockMenu;
+}
+
+/*!
+ If \a b is true, then right clicking on a dock window or dock area
+ will pop up the dock window menu. If \a b is false, right clicking
+ a dock window or dock area will not pop up the menu.
+
+ The menu lists the (appropriate()) dock windows (which may be
+ shown or hidden), and has a "Line Up Dock Windows" item. It will
+ also have a "Customize" menu item if isCustomizable() returns
+ true.
+
+ \sa lineUpDockWindows(), isDockMenuEnabled()
+*/
+
+void Q3MainWindow::setDockMenuEnabled(bool b)
+{
+ d_func()->dockMenu = b;
+}
+
+/*!
+ Creates the dock window menu which contains all toolbars (if \a
+ dockWindows is \c OnlyToolBars), all dock windows (if \a
+ dockWindows is \c NoToolBars) or all toolbars and dock windows (if
+ \a dockWindows is \c AllDockWindows - the default).
+
+ This function is called internally when necessary, e.g. when the
+ user right clicks a dock area (providing isDockMenuEnabled()
+ returns true). You can reimplement this function if you wish to
+ customize the behavior.
+
+ The menu items representing the toolbars and dock windows are
+ checkable. The visible dock windows are checked and the hidden
+ dock windows are unchecked. The user can click a menu item to
+ change its state (show or hide the dock window).
+
+ The list and the state are always kept up-to-date.
+
+ Toolbars and dock windows which are not appropriate in the current
+ context (see setAppropriate()) are not listed in the menu.
+
+ The menu also has a menu item for lining up the dock windows.
+
+ If isCustomizable() returns true, a Customize menu item is added
+ to the menu, which if clicked will call customize(). The
+ isCustomizable() function we provide returns false and customize()
+ does nothing, so they must be reimplemented in a subclass to be
+ useful.
+*/
+
+Q3PopupMenu *Q3MainWindow::createDockWindowMenu(DockWindows dockWindows) const
+{
+ Q_D(const Q3MainWindow);
+ QObjectList l = queryList("Q3DockWindow");
+ if (l.isEmpty())
+ return 0;
+
+ Q3PopupMenu *menu = new Q3PopupMenu((Q3MainWindow*)this);
+ menu->setObjectName(QLatin1String("qt_customize_menu"));
+ d->dockWindowModes.replace( menu, dockWindows );
+ menu->setCheckable(true);
+ connect( menu, SIGNAL(aboutToShow()), this, SLOT(menuAboutToShow()) );
+ return menu;
+}
+
+/*!
+ This slot is called from the aboutToShow() signal of the default
+ dock menu of the mainwindow. The default implementation
+ initializes the menu with all dock windows and toolbars in this
+ slot.
+*/
+
+void Q3MainWindow::menuAboutToShow()
+{
+ Q_D(Q3MainWindow);
+ Q3PopupMenu *menu = (Q3PopupMenu*)sender();
+ menu->clear();
+
+ DockWindows dockWindows;
+ {
+ QMap<Q3PopupMenu*, DockWindows>::Iterator it = d->dockWindowModes.find( menu );
+ if ( it == d->dockWindowModes.end() )
+ return;
+ dockWindows = (*it);
+ }
+
+ QObjectList l = queryList("Q3DockWindow");
+ bool empty = true;
+ if (!l.isEmpty()) {
+ if (dockWindows == AllDockWindows || dockWindows == NoToolBars) {
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = (Q3DockWindow*)l.at(i);
+ if (!appropriate(dw) || qobject_cast<Q3ToolBar*>(dw) || !dockMainWindow(dw))
+ continue;
+ QString label = dw->windowTitle();
+ if (!label.isEmpty()) {
+ QAction *act = menu->addAction(label);
+ act->setCheckable(true);
+ act->setChecked(dw->isVisible());
+ QObject::connect(act, SIGNAL(triggered()), dw, SLOT(toggleVisible()));
+ empty = false;
+ }
+ }
+ }
+ if (!empty) {
+ menu->addSeparator();
+ empty = true;
+ }
+#ifndef QT_NO_TOOLBAR
+ if (dockWindows == AllDockWindows || dockWindows == OnlyToolBars) {
+ for (int i = 0; i < l.size(); ++i) {
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(l.at(i));
+ if (!tb || !appropriate(tb) || !dockMainWindow(tb))
+ continue;
+ QString label = tb->label();
+ if (!label.isEmpty()) {
+ QAction *act = menu->addAction(label);
+ act->setCheckable(true);
+ act->setChecked(tb->isVisible());
+ QObject::connect(act, SIGNAL(triggered()), tb, SLOT(toggleVisible()));
+ empty = false;
+ }
+ }
+ }
+#endif
+ }
+ if (!empty) {
+ menu->addSeparator();
+ empty = true;
+ }
+
+ if (dockWindowsMovable())
+ menu->addAction(tr("Line up"), this, SLOT(doLineUp()));
+ if (isCustomizable())
+ menu->addAction(tr("Customize..."), this, SLOT(customize()));
+}
+
+
+/*!
+ Shows the dock menu at the position \a globalPos. The menu lists
+ the dock windows so that they can be shown (or hidden), lined up,
+ and possibly customized. Returns true if the menu is shown;
+ otherwise returns false.
+
+ If you want a custom menu, reimplement this function. You can
+ create the menu from scratch or call createDockWindowMenu() and
+ modify the result.
+
+ The default implementation uses the dock window menu which gets
+ created by createDockWindowMenu(). You can reimplement
+ createDockWindowMenu() if you want to use your own specialized
+ popup menu.
+*/
+
+bool Q3MainWindow::showDockMenu(const QPoint &globalPos)
+{
+ Q_D(Q3MainWindow);
+ if (!d->dockMenu)
+ return false;
+
+ if(Q3PopupMenu *ret = createDockWindowMenu()) {
+ ret->exec(globalPos);
+ delete ret;
+ return true;
+ }
+ return false;
+}
+
+void Q3MainWindow::slotPlaceChanged()
+{
+ QObject* obj = (QObject*)sender();
+ Q3DockWindow *dw = qobject_cast<Q3DockWindow*>(obj);
+ if (dw)
+ emit dockWindowPositionChanged(dw);
+#ifndef QT_NO_TOOLBAR
+ Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(obj);
+ if (tb)
+ emit toolBarPositionChanged(tb);
+#endif
+}
+
+/*!
+ \internal
+ For internal use of Q3DockWindow only.
+ */
+
+Q3DockArea *Q3MainWindow::dockingArea(const QPoint &p)
+{
+ Q_D(Q3MainWindow);
+ int mh = d->mb ? d->mb->height() : 0;
+ int sh = d->sb ? d->sb->height() : 0;
+ if (p.x() >= -5 && p.x() <= 100 && p.y() > mh && p.y() - height() - sh)
+ return d->leftDock;
+ if (p.x() >= width() - 100 && p.x() <= width() + 5 && p.y() > mh && p.y() - height() - sh)
+ return d->rightDock;
+ if (p.y() >= -5 && p.y() < mh + 100 && p.x() >= 0 && p.x() <= width())
+ return d->topDock;
+ if (p.y() >= height() - sh - 100 && p.y() <= height() + 5 && p.x() >= 0 && p.x() <= width())
+ return d->bottomDock;
+ return 0;
+}
+
+/*!
+ Returns true if \a dw is a dock window known to the main window;
+ otherwise returns false.
+*/
+
+bool Q3MainWindow::hasDockWindow(Q3DockWindow *dw)
+{
+ return d_func()->dockWindows.contains(dw);
+}
+
+/*!
+ Returns the \c Left dock area
+
+ \sa rightDock() topDock() bottomDock()
+*/
+
+Q3DockArea *Q3MainWindow::leftDock() const
+{
+ return d_func()->leftDock;
+}
+
+/*!
+ Returns the \c Right dock area
+
+ \sa leftDock() topDock() bottomDock()
+*/
+
+Q3DockArea *Q3MainWindow::rightDock() const
+{
+ return d_func()->rightDock;
+}
+
+/*!
+ Returns the \c Top dock area
+
+ \sa bottomDock() leftDock() rightDock()
+*/
+
+Q3DockArea *Q3MainWindow::topDock() const
+{
+ return d_func()->topDock;
+}
+
+/*!
+ Returns a pointer the \c Bottom dock area
+
+ \sa topDock() leftDock() rightDock()
+*/
+
+Q3DockArea *Q3MainWindow::bottomDock() const
+{
+ return d_func()->bottomDock;
+}
+
+/*!
+ This function is called when the user clicks the Customize menu
+ item on the dock window menu.
+
+ The customize menu item will only appear if isCustomizable()
+ returns true (it returns false by default).
+
+ The function is intended, for example, to provide the user with a
+ means of telling the application that they wish to customize the
+ main window, dock windows or dock areas.
+
+ The default implementation does nothing and the Customize menu
+ item is not shown on the right-click menu by default. If you want
+ the item to appear then reimplement isCustomizable() to return
+ true, and reimplement this function to do whatever you want.
+
+ \sa isCustomizable()
+*/
+
+void Q3MainWindow::customize()
+{
+}
+
+/*!
+ Returns true if the dock area dock window menu includes the
+ Customize menu item (which calls customize() when clicked).
+ Returns false by default, i.e. the popup menu will not contain a
+ Customize menu item. You will need to reimplement this function
+ and set it to return true if you wish the user to be able to see
+ the dock window menu.
+
+ \sa customize()
+*/
+
+bool Q3MainWindow::isCustomizable() const
+{
+ return false;
+}
+
+/*!
+ Returns true if it is appropriate to include a menu item for the
+ \a dw dock window in the dock window menu; otherwise returns
+ false.
+
+ The user is able to change the state (show or hide) a dock window
+ that has a menu item by clicking the item.
+
+ Call setAppropriate() to indicate whether or not a particular dock
+ window should appear on the popup menu.
+
+ \sa setAppropriate()
+*/
+
+bool Q3MainWindow::appropriate(Q3DockWindow *dw) const
+{
+ Q_D(const Q3MainWindow);
+ QMap<Q3DockWindow*, bool>::ConstIterator it = d->appropriate.find(dw);
+ if (it == d->appropriate.end())
+ return true;
+ return *it;
+}
+
+/*!
+ Use this function to control whether or not the \a dw dock
+ window's caption should appear as a menu item on the dock window
+ menu that lists the dock windows.
+
+ If \a a is true then the \a dw will appear as a menu item on the
+ dock window menu. The user is able to change the state (show or
+ hide) a dock window that has a menu item by clicking the item;
+ depending on the state of your application, this may or may not be
+ appropriate. If \a a is false the \a dw will not appear on the
+ popup menu.
+
+ \sa showDockMenu() isCustomizable() customize()
+*/
+
+void Q3MainWindow::setAppropriate(Q3DockWindow *dw, bool a)
+{
+ d_func()->appropriate.insert(dw, a);
+}
+
+#ifndef QT_NO_TEXTSTREAM
+static void saveDockArea(QTextStream &ts, Q3DockArea *a)
+{
+ QList<Q3DockWindow *> l = a->dockWindowList();
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ ts << QString(dw->windowTitle());
+ ts << ",";
+ }
+ ts << endl;
+ ts << *a;
+}
+
+/*!
+ \relates Q3MainWindow
+
+ Writes the layout (sizes and positions) of the dock windows in the
+ dock areas of the Q3MainWindow \a mainWindow, including \c
+ Minimized and \c TornOff dock windows, to the text stream \a ts.
+
+ This can be used, for example, in conjunction with QSettings to
+ save the user's layout when the \a mainWindow receives a
+ close event.
+
+ \sa QWidget::closeEvent()
+*/
+
+QTextStream &operator<<(QTextStream &ts, const Q3MainWindow &mainWindow)
+{
+ QList<Q3DockWindow *> l = mainWindow.dockWindows(Qt::DockMinimized);
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ ts << dw->windowTitle();
+ ts << ",";
+ }
+ ts << endl;
+
+ l = mainWindow.dockWindows(Qt::DockTornOff);
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ ts << dw->windowTitle();
+ ts << ",";
+ }
+ ts << endl;
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ ts << "[" << dw->windowTitle() << ","
+ << (int)dw->geometry().x() << ","
+ << (int)dw->geometry().y() << ","
+ << (int)dw->geometry().width() << ","
+ << (int)dw->geometry().height() << ","
+ << (int)dw->isVisible() << "]";
+ }
+ ts << endl;
+
+ saveDockArea(ts, mainWindow.topDock());
+ saveDockArea(ts, mainWindow.bottomDock());
+ saveDockArea(ts, mainWindow.rightDock());
+ saveDockArea(ts, mainWindow.leftDock());
+ return ts;
+}
+
+static void loadDockArea(const QStringList &names, Q3DockArea *a, Qt::Dock dl, QList<Q3DockWindow *> &l, Q3MainWindow *mw, QTextStream &ts)
+{
+ for (QStringList::ConstIterator it = names.begin(); it != names.end(); ++it) {
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ if (dw->windowTitle() == *it) {
+ mw->addDockWindow(dw, dl);
+ break;
+ }
+ }
+ }
+ if (a) {
+ ts >> *a;
+ } else if (dl == Qt::DockTornOff) {
+ QString s = ts.readLine();
+ enum State { Pre, Name, X, Y, Width, Height, Visible, Post };
+ int state = Pre;
+ QString name, x, y, w, h, visible;
+ QChar c;
+ for (int i = 0; i < (int)s.length(); ++i) {
+ c = s[i];
+ if (state == Pre && c == QLatin1Char('[')) {
+ state++;
+ continue;
+ }
+ if (c == QLatin1Char(',') &&
+ (state == Name || state == X || state == Y || state == Width || state == Height)) {
+ state++;
+ continue;
+ }
+ if (state == Visible && c == QLatin1Char(']')) {
+ for (int i = 0; i < l.size(); ++i) {
+ Q3DockWindow *dw = l.at(i);
+ if (QString(dw->windowTitle()) == name) {
+ if (!qobject_cast<Q3ToolBar*>(dw))
+ dw->setGeometry(x.toInt(), y.toInt(), w.toInt(), h.toInt());
+ else
+ dw->setGeometry(x.toInt(), y.toInt(), dw->width(), dw->height());
+ if (!(bool)visible.toInt())
+ dw->hide();
+ else
+ dw->show();
+ break;
+ }
+ }
+
+ name = x = y = w = h = visible = QLatin1String("");
+
+ state = Pre;
+ continue;
+ }
+ if (state == Name)
+ name += c;
+ else if (state == X)
+ x += c;
+ else if (state == Y)
+ y += c;
+ else if (state == Width)
+ w += c;
+ else if (state == Height)
+ h += c;
+ else if (state == Visible)
+ visible += c;
+ }
+ }
+}
+
+/*!
+ \relates Q3MainWindow
+
+ Reads the layout (sizes and positions) of the dock windows in the
+ dock areas of the Q3MainWindow \a mainWindow from the text stream,
+ \a ts, including \c Minimized and \c TornOff dock windows.
+ Restores the dock windows and dock areas to these sizes and
+ positions. The layout information must be in the format produced
+ by operator<<().
+
+ This can be used, for example, in conjunction with QSettings to
+ restore the user's layout.
+*/
+
+QTextStream &operator>>(QTextStream &ts, Q3MainWindow &mainWindow)
+{
+ QList<Q3DockWindow *> l = mainWindow.dockWindows();
+
+ QString s = ts.readLine();
+ QStringList names = s.split(QLatin1Char(','));
+ loadDockArea(names, 0, Qt::DockMinimized, l, &mainWindow, ts);
+
+ s = ts.readLine();
+ names = s.split(QLatin1Char(','));
+ loadDockArea(names, 0, Qt::DockTornOff, l, &mainWindow, ts);
+
+ int i = 0;
+ Q3DockArea *areas[] = { mainWindow.topDock(), mainWindow.bottomDock(), mainWindow.rightDock(), mainWindow.leftDock() };
+ for (int dl = (int)Qt::DockTop; dl != (int)Qt::DockMinimized; ++dl, ++i) {
+ s = ts.readLine();
+ names = s.split(QLatin1Char(','));
+ loadDockArea(names, areas[i], (Qt::Dock)dl, l, &mainWindow, ts);
+ }
+ return ts;
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "q3mainwindow.moc"
+
+#endif
diff --git a/src/qt3support/widgets/q3mainwindow.h b/src/qt3support/widgets/q3mainwindow.h
new file mode 100644
index 0000000..d3a582d
--- /dev/null
+++ b/src/qt3support/widgets/q3mainwindow.h
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3MAINWINDOW_H
+#define Q3MAINWINDOW_H
+
+#include <QtGui/qwidget.h>
+#include <Qt3Support/q3toolbar.h>
+#include <QtCore/qtextstream.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_MAINWINDOW
+
+class QMenuBar;
+class QStatusBar;
+class QToolTipGroup;
+class Q3MainWindowPrivate;
+class Q3MainWindowLayout;
+class Q3PopupMenu;
+class QHideDock;
+template<class T> class QList;
+
+class Q_COMPAT_EXPORT Q3MainWindow: public QWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3MainWindow)
+
+ Q_PROPERTY(bool rightJustification READ rightJustification WRITE setRightJustification DESIGNABLE false)
+ Q_PROPERTY(bool usesBigPixmaps READ usesBigPixmaps WRITE setUsesBigPixmaps)
+ Q_PROPERTY(bool usesTextLabel READ usesTextLabel WRITE setUsesTextLabel)
+ Q_PROPERTY(bool dockWindowsMovable READ dockWindowsMovable WRITE setDockWindowsMovable)
+ Q_PROPERTY(bool opaqueMoving READ opaqueMoving WRITE setOpaqueMoving)
+
+public:
+ Q3MainWindow(QWidget* parent=0, const char* name=0, Qt::WindowFlags f = Qt::WType_TopLevel);
+ ~Q3MainWindow();
+
+#ifndef QT_NO_MENUBAR
+ QMenuBar * menuBar() const;
+#endif
+ QStatusBar * statusBar() const;
+#if 0
+ QToolTipGroup * toolTipGroup() const;
+#endif
+
+ virtual void setCentralWidget(QWidget *);
+ QWidget * centralWidget() const;
+
+ virtual void setDockEnabled(Qt::Dock dock, bool enable);
+ bool isDockEnabled(Qt::Dock dock) const;
+ bool isDockEnabled(Q3DockArea *area) const;
+ virtual void setDockEnabled(Q3DockWindow *tb, Qt::Dock dock, bool enable);
+ bool isDockEnabled(Q3DockWindow *tb, Qt::Dock dock) const;
+ bool isDockEnabled(Q3DockWindow *tb, Q3DockArea *area) const;
+
+ virtual void addDockWindow(Q3DockWindow *, Qt::Dock = Qt::DockTop, bool newLine = false);
+ virtual void addDockWindow(Q3DockWindow *, const QString &label,
+ Qt::Dock = Qt::DockTop, bool newLine = false);
+ virtual void moveDockWindow(Q3DockWindow *, Qt::Dock = Qt::DockTop);
+ virtual void moveDockWindow(Q3DockWindow *, Qt::Dock, bool nl, int index, int extraOffset = -1);
+ virtual void removeDockWindow(Q3DockWindow *);
+
+ void setVisible(bool);
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ bool rightJustification() const;
+ bool usesBigPixmaps() const;
+ bool usesTextLabel() const;
+ bool dockWindowsMovable() const;
+ bool opaqueMoving() const;
+
+ bool eventFilter(QObject*, QEvent*);
+
+ bool getLocation(Q3DockWindow *tb, Qt::Dock &dock, int &index, bool &nl, int &extraOffset) const;
+
+ QList<Q3DockWindow *> dockWindows(Qt::Dock dock) const;
+ QList<Q3DockWindow *> dockWindows() const;
+ void lineUpDockWindows(bool keepNewLines = false);
+
+ bool isDockMenuEnabled() const;
+
+ // compatibility stuff
+ bool hasDockWindow(Q3DockWindow *dw);
+#ifndef QT_NO_TOOLBAR
+ void addToolBar(Q3DockWindow *, Qt::Dock = Qt::DockTop, bool newLine = false);
+ void addToolBar(Q3DockWindow *, const QString &label,
+ Qt::Dock = Qt::DockTop, bool newLine = false);
+ void moveToolBar(Q3DockWindow *, Qt::Dock = Qt::DockTop);
+ void moveToolBar(Q3DockWindow *, Qt::Dock, bool nl, int index, int extraOffset = -1);
+ void removeToolBar(Q3DockWindow *);
+
+ bool toolBarsMovable() const;
+ QList<Q3ToolBar *> toolBars(Qt::Dock dock) const;
+ void lineUpToolBars(bool keepNewLines = false);
+#endif
+
+ virtual Q3DockArea *dockingArea(const QPoint &p);
+ Q3DockArea *leftDock() const;
+ Q3DockArea *rightDock() const;
+ Q3DockArea *topDock() const;
+ Q3DockArea *bottomDock() const;
+
+ virtual bool isCustomizable() const;
+
+ bool appropriate(Q3DockWindow *dw) const;
+
+ enum DockWindows { OnlyToolBars, NoToolBars, AllDockWindows };
+ virtual Q3PopupMenu *createDockWindowMenu(DockWindows dockWindows = AllDockWindows) const;
+
+public Q_SLOTS:
+ virtual void setRightJustification(bool);
+ virtual void setUsesBigPixmaps(bool);
+ virtual void setUsesTextLabel(bool);
+ virtual void setDockWindowsMovable(bool);
+ virtual void setOpaqueMoving(bool);
+ virtual void setDockMenuEnabled(bool);
+ virtual void whatsThis();
+ virtual void setAppropriate(Q3DockWindow *dw, bool a);
+ virtual void customize();
+
+ // compatibility stuff
+ void setToolBarsMovable(bool);
+
+Q_SIGNALS:
+ void pixmapSizeChanged(bool);
+ void usesTextLabelChanged(bool);
+ void dockWindowPositionChanged(Q3DockWindow *);
+
+#ifndef QT_NO_TOOLBAR
+ // compatibility stuff
+ void toolBarPositionChanged(Q3ToolBar *);
+#endif
+
+protected Q_SLOTS:
+ virtual void setUpLayout();
+ virtual bool showDockMenu(const QPoint &globalPos);
+ void menuAboutToShow();
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void childEvent(QChildEvent *);
+ bool event(QEvent *);
+
+private Q_SLOTS:
+ void slotPlaceChanged();
+ void doLineUp() { lineUpDockWindows(true); }
+
+private:
+ Q_DISABLE_COPY(Q3MainWindow)
+
+ void triggerLayout(bool deleteLayout = true);
+ bool dockMainWindow(QObject *dock) const;
+
+#ifndef QT_NO_MENUBAR
+ virtual void setMenuBar(QMenuBar *);
+#endif
+ virtual void setStatusBar(QStatusBar *);
+#if 0
+ virtual void setToolTipGroup(QToolTipGroup *);
+#endif
+
+ friend class Q3DockWindow;
+ friend class QMenuBarPrivate;
+ friend class QHideDock;
+ friend class Q3ToolBar;
+ friend class Q3MainWindowLayout;
+};
+
+#ifndef QT_NO_TOOLBAR
+inline void Q3MainWindow::addToolBar(Q3DockWindow *w, Qt::ToolBarDock dock, bool newLine)
+{
+ addDockWindow(w, dock, newLine);
+}
+
+inline void Q3MainWindow::addToolBar(Q3DockWindow *w, const QString &label,
+ Qt::ToolBarDock dock, bool newLine)
+{
+ addDockWindow(w, label, dock, newLine);
+}
+
+inline void Q3MainWindow::moveToolBar(Q3DockWindow *w, Qt::ToolBarDock dock)
+{
+ moveDockWindow(w, dock);
+}
+
+inline void Q3MainWindow::moveToolBar(Q3DockWindow *w, Qt::ToolBarDock dock, bool nl, int index, int extraOffset)
+{
+ moveDockWindow(w, dock, nl, index, extraOffset);
+}
+
+inline void Q3MainWindow::removeToolBar(Q3DockWindow *w)
+{
+ removeDockWindow(w);
+}
+
+inline bool Q3MainWindow::toolBarsMovable() const
+{
+ return dockWindowsMovable();
+}
+
+inline void Q3MainWindow::lineUpToolBars(bool keepNewLines)
+{
+ lineUpDockWindows(keepNewLines);
+}
+
+inline void Q3MainWindow::setToolBarsMovable(bool b)
+{
+ setDockWindowsMovable(b);
+}
+#endif
+
+#ifndef QT_NO_TEXTSTREAM
+Q_COMPAT_EXPORT QTextStream &operator<<(QTextStream &, const Q3MainWindow &);
+Q_COMPAT_EXPORT QTextStream &operator>>(QTextStream &, Q3MainWindow &);
+#endif
+
+#endif // QT_NO_MAINWINDOW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3MAINWINDOW_H
diff --git a/src/qt3support/widgets/q3mainwindow_p.h b/src/qt3support/widgets/q3mainwindow_p.h
new file mode 100644
index 0000000..31bea4f
--- /dev/null
+++ b/src/qt3support/widgets/q3mainwindow_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3MAINWINDOW_P_H
+#define Q3MAINWINDOW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qwidget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3MainWindowLayout;
+
+class Q3MainWindowPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(Q3MainWindow)
+public:
+ Q3MainWindowPrivate()
+ : mb(0), sb(0), ttg(0), mc(0), tll(0), mwl(0), ubp(false), utl(false),
+ justify(false), movable(true), opaque(false), dockMenu(true)
+ {
+ docks.insert(Qt::DockTop, true);
+ docks.insert(Qt::DockBottom, true);
+ docks.insert(Qt::DockLeft, true);
+ docks.insert(Qt::DockRight, true);
+ docks.insert(Qt::DockMinimized, false);
+ docks.insert(Qt::DockTornOff, true);
+ }
+
+ ~Q3MainWindowPrivate()
+ {
+ }
+
+#ifndef QT_NO_MENUBAR
+ mutable QMenuBar * mb;
+#else
+ mutable QWidget * mb;
+#endif
+ QStatusBar * sb;
+ QToolTipGroup * ttg;
+
+ QWidget * mc;
+
+ QBoxLayout * tll;
+ Q3MainWindowLayout * mwl;
+
+ uint ubp :1;
+ uint utl :1;
+ uint justify :1;
+ uint movable :1;
+ uint opaque :1;
+ uint dockMenu :1;
+
+ Q3DockArea *topDock, *bottomDock, *leftDock, *rightDock;
+
+ QList<Q3DockWindow *> dockWindows;
+ QMap<Qt::Dock, bool> docks;
+ QStringList disabledDocks;
+ QHideDock *hideDock;
+
+ QPointer<Q3PopupMenu> rmbMenu, tbMenu, dwMenu;
+ QMap<Q3DockWindow*, bool> appropriate;
+ mutable QMap<Q3PopupMenu*, Q3MainWindow::DockWindows> dockWindowModes;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3MAINWINDOW_P_H
diff --git a/src/qt3support/widgets/q3popupmenu.cpp b/src/qt3support/widgets/q3popupmenu.cpp
new file mode 100644
index 0000000..7f890b5
--- /dev/null
+++ b/src/qt3support/widgets/q3popupmenu.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3popupmenu.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \fn void Q3PopupMenu::setFrameRect(QRect)
+ \internal
+*/
+
+/*!
+ \fn QRect Q3PopupMenu::frameRect() const
+ \internal
+*/
+/*!
+ \enum Q3PopupMenu::DummyFrame
+ \internal
+
+ \value Box
+ \value Sunken
+ \value Plain
+ \value Raised
+ \value MShadow
+ \value NoFrame
+ \value Panel
+ \value StyledPanel
+ \value HLine
+ \value VLine
+ \value GroupBoxPanel
+ \value WinPanel
+ \value ToolBarPanel
+ \value MenuBarPanel
+ \value PopupPanel
+ \value LineEditPanel
+ \value TabWidgetPanel
+ \value MShape
+*/
+
+/*!
+ \fn void Q3PopupMenu::setFrameShadow(DummyFrame)
+ \internal
+*/
+
+/*!
+ \fn DummyFrame Q3PopupMenu::frameShadow() const
+ \internal
+*/
+
+/*!
+ \fn void Q3PopupMenu::setFrameShape(DummyFrame)
+ \internal
+*/
+
+/*!
+ \fn DummyFrame Q3PopupMenu::frameShape() const
+ \internal
+*/
+
+/*!
+ \fn void Q3PopupMenu::setFrameStyle(int)
+ \internal
+*/
+
+/*!
+ \fn int Q3PopupMenu::frameStyle() const
+ \internal
+*/
+
+/*!
+ \fn int Q3PopupMenu::frameWidth() const
+ \internal
+*/
+
+/*!
+ \fn void Q3PopupMenu::setLineWidth(int)
+ \internal
+*/
+
+/*!
+ \fn int Q3PopupMenu::lineWidth() const
+ \internal
+*/
+
+/*!
+ \fn void Q3PopupMenu::setMargin(int margin)
+ \since 4.2
+
+ Sets the width of the margin around the contents of the widget to \a margin.
+
+ This function uses QWidget::setContentsMargins() to set the margin.
+ \sa margin(), QWidget::setContentsMargins()
+*/
+
+/*!
+ \fn int Q3PopupMenu::margin() const
+ \since 4.2
+
+ Returns the with of the the margin around the contents of the widget.
+
+ This function uses QWidget::getContentsMargins() to get the margin.
+ \sa setMargin(), QWidget::getContentsMargins()
+*/
+
+/*!
+ \fn void Q3PopupMenu::setMidLineWidth(int)
+ \internal
+*/
+
+/*!
+ \fn int Q3PopupMenu::midLineWidth() const
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3popupmenu.h b/src/qt3support/widgets/q3popupmenu.h
new file mode 100644
index 0000000..baf5494
--- /dev/null
+++ b/src/qt3support/widgets/q3popupmenu.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3POPUPMENU_H
+#define Q3POPUPMENU_H
+
+#include <QtGui/qmenu.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3PopupMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ inline Q3PopupMenu(QWidget *parent = 0, const char * =0) : QMenu(parent)
+ { }
+
+ inline int exec() { return findIdForAction(QMenu::exec()); }
+ inline int exec(const QPoint & pos, int indexAtPoint = 0) {
+ return findIdForAction(QMenu::exec(pos, actions().value(indexAtPoint)));
+ }
+
+ void setFrameRect(QRect) {}
+ QRect frameRect() const { return QRect(); }
+ enum DummyFrame { Box, Sunken, Plain, Raised, MShadow, NoFrame, Panel, StyledPanel,
+ HLine, VLine, GroupBoxPanel, WinPanel, ToolBarPanel, MenuBarPanel,
+ PopupPanel, LineEditPanel, TabWidgetPanel, MShape };
+ void setFrameShadow(DummyFrame) {}
+ DummyFrame frameShadow() const { return Plain; }
+ void setFrameShape(DummyFrame) {}
+ DummyFrame frameShape() const { return NoFrame; }
+ void setFrameStyle(int) {}
+ int frameStyle() const { return 0; }
+ int frameWidth() const { return 0; }
+ void setLineWidth(int) {}
+ int lineWidth() const { return 0; }
+ void setMargin(int margin) { setContentsMargins(margin, margin, margin, margin); }
+ int margin() const
+ { int margin; int dummy; getContentsMargins(&margin, &dummy, &dummy, &dummy); return margin; }
+ void setMidLineWidth(int) {}
+ int midLineWidth() const { return 0; }
+
+private:
+ Q_DISABLE_COPY(Q3PopupMenu)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPOPUPMENU_H
diff --git a/src/qt3support/widgets/q3progressbar.cpp b/src/qt3support/widgets/q3progressbar.cpp
new file mode 100644
index 0000000..caae460
--- /dev/null
+++ b/src/qt3support/widgets/q3progressbar.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3progressbar.h"
+#ifndef QT_NO_PROGRESSBAR
+#include "qpainter.h"
+#include "qdrawutil.h"
+#include "qpixmap.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#include "qevent.h"
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3ProgressBar
+ \brief The Q3ProgressBar widget provides a horizontal progress bar.
+
+ \compat
+
+ A progress bar is used to give the user an indication of the
+ progress of an operation and to reassure them that the application
+ is still running.
+
+ The progress bar uses the concept of \e steps; you give it the
+ total number of steps and the number of steps completed so far and
+ it will display the percentage of steps that have been completed.
+ You can specify the total number of steps in the constructor or
+ later with setTotalSteps(). The current number of steps is set
+ with setProgress(). The progress bar can be rewound to the
+ beginning with reset().
+
+ If the total is given as 0 the progress bar shows a busy indicator
+ instead of a percentage of steps. This is useful, for example,
+ when using QFtp or QHttp to download items when they are unable to
+ determine the size of the item being downloaded.
+
+ \sa QProgressDialog
+
+ \inlineimage qprogbar-m.png Screenshot in Motif style
+ \inlineimage qprogbar-w.png Screenshot in Windows style
+
+ \sa QProgressDialog
+*/
+
+
+/*! \obsolete
+ Constructs a progress bar.
+
+ The total number of steps is set to 100 by default.
+
+ The \a parent, \a name and widget flags, \a f, are passed on to
+ the QFrame::QFrame() constructor.
+
+ \sa setTotalSteps()
+*/
+
+Q3ProgressBar::Q3ProgressBar(QWidget *parent, const char *name, Qt::WindowFlags f)
+ : QFrame(parent, f),
+ total_steps(100),
+ progress_val(-1),
+ percentage(-1),
+ center_indicator(true),
+ percentage_visible(true),
+ d(0)
+{
+ setObjectName(QLatin1String(name));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ initFrame();
+}
+
+
+/*! \obsolete
+ Constructs a progress bar.
+
+ The \a totalSteps is the total number of steps that need to be
+ completed for the operation which this progress bar represents.
+ For example, if the operation is to examine 50 files, this value
+ would be 50. Before examining the first file, call setProgress(0);
+ call setProgress(50) after examining the last file.
+
+ The \a parent, \a name and widget flags, \a f, are passed to the
+ QFrame::QFrame() constructor.
+
+ \sa setTotalSteps(), setProgress()
+*/
+
+Q3ProgressBar::Q3ProgressBar(int totalSteps, QWidget *parent, const char *name, Qt::WindowFlags f)
+ : QFrame(parent, f),
+ total_steps(totalSteps),
+ progress_val(-1),
+ percentage(-1),
+ center_indicator(true),
+ percentage_visible(true),
+ d(0)
+{
+ setObjectName(QLatin1String(name));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ initFrame();
+}
+#endif
+
+/*!
+ Constructs a progress bar.
+
+ The total number of steps is set to 100 by default.
+
+ The \a parent, and widget flags, \a f, are passed on to
+ the QFrame::QFrame() constructor.
+
+ \sa setTotalSteps()
+*/
+
+Q3ProgressBar::Q3ProgressBar(QWidget *parent, Qt::WindowFlags f)
+ : QFrame(parent, f),
+ total_steps(100),
+ progress_val(-1),
+ percentage(-1),
+ center_indicator(true),
+ percentage_visible(true),
+ d(0)
+{
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ initFrame();
+}
+
+
+/*!
+ Constructs a progress bar.
+
+ The \a totalSteps is the total number of steps that need to be
+ completed for the operation which this progress bar represents.
+ For example, if the operation is to examine 50 files, this value
+ would be 50. Before examining the first file, call setProgress(0);
+ call setProgress(50) after examining the last file.
+
+ The \a parent, and widget flags, \a f, are passed to the
+ QFrame::QFrame() constructor.
+
+ \sa setTotalSteps(), setProgress()
+*/
+
+Q3ProgressBar::Q3ProgressBar(int totalSteps, QWidget *parent, Qt::WindowFlags f)
+ : QFrame(parent, f),
+ total_steps(totalSteps),
+ progress_val(-1),
+ percentage(-1),
+ center_indicator(true),
+ percentage_visible(true),
+ d(0)
+{
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ initFrame();
+}
+
+
+/*!
+ Reset the progress bar. The progress bar "rewinds" and shows no
+ progress.
+*/
+
+void Q3ProgressBar::reset()
+{
+ progress_val = -1;
+ percentage = -1;
+ setIndicator(progress_str, progress_val, total_steps);
+ repaint();
+}
+
+
+/*!
+ \property Q3ProgressBar::totalSteps
+ \brief The total number of steps.
+
+ If totalSteps is 0, the progress bar will display a busy
+ indicator.
+*/
+
+void Q3ProgressBar::setTotalSteps(int totalSteps)
+{
+ total_steps = totalSteps;
+
+ // Current progress is invalid if larger than total
+ if (total_steps < progress_val)
+ progress_val = -1;
+
+ if (isVisible() &&
+ (setIndicator(progress_str, progress_val, total_steps) || !total_steps))
+ repaint();
+}
+
+
+/*!
+ \property Q3ProgressBar::progress
+ \brief The current amount of progress
+
+ This property is -1 if progress counting has not started.
+*/
+
+void Q3ProgressBar::setProgress(int progress)
+{
+ if (progress == progress_val ||
+ progress < 0 || ((progress > total_steps) && total_steps))
+ return;
+
+ int old_progress_val = progress_val;
+ progress_val = progress;
+
+ if (setIndicator(progress_str, progress_val, total_steps)
+ || ( total_steps == 0 || (width() * progress_val / total_steps != width() * old_progress_val / total_steps )))
+ repaint();
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged);
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the amount of progress to \a progress and the total number of
+ steps to \a totalSteps.
+
+ \sa setTotalSteps()
+*/
+
+void Q3ProgressBar::setProgress(int progress, int totalSteps)
+{
+ if (total_steps != totalSteps)
+ setTotalSteps(totalSteps);
+ setProgress(progress);
+}
+
+/*!
+ \property Q3ProgressBar::progressString
+ \brief the amount of progress as a string
+
+ This property is an empty string if progress counting has not started.
+*/
+
+static QStyleOptionProgressBar getStyleOption(const Q3ProgressBar *pb)
+{
+ QStyleOptionProgressBar opt;
+ opt.init(pb);
+ opt.rect = pb->contentsRect();
+ opt.minimum = 0;
+ opt.maximum = pb->totalSteps();
+ opt.progress = pb->progress();
+ if (pb->centerIndicator())
+ opt.textAlignment = Qt::AlignCenter;
+ else
+ opt.textAlignment = Qt::AlignAuto;
+ opt.textVisible = pb->percentageVisible();
+ opt.text = pb->progressString();
+ return opt;
+}
+
+/*!
+ \reimp
+*/
+QSize Q3ProgressBar::sizeHint() const
+{
+ ensurePolished();
+ QFontMetrics fm = fontMetrics();
+ QStyleOptionProgressBar opt = getStyleOption(this);
+ int cw = style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &opt, this);
+ return style()->sizeFromContents(QStyle::CT_ProgressBar, &opt,
+ QSize(cw * 7 + fm.width(QLatin1Char('0')) * 4, fm.height() + 8), this);
+}
+
+/*!
+ \reimp
+*/
+QSize Q3ProgressBar::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+/*!
+ \property Q3ProgressBar::centerIndicator
+ \brief whether the indicator string should be centered
+*/
+
+void Q3ProgressBar::setCenterIndicator(bool on)
+{
+ if (on == center_indicator)
+ return;
+ center_indicator = on;
+ repaint();
+}
+
+/*!
+ \property Q3ProgressBar::percentageVisible
+ \brief whether the current progress value is displayed
+
+ The default is true.
+
+ \sa centerIndicator
+*/
+void Q3ProgressBar::setPercentageVisible(bool on)
+{
+ if (on == percentage_visible)
+ return;
+ percentage_visible = on;
+ repaint();
+}
+
+/*!
+ \reimp
+*/
+void Q3ProgressBar::setVisible(bool visible)
+{
+ if (visible)
+ setIndicator(progress_str, progress_val, total_steps);
+ QFrame::setVisible(visible);
+}
+
+void Q3ProgressBar::initFrame()
+{
+ setFrameStyle(QFrame::NoFrame);
+}
+
+/*!
+ \reimp
+*/
+void Q3ProgressBar::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::StyleChange)
+ initFrame();
+ QFrame::changeEvent(ev);
+}
+
+
+/*!
+ This method is called to generate the text displayed in the center
+ (or in some styles, to the left) of the progress bar.
+
+ The \a progress may be negative, indicating that the progress bar
+ is in the "reset" state before any progress is set.
+
+ The default implementation is the percentage of completion or
+ blank in the reset state. The percentage is calculated based on
+ the \a progress and \a totalSteps. You can set the \a indicator
+ text if you wish.
+
+ To allow efficient repainting of the progress bar, this method
+ should return false if the string is unchanged from the last call
+ to this function.
+*/
+
+bool Q3ProgressBar::setIndicator(QString & indicator, int progress,
+ int totalSteps)
+{
+ if (!totalSteps)
+ return false;
+ if (progress < 0) {
+ indicator = QString::fromLatin1("");
+ return true;
+ } else {
+ // Get the values down to something usable.
+ if (totalSteps > INT_MAX/1000) {
+ progress /= 1000;
+ totalSteps /= 1000;
+ }
+
+ int np = progress * 100 / totalSteps;
+ if (np != percentage) {
+ percentage = np;
+ indicator.sprintf("%d%%", np);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void Q3ProgressBar::paintEvent(QPaintEvent *)
+{
+ QPainter paint(this);
+ QPainter *p = &paint;
+ drawFrame(p);
+
+ QStyleOptionProgressBar opt = getStyleOption(this);
+ opt.rect = style()->subElementRect(QStyle::SE_ProgressBarGroove, &opt, this);
+
+ style()->drawControl(QStyle::CE_ProgressBarGroove, &opt, p, this);
+ opt.rect = contentsRect();
+ opt.rect = style()->subElementRect(QStyle::SE_ProgressBarContents, &opt, this);
+ style()->drawControl(QStyle::CE_ProgressBarContents, &opt, p, this);
+
+ if (percentageVisible()) {
+ opt.rect = contentsRect();
+ opt.rect = style()->subElementRect(QStyle::SE_ProgressBarLabel, &opt, this);
+ style()->drawControl(QStyle::CE_ProgressBarLabel, &opt, p, this);
+ }
+}
+
+/*!
+ \fn void Q3ProgressBar::setMargin(int margin)
+ \since 4.2
+
+ Sets the width of the margin around the contents of the widget to \a margin.
+
+ This function uses QWidget::setContentsMargins() to set the margin.
+ \sa margin(), QWidget::setContentsMargins()
+*/
+
+/*!
+ \fn int Q3ProgressBar::margin() const
+ \since 4.2
+
+ Returns the with of the the margin around the contents of the widget.
+
+ This function uses QWidget::getContentsMargins() to get the margin.
+ \sa setMargin(), QWidget::getContentsMargins()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3progressbar.h b/src/qt3support/widgets/q3progressbar.h
new file mode 100644
index 0000000..fdf7d9a
--- /dev/null
+++ b/src/qt3support/widgets/q3progressbar.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3PROGRESSBAR_H
+#define Q3PROGRESSBAR_H
+
+#include <QtGui/qframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_PROGRESSBAR
+
+class Q3ProgressBarPrivate;
+
+class Q_COMPAT_EXPORT Q3ProgressBar : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY(int totalSteps READ totalSteps WRITE setTotalSteps)
+ Q_PROPERTY(int progress READ progress WRITE setProgress)
+ Q_PROPERTY(QString progressString READ progressString)
+ Q_PROPERTY(bool centerIndicator READ centerIndicator WRITE setCenterIndicator)
+ Q_PROPERTY(bool percentageVisible READ percentageVisible WRITE setPercentageVisible)
+
+public:
+ Q3ProgressBar(QWidget *parent, const char *name, Qt::WindowFlags f=0);
+ Q3ProgressBar(int totalSteps, QWidget *parent, const char *name,
+ Qt::WindowFlags f=0);
+ Q3ProgressBar(QWidget *parent = 0, Qt::WindowFlags f = 0);
+ Q3ProgressBar(int totalSteps, QWidget *parent = 0, Qt::WindowFlags f=0);
+
+ int totalSteps() const;
+ int progress() const;
+ const QString &progressString() const;
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ void setCenterIndicator(bool on);
+ bool centerIndicator() const;
+
+ bool percentageVisible() const;
+ void setPercentageVisible(bool);
+
+ void setVisible(bool visible);
+
+ void setMargin(int margin) { setContentsMargins(margin, margin, margin, margin); }
+ int margin() const
+ { int margin; int dummy; getContentsMargins(&margin, &dummy, &dummy, &dummy); return margin; }
+
+public Q_SLOTS:
+ void reset();
+ virtual void setTotalSteps(int totalSteps);
+ virtual void setProgress(int progress);
+ void setProgress(int progress, int totalSteps);
+
+protected:
+ void paintEvent(QPaintEvent *);
+ virtual bool setIndicator(QString &progress_str, int progress, int totalSteps);
+ void changeEvent(QEvent *);
+
+private:
+ Q_DISABLE_COPY(Q3ProgressBar)
+
+ int total_steps;
+ int progress_val;
+ int percentage;
+ QString progress_str;
+ bool center_indicator : 1;
+ bool percentage_visible : 1;
+ Q3ProgressBarPrivate *d;
+ void initFrame();
+};
+
+
+inline int Q3ProgressBar::totalSteps() const
+{
+ return total_steps;
+}
+
+inline int Q3ProgressBar::progress() const
+{
+ return progress_val;
+}
+
+inline const QString &Q3ProgressBar::progressString() const
+{
+ return progress_str;
+}
+
+inline bool Q3ProgressBar::centerIndicator() const
+{
+ return center_indicator;
+}
+
+inline bool Q3ProgressBar::percentageVisible() const
+{
+ return percentage_visible;
+}
+
+#endif // QT_NO_PROGRESSBAR
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3PROGRESSBAR_H
diff --git a/src/qt3support/widgets/q3rangecontrol.cpp b/src/qt3support/widgets/q3rangecontrol.cpp
new file mode 100644
index 0000000..1373f28
--- /dev/null
+++ b/src/qt3support/widgets/q3rangecontrol.cpp
@@ -0,0 +1,550 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3rangecontrol.h"
+#ifndef QT_NO_RANGECONTROL
+#include "qglobal.h"
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3RangeControl
+ \brief The Q3RangeControl class provides an integer value within a range.
+
+ \compat
+
+ Although originally designed for the QScrollBar widget, the
+ Q3RangeControl can also be used in conjunction with other widgets
+ such as QSlider and QSpinBox. Here are the five main concepts in
+ the class:
+
+ \list 1
+
+ \i \e{Current value} The bounded integer that
+ Q3RangeControl maintains. value() returns it, and several
+ functions, including setValue(), set it.
+
+ \i \e{Minimum} The lowest value that value() can ever
+ return. Returned by minValue() and set by setRange() or one of the
+ constructors.
+
+ \i \e{Maximum} The highest value that value() can ever
+ return. Returned by maxValue() and set by setRange() or one of the
+ constructors.
+
+ \i \e{Line step} The smaller of two natural steps that
+ Q3RangeControl provides and typically corresponds to the user
+ pressing an arrow key. The line step is returned by lineStep()
+ and set using setSteps(). The functions addLine() and
+ subtractLine() respectively increment and decrement the current
+ value by lineStep().
+
+ \i \e{Page step} The larger of two natural steps that
+ Q3RangeControl provides and typically corresponds to the user
+ pressing PageUp or PageDown. The page step is returned by
+ pageStep() and set using setSteps(). The functions addPage() and
+ substractPage() respectively increment and decrement the current
+ value by pageStep().
+
+ \endlist
+
+ Unity (1) may be viewed as a third step size. setValue() lets you
+ set the current value to any integer in the allowed range, not
+ just minValue() + \e n * lineStep() for integer values of \e n.
+ Some widgets may allow the user to set any value at all; others
+ may just provide multiples of lineStep() or pageStep().
+
+ Q3RangeControl provides three virtual functions that are well
+ suited for updating the on-screen representation of range controls
+ and emitting signals: valueChange(), rangeChange() and
+ stepChange().
+
+ Q3RangeControl also provides a function called bound() which lets
+ you force arbitrary integers to be within the allowed range of the
+ range control.
+
+ We recommend that all widgets that inherit Q3RangeControl provide
+ at least a signal called valueChanged(); many widgets will want to
+ provide addStep(), addPage(), substractStep() and substractPage()
+ as slots.
+
+ Note that you must use multiple inheritance if you plan to
+ implement a widget using Q3RangeControl because Q3RangeControl is
+ not derived from QWidget.
+*/
+
+
+/*!
+ Constructs a range control with a minimum value of 0, maximum
+ value of 99, line step of 1, page step of 10 and initial value 0.
+*/
+
+Q3RangeControl::Q3RangeControl()
+{
+ minVal = 0;
+ maxVal = 99;
+ line = 1;
+ page = 10;
+ val = 0;
+ prevVal = -1;
+ d = 0;
+}
+
+/*!
+ Constructs a range control whose value can never be smaller than
+ \a minValue or greater than \a maxValue, whose line step size is
+ \a lineStep and page step size is \a pageStep and whose value is
+ initially \a value (which is guaranteed to be in range using
+ bound()).
+*/
+
+Q3RangeControl::Q3RangeControl(int minValue, int maxValue,
+ int lineStep, int pageStep,
+ int value)
+{
+ minVal = minValue;
+ maxVal = maxValue;
+ line = QABS(lineStep);
+ page = QABS(pageStep);
+ prevVal = minVal - 1;
+ val = bound(value);
+ d = 0;
+}
+
+/*!
+ Destroys the range control
+*/
+
+Q3RangeControl::~Q3RangeControl()
+{
+}
+
+
+/*!
+ \fn int Q3RangeControl::value() const
+
+ Returns the current range control value. This is guaranteed to be
+ within the range [minValue(), maxValue()].
+
+ \sa setValue() prevValue()
+*/
+
+/*!
+ \fn int Q3RangeControl::prevValue() const
+
+ Returns the previous value of the range control. "Previous value"
+ means the value before the last change occurred. Setting a new
+ range may affect the value, too, because the value is forced to be
+ inside the specified range. When the range control is initially
+ created, this is the same as value().
+
+ prevValue() can be outside the current legal range if a call to
+ setRange() causes the current value to change. For example, if the
+ range was [0, 1000] and the current value is 500, setRange(0, 400)
+ makes value() return 400 and prevValue() return 500.
+
+ \sa value() setRange()
+*/
+
+/*!
+ Sets the range control's value to \a value and forces it to be
+ within the legal range.
+
+ Calls the virtual valueChange() function if the new value is
+ different from the previous value. The old value can still be
+ retrieved using prevValue().
+
+ \sa value()
+*/
+
+void Q3RangeControl::setValue(int value)
+{
+ directSetValue(value);
+ if (prevVal != val)
+ valueChange();
+}
+
+/*!
+ Sets the range control \a value directly without calling
+ valueChange().
+
+ Forces the new \a value to be within the legal range.
+
+ You will rarely have to call this function. However, if you want
+ to change the range control's value inside the overloaded method
+ valueChange(), setValue() would call the function valueChange()
+ again. To avoid this recursion you must use directSetValue()
+ instead.
+
+ \sa setValue()
+*/
+
+void Q3RangeControl::directSetValue(int value)
+{
+ prevVal = val;
+ val = bound(value);
+}
+
+/*!
+ Equivalent to \c{setValue(value() + pageStep())}.
+
+ If the value is changed, then valueChange() is called.
+
+ \sa subtractPage() addLine() setValue()
+*/
+
+void Q3RangeControl::addPage()
+{
+ setValue(value() + pageStep());
+}
+
+/*!
+ Equivalent to \c{setValue(value() - pageStep())}.
+
+ If the value is changed, then valueChange() is called.
+
+ \sa addPage() subtractLine() setValue()
+*/
+
+void Q3RangeControl::subtractPage()
+{
+ setValue(value() - pageStep());
+}
+
+/*!
+ Equivalent to \c{setValue(value() + lineStep())}.
+
+ If the value is changed, then valueChange() is called.
+
+ \sa subtractLine() addPage() setValue()
+*/
+
+void Q3RangeControl::addLine()
+{
+ setValue(value() + lineStep());
+}
+
+/*!
+ Equivalent to \c{setValue(value() - lineStep())}.
+
+ If the value is changed, then valueChange() is called.
+
+ \sa addLine() subtractPage() setValue()
+*/
+
+void Q3RangeControl::subtractLine()
+{
+ setValue(value() - lineStep());
+}
+
+
+/*!
+ \fn int Q3RangeControl::minValue() const
+
+ Returns the minimum value of the range.
+
+ \sa setMinValue() setRange() maxValue()
+*/
+
+/*!
+ \fn int Q3RangeControl::maxValue() const
+
+ Returns the maximum value of the range.
+
+ \sa setMaxValue() setRange() minValue()
+*/
+
+/*!
+ Sets the minimum value of the range to \a minVal.
+
+ If necessary, the maxValue() is adjusted so that the range remains
+ valid.
+
+ \sa minValue() setMaxValue()
+*/
+void Q3RangeControl::setMinValue(int minVal)
+{
+ int maxVal = maxValue();
+ if (maxVal < minVal)
+ maxVal = minVal;
+ setRange(minVal, maxVal);
+}
+
+/*!
+ Sets the minimum value of the range to \a maxVal.
+
+ If necessary, the minValue() is adjusted so that the range remains
+ valid.
+
+ \sa maxValue() setMinValue()
+*/
+void Q3RangeControl::setMaxValue(int maxVal)
+{
+ int minVal = minValue();
+ if (minVal > maxVal)
+ minVal = maxVal;
+ setRange(minVal, maxVal);
+}
+
+/*!
+ Sets the range control's minimum value to \a minValue and its
+ maximum value to \a maxValue.
+
+ Calls the virtual rangeChange() function if one or both of the new
+ minimum and maximum values are different from the previous
+ setting. Calls the virtual valueChange() function if the current
+ value is adjusted because it was outside the new range.
+
+ If \a maxValue is smaller than \a minValue, \a minValue becomes
+ the only legal value.
+
+ \sa minValue() maxValue()
+*/
+
+void Q3RangeControl::setRange(int minValue, int maxValue)
+{
+ if (minValue > maxValue) {
+ qWarning("Q3RangeControl::setRange: minValue %d > maxValue %d",
+ minValue, maxValue);
+ maxValue = minValue;
+ }
+ if (minValue == minVal && maxValue == maxVal)
+ return;
+ minVal = minValue;
+ maxVal = maxValue;
+ int tmp = bound(val);
+ rangeChange();
+ if (tmp != val) {
+ prevVal = val;
+ val = tmp;
+ valueChange();
+ }
+}
+
+
+/*!
+ \fn int Q3RangeControl::lineStep() const
+
+ Returns the line step.
+
+ \sa setSteps() pageStep()
+*/
+
+/*!
+ \fn int Q3RangeControl::pageStep() const
+
+ Returns the page step.
+
+ \sa setSteps() lineStep()
+*/
+
+/*!
+ Sets the range's line step to \a lineStep and page step to \a
+ pageStep.
+
+ Calls the virtual stepChange() function if the new line step
+ or page step are different from the previous settings.
+
+ \sa lineStep() pageStep() setRange()
+*/
+
+void Q3RangeControl::setSteps(int lineStep, int pageStep)
+{
+ if (lineStep != line || pageStep != page) {
+ line = QABS(lineStep);
+ page = QABS(pageStep);
+ stepChange();
+ }
+}
+
+
+/*!
+ This virtual function is called whenever the range control value
+ changes. You can reimplement it if you want to be notified when
+ the value changes. The default implementation does nothing.
+
+ Note that this method is called after the value has changed. The
+ previous value can be retrieved using prevValue().
+
+ \sa setValue(), addPage(), subtractPage(), addLine(),
+ subtractLine() rangeChange(), stepChange()
+*/
+
+void Q3RangeControl::valueChange()
+{
+}
+
+
+/*!
+ This virtual function is called whenever the range control's range
+ changes. You can reimplement it if you want to be notified when
+ the range changes. The default implementation does nothing.
+
+ Note that this method is called after the range has changed.
+
+ \sa setRange(), valueChange(), stepChange()
+*/
+
+void Q3RangeControl::rangeChange()
+{
+}
+
+
+/*!
+ This virtual function is called whenever the range control's
+ line or page step settings change. You can reimplement it if you
+ want to be notified when the step changes. The default
+ implementation does nothing.
+
+ Note that this method is called after a step setting has changed.
+
+ \sa setSteps(), rangeChange(), valueChange()
+*/
+
+void Q3RangeControl::stepChange()
+{
+}
+
+
+/*!
+ Forces the value \a v to be within the range from minValue() to
+ maxValue() inclusive, and returns the result.
+
+ This function is provided so that you can easily force other
+ numbers than value() into the allowed range. You do not need to
+ call it in order to use Q3RangeControl itself.
+
+ \sa setValue() value() minValue() maxValue()
+*/
+
+int Q3RangeControl::bound(int v) const
+{
+ if (v < minVal)
+ return minVal;
+ if (v > maxVal)
+ return maxVal;
+ return v;
+}
+
+
+/*!
+ Converts \a logical_val to a pixel position. minValue() maps to 0,
+ maxValue() maps to \a span and other values are distributed evenly
+ in-between.
+
+ This function can handle the entire integer range without
+ overflow, providing \a span is \<= 4096.
+
+ Calling this method is useful when actually drawing a range
+ control such as a QScrollBar on-screen.
+
+ \sa valueFromPosition()
+*/
+
+int Q3RangeControl::positionFromValue(int logical_val, int span) const
+{
+ if (span <= 0 || logical_val < minValue() || maxValue() <= minValue())
+ return 0;
+ if (logical_val > maxValue())
+ return span;
+
+ uint range = maxValue() - minValue();
+ uint p = logical_val - minValue();
+
+ if (range > (uint)INT_MAX/4096) {
+ const int scale = 4096*2;
+ return ((p/scale) * span) / (range/scale);
+ // ### the above line is probably not 100% correct
+ // ### but fixing it isn't worth the extreme pain...
+ } else if (range > (uint)span) {
+ return (2*p*span + range) / (2*range);
+ } else {
+ uint div = span / range;
+ uint mod = span % range;
+ return p*div + (2*p*mod + range) / (2*range);
+ }
+ //equiv. to (p*span)/range + 0.5
+ // no overflow because of this implicit assumption:
+ // span <= 4096
+}
+
+
+/*!
+ Converts the pixel position \a pos to a value. 0 maps to
+ minValue(), \a span maps to maxValue() and other values are
+ distributed evenly in-between.
+
+ This function can handle the entire integer range without
+ overflow.
+
+ Calling this method is useful if you actually implemented a range
+ control widget such as QScrollBar and want to handle mouse press
+ events. This function then maps screen coordinates to the logical
+ values.
+
+ \sa positionFromValue()
+*/
+
+int Q3RangeControl::valueFromPosition(int pos, int span) const
+{
+ if (span <= 0 || pos <= 0)
+ return minValue();
+ if (pos >= span)
+ return maxValue();
+
+ uint range = maxValue() - minValue();
+
+ if ((uint)span > range)
+ return minValue() + (2*pos*range + span) / (2*span);
+ else {
+ uint div = range / span;
+ uint mod = range % span;
+ return minValue() + pos*div + (2*pos*mod + span) / (2*span);
+ }
+ // equiv. to minValue() + (pos*range)/span + 0.5
+ // no overflow because of this implicit assumption:
+ // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX)
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RANGECONTROL
diff --git a/src/qt3support/widgets/q3rangecontrol.h b/src/qt3support/widgets/q3rangecontrol.h
new file mode 100644
index 0000000..651ca7a
--- /dev/null
+++ b/src/qt3support/widgets/q3rangecontrol.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3RANGECONTROL_H
+#define Q3RANGECONTROL_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_RANGECONTROL
+
+class Q3RangeControlPrivate;
+
+class Q_COMPAT_EXPORT Q3RangeControl
+{
+public:
+ Q3RangeControl();
+ Q3RangeControl(int minValue, int maxValue,
+ int lineStep, int pageStep, int value);
+ virtual ~Q3RangeControl();
+
+ int value() const;
+ void setValue(int);
+ void addPage();
+ void subtractPage();
+ void addLine();
+ void subtractLine();
+
+ int minValue() const;
+ int maxValue() const;
+ void setRange(int minValue, int maxValue);
+ void setMinValue(int minVal);
+ void setMaxValue(int minVal);
+
+ int lineStep() const;
+ int pageStep() const;
+ void setSteps(int line, int page);
+
+ int bound(int) const;
+
+protected:
+ int positionFromValue(int val, int space) const;
+ int valueFromPosition(int pos, int space) const;
+ void directSetValue(int val);
+ int prevValue() const;
+
+ virtual void valueChange();
+ virtual void rangeChange();
+ virtual void stepChange();
+
+private:
+ int minVal, maxVal;
+ int line, page;
+ int val, prevVal;
+
+ Q3RangeControlPrivate * d;
+
+private:
+ Q_DISABLE_COPY(Q3RangeControl)
+};
+
+
+inline int Q3RangeControl::value() const
+{ return val; }
+
+inline int Q3RangeControl::prevValue() const
+{ return prevVal; }
+
+inline int Q3RangeControl::minValue() const
+{ return minVal; }
+
+inline int Q3RangeControl::maxValue() const
+{ return maxVal; }
+
+inline int Q3RangeControl::lineStep() const
+{ return line; }
+
+inline int Q3RangeControl::pageStep() const
+{ return page; }
+
+
+#endif // QT_NO_RANGECONTROL
+
+#ifndef QT_NO_SPINWIDGET
+
+class Q3SpinWidgetPrivate;
+class Q_COMPAT_EXPORT Q3SpinWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ Q3SpinWidget(QWidget* parent=0, const char* name=0);
+ ~Q3SpinWidget();
+
+ void setEditWidget(QWidget * widget);
+ QWidget * editWidget();
+
+ QRect upRect() const;
+ QRect downRect() const;
+
+ void setUpEnabled(bool on);
+ void setDownEnabled(bool on);
+
+ bool isUpEnabled() const;
+ bool isDownEnabled() const;
+
+ enum ButtonSymbols { UpDownArrows, PlusMinus };
+ virtual void setButtonSymbols(ButtonSymbols bs);
+ ButtonSymbols buttonSymbols() const;
+
+ void arrange();
+
+Q_SIGNALS:
+ void stepUpPressed();
+ void stepDownPressed();
+
+public Q_SLOTS:
+ void stepUp();
+ void stepDown();
+
+protected:
+ void mousePressEvent(QMouseEvent *e);
+ void resizeEvent(QResizeEvent* ev);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+#ifndef QT_NO_WHEELEVENT
+ void wheelEvent(QWheelEvent *);
+#endif
+ void changeEvent(QEvent *);
+ void paintEvent(QPaintEvent *);
+
+private Q_SLOTS:
+ void timerDone();
+ void timerDoneEx();
+
+private:
+ Q3SpinWidgetPrivate * d;
+
+ void updateDisplay();
+
+private:
+ Q_DISABLE_COPY(Q3SpinWidget)
+};
+
+#endif // QT_NO_RANGECONTROL
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3RANGECONTROL_H
diff --git a/src/qt3support/widgets/q3scrollview.cpp b/src/qt3support/widgets/q3scrollview.cpp
new file mode 100644
index 0000000..91a9203
--- /dev/null
+++ b/src/qt3support/widgets/q3scrollview.cpp
@@ -0,0 +1,2803 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "qwidget.h"
+#ifndef QT_NO_SCROLLVIEW
+#include "qscrollbar.h"
+#include "qpainter.h"
+#include "qpixmap.h"
+#include "qcursor.h"
+#include "q3scrollview.h"
+#include "q3ptrdict.h"
+#include "qapplication.h"
+#include "qtimer.h"
+#include "qstyle.h"
+#include "q3ptrlist.h"
+#include "qevent.h"
+#include "q3listview.h"
+#ifdef Q_WS_MAC
+# include "private/qt_mac_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt;
+
+static const int coord_limit = 4000;
+static const int autoscroll_margin = 16;
+static const int initialScrollTime = 30;
+static const int initialScrollAccel = 5;
+
+struct QSVChildRec {
+ QSVChildRec(QWidget* c, int xx, int yy) :
+ child(c),
+ x(xx), y(yy)
+ {
+ }
+
+ void hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport);
+ void moveTo(Q3ScrollView* sv, int xx, int yy, QWidget* clipped_viewport)
+ {
+ if (x != xx || y != yy) {
+ x = xx;
+ y = yy;
+ hideOrShow(sv,clipped_viewport);
+ }
+ }
+ QWidget* child;
+ int x, y;
+};
+
+void QSVChildRec::hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport)
+{
+ if (clipped_viewport) {
+ if (x+child->width() < sv->contentsX()+clipped_viewport->x()
+ || x > sv->contentsX()+clipped_viewport->width()
+ || y+child->height() < sv->contentsY()+clipped_viewport->y()
+ || y > sv->contentsY()+clipped_viewport->height()) {
+ child->move(clipped_viewport->width(),
+ clipped_viewport->height());
+ } else {
+ child->move(x-sv->contentsX()-clipped_viewport->x(),
+ y-sv->contentsY()-clipped_viewport->y());
+ }
+ } else {
+ child->move(x-sv->contentsX(), y-sv->contentsY());
+ }
+}
+
+class QAbstractScrollAreaWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QAbstractScrollAreaWidget(Q3ScrollView* parent=0, const char* name=0, Qt::WindowFlags f = 0)
+ : QWidget(parent, name, f)
+ {
+ setAutoFillBackground(true);
+ }
+};
+
+class QClipperWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QClipperWidget(QWidget * parent=0, const char * name=0, Qt::WindowFlags f=0)
+ : QWidget (parent,name,f) {}
+};
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "q3scrollview.moc"
+QT_END_INCLUDE_NAMESPACE
+
+class Q3ScrollViewData {
+public:
+ Q3ScrollViewData(Q3ScrollView* parent, int vpwflags) :
+ hbar(new QScrollBar(Qt::Horizontal, parent, "qt_hbar")),
+ vbar(new QScrollBar(Qt::Vertical, parent, "qt_vbar")),
+ viewport(new QAbstractScrollAreaWidget(parent, "qt_viewport", QFlag(vpwflags))),
+ clipped_viewport(0),
+ flags(vpwflags),
+ vx(0), vy(0), vwidth(1), vheight(1),
+#ifndef QT_NO_DRAGANDDROP
+ autoscroll_timer(parent, "scrollview autoscroll timer"),
+ drag_autoscroll(true),
+#endif
+ scrollbar_timer(parent, "scrollview scrollbar timer"),
+ inresize(false), use_cached_size_hint(true)
+ {
+ l_marg = r_marg = t_marg = b_marg = 0;
+ viewport->polish();
+ vMode = Q3ScrollView::Auto;
+ hMode = Q3ScrollView::Auto;
+ corner = 0;
+ vbar->setSteps(20, 1/*set later*/);
+ hbar->setSteps(20, 1/*set later*/);
+ policy = Q3ScrollView::Default;
+ signal_choke = false;
+ static_bg = false;
+ fake_scroll = false;
+ hbarPressed = false;
+ vbarPressed = false;
+ hbar->setLayoutDirection(Qt::LeftToRight);
+ }
+ ~Q3ScrollViewData();
+
+ QSVChildRec* rec(QWidget* w) { return childDict.find(w); }
+ QSVChildRec* ancestorRec(QWidget* w);
+ QSVChildRec* addChildRec(QWidget* w, int x, int y)
+ {
+ QSVChildRec *r = new QSVChildRec(w,x,y);
+ children.append(r);
+ childDict.insert(w, r);
+ return r;
+ }
+ void deleteChildRec(QSVChildRec* r)
+ {
+ childDict.remove(r->child);
+ children.removeRef(r);
+ delete r;
+ }
+
+ void hideOrShowAll(Q3ScrollView* sv, bool isScroll = false);
+ void moveAllBy(int dx, int dy);
+ bool anyVisibleChildren();
+ void autoMove(Q3ScrollView* sv);
+ void autoResize(Q3ScrollView* sv);
+ void autoResizeHint(Q3ScrollView* sv);
+ void viewportResized(int w, int h);
+
+ QScrollBar* hbar;
+ QScrollBar* vbar;
+ bool hbarPressed;
+ bool vbarPressed;
+ QAbstractScrollAreaWidget* viewport;
+ QClipperWidget* clipped_viewport;
+ int flags;
+ Q3PtrList<QSVChildRec> children;
+ Q3PtrDict<QSVChildRec> childDict;
+ QWidget* corner;
+ int vx, vy, vwidth, vheight; // for drawContents-style usage
+ int l_marg, r_marg, t_marg, b_marg;
+ Q3ScrollView::ResizePolicy policy;
+ Q3ScrollView::ScrollBarMode vMode;
+ Q3ScrollView::ScrollBarMode hMode;
+#ifndef QT_NO_DRAGANDDROP
+ QPoint cpDragStart;
+ QTimer autoscroll_timer;
+ int autoscroll_time;
+ int autoscroll_accel;
+ bool drag_autoscroll;
+#endif
+ QTimer scrollbar_timer;
+
+ uint static_bg : 1;
+ uint fake_scroll : 1;
+
+ // This variable allows ensureVisible to move the contents then
+ // update both the sliders. Otherwise, updating the sliders would
+ // cause two image scrolls, creating ugly flashing.
+ //
+ uint signal_choke : 1;
+
+ // This variables indicates in updateScrollBars() that we are
+ // in a resizeEvent() and thus don't want to flash scroll bars
+ uint inresize : 1;
+ uint use_cached_size_hint : 1;
+ QSize cachedSizeHint;
+
+ inline int contentsX() const { return -vx; }
+ inline int contentsY() const { return -vy; }
+ inline int contentsWidth() const { return vwidth; }
+};
+
+inline Q3ScrollViewData::~Q3ScrollViewData()
+{
+ children.setAutoDelete(true);
+}
+
+QSVChildRec* Q3ScrollViewData::ancestorRec(QWidget* w)
+{
+ if (clipped_viewport) {
+ while (w->parentWidget() != clipped_viewport) {
+ w = w->parentWidget();
+ if (!w) return 0;
+ }
+ } else {
+ while (w->parentWidget() != viewport) {
+ w = w->parentWidget();
+ if (!w) return 0;
+ }
+ }
+ return rec(w);
+}
+
+void Q3ScrollViewData::hideOrShowAll(Q3ScrollView* sv, bool isScroll)
+{
+ if (!clipped_viewport)
+ return;
+ if (clipped_viewport->x() <= 0
+ && clipped_viewport->y() <= 0
+ && clipped_viewport->width()+clipped_viewport->x() >=
+ viewport->width()
+ && clipped_viewport->height()+clipped_viewport->y() >=
+ viewport->height()) {
+ // clipped_viewport still covers viewport
+ if(static_bg)
+ clipped_viewport->repaint(true);
+ else if ((!isScroll && !clipped_viewport->testAttribute(Qt::WA_StaticContents)) || static_bg)
+ clipped_viewport->update();
+ } else {
+ // Re-center
+ int nx = (viewport->width() - clipped_viewport->width()) / 2;
+ int ny = (viewport->height() - clipped_viewport->height()) / 2;
+ clipped_viewport->move(nx,ny);
+ clipped_viewport->update();
+ }
+ for (QSVChildRec *r = children.first(); r; r=children.next()) {
+ r->hideOrShow(sv, clipped_viewport);
+ }
+}
+
+void Q3ScrollViewData::moveAllBy(int dx, int dy)
+{
+ if (clipped_viewport && !static_bg) {
+ clipped_viewport->move(clipped_viewport->x()+dx,
+ clipped_viewport->y()+dy);
+ } else {
+ for (QSVChildRec *r = children.first(); r; r=children.next()) {
+ r->child->move(r->child->x()+dx,r->child->y()+dy);
+ }
+ if (static_bg)
+ viewport->repaint(true);
+ }
+}
+
+bool Q3ScrollViewData::anyVisibleChildren()
+{
+ for (QSVChildRec *r = children.first(); r; r=children.next()) {
+ if (r->child->isVisible()) return true;
+ }
+ return false;
+}
+
+void Q3ScrollViewData::autoMove(Q3ScrollView* sv)
+{
+ if (policy == Q3ScrollView::AutoOne) {
+ QSVChildRec* r = children.first();
+ if (r)
+ sv->setContentsPos(-r->child->x(),-r->child->y());
+ }
+}
+
+void Q3ScrollViewData::autoResize(Q3ScrollView* sv)
+{
+ if (policy == Q3ScrollView::AutoOne) {
+ QSVChildRec* r = children.first();
+ if (r)
+ sv->resizeContents(r->child->width(),r->child->height());
+ }
+}
+
+void Q3ScrollViewData::autoResizeHint(Q3ScrollView* sv)
+{
+ if (policy == Q3ScrollView::AutoOne) {
+ QSVChildRec* r = children.first();
+ if (r) {
+ QSize s = r->child->sizeHint();
+ if (s.isValid())
+ r->child->resize(s);
+ }
+ } else if (policy == Q3ScrollView::AutoOneFit) {
+ QSVChildRec* r = children.first();
+ if (r) {
+ QSize sh = r->child->sizeHint();
+ sh = sh.boundedTo(r->child->maximumSize());
+ sv->resizeContents(sh.width(), sh.height());
+ }
+ }
+}
+
+void Q3ScrollViewData::viewportResized(int w, int h)
+{
+ if (policy == Q3ScrollView::AutoOneFit) {
+ QSVChildRec* r = children.first();
+ if (r) {
+ QSize sh = r->child->sizeHint();
+ sh = sh.boundedTo(r->child->maximumSize());
+ r->child->resize(QMAX(w,sh.width()), QMAX(h,sh.height()));
+ }
+
+ }
+}
+
+
+/*!
+ \class Q3ScrollView
+ \brief The Q3ScrollView widget provides a scrolling area with on-demand scroll bars.
+
+ \compat
+
+ The Q3ScrollView is a large canvas - potentially larger than the
+ coordinate system normally supported by the underlying window
+ system. This is important because it is quite easy to go beyond
+ these limitations (e.g. many web pages are more than 32000 pixels
+ high). Additionally, the Q3ScrollView can have QWidgets positioned
+ on it that scroll around with the drawn content. These sub-widgets
+ can also have positions outside the normal coordinate range (but
+ they are still limited in size).
+
+ To provide content for the widget, inherit from Q3ScrollView,
+ reimplement drawContents() and use resizeContents() to set the
+ size of the viewed area. Use addChild() and moveChild() to
+ position widgets on the view.
+
+ To use Q3ScrollView effectively it is important to understand its
+ widget structure in the three styles of use: a single large child
+ widget, a large panning area with some widgets and a large panning
+ area with many widgets.
+
+ \section1 Using One Big Widget
+
+ \img qscrollview-vp2.png
+
+ The first, simplest usage of Q3ScrollView (depicted above), is
+ appropriate for scrolling areas that are never more than about
+ 4000 pixels in either dimension (this is about the maximum
+ reliable size on X11 servers). In this usage, you just make one
+ large child in the Q3ScrollView. The child should be a child of the
+ viewport() of the scrollview and be added with addChild():
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 0
+ You can go on to add arbitrary child widgets to the single child
+ in the scrollview as you would with any widget:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 1
+
+ Here the Q3ScrollView has four children: the viewport(), the
+ verticalScrollBar(), the horizontalScrollBar() and a small
+ cornerWidget(). The viewport() has one child: the QWidget. The
+ QWidget has the three QLabel objects as child widgets. When the view
+ is scrolled, the QWidget is moved; its children move with it as
+ child widgets normally do.
+
+ \section1 Using a Very Big View with Some Widgets
+
+ \img qscrollview-vp.png
+
+ The second usage of Q3ScrollView (depicted above) is appropriate
+ when few, if any, widgets are on a very large scrolling area that
+ is potentially larger than 4000 pixels in either dimension. In
+ this usage you call resizeContents() to set the size of the area
+ and reimplement drawContents() to paint the contents. You may also
+ add some widgets by making them children of the viewport() and
+ adding them with addChild() (this is the same as the process for
+ the single large widget in the previous example):
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 2
+ Here, the Q3ScrollView has the same four children: the viewport(),
+ the verticalScrollBar(), the horizontalScrollBar() and a small
+ cornerWidget(). The viewport() has the three QLabel objects as
+ child widgets. When the view is scrolled, the scrollview moves the
+ child widgets individually.
+
+ \section1 Using a Very Big View with Many Widgets
+
+ \img qscrollview-cl.png
+
+ The final usage of Q3ScrollView (depicted above) is appropriate
+ when many widgets are on a very large scrolling area that is
+ potentially larger than 4000 pixels in either dimension. In this
+ usage you call resizeContents() to set the size of the area and
+ reimplement drawContents() to paint the contents. You then call
+ enableClipper(true) and add widgets, again by making them children
+ of the viewport(), and adding them with addChild():
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 3
+
+ Here, the Q3ScrollView has four children: the clipper() (not the
+ viewport() this time), the verticalScrollBar(), the
+ horizontalScrollBar() and a small cornerWidget(). The clipper()
+ has one child: the viewport(). The viewport() has the same three
+ labels as child widgets. When the view is scrolled the viewport()
+ is moved; its children move with it as child widgets normally do.
+
+ \target allviews
+ \section1 Details Relevant for All Views
+
+ Normally you will use the first or third method if you want any
+ child widgets in the view.
+
+ Note that the widget you see in the scrolled area is the
+ viewport() widget, not the Q3ScrollView itself. So to turn mouse
+ tracking on, for example, use viewport()->setMouseTracking(true).
+
+ To enable drag-and-drop, you would setAcceptDrops(true) on the
+ Q3ScrollView (because drag-and-drop events propagate to the
+ parent). But to work out the logical position in the view, you
+ would need to map the drop co-ordinate from being relative to the
+ Q3ScrollView to being relative to the contents; use the function
+ viewportToContents() for this.
+
+ To handle mouse events on the scrolling area, subclass scrollview
+ as you would subclass other widgets, but rather than
+ reimplementing mousePressEvent(), reimplement
+ contentsMousePressEvent() instead. The contents specific event
+ handlers provide translated events in the coordinate system of the
+ scrollview. If you reimplement mousePressEvent(), you'll get
+ called only when part of the Q3ScrollView is clicked: and the only
+ such part is the "corner" (if you don't set a cornerWidget()) and
+ the frame; everything else is covered up by the viewport, clipper
+ or scroll bars.
+
+ When you construct a Q3ScrollView, some of the window flags apply
+ to the viewport() instead of being sent to the QWidget constructor
+ for the Q3ScrollView.
+
+ \list
+
+ \i An image-manipulation widget would use \c
+ WNoAutoErase|WStaticContents because the widget draws all pixels
+ itself, and when its size increases, it only needs a paint event
+ for the new part because the old part remains unchanged.
+
+ \i A scrolling game widget in which the background scrolls as the
+ characters move might use \c WNoAutoErase (in addition to \c
+ WStaticContents) so that the window system background does not
+ flash in and out during scrolling.
+
+ \i A word processing widget might use \c WNoAutoErase and repaint
+ itself line by line to get a less-flickery resizing. If the widget
+ is in a mode in which no text justification can take place, it
+ might use \c WStaticContents too, so that it would only get a
+ repaint for the newly visible parts.
+
+ \endlist
+
+ Child widgets may be moved using addChild() or moveChild(). Use
+ childX() and childY() to get the position of a child widget.
+
+ A widget may be placed in the corner between the vertical and
+ horizontal scroll bars with setCornerWidget(). You can get access
+ to the scroll bars using horizontalScrollBar() and
+ verticalScrollBar(), and to the viewport with viewport(). The
+ scroll view can be scrolled using scrollBy(), ensureVisible(),
+ setContentsPos() or center().
+
+ The visible area is given by visibleWidth() and visibleHeight(),
+ and the contents area by contentsWidth() and contentsHeight(). The
+ contents may be repainted using one of the repaintContents() or
+ updateContents() functions.
+
+ Coordinate conversion is provided by contentsToViewport() and
+ viewportToContents().
+
+ The contentsMoving() signal is emitted just before the contents
+ are moved to a new position.
+
+ \warning Q3ScrollView currently does not erase the background when
+ resized, i.e. you must always clear the background manually in
+ scrollview subclasses. This will change in a future version of Qt
+ and we recommend specifying the \c WNoAutoErase flag explicitly.
+*/
+
+
+/*!
+ \enum Q3ScrollView::ResizePolicy
+
+ This enum type is used to control a Q3ScrollView's reaction to
+ resize events.
+
+ \value Default the Q3ScrollView selects one of the other settings
+ automatically when it has to. In this version of Qt, Q3ScrollView
+ changes to \c Manual if you resize the contents with
+ resizeContents() and to \c AutoOne if a child is added.
+
+ \value Manual the contents stays the size set by resizeContents().
+
+ \value AutoOne if there is only one child widget the contents stays
+ the size of that widget. Otherwise the behavior is undefined.
+
+ \value AutoOneFit if there is only one child widget the contents stays
+ the size of that widget's sizeHint(). If the scrollview is resized
+ larger than the child's sizeHint(), the child will be resized to
+ fit. If there is more than one child, the behavior is undefined.
+
+*/
+//#### The widget will be resized to its sizeHint() when a LayoutHint event
+//#### is received
+
+/*!
+ Constructs a Q3ScrollView called \a name with parent \a parent and
+ widget flags \a f.
+
+ The widget flags \c WStaticContents, \c WNoAutoErase and \c
+ WPaintClever are propagated to the viewport() widget. The other
+ widget flags are propagated to the parent constructor as usual.
+*/
+
+Q3ScrollView::Q3ScrollView(QWidget *parent, const char *name, Qt::WindowFlags f) :
+ Q3Frame(parent, name, f & (~WStaticContents) & (~WNoAutoErase) & (~WResizeNoErase))
+{
+ WindowFlags flags = WResizeNoErase | (f&WPaintClever) | (f&WRepaintNoErase) | (f&WStaticContents);
+ d = new Q3ScrollViewData(this, flags);
+
+#ifndef QT_NO_DRAGANDDROP
+ connect(&d->autoscroll_timer, SIGNAL(timeout()),
+ this, SLOT(doDragAutoScroll()));
+#endif
+
+ connect(d->hbar, SIGNAL(valueChanged(int)),
+ this, SLOT(hslide(int)));
+ connect(d->vbar, SIGNAL(valueChanged(int)),
+ this, SLOT(vslide(int)));
+
+ connect(d->hbar, SIGNAL(sliderPressed()), this, SLOT(hbarIsPressed()));
+ connect(d->hbar, SIGNAL(sliderReleased()), this, SLOT(hbarIsReleased()));
+ connect(d->vbar, SIGNAL(sliderPressed()), this, SLOT(vbarIsPressed()));
+ connect(d->vbar, SIGNAL(sliderReleased()), this, SLOT(vbarIsReleased()));
+
+
+ d->viewport->installEventFilter(this);
+
+ connect(&d->scrollbar_timer, SIGNAL(timeout()),
+ this, SLOT(updateScrollBars()));
+
+ setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Sunken);
+ setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+}
+
+
+/*!
+ Destroys the Q3ScrollView. Any children added with addChild() will
+ be deleted.
+*/
+Q3ScrollView::~Q3ScrollView()
+{
+ // Be careful not to get all those useless events...
+ if (d->clipped_viewport)
+ d->clipped_viewport->removeEventFilter(this);
+ else
+ d->viewport->removeEventFilter(this);
+
+ // order is important
+ // ~QWidget may cause a WM_ERASEBKGND on Windows
+ delete d->vbar;
+ d->vbar = 0;
+ delete d->hbar;
+ d->hbar = 0;
+ delete d->viewport;
+ d->viewport = 0;
+ delete d;
+ d = 0;
+}
+
+/*!
+ \fn void Q3ScrollView::horizontalSliderPressed()
+
+ This signal is emitted whenever the user presses the horizontal slider.
+*/
+/*!
+ \fn void Q3ScrollView::horizontalSliderReleased()
+
+ This signal is emitted whenever the user releases the horizontal slider.
+*/
+/*!
+ \fn void Q3ScrollView::verticalSliderPressed()
+
+ This signal is emitted whenever the user presses the vertical slider.
+*/
+/*!
+ \fn void Q3ScrollView::verticalSliderReleased()
+
+ This signal is emitted whenever the user releases the vertical slider.
+*/
+void Q3ScrollView::hbarIsPressed()
+{
+ d->hbarPressed = true;
+ emit(horizontalSliderPressed());
+}
+
+void Q3ScrollView::hbarIsReleased()
+{
+ d->hbarPressed = false;
+ emit(horizontalSliderReleased());
+}
+
+/*!
+ Returns true if horizontal slider is pressed by user; otherwise returns false.
+*/
+bool Q3ScrollView::isHorizontalSliderPressed()
+{
+ return d->hbarPressed;
+}
+
+void Q3ScrollView::vbarIsPressed()
+{
+ d->vbarPressed = true;
+ emit(verticalSliderPressed());
+}
+
+void Q3ScrollView::vbarIsReleased()
+{
+ d->vbarPressed = false;
+ emit(verticalSliderReleased());
+}
+
+/*!
+ Returns true if vertical slider is pressed by user; otherwise returns false.
+*/
+bool Q3ScrollView::isVerticalSliderPressed()
+{
+ return d->vbarPressed;
+}
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::styleChange(QStyle& old)
+{
+ QWidget::styleChange(old);
+ updateScrollBars();
+ d->cachedSizeHint = QSize();
+}
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::fontChange(const QFont &old)
+{
+ QWidget::fontChange(old);
+ updateScrollBars();
+ d->cachedSizeHint = QSize();
+}
+
+void Q3ScrollView::hslide(int pos)
+{
+ if (!d->signal_choke) {
+ moveContents(-pos, -d->contentsY());
+ QApplication::syncX();
+ }
+}
+
+void Q3ScrollView::vslide(int pos)
+{
+ if (!d->signal_choke) {
+ moveContents(-d->contentsX(), -pos);
+ QApplication::syncX();
+ }
+}
+
+/*!
+ Called when the horizontal scroll bar geometry changes. This is
+ provided as a protected function so that subclasses can do
+ interesting things such as providing extra buttons in some of the
+ space normally used by the scroll bars.
+
+ The default implementation simply gives all the space to \a hbar.
+ The new geometry is given by \a x, \a y, \a w and \a h.
+
+ \sa setVBarGeometry()
+*/
+void Q3ScrollView::setHBarGeometry(QScrollBar& hbar,
+ int x, int y, int w, int h)
+{
+ hbar.setGeometry(x, y, w, h);
+}
+
+/*!
+ Called when the vertical scroll bar geometry changes. This is
+ provided as a protected function so that subclasses can do
+ interesting things such as providing extra buttons in some of the
+ space normally used by the scroll bars.
+
+ The default implementation simply gives all the space to \a vbar.
+ The new geometry is given by \a x, \a y, \a w and \a h.
+
+ \sa setHBarGeometry()
+*/
+void Q3ScrollView::setVBarGeometry(QScrollBar& vbar,
+ int x, int y, int w, int h)
+{
+ vbar.setGeometry(x, y, w, h);
+}
+
+
+/*!
+ Returns the viewport size for size (\a x, \a y).
+
+ The viewport size depends on (\a x, \a y) (the size of the contents),
+ the size of this widget and the modes of the horizontal and
+ vertical scroll bars.
+
+ This function permits widgets that can trade vertical and
+ horizontal space for each other to control scroll bar appearance
+ better. For example, a word processor or web browser can control
+ the width of the right margin accurately, whether or not there
+ needs to be a vertical scroll bar.
+*/
+
+QSize Q3ScrollView::viewportSize(int x, int y) const
+{
+ int fw = frameWidth();
+ int lmarg = fw+d->l_marg;
+ int rmarg = fw+d->r_marg;
+ int tmarg = fw+d->t_marg;
+ int bmarg = fw+d->b_marg;
+
+ int w = width();
+ int h = height();
+
+ bool needh, needv;
+ bool showh, showv;
+ int hsbExt = horizontalScrollBar()->sizeHint().height();
+ int vsbExt = verticalScrollBar()->sizeHint().width();
+
+ if (d->policy != AutoOne || d->anyVisibleChildren()) {
+ // Do we definitely need the scroll bar?
+ needh = w-lmarg-rmarg < x;
+ needv = h-tmarg-bmarg < y;
+
+ // Do we intend to show the scroll bar?
+ if (d->hMode == AlwaysOn)
+ showh = true;
+ else if (d->hMode == AlwaysOff)
+ showh = false;
+ else
+ showh = needh;
+
+ if (d->vMode == AlwaysOn)
+ showv = true;
+ else if (d->vMode == AlwaysOff)
+ showv = false;
+ else
+ showv = needv;
+
+ // Given other scroll bar will be shown, NOW do we need one?
+ if (showh && h-vsbExt-tmarg-bmarg < y) {
+ if (d->vMode == Auto)
+ showv=true;
+ }
+ if (showv && w-hsbExt-lmarg-rmarg < x) {
+ if (d->hMode == Auto)
+ showh=true;
+ }
+ } else {
+ // Scroll bars not needed, only show scroll bar that are always on.
+ showh = d->hMode == AlwaysOn;
+ showv = d->vMode == AlwaysOn;
+ }
+
+ return QSize(w-lmarg-rmarg - (showv ? vsbExt : 0),
+ h-tmarg-bmarg - (showh ? hsbExt : 0));
+}
+
+
+/*!
+ Updates scroll bars: all possibilities are considered. You should
+ never need to call this in your code.
+*/
+void Q3ScrollView::updateScrollBars()
+{
+ if(!horizontalScrollBar() && !verticalScrollBar())
+ return;
+
+ // I support this should use viewportSize()... but it needs
+ // so many of the temporary variables from viewportSize. hm.
+ int fw = frameWidth();
+ int lmarg = fw+d->l_marg;
+ int rmarg = fw+d->r_marg;
+ int tmarg = fw+d->t_marg;
+ int bmarg = fw+d->b_marg;
+
+ int w = width();
+ int h = height();
+
+ int portw, porth;
+
+ bool needh;
+ bool needv;
+ bool showh;
+ bool showv;
+ bool showc = false;
+
+ int hsbExt = horizontalScrollBar()->sizeHint().height();
+ int vsbExt = verticalScrollBar()->sizeHint().width();
+
+ QSize oldVisibleSize(visibleWidth(), visibleHeight());
+
+ if (d->policy != AutoOne || d->anyVisibleChildren()) {
+ // Do we definitely need the scroll bar?
+ needh = w-lmarg-rmarg < d->contentsWidth();
+ if (d->inresize)
+ needh = !horizontalScrollBar()->isHidden();
+ needv = h-tmarg-bmarg < contentsHeight();
+
+ // Do we intend to show the scroll bar?
+ if (d->hMode == AlwaysOn)
+ showh = true;
+ else if (d->hMode == AlwaysOff)
+ showh = false;
+ else
+ showh = needh;
+
+ if (d->vMode == AlwaysOn)
+ showv = true;
+ else if (d->vMode == AlwaysOff)
+ showv = false;
+ else
+ showv = needv;
+
+#ifdef Q_WS_MAC
+ bool mac_need_scroll = false;
+ if(!parentWidget()) {
+ mac_need_scroll = true;
+ } else {
+ QWidget *tlw = window();
+ QPoint tlw_br = QPoint(tlw->width(), tlw->height()),
+ my_br = qt_mac_posInWindow(this) + QPoint(w, h);
+ if(my_br.x() >= tlw_br.x() - 3 && my_br.y() >= tlw_br.y() - 3)
+ mac_need_scroll = true;
+ }
+ if(mac_need_scroll) {
+ WindowAttributes attr;
+ GetWindowAttributes((WindowPtr)handle(), &attr);
+ mac_need_scroll = (attr & kWindowResizableAttribute);
+ }
+ if(mac_need_scroll) {
+ showc = true;
+ if(d->vMode == Auto)
+ showv = true;
+ if(d->hMode == Auto)
+ showh = true;
+ }
+#endif
+
+ // Given other scroll bar will be shown, NOW do we need one?
+ if (showh && h-vsbExt-tmarg-bmarg < contentsHeight()) {
+ needv=true;
+ if (d->vMode == Auto)
+ showv=true;
+ }
+ if (showv && !d->inresize && w-hsbExt-lmarg-rmarg < d->contentsWidth()) {
+ needh=true;
+ if (d->hMode == Auto)
+ showh=true;
+ }
+ } else {
+ // Scrollbars not needed, only show scroll bar that are always on.
+ needh = needv = false;
+ showh = d->hMode == AlwaysOn;
+ showv = d->vMode == AlwaysOn;
+ }
+
+ bool sc = d->signal_choke;
+ d->signal_choke=true;
+
+ // Hide unneeded scroll bar, calculate viewport size
+ if (showh) {
+ porth=h-hsbExt-tmarg-bmarg;
+ } else {
+ if (!needh)
+ d->hbar->setValue(0);
+ d->hbar->hide();
+ porth=h-tmarg-bmarg;
+ }
+ if (showv) {
+ portw=w-vsbExt-lmarg-rmarg;
+ } else {
+ if (!needv)
+ d->vbar->setValue(0);
+ d->vbar->hide();
+ portw=w-lmarg-rmarg;
+ }
+
+ // Configure scroll bars that we will show
+ if (needv) {
+ d->vbar->setRange(0, contentsHeight()-porth);
+ d->vbar->setSteps(Q3ScrollView::d->vbar->lineStep(), porth);
+ } else {
+ d->vbar->setRange(0, 0);
+ }
+ if (needh) {
+ d->hbar->setRange(0, QMAX(0, d->contentsWidth()-portw));
+ d->hbar->setSteps(Q3ScrollView::d->hbar->lineStep(), portw);
+ } else {
+ d->hbar->setRange(0, 0);
+ }
+
+ // Position the scroll bars, viewport and corner widget.
+ int bottom;
+ bool reverse = QApplication::reverseLayout();
+ int xoffset = (reverse && (showv || cornerWidget())) ? vsbExt : 0;
+ int xpos = reverse ? 0 : w - vsbExt;
+ bool frameContentsOnly =
+ style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
+
+ if(! frameContentsOnly) {
+ if (reverse)
+ xpos += fw;
+ else
+ xpos -= fw;
+ }
+ if (showh) {
+ int right = (showc || showv || cornerWidget()) ? w-vsbExt : w;
+ if (! frameContentsOnly)
+ setHBarGeometry(*d->hbar, fw + xoffset, h-hsbExt-fw,
+ right-fw-fw, hsbExt);
+ else
+ setHBarGeometry(*d->hbar, 0 + xoffset, h-hsbExt, right,
+ hsbExt);
+ bottom=h-hsbExt;
+ } else {
+ bottom=h;
+ }
+ if (showv) {
+ clipper()->setGeometry(lmarg + xoffset, tmarg,
+ w-vsbExt-lmarg-rmarg,
+ bottom-tmarg-bmarg);
+ d->viewportResized(w-vsbExt-lmarg-rmarg, bottom-tmarg-bmarg);
+ if (! frameContentsOnly)
+ changeFrameRect(QRect(0, 0, w, h));
+ else
+ changeFrameRect(QRect(xoffset, 0, w-vsbExt, bottom));
+ if (showc || cornerWidget()) {
+ if (! frameContentsOnly)
+ setVBarGeometry(*d->vbar, xpos,
+ fw, vsbExt,
+ h-hsbExt-fw-fw);
+ else
+ setVBarGeometry(*d->vbar, xpos, 0,
+ vsbExt,
+ h-hsbExt);
+ }
+ else {
+ if (! frameContentsOnly)
+ setVBarGeometry(*d->vbar, xpos,
+ fw, vsbExt,
+ bottom-fw-fw);
+ else
+ setVBarGeometry(*d->vbar, xpos, 0,
+ vsbExt, bottom);
+ }
+ } else {
+ if (! frameContentsOnly)
+ changeFrameRect(QRect(0, 0, w, h));
+ else
+ changeFrameRect(QRect(0, 0, w, bottom));
+ clipper()->setGeometry(lmarg, tmarg,
+ w-lmarg-rmarg, bottom-tmarg-bmarg);
+ d->viewportResized(w-lmarg-rmarg, bottom-tmarg-bmarg);
+ }
+
+ QWidget *corner = d->corner;
+ if (d->corner) {
+ if (! frameContentsOnly)
+ corner->setGeometry(xpos,
+ h-hsbExt-fw,
+ vsbExt,
+ hsbExt);
+ else
+ corner->setGeometry(xpos,
+ h-hsbExt,
+ vsbExt,
+ hsbExt);
+ }
+
+ d->signal_choke=sc;
+
+ if (d->contentsX()+visibleWidth() > d->contentsWidth()) {
+ int x;
+#if 0
+ if (reverse)
+ x =QMIN(0,d->contentsWidth()-visibleWidth());
+ else
+#endif
+ x =QMAX(0,d->contentsWidth()-visibleWidth());
+ d->hbar->setValue(x);
+ // Do it even if it is recursive
+ moveContents(-x, -d->contentsY());
+ }
+ if (d->contentsY()+visibleHeight() > contentsHeight()) {
+ int y=QMAX(0,contentsHeight()-visibleHeight());
+ d->vbar->setValue(y);
+ // Do it even if it is recursive
+ moveContents(-d->contentsX(), -y);
+ }
+
+ // Finally, show the scroll bars
+ if (showh && (d->hbar->isHidden() || !d->hbar->isVisible()))
+ d->hbar->show();
+ if (showv && (d->vbar->isHidden() || !d->vbar->isVisible()))
+ d->vbar->show();
+
+ d->signal_choke=true;
+ d->vbar->setValue(d->contentsY());
+ d->hbar->setValue(d->contentsX());
+ d->signal_choke=false;
+
+ QSize newVisibleSize(visibleWidth(), visibleHeight());
+ if (d->clipped_viewport && oldVisibleSize != newVisibleSize) {
+ QResizeEvent e(newVisibleSize, oldVisibleSize);
+ viewportResizeEvent(&e);
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::setVisible(bool visible)
+{
+ if (visible && !isVisible()) {
+ QWidget::setVisible(visible);
+ updateScrollBars();
+ d->hideOrShowAll(this);
+ } else {
+ QWidget::setVisible(visible);
+ }
+}
+
+/*!
+ \internal
+ */
+void Q3ScrollView::resize(int w, int h)
+{
+ QWidget::resize(w, h);
+}
+
+/*!
+ \internal
+*/
+void Q3ScrollView::resize(const QSize& s)
+{
+ resize(s.width(), s.height());
+}
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::resizeEvent(QResizeEvent* event)
+{
+ Q3Frame::resizeEvent(event);
+
+#if 0
+ if (QApplication::reverseLayout()) {
+ d->fake_scroll = true;
+ scrollBy(-event->size().width() + event->oldSize().width(), 0);
+ d->fake_scroll = false;
+ }
+#endif
+
+ bool inresize = d->inresize;
+ d->inresize = true;
+ updateScrollBars();
+ d->inresize = inresize;
+ d->scrollbar_timer.start(0, true);
+
+ d->hideOrShowAll(this);
+}
+
+
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::mousePressEvent(QMouseEvent * e)
+{
+ e->ignore();
+}
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::mouseReleaseEvent(QMouseEvent *e)
+{
+ e->ignore();
+}
+
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ e->ignore();
+}
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::mouseMoveEvent(QMouseEvent *e)
+{
+ e->ignore();
+}
+
+/*!
+ \reimp
+*/
+#ifndef QT_NO_WHEELEVENT
+void Q3ScrollView::wheelEvent(QWheelEvent *e)
+{
+ QWheelEvent ce(viewport()->mapFromGlobal(e->globalPos()),
+ e->globalPos(), e->delta(), e->state());
+ viewportWheelEvent(&ce);
+ if (!ce.isAccepted()) {
+ if (e->orientation() == Horizontal && horizontalScrollBar())
+ horizontalScrollBar()->event(e);
+ else if (e->orientation() == Vertical && verticalScrollBar())
+ verticalScrollBar()->event(e);
+ } else {
+ e->accept();
+ }
+}
+#endif
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::contextMenuEvent(QContextMenuEvent *e)
+{
+ if (e->reason() != QContextMenuEvent::Keyboard) {
+ e->ignore();
+ return;
+ }
+
+ QContextMenuEvent ce(e->reason(), viewport()->mapFromGlobal(e->globalPos()),
+ e->globalPos(), e->state());
+ viewportContextMenuEvent(&ce);
+ if (ce.isAccepted())
+ e->accept();
+ else
+ e->ignore();
+}
+
+Q3ScrollView::ScrollBarMode Q3ScrollView::vScrollBarMode() const
+{
+ return d->vMode;
+}
+
+
+/*!
+ \enum Q3ScrollView::ScrollBarMode
+
+ This enum type describes the various modes of Q3ScrollView's scroll
+ bars.
+
+ \value Auto Q3ScrollView shows a scroll bar when the content is
+ too large to fit and not otherwise. This is the default.
+
+ \value AlwaysOff Q3ScrollView never shows a scroll bar.
+
+ \value AlwaysOn Q3ScrollView always shows a scroll bar.
+
+ (The modes for the horizontal and vertical scroll bars are
+ independent.)
+*/
+
+
+/*!
+ \property Q3ScrollView::vScrollBarMode
+ \brief the mode for the vertical scroll bar
+
+ The default mode is Q3ScrollView::Auto.
+
+ \sa hScrollBarMode
+*/
+void Q3ScrollView::setVScrollBarMode(ScrollBarMode mode)
+{
+ if (d->vMode != mode) {
+ d->vMode = mode;
+ updateScrollBars();
+ }
+}
+
+
+/*!
+ \property Q3ScrollView::hScrollBarMode
+ \brief the mode for the horizontal scroll bar
+
+ The default mode is Q3ScrollView::Auto.
+
+ \sa vScrollBarMode
+*/
+Q3ScrollView::ScrollBarMode Q3ScrollView::hScrollBarMode() const
+{
+ return d->hMode;
+}
+
+void Q3ScrollView::setHScrollBarMode(ScrollBarMode mode)
+{
+ if (d->hMode != mode) {
+ d->hMode = mode;
+ updateScrollBars();
+ }
+}
+
+
+/*!
+ Returns the widget in the corner between the two scroll bars.
+
+ By default, no corner widget is present.
+*/
+QWidget* Q3ScrollView::cornerWidget() const
+{
+ return d->corner;
+}
+
+/*!
+ Sets the widget in the \a corner between the two scroll bars.
+
+ You will probably also want to set at least one of the scroll bar
+ modes to \c AlwaysOn.
+
+ Passing 0 shows no widget in the corner.
+
+ Any previous \a corner widget is hidden.
+
+ You may call setCornerWidget() with the same widget at different
+ times.
+
+ All widgets set here will be deleted by the Q3ScrollView when it is
+ destroyed unless you separately reparent the widget after setting
+ some other corner widget (or 0).
+
+ Any \e newly set widget should have no current parent.
+
+ By default, no corner widget is present.
+
+ \sa setVScrollBarMode(), setHScrollBarMode()
+*/
+void Q3ScrollView::setCornerWidget(QWidget* corner)
+{
+ QWidget* oldcorner = d->corner;
+ if (oldcorner != corner) {
+ if (oldcorner) oldcorner->hide();
+ d->corner = corner;
+ if (corner) corner->setParent(this);
+ updateScrollBars();
+ if (corner) corner->show();
+ }
+}
+
+
+void Q3ScrollView::setResizePolicy(ResizePolicy r)
+{
+ d->policy = r;
+}
+
+/*!
+ \property Q3ScrollView::resizePolicy
+ \brief the resize policy
+
+ The default is \c Default.
+
+ \sa ResizePolicy
+*/
+Q3ScrollView::ResizePolicy Q3ScrollView::resizePolicy() const
+{
+ return d->policy;
+}
+
+/*!
+ \internal
+*/
+void Q3ScrollView::setEnabled(bool enable)
+{
+ Q3Frame::setEnabled(enable);
+}
+
+/*!
+ Removes the \a child widget from the scrolled area. Note that this
+ happens automatically if the \a child is deleted.
+*/
+void Q3ScrollView::removeChild(QWidget* child)
+{
+ if (!d || !child) // First check in case we are destructing
+ return;
+
+ QSVChildRec *r = d->rec(child);
+ if (r) d->deleteChildRec(r);
+}
+
+/*!
+ \internal
+*/
+void Q3ScrollView::removeChild(QObject* child)
+{
+ Q3Frame::removeChild(child);
+}
+
+/*!
+ Inserts the widget, \a child, into the scrolled area positioned at
+ (\a x, \a y). The position defaults to (0, 0). If the child is
+ already in the view, it is just moved.
+
+ You may want to call enableClipper(true) if you add a large number
+ of widgets.
+*/
+void Q3ScrollView::addChild(QWidget* child, int x, int y)
+{
+ if (!child) {
+#if defined(QT_CHECK_NULL)
+ qWarning("Q3ScrollView::addChild(): Cannot add null child");
+#endif
+ return;
+ }
+ child->polish();
+ child->setBackgroundOrigin(WidgetOrigin);
+
+ if (child->parentWidget() == viewport()) {
+ // May already be there
+ QSVChildRec *r = d->rec(child);
+ if (r) {
+ r->moveTo(this,x,y,d->clipped_viewport);
+ if (d->policy > Manual) {
+ d->autoResizeHint(this);
+ d->autoResize(this); // #### better to just deal with this one widget!
+ }
+ return;
+ }
+ }
+
+ if (d->children.isEmpty() && d->policy != Manual) {
+ if (d->policy == Default)
+ setResizePolicy(AutoOne);
+ child->installEventFilter(this);
+ } else if (d->policy == AutoOne) {
+ child->removeEventFilter(this); //#### ?????
+ setResizePolicy(Manual);
+ }
+ if (child->parentWidget() != viewport()) {
+ child->reparent(viewport(), 0, QPoint(0,0), false);
+ }
+ d->addChildRec(child,x,y)->hideOrShow(this, d->clipped_viewport);
+
+ if (d->policy > Manual) {
+ d->autoResizeHint(this);
+ d->autoResize(this); // #### better to just deal with this one widget!
+ }
+}
+
+/*!
+ Repositions the \a child widget to (\a x, \a y). This function is
+ the same as addChild().
+*/
+void Q3ScrollView::moveChild(QWidget* child, int x, int y)
+{
+ addChild(child,x,y);
+}
+
+/*!
+ Returns the X position of the given \a child widget. Use this
+ rather than QWidget::x() for widgets added to the view.
+
+ This function returns 0 if \a child has not been added to the view.
+*/
+int Q3ScrollView::childX(QWidget* child)
+{
+ QSVChildRec *r = d->rec(child);
+ return r ? r->x : 0;
+}
+
+/*!
+ Returns the Y position of the given \a child widget. Use this
+ rather than QWidget::y() for widgets added to the view.
+
+ This function returns 0 if \a child has not been added to the view.
+*/
+int Q3ScrollView::childY(QWidget* child)
+{
+ QSVChildRec *r = d->rec(child);
+ return r ? r->y : 0;
+}
+
+/*! \fn bool Q3ScrollView::childIsVisible(QWidget*)
+ \obsolete
+
+ Returns true if \a child is visible. This is equivalent
+ to child->isVisible().
+*/
+
+/*! \fn void Q3ScrollView::showChild(QWidget* child, bool y)
+ \obsolete
+
+ Sets the visibility of \a child. Equivalent to
+ QWidget::show() or QWidget::hide().
+*/
+
+/*!
+ This event filter ensures the scroll bars are updated when a
+ single contents widget is resized, shown, hidden or destroyed; it
+ passes mouse events to the Q3ScrollView. The event is in \a e and
+ the object is in \a obj.
+*/
+
+bool Q3ScrollView::eventFilter(QObject *obj, QEvent *e)
+{
+ bool disabled = !(qobject_cast<QWidget*>(obj)->isEnabled());
+ if (!d)
+ return false; // we are destructing
+ if (obj == d->viewport || obj == d->clipped_viewport) {
+ switch (e->type()) {
+ /* Forward many events to viewport...() functions */
+ case QEvent::Paint:
+ viewportPaintEvent((QPaintEvent*)e);
+ break;
+ case QEvent::Resize:
+ if (!d->clipped_viewport)
+ viewportResizeEvent((QResizeEvent *)e);
+ break;
+ case QEvent::MouseButtonPress:
+ if (disabled)
+ return false;
+ viewportMousePressEvent((QMouseEvent*)e);
+ if (((QMouseEvent*)e)->isAccepted())
+ return true;
+ break;
+ case QEvent::MouseButtonRelease:
+ if (disabled)
+ return false;
+ viewportMouseReleaseEvent((QMouseEvent*)e);
+ if (((QMouseEvent*)e)->isAccepted())
+ return true;
+ break;
+ case QEvent::MouseButtonDblClick:
+ if (disabled)
+ return false;
+ viewportMouseDoubleClickEvent((QMouseEvent*)e);
+ if (((QMouseEvent*)e)->isAccepted())
+ return true;
+ break;
+ case QEvent::MouseMove:
+ if (disabled)
+ return false;
+ viewportMouseMoveEvent((QMouseEvent*)e);
+ if (((QMouseEvent*)e)->isAccepted())
+ return true;
+ break;
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter:
+ if (disabled)
+ return false;
+ viewportDragEnterEvent((QDragEnterEvent*)e);
+ break;
+ case QEvent::DragMove: {
+ if (disabled)
+ return false;
+ if (d->drag_autoscroll) {
+ QPoint vp = ((QDragMoveEvent*) e)->pos();
+ QRect inside_margin(autoscroll_margin, autoscroll_margin,
+ visibleWidth() - autoscroll_margin * 2,
+ visibleHeight() - autoscroll_margin * 2);
+ if (!inside_margin.contains(vp)) {
+ startDragAutoScroll();
+ // Keep sending move events
+ ((QDragMoveEvent*)e)->accept(QRect(0,0,0,0));
+ }
+ }
+ viewportDragMoveEvent((QDragMoveEvent*)e);
+ } break;
+ case QEvent::DragLeave:
+ if (disabled)
+ return false;
+ stopDragAutoScroll();
+ viewportDragLeaveEvent((QDragLeaveEvent*)e);
+ break;
+ case QEvent::Drop:
+ if (disabled)
+ return false;
+ stopDragAutoScroll();
+ viewportDropEvent((QDropEvent*)e);
+ break;
+#endif // QT_NO_DRAGANDDROP
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ if (disabled)
+ return false;
+ break;
+#endif
+ case QEvent::ContextMenu:
+ if (disabled)
+ return false;
+ viewportContextMenuEvent((QContextMenuEvent*)e);
+ if (((QContextMenuEvent*)e)->isAccepted())
+ return true;
+ break;
+ case QEvent::ChildRemoved:
+ removeChild((QWidget*)((QChildEvent*)e)->child());
+ break;
+ case QEvent::LayoutHint:
+ d->autoResizeHint(this);
+ break;
+ default:
+ break;
+ }
+ } else if (d && d->rec((QWidget*)obj)) { // must be a child
+ if (e->type() == QEvent::Resize)
+ d->autoResize(this);
+ else if (e->type() == QEvent::Move)
+ d->autoMove(this);
+ }
+ return Q3Frame::eventFilter(obj, e); // always continue with standard event processing
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ mousePressEvent(): the press position in \a e is translated to be a point
+ on the contents.
+*/
+void Q3ScrollView::contentsMousePressEvent(QMouseEvent* e)
+{
+ e->ignore();
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ mouseReleaseEvent(): the release position in \a e is translated to be a
+ point on the contents.
+*/
+void Q3ScrollView::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ e->ignore();
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ mouseDoubleClickEvent(): the click position in \a e is translated to be a
+ point on the contents.
+
+ The default implementation generates a normal mouse press event.
+*/
+void Q3ScrollView::contentsMouseDoubleClickEvent(QMouseEvent* e)
+{
+ contentsMousePressEvent(e); // try mouse press event
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ mouseMoveEvent(): the mouse position in \a e is translated to be a point
+ on the contents.
+*/
+void Q3ScrollView::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ e->ignore();
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ dragEnterEvent(): the drag position is translated to be a point
+ on the contents.
+
+ The default implementation does nothing. The \a event parameter is
+ ignored.
+*/
+void Q3ScrollView::contentsDragEnterEvent(QDragEnterEvent * /* event */)
+{
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ dragMoveEvent(): the drag position is translated to be a point on
+ the contents.
+
+ The default implementation does nothing. The \a event parameter is
+ ignored.
+*/
+void Q3ScrollView::contentsDragMoveEvent(QDragMoveEvent * /* event */)
+{
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ dragLeaveEvent(): the drag position is translated to be a point
+ on the contents.
+
+ The default implementation does nothing. The \a event parameter is
+ ignored.
+*/
+void Q3ScrollView::contentsDragLeaveEvent(QDragLeaveEvent * /* event */)
+{
+}
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ dropEvent(): the drop position is translated to be a point on the
+ contents.
+
+ The default implementation does nothing. The \a event parameter is
+ ignored.
+*/
+
+void Q3ScrollView::contentsDropEvent(QDropEvent * /* event */)
+{
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ wheelEvent() in \a{e}: the mouse position is translated to be a
+ point on the contents.
+*/
+#ifndef QT_NO_WHEELEVENT
+void Q3ScrollView::contentsWheelEvent(QWheelEvent * e)
+{
+ e->ignore();
+}
+#endif
+/*!
+ This event handler is called whenever the Q3ScrollView receives a
+ contextMenuEvent() in \a{e}: the mouse position is translated to
+ be a point on the contents.
+*/
+void Q3ScrollView::contentsContextMenuEvent(QContextMenuEvent *e)
+{
+ e->ignore();
+}
+
+/*!
+ This is a low-level painting routine that draws the viewport
+ contents. Reimplement this if drawContents() is too high-level
+ (for example, if you don't want to open a QPainter on the
+ viewport). The paint event is passed in \a pe.
+*/
+void Q3ScrollView::viewportPaintEvent(QPaintEvent* pe)
+{
+ QWidget* vp = viewport();
+
+ QPainter p(vp);
+ QRect r = pe->rect();
+
+ if (d->clipped_viewport) {
+ QRect rr(
+ -d->clipped_viewport->x(), -d->clipped_viewport->y(),
+ d->viewport->width(), d->viewport->height()
+ );
+ r &= rr;
+ if (r.isValid()) {
+ int ex = r.x() + d->clipped_viewport->x() + d->contentsX();
+ int ey = r.y() + d->clipped_viewport->y() + d->contentsY();
+ int ew = r.width();
+ int eh = r.height();
+ drawContentsOffset(&p,
+ d->contentsX()+d->clipped_viewport->x(),
+ d->contentsY()+d->clipped_viewport->y(),
+ ex, ey, ew, eh);
+ }
+ } else {
+ r &= d->viewport->rect();
+ int ex = r.x() + d->contentsX();
+ int ey = r.y() + d->contentsY();
+ int ew = r.width();
+ int eh = r.height();
+ drawContentsOffset(&p, d->contentsX(), d->contentsY(), ex, ey, ew, eh);
+ }
+}
+
+
+/*!
+ To provide simple processing of events on the contents, this
+ function receives all resize events sent to the viewport.
+
+ The default implementation does nothing. The \a event parameter is
+ ignored.
+
+ \sa QWidget::resizeEvent()
+*/
+void Q3ScrollView::viewportResizeEvent(QResizeEvent * /* event */)
+{
+}
+
+/*! \internal
+
+ To provide simple processing of events on the contents, this
+ function receives all mouse press events sent to the viewport,
+ translates the event and calls contentsMousePressEvent().
+
+ \sa contentsMousePressEvent(), QWidget::mousePressEvent()
+*/
+void Q3ScrollView::viewportMousePressEvent(QMouseEvent* e)
+{
+ QMouseEvent ce(e->type(), viewportToContents(e->pos()),
+ e->globalPos(), e->button(), e->state());
+ contentsMousePressEvent(&ce);
+ if (!ce.isAccepted())
+ e->ignore();
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all mouse release events sent to the viewport, translates
+ the event and calls contentsMouseReleaseEvent().
+
+ \sa QWidget::mouseReleaseEvent()
+*/
+void Q3ScrollView::viewportMouseReleaseEvent(QMouseEvent* e)
+{
+ QMouseEvent ce(e->type(), viewportToContents(e->pos()),
+ e->globalPos(), e->button(), e->state());
+ contentsMouseReleaseEvent(&ce);
+ if (!ce.isAccepted())
+ e->ignore();
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all mouse double click events sent to the viewport,
+ translates the event and calls contentsMouseDoubleClickEvent().
+
+ \sa QWidget::mouseDoubleClickEvent()
+*/
+void Q3ScrollView::viewportMouseDoubleClickEvent(QMouseEvent* e)
+{
+ QMouseEvent ce(e->type(), viewportToContents(e->pos()),
+ e->globalPos(), e->button(), e->state());
+ contentsMouseDoubleClickEvent(&ce);
+ if (!ce.isAccepted())
+ e->ignore();
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all mouse move events sent to the viewport, translates the
+ event and calls contentsMouseMoveEvent().
+
+ \sa QWidget::mouseMoveEvent()
+*/
+void Q3ScrollView::viewportMouseMoveEvent(QMouseEvent* e)
+{
+ QMouseEvent ce(e->type(), viewportToContents(e->pos()),
+ e->globalPos(), e->button(), e->state());
+ contentsMouseMoveEvent(&ce);
+ if (!ce.isAccepted())
+ e->ignore();
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all drag enter events sent to the viewport, translates the
+ event and calls contentsDragEnterEvent().
+
+ \sa QWidget::dragEnterEvent()
+*/
+void Q3ScrollView::viewportDragEnterEvent(QDragEnterEvent* e)
+{
+ e->setPoint(viewportToContents(e->pos()));
+ contentsDragEnterEvent(e);
+ e->setPoint(contentsToViewport(e->pos()));
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all drag move events sent to the viewport, translates the
+ event and calls contentsDragMoveEvent().
+
+ \sa QWidget::dragMoveEvent()
+*/
+void Q3ScrollView::viewportDragMoveEvent(QDragMoveEvent* e)
+{
+ e->setPoint(viewportToContents(e->pos()));
+ contentsDragMoveEvent(e);
+ e->setPoint(contentsToViewport(e->pos()));
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all drag leave events sent to the viewport and calls
+ contentsDragLeaveEvent().
+
+ \sa QWidget::dragLeaveEvent()
+*/
+void Q3ScrollView::viewportDragLeaveEvent(QDragLeaveEvent* e)
+{
+ contentsDragLeaveEvent(e);
+}
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all drop events sent to the viewport, translates the event
+ and calls contentsDropEvent().
+
+ \sa QWidget::dropEvent()
+*/
+void Q3ScrollView::viewportDropEvent(QDropEvent* e)
+{
+ e->setPoint(viewportToContents(e->pos()));
+ contentsDropEvent(e);
+ e->setPoint(contentsToViewport(e->pos()));
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+/*!\internal
+
+ To provide simple processing of events on the contents, this function
+ receives all wheel events sent to the viewport, translates the
+ event and calls contentsWheelEvent().
+
+ \sa QWidget::wheelEvent()
+*/
+#ifndef QT_NO_WHEELEVENT
+void Q3ScrollView::viewportWheelEvent(QWheelEvent* e)
+{
+ /*
+ Different than standard mouse events, because wheel events might
+ be sent to the focus widget if the widget-under-mouse doesn't want
+ the event itself.
+ */
+ QWheelEvent ce(viewportToContents(e->pos()),
+ e->globalPos(), e->delta(), e->state());
+ contentsWheelEvent(&ce);
+ if (ce.isAccepted())
+ e->accept();
+ else
+ e->ignore();
+}
+#endif
+
+/*! \internal
+
+ To provide simple processing of events on the contents, this function
+ receives all context menu events sent to the viewport, translates the
+ event and calls contentsContextMenuEvent().
+*/
+void Q3ScrollView::viewportContextMenuEvent(QContextMenuEvent *e)
+{
+ QContextMenuEvent ce(e->reason(), viewportToContents(e->pos()), e->globalPos(), e->state());
+ contentsContextMenuEvent(&ce);
+ if (ce.isAccepted())
+ e->accept();
+ else
+ e->ignore();
+}
+
+/*!
+ Returns the component horizontal scroll bar. It is made available
+ to allow accelerators, autoscrolling, etc.
+
+ It should not be used for other purposes.
+
+ This function never returns 0.
+*/
+QScrollBar* Q3ScrollView::horizontalScrollBar() const
+{
+ return d->hbar;
+}
+
+/*!
+ Returns the component vertical scroll bar. It is made available to
+ allow accelerators, autoscrolling, etc.
+
+ It should not be used for other purposes.
+
+ This function never returns 0.
+*/
+QScrollBar* Q3ScrollView::verticalScrollBar() const {
+ return d->vbar;
+}
+
+
+/*!
+ Scrolls the content so that the point (\a x, \a y) is visible with at
+ least 50-pixel margins (if possible, otherwise centered).
+*/
+void Q3ScrollView::ensureVisible(int x, int y)
+{
+ ensureVisible(x, y, 50, 50);
+}
+
+/*!
+ \overload
+
+ Scrolls the content so that the point (\a x, \a y) is visible with at
+ least the \a xmargin and \a ymargin margins (if possible,
+ otherwise centered).
+*/
+void Q3ScrollView::ensureVisible(int x, int y, int xmargin, int ymargin)
+{
+ int pw=visibleWidth();
+ int ph=visibleHeight();
+
+ int cx=-d->contentsX();
+ int cy=-d->contentsY();
+ int cw=d->contentsWidth();
+ int ch=contentsHeight();
+
+ if (pw < xmargin*2)
+ xmargin=pw/2;
+ if (ph < ymargin*2)
+ ymargin=ph/2;
+
+ if (cw <= pw) {
+ xmargin=0;
+ cx=0;
+ }
+ if (ch <= ph) {
+ ymargin=0;
+ cy=0;
+ }
+
+ if (x < -cx+xmargin)
+ cx = -x+xmargin;
+ else if (x >= -cx+pw-xmargin)
+ cx = -x+pw-xmargin;
+
+ if (y < -cy+ymargin)
+ cy = -y+ymargin;
+ else if (y >= -cy+ph-ymargin)
+ cy = -y+ph-ymargin;
+
+ if (cx > 0)
+ cx=0;
+ else if (cx < pw-cw && cw>pw)
+ cx=pw-cw;
+
+ if (cy > 0)
+ cy=0;
+ else if (cy < ph-ch && ch>ph)
+ cy=ph-ch;
+
+ setContentsPos(-cx, -cy);
+}
+
+/*!
+ Scrolls the content so that the point (\a x, \a y) is in the top-left
+ corner.
+*/
+void Q3ScrollView::setContentsPos(int x, int y)
+{
+#if 0
+ // bounds checking...
+ if (QApplication::reverseLayout())
+ if (x > d->contentsWidth() - visibleWidth()) x = d->contentsWidth() - visibleWidth();
+ else
+#endif
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ // Choke signal handling while we update BOTH sliders.
+ d->signal_choke=true;
+ moveContents(-x, -y);
+ d->vbar->setValue(y);
+ d->hbar->setValue(x);
+ d->signal_choke=false;
+}
+
+/*!
+ Scrolls the content by \a dx to the left and \a dy upwards.
+*/
+void Q3ScrollView::scrollBy(int dx, int dy)
+{
+ setContentsPos(QMAX(d->contentsX()+dx, 0), QMAX(d->contentsY()+dy, 0));
+}
+
+/*!
+ Scrolls the content so that the point (\a x, \a y) is in the center
+ of visible area.
+*/
+void Q3ScrollView::center(int x, int y)
+{
+ ensureVisible(x, y, 32000, 32000);
+}
+
+/*!
+ \overload
+
+ Scrolls the content so that the point (\a x, \a y) is visible with
+ the \a xmargin and \a ymargin margins (as fractions of visible
+ the area).
+
+ For example:
+ \list
+ \i Margin 0.0 allows (x, y) to be on the edge of the visible area.
+ \i Margin 0.5 ensures that (x, y) is in middle 50% of the visible area.
+ \i Margin 1.0 ensures that (x, y) is in the center of the the visible area.
+ \endlist
+*/
+void Q3ScrollView::center(int x, int y, float xmargin, float ymargin)
+{
+ int pw=visibleWidth();
+ int ph=visibleHeight();
+ ensureVisible(x, y, int(xmargin/2.0*pw+0.5), int(ymargin/2.0*ph+0.5));
+}
+
+
+/*!
+ \fn void Q3ScrollView::contentsMoving(int x, int y)
+
+ This signal is emitted just before the contents are moved to
+ position (\a x, \a y).
+
+ \sa contentsX(), contentsY()
+*/
+
+/*!
+ Moves the contents by (\a x, \a y).
+*/
+void Q3ScrollView::moveContents(int x, int y)
+{
+ if (-x+visibleWidth() > d->contentsWidth())
+#if 0
+ if(QApplication::reverseLayout())
+ x=QMAX(0,-d->contentsWidth()+visibleWidth());
+ else
+#endif
+ x=QMIN(0,-d->contentsWidth()+visibleWidth());
+ if (-y+visibleHeight() > contentsHeight())
+ y=QMIN(0,-contentsHeight()+visibleHeight());
+
+ int dx = x - d->vx;
+ int dy = y - d->vy;
+
+ if (!dx && !dy)
+ return; // Nothing to do
+
+ emit contentsMoving(-x, -y);
+
+ d->vx = x;
+ d->vy = y;
+
+ if (d->clipped_viewport || d->static_bg) {
+ // Cheap move (usually)
+ d->moveAllBy(dx,dy);
+ } else if (/*dx && dy ||*/
+ (QABS(dy) * 5 > visibleHeight() * 4) ||
+ (QABS(dx) * 5 > visibleWidth() * 4)
+ )
+ {
+ // Big move
+ if (viewport()->updatesEnabled())
+ viewport()->update();
+ d->moveAllBy(dx,dy);
+ } else if (!d->fake_scroll || d->contentsWidth() > visibleWidth()) {
+ // Small move
+ clipper()->scroll(dx,dy);
+ }
+ d->hideOrShowAll(this, true);
+}
+
+/*!
+ \property Q3ScrollView::contentsX
+ \brief the X coordinate of the contents that are at the left edge of
+ the viewport.
+*/
+int Q3ScrollView::contentsX() const
+{
+ return d->contentsX();
+}
+
+/*!
+ \property Q3ScrollView::contentsY
+ \brief the Y coordinate of the contents that are at the top edge of
+ the viewport.
+*/
+int Q3ScrollView::contentsY() const
+{
+ return d->contentsY();
+}
+
+/*!
+ \property Q3ScrollView::contentsWidth
+ \brief the width of the contents area
+*/
+int Q3ScrollView::contentsWidth() const
+{
+ return d->contentsWidth();
+}
+
+/*!
+ \property Q3ScrollView::contentsHeight
+ \brief the height of the contents area
+*/
+int Q3ScrollView::contentsHeight() const
+{
+ return d->vheight;
+}
+
+/*!
+ Sets the size of the contents area to \a w pixels wide and \a h
+ pixels high and updates the viewport accordingly.
+*/
+void Q3ScrollView::resizeContents(int w, int h)
+{
+ int ow = d->vwidth;
+ int oh = d->vheight;
+ d->vwidth = w;
+ d->vheight = h;
+
+ d->scrollbar_timer.start(0, true);
+
+ if (d->children.isEmpty() && d->policy == Default)
+ setResizePolicy(Manual);
+
+ if (ow > w) {
+ // Swap
+ int t=w;
+ w=ow;
+ ow=t;
+ }
+ // Refresh area ow..w
+ if (ow < visibleWidth() && w >= 0) {
+ if (ow < 0)
+ ow = 0;
+ if (w > visibleWidth())
+ w = visibleWidth();
+ clipper()->update(d->contentsX()+ow, 0, w-ow, visibleHeight());
+ }
+
+ if (oh > h) {
+ // Swap
+ int t=h;
+ h=oh;
+ oh=t;
+ }
+ // Refresh area oh..h
+ if (oh < visibleHeight() && h >= 0) {
+ if (oh < 0)
+ oh = 0;
+ if (h > visibleHeight())
+ h = visibleHeight();
+ clipper()->update(0, d->contentsY()+oh, visibleWidth(), h-oh);
+ }
+}
+
+/*!
+ Calls update() on a rectangle defined by \a x, \a y, \a w, \a h,
+ translated appropriately. If the rectangle is not visible, nothing
+ is repainted.
+
+ \sa repaintContents()
+*/
+void Q3ScrollView::updateContents(int x, int y, int w, int h)
+{
+ if (!isVisible() || !updatesEnabled())
+ return;
+
+ QWidget* vp = viewport();
+
+ // Translate
+ x -= d->contentsX();
+ y -= d->contentsY();
+
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ y = 0;
+ }
+
+ if (w < 0 || h < 0)
+ return;
+ if (x > visibleWidth() || y > visibleHeight())
+ return;
+
+ if (w > visibleWidth())
+ w = visibleWidth();
+ if (h > visibleHeight())
+ h = visibleHeight();
+
+ if (d->clipped_viewport) {
+ // Translate clipper() to viewport()
+ x -= d->clipped_viewport->x();
+ y -= d->clipped_viewport->y();
+ }
+
+ vp->update(x, y, w, h);
+}
+
+/*!
+ \overload
+
+ Updates the contents in rectangle \a r
+*/
+void Q3ScrollView::updateContents(const QRect& r)
+{
+ updateContents(r.x(), r.y(), r.width(), r.height());
+}
+
+/*!
+ \overload
+*/
+void Q3ScrollView::updateContents()
+{
+ updateContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight());
+}
+
+/*!
+ \overload
+
+ Repaints the contents of rectangle \a r. If \a erase is true the
+ background is cleared using the background color.
+*/
+void Q3ScrollView::repaintContents(const QRect& r, bool erase)
+{
+ repaintContents(r.x(), r.y(), r.width(), r.height(), erase);
+}
+
+
+/*!
+ \overload
+
+ Repaints the contents. If \a erase is true the background is
+ cleared using the background color.
+*/
+void Q3ScrollView::repaintContents(bool erase)
+{
+ repaintContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight(), erase);
+}
+
+
+/*!
+ Calls repaint() on a rectangle defined by \a x, \a y, \a w, \a h,
+ translated appropriately. If the rectangle is not visible, nothing
+ is repainted. If \a erase is true the background is cleared using
+ the background color.
+
+ \sa updateContents()
+*/
+void Q3ScrollView::repaintContents(int x, int y, int w, int h, bool /*erase*/)
+{
+ if (!isVisible() || !updatesEnabled())
+ return;
+
+ QWidget* vp = viewport();
+
+ // Translate logical to clipper()
+ x -= d->contentsX();
+ y -= d->contentsY();
+
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ y = 0;
+ }
+
+ if (w < 0 || h < 0)
+ return;
+ if (w > visibleWidth())
+ w = visibleWidth();
+ if (h > visibleHeight())
+ h = visibleHeight();
+
+ if (d->clipped_viewport) {
+ // Translate clipper() to viewport()
+ x -= d->clipped_viewport->x();
+ y -= d->clipped_viewport->y();
+ }
+
+ vp->update(x, y, w, h);
+}
+
+
+/*!
+ For backward-compatibility only. It is easier to use
+ drawContents(QPainter*,int,int,int,int).
+
+ The default implementation translates the painter appropriately
+ and calls drawContents(QPainter*,int,int,int,int). See
+ drawContents() for an explanation of the parameters \a p, \a
+ offsetx, \a offsety, \a clipx, \a clipy, \a clipw and \a cliph.
+*/
+void Q3ScrollView::drawContentsOffset(QPainter* p, int offsetx, int offsety, int clipx, int clipy, int clipw, int cliph)
+{
+ p->translate(-offsetx,-offsety);
+ drawContents(p, clipx, clipy, clipw, cliph);
+}
+
+/*!
+ \fn void Q3ScrollView::drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph)
+
+ Reimplement this function if you are viewing a drawing area rather
+ than a widget.
+
+ The function should draw the rectangle (\a clipx, \a clipy, \a
+ clipw, \a cliph) of the contents using painter \a p. The clip
+ rectangle is in the scrollview's coordinates.
+
+ For example:
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 4
+
+ The clip rectangle and translation of the painter \a p is already
+ set appropriately.
+*/
+void Q3ScrollView::drawContents(QPainter*, int, int, int, int)
+{
+}
+
+
+/*!
+ \reimp
+*/
+void Q3ScrollView::frameChanged()
+{
+ // slight ugle-hack - the listview header needs readjusting when
+ // changing the frame
+ if (Q3ListView *lv = qobject_cast<Q3ListView *>(this))
+ lv->triggerUpdate();
+ Q3Frame::frameChanged();
+ updateScrollBars();
+}
+
+
+/*!
+ Returns the viewport widget of the scrollview. This is the widget
+ containing the contents widget or which is the drawing area.
+*/
+QWidget* Q3ScrollView::viewport() const
+{
+ if (d->clipped_viewport)
+ return d->clipped_viewport;
+ return d->viewport;
+}
+
+/*!
+ Returns the clipper widget. Contents in the scrollview are
+ ultimately clipped to be inside the clipper widget.
+
+ You should not need to use this function.
+
+ \sa visibleWidth(), visibleHeight()
+*/
+QWidget* Q3ScrollView::clipper() const
+{
+ return d->viewport;
+}
+
+/*!
+ \property Q3ScrollView::visibleWidth
+ \brief the horizontal amount of the content that is visible
+*/
+int Q3ScrollView::visibleWidth() const
+{
+ return clipper()->width();
+}
+
+/*!
+ \property Q3ScrollView::visibleHeight
+ \brief the vertical amount of the content that is visible
+*/
+int Q3ScrollView::visibleHeight() const
+{
+ return clipper()->height();
+}
+
+
+void Q3ScrollView::changeFrameRect(const QRect& r)
+{
+ QRect oldr = frameRect();
+ if (oldr != r) {
+ QRect cr = contentsRect();
+ QRegion fr(frameRect());
+ fr = fr.subtracted(contentsRect());
+ setFrameRect(r);
+ if (isVisible()) {
+ cr = cr.intersected(contentsRect());
+ fr = fr.united(frameRect());
+ fr = fr.subtracted(cr);
+ if (!fr.isEmpty())
+ update(fr);
+ }
+ }
+}
+
+
+/*!
+ Sets the margins around the scrolling area to \a left, \a top, \a
+ right and \a bottom. This is useful for applications such as
+ spreadsheets with "locked" rows and columns. The marginal space is
+ \e inside the frameRect() and is left blank; reimplement
+ drawFrame() or put widgets in the unused area.
+
+ By default all margins are zero.
+
+ \sa frameChanged()
+*/
+void Q3ScrollView::setMargins(int left, int top, int right, int bottom)
+{
+ if (left == d->l_marg &&
+ top == d->t_marg &&
+ right == d->r_marg &&
+ bottom == d->b_marg)
+ return;
+
+ d->l_marg = left;
+ d->t_marg = top;
+ d->r_marg = right;
+ d->b_marg = bottom;
+ updateScrollBars();
+}
+
+
+/*!
+ Returns the left margin.
+
+ \sa setMargins()
+*/
+int Q3ScrollView::leftMargin() const
+{
+ return d->l_marg;
+}
+
+
+/*!
+ Returns the top margin.
+
+ \sa setMargins()
+*/
+int Q3ScrollView::topMargin() const
+{
+ return d->t_marg;
+}
+
+
+/*!
+ Returns the right margin.
+
+ \sa setMargins()
+*/
+int Q3ScrollView::rightMargin() const
+{
+ return d->r_marg;
+}
+
+
+/*!
+ Returns the bottom margin.
+
+ \sa setMargins()
+*/
+int Q3ScrollView::bottomMargin() const
+{
+ return d->b_marg;
+}
+
+/*!
+ \reimp
+*/
+bool Q3ScrollView::focusNextPrevChild(bool next)
+{
+ // Makes sure that the new focus widget is on-screen, if
+ // necessary by scrolling the scroll view.
+ bool retval = Q3Frame::focusNextPrevChild(next);
+ if (retval) {
+ QWidget *w = window()->focusWidget();
+ if (isAncestorOf(w)) {
+ QSVChildRec *r = d->ancestorRec(w);
+ if (r && (r->child == w || w->isVisibleTo(r->child))) {
+ QPoint cp = r->child->mapToGlobal(QPoint(0, 0));
+ QPoint cr = w->mapToGlobal(QPoint(0, 0)) - cp;
+ ensureVisible(r->x + cr.x() + w->width()/2, r->y + cr.y() + w->height()/2,
+ w->width()/2, w->height()/2);
+ }
+ }
+ }
+ return retval;
+}
+
+
+
+/*!
+ When a large numbers of child widgets are in a scrollview,
+ especially if they are close together, the scrolling performance
+ can suffer greatly. If \a y is true the scrollview will use an
+ extra widget to group child widgets.
+
+ Note that you may only call enableClipper() prior to adding
+ widgets.
+*/
+void Q3ScrollView::enableClipper(bool y)
+{
+ if (!d->clipped_viewport == !y)
+ return;
+ if (d->children.count())
+ qFatal("May only call Q3ScrollView::enableClipper() before adding widgets");
+ if (y) {
+ d->clipped_viewport = new QClipperWidget(clipper(), "qt_clipped_viewport", QFlag(d->flags));
+ d->clipped_viewport->setGeometry(-coord_limit/2,-coord_limit/2,
+ coord_limit,coord_limit);
+ d->clipped_viewport->setBackgroundMode(d->viewport->backgroundMode());
+ d->viewport->setBackgroundMode(NoBackground); // no exposures for this
+ d->viewport->removeEventFilter(this);
+ d->clipped_viewport->installEventFilter(this);
+ d->clipped_viewport->show();
+ } else {
+ delete d->clipped_viewport;
+ d->clipped_viewport = 0;
+ }
+}
+
+/*!
+ Sets the scrollview to have a static background if \a y is true,
+ or a scrolling background if \a y is false. By default, the
+ background is scrolling.
+
+ Be aware that this mode is quite slow, as a full repaint of the
+ visible area has to be triggered on every contents move.
+
+ \sa hasStaticBackground()
+*/
+void Q3ScrollView::setStaticBackground(bool y)
+{
+ d->static_bg = y;
+}
+
+/*!
+ Returns true if Q3ScrollView uses a static background; otherwise
+ returns false.
+
+ \sa setStaticBackground()
+*/
+bool Q3ScrollView::hasStaticBackground() const
+{
+ return d->static_bg;
+}
+
+/*!
+ \overload
+
+ Returns the point \a p translated to a point on the viewport()
+ widget.
+*/
+QPoint Q3ScrollView::contentsToViewport(const QPoint& p) const
+{
+ if (d->clipped_viewport) {
+ return QPoint(p.x() - d->contentsX() - d->clipped_viewport->x(),
+ p.y() - d->contentsY() - d->clipped_viewport->y());
+ } else {
+ return QPoint(p.x() - d->contentsX(),
+ p.y() - d->contentsY());
+ }
+}
+
+/*!
+ \overload
+
+ Returns the point on the viewport \a vp translated to a point in
+ the contents.
+*/
+QPoint Q3ScrollView::viewportToContents(const QPoint& vp) const
+{
+ if (d->clipped_viewport) {
+ return QPoint(vp.x() + d->contentsX() + d->clipped_viewport->x(),
+ vp.y() + d->contentsY() + d->clipped_viewport->y());
+ } else {
+ return QPoint(vp.x() + d->contentsX(),
+ vp.y() + d->contentsY());
+ }
+}
+
+
+/*!
+ Translates a point (\a x, \a y) in the contents to a point (\a vx,
+ \a vy) on the viewport() widget.
+*/
+void Q3ScrollView::contentsToViewport(int x, int y, int& vx, int& vy) const
+{
+ const QPoint v = contentsToViewport(QPoint(x,y));
+ vx = v.x();
+ vy = v.y();
+}
+
+/*!
+ Translates a point (\a vx, \a vy) on the viewport() widget to a
+ point (\a x, \a y) in the contents.
+*/
+void Q3ScrollView::viewportToContents(int vx, int vy, int& x, int& y) const
+{
+ const QPoint c = viewportToContents(QPoint(vx,vy));
+ x = c.x();
+ y = c.y();
+}
+
+/*!
+ \reimp
+*/
+QSize Q3ScrollView::sizeHint() const
+{
+ if (d->use_cached_size_hint && d->cachedSizeHint.isValid())
+ return d->cachedSizeHint;
+
+ constPolish();
+ int f = 2 * frameWidth();
+ int h = fontMetrics().height();
+ QSize sz(f, f);
+ if (d->policy > Manual) {
+ QSVChildRec *r = d->children.first();
+ if (r) {
+ QSize cs = r->child->sizeHint();
+ if (cs.isValid())
+ sz += cs.boundedTo(r->child->maximumSize());
+ else
+ sz += r->child->size();
+ }
+ } else {
+ sz += QSize(d->contentsWidth(), contentsHeight());
+ }
+ if (d->vMode == AlwaysOn)
+ sz.setWidth(sz.width() + d->vbar->sizeHint().width());
+ if (d->hMode == AlwaysOn)
+ sz.setHeight(sz.height() + d->hbar->sizeHint().height());
+ return sz.expandedTo(QSize(12 * h, 8 * h))
+ .boundedTo(QSize(36 * h, 24 * h));
+}
+
+
+/*!
+ \reimp
+*/
+QSize Q3ScrollView::minimumSizeHint() const
+{
+ int h = fontMetrics().height();
+ if (h < 10)
+ h = 10;
+ int f = 2 * frameWidth();
+ return QSize((6 * h) + f, (4 * h) + f);
+}
+
+
+/*!
+ \reimp
+
+ (Implemented to get rid of a compiler warning.)
+*/
+void Q3ScrollView::drawContents(QPainter *)
+{
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*!
+ \internal
+*/
+void Q3ScrollView::startDragAutoScroll()
+{
+ if (!d->autoscroll_timer.isActive()) {
+ d->autoscroll_time = initialScrollTime;
+ d->autoscroll_accel = initialScrollAccel;
+ d->autoscroll_timer.start(d->autoscroll_time);
+ }
+}
+
+
+/*!
+ \internal
+*/
+void Q3ScrollView::stopDragAutoScroll()
+{
+ d->autoscroll_timer.stop();
+}
+
+
+/*!
+ \internal
+*/
+void Q3ScrollView::doDragAutoScroll()
+{
+ QPoint p = d->viewport->mapFromGlobal(QCursor::pos());
+
+ if (d->autoscroll_accel-- <= 0 && d->autoscroll_time) {
+ d->autoscroll_accel = initialScrollAccel;
+ d->autoscroll_time--;
+ d->autoscroll_timer.start(d->autoscroll_time);
+ }
+ int l = QMAX(1, (initialScrollTime- d->autoscroll_time));
+
+ int dx = 0, dy = 0;
+ if (p.y() < autoscroll_margin) {
+ dy = -l;
+ } else if (p.y() > visibleHeight() - autoscroll_margin) {
+ dy = +l;
+ }
+ if (p.x() < autoscroll_margin) {
+ dx = -l;
+ } else if (p.x() > visibleWidth() - autoscroll_margin) {
+ dx = +l;
+ }
+ if (dx || dy) {
+ scrollBy(dx,dy);
+ } else {
+ stopDragAutoScroll();
+ }
+}
+
+
+/*!
+ \property Q3ScrollView::dragAutoScroll
+ \brief whether autoscrolling in drag move events is enabled
+
+ If this property is set to true (the default), the Q3ScrollView
+ automatically scrolls the contents in drag move events if the user
+ moves the cursor close to a border of the view. Of course this
+ works only if the viewport accepts drops. Specifying false
+ disables this autoscroll feature.
+*/
+
+void Q3ScrollView::setDragAutoScroll(bool b)
+{
+ d->drag_autoscroll = b;
+}
+
+bool Q3ScrollView::dragAutoScroll() const
+{
+ return d->drag_autoscroll;
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+/*!\internal
+ */
+void Q3ScrollView::setCachedSizeHint(const QSize &sh) const
+{
+ if (isVisible() && !d->cachedSizeHint.isValid())
+ d->cachedSizeHint = sh;
+}
+
+/*!\internal
+ */
+void Q3ScrollView::disableSizeHintCaching()
+{
+ d->use_cached_size_hint = false;
+}
+
+/*!\internal
+ */
+QSize Q3ScrollView::cachedSizeHint() const
+{
+ return d->use_cached_size_hint ? d->cachedSizeHint : QSize();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SCROLLVIEW
diff --git a/src/qt3support/widgets/q3scrollview.h b/src/qt3support/widgets/q3scrollview.h
new file mode 100644
index 0000000..14c2720
--- /dev/null
+++ b/src/qt3support/widgets/q3scrollview.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3SCROLLVIEW_H
+#define Q3SCROLLVIEW_H
+
+#include <Qt3Support/q3frame.h>
+#include <QtGui/qscrollbar.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q3ScrollViewData;
+
+class Q_COMPAT_EXPORT Q3ScrollView : public Q3Frame
+{
+ Q_OBJECT
+ Q_ENUMS( ResizePolicy ScrollBarMode )
+ Q_PROPERTY( ResizePolicy resizePolicy READ resizePolicy WRITE setResizePolicy )
+ Q_PROPERTY( ScrollBarMode vScrollBarMode READ vScrollBarMode WRITE setVScrollBarMode )
+ Q_PROPERTY( ScrollBarMode hScrollBarMode READ hScrollBarMode WRITE setHScrollBarMode )
+ Q_PROPERTY( int visibleWidth READ visibleWidth )
+ Q_PROPERTY( int visibleHeight READ visibleHeight )
+ Q_PROPERTY( int contentsWidth READ contentsWidth )
+ Q_PROPERTY( int contentsHeight READ contentsHeight )
+ Q_PROPERTY( int contentsX READ contentsX )
+ Q_PROPERTY( int contentsY READ contentsY )
+ Q_PROPERTY( bool dragAutoScroll READ dragAutoScroll WRITE setDragAutoScroll )
+
+public:
+ Q3ScrollView(QWidget* parent=0, const char* name=0, Qt::WindowFlags f=0);
+ ~Q3ScrollView();
+
+ enum ResizePolicy { Default, Manual, AutoOne, AutoOneFit };
+ virtual void setResizePolicy( ResizePolicy );
+ ResizePolicy resizePolicy() const;
+
+ void styleChange( QStyle & );
+ void removeChild(QWidget* child);
+ virtual void addChild( QWidget* child, int x=0, int y=0 );
+ virtual void moveChild( QWidget* child, int x, int y );
+ int childX(QWidget* child);
+ int childY(QWidget* child);
+ bool childIsVisible(QWidget* child) { return child->isVisible(); } // obsolete functions
+ void showChild(QWidget* child, bool yes=true) { child->setVisible(yes); }
+
+ enum ScrollBarMode { Auto, AlwaysOff, AlwaysOn };
+
+ ScrollBarMode vScrollBarMode() const;
+ virtual void setVScrollBarMode( ScrollBarMode );
+
+ ScrollBarMode hScrollBarMode() const;
+ virtual void setHScrollBarMode( ScrollBarMode );
+
+ QWidget* cornerWidget() const;
+ virtual void setCornerWidget(QWidget*);
+
+ // ### 4.0: Consider providing a factory function for scrollbars
+ // (e.g. make the two following functions virtual)
+ QScrollBar* horizontalScrollBar() const;
+ QScrollBar* verticalScrollBar() const;
+ QWidget* viewport() const;
+ QWidget* clipper() const;
+
+ int visibleWidth() const;
+ int visibleHeight() const;
+
+ int contentsWidth() const;
+ int contentsHeight() const;
+ int contentsX() const;
+ int contentsY() const;
+
+ void resize( int w, int h );
+ void resize( const QSize& );
+ void setVisible(bool visible);
+
+ void updateContents( int x, int y, int w, int h );
+ void updateContents( const QRect& r );
+ void updateContents();
+ void repaintContents( int x, int y, int w, int h, bool erase=true );
+ void repaintContents( const QRect& r, bool erase=true );
+ void repaintContents( bool erase=true );
+ void contentsToViewport( int x, int y, int& vx, int& vy ) const;
+ void viewportToContents( int vx, int vy, int& x, int& y ) const;
+ QPoint contentsToViewport( const QPoint& ) const;
+ QPoint viewportToContents( const QPoint& ) const;
+ void enableClipper( bool y );
+
+ void setStaticBackground( bool y );
+ bool hasStaticBackground() const;
+
+ QSize viewportSize( int, int ) const;
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ void removeChild(QObject* child);
+
+ bool isHorizontalSliderPressed();
+ bool isVerticalSliderPressed();
+
+ virtual void setDragAutoScroll( bool b );
+ bool dragAutoScroll() const;
+
+Q_SIGNALS:
+ void contentsMoving(int x, int y);
+ void horizontalSliderPressed();
+ void horizontalSliderReleased();
+ void verticalSliderPressed();
+ void verticalSliderReleased();
+
+public Q_SLOTS:
+ virtual void resizeContents( int w, int h );
+ void scrollBy( int dx, int dy );
+ virtual void setContentsPos( int x, int y );
+ void ensureVisible(int x, int y);
+ void ensureVisible(int x, int y, int xmargin, int ymargin);
+ void center(int x, int y);
+ void center(int x, int y, float xmargin, float ymargin);
+
+ void updateScrollBars(); // ### virtual in 4.0
+ void setEnabled( bool enable );
+
+protected:
+ virtual void drawContents(QPainter*, int cx, int cy, int cw, int ch);
+ virtual void drawContentsOffset(QPainter*, int ox, int oy,
+ int cx, int cy, int cw, int ch);
+
+
+ virtual void contentsMousePressEvent( QMouseEvent* );
+ virtual void contentsMouseReleaseEvent( QMouseEvent* );
+ virtual void contentsMouseDoubleClickEvent( QMouseEvent* );
+ virtual void contentsMouseMoveEvent( QMouseEvent* );
+ virtual void contentsDragEnterEvent( QDragEnterEvent * );
+ virtual void contentsDragMoveEvent( QDragMoveEvent * );
+ virtual void contentsDragLeaveEvent( QDragLeaveEvent * );
+ virtual void contentsDropEvent( QDropEvent * );
+ virtual void contentsWheelEvent( QWheelEvent * );
+ virtual void contentsContextMenuEvent( QContextMenuEvent * );
+
+
+ virtual void viewportPaintEvent( QPaintEvent* );
+ virtual void viewportResizeEvent( QResizeEvent* );
+ virtual void viewportMousePressEvent( QMouseEvent* );
+ virtual void viewportMouseReleaseEvent( QMouseEvent* );
+ virtual void viewportMouseDoubleClickEvent( QMouseEvent* );
+ virtual void viewportMouseMoveEvent( QMouseEvent* );
+ virtual void viewportDragEnterEvent( QDragEnterEvent * );
+ virtual void viewportDragMoveEvent( QDragMoveEvent * );
+ virtual void viewportDragLeaveEvent( QDragLeaveEvent * );
+ virtual void viewportDropEvent( QDropEvent * );
+ virtual void viewportWheelEvent( QWheelEvent * );
+ virtual void viewportContextMenuEvent( QContextMenuEvent * );
+
+ void frameChanged();
+
+public:
+ virtual void setMargins(int left, int top, int right, int bottom);
+ int leftMargin() const;
+ int topMargin() const;
+ int rightMargin() const;
+ int bottomMargin() const;
+protected:
+
+ bool focusNextPrevChild( bool next );
+
+ virtual void setHBarGeometry(QScrollBar& hbar, int x, int y, int w, int h);
+ virtual void setVBarGeometry(QScrollBar& vbar, int x, int y, int w, int h);
+
+ void resizeEvent(QResizeEvent*);
+ void mousePressEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void mouseDoubleClickEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void wheelEvent( QWheelEvent * );
+ void contextMenuEvent( QContextMenuEvent * );
+ bool eventFilter( QObject *, QEvent *e );
+
+ void setCachedSizeHint( const QSize &sh ) const;
+ QSize cachedSizeHint() const;
+ void fontChange( const QFont & );
+
+private:
+ void drawContents( QPainter* );
+ void moveContents(int x, int y);
+
+ Q3ScrollViewData* d;
+
+private Q_SLOTS:
+ void hslide(int);
+ void vslide(int);
+ void hbarIsPressed();
+ void hbarIsReleased();
+ void vbarIsPressed();
+ void vbarIsReleased();
+ void doDragAutoScroll();
+ void startDragAutoScroll();
+ void stopDragAutoScroll();
+
+private: // Disabled copy constructor and operator=
+ Q_DISABLE_COPY(Q3ScrollView)
+ void changeFrameRect(const QRect&);
+
+public:
+ void disableSizeHintCaching();
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3SCROLLVIEW_H
diff --git a/src/qt3support/widgets/q3spinwidget.cpp b/src/qt3support/widgets/q3spinwidget.cpp
new file mode 100644
index 0000000..8a6152b
--- /dev/null
+++ b/src/qt3support/widgets/q3spinwidget.cpp
@@ -0,0 +1,473 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3rangecontrol.h"
+
+#ifndef QT_NO_SPINWIDGET
+
+#include "qabstractspinbox.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qrect.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3SpinWidgetPrivate
+{
+public:
+ Q3SpinWidgetPrivate()
+ : upEnabled(true),
+ downEnabled(true),
+ theButton(0),
+ buttonDown(0),
+ timerUp(0),
+ bsyms(Q3SpinWidget::UpDownArrows),
+ ed (0) {}
+ uint upEnabled :1;
+ uint downEnabled :1;
+ uint theButton :2;
+ uint buttonDown :2;
+ uint timerUp : 1;
+ QRect up;
+ QRect down;
+ QTimer auRepTimer;
+ Q3SpinWidget::ButtonSymbols bsyms;
+ QWidget *ed;
+ void startTimer(int msec) { auRepTimer.start(msec, true); }
+ void startTimer(bool up, int msec) { timerUp = up; startTimer(msec); }
+ void stopTimer() { auRepTimer.stop(); }
+};
+
+/*!
+ \class Q3SpinWidget
+ \brief The Q3SpinWidget class is an internal range control related class.
+
+ \internal
+
+ Constructs an empty range control widget with parent \a parent
+ called \a name.
+
+*/
+
+Q3SpinWidget::Q3SpinWidget(QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ d = new Q3SpinWidgetPrivate();
+ connect(&d->auRepTimer, SIGNAL(timeout()), this, SLOT(timerDone()));
+ setFocusPolicy(Qt::StrongFocus);
+
+ arrange();
+ updateDisplay();
+}
+
+
+/*! Destroys the object and frees any allocated resources.
+
+*/
+
+Q3SpinWidget::~Q3SpinWidget()
+{
+ delete d;
+}
+
+/*! */
+QWidget * Q3SpinWidget::editWidget()
+{
+ return d->ed;
+}
+
+/*!
+ Sets the editing widget to \a w.
+*/
+void Q3SpinWidget::setEditWidget(QWidget * w)
+{
+ if (w) {
+ if (w->parentWidget() != this)
+ w->setParent(this);
+ setFocusProxy(w);
+ }
+ d->ed = w;
+ arrange();
+ updateDisplay();
+}
+
+/*! \reimp
+
+*/
+
+void Q3SpinWidget::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton) {
+ d->stopTimer();
+ d->buttonDown = 0;
+ d->theButton = 0;
+ repaint(d->down.united(d->up));
+ return;
+ }
+
+ uint oldButtonDown = d->buttonDown;
+
+ if (d->down.contains(e->pos()) && d->downEnabled)
+ d->buttonDown = 1;
+ else if (d->up.contains(e->pos()) && d->upEnabled)
+ d->buttonDown = 2;
+ else
+ d->buttonDown = 0;
+
+ d->theButton = d->buttonDown;
+ if (oldButtonDown != d->buttonDown) {
+ if (!d->buttonDown) {
+ repaint(d->down.united(d->up));
+ } else if (d->buttonDown & 1) {
+ repaint(d->down);
+ stepDown();
+ d->startTimer(false, 300);
+ } else if (d->buttonDown & 2) {
+ repaint(d->up);
+ stepUp();
+ d->startTimer(true, 300);
+ }
+ }
+
+ if (!oldButtonDown && !d->buttonDown)
+ e->ignore();
+
+}
+
+static QStyleOptionSpinBox getStyleOption(const Q3SpinWidget *spin)
+{
+ QStyleOptionSpinBox opt;
+ opt.init(spin);
+ opt.frame = true;
+ opt.subControls = 0;
+ opt.buttonSymbols = (QAbstractSpinBox::ButtonSymbols)spin->buttonSymbols();
+ opt.stepEnabled = 0;
+ if (spin->isUpEnabled())
+ opt.stepEnabled |= QAbstractSpinBox::StepUpEnabled;
+ if (spin->isDownEnabled())
+ opt.stepEnabled |= QAbstractSpinBox::StepDownEnabled;
+ opt.activeSubControls = 0;
+ return opt;
+}
+
+/*!
+
+*/
+
+void Q3SpinWidget::arrange()
+{
+ QStyleOptionSpinBox opt = getStyleOption(this);
+ d->up = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp, this);
+ d->down = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxDown, this);
+ if (d->ed) {
+ QRect r = style()->subControlRect(QStyle::CC_SpinBox, &opt,
+ QStyle::SC_SpinBoxEditField, this);
+ d->ed->setGeometry(r);
+ }
+}
+
+/*!
+
+*/
+
+void Q3SpinWidget::stepUp()
+{
+ emit stepUpPressed();
+}
+
+void Q3SpinWidget::resizeEvent(QResizeEvent*)
+{
+ arrange();
+}
+
+/*!
+
+*/
+
+void Q3SpinWidget::stepDown()
+{
+ emit stepDownPressed();
+}
+
+
+void Q3SpinWidget::timerDone()
+{
+ // we use a double timer to make it possible for users to do
+ // something with 0-timer on valueChanged.
+ QTimer::singleShot(1, this, SLOT(timerDoneEx()));
+}
+
+void Q3SpinWidget::timerDoneEx()
+{
+ if (!d->buttonDown)
+ return;
+ if (d->timerUp)
+ stepUp();
+ else
+ stepDown();
+ d->startTimer(100);
+}
+
+
+/*!
+ The event is passed in \a e.
+*/
+
+void Q3SpinWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ uint oldButtonDown = d->theButton;
+ d->theButton = 0;
+ if (oldButtonDown != d->theButton) {
+ if (oldButtonDown & 1)
+ repaint(d->down);
+ else if (oldButtonDown & 2)
+ repaint(d->up);
+ }
+ d->stopTimer();
+ d->buttonDown = 0;
+
+ if (!oldButtonDown && !d->buttonDown)
+ e->ignore();
+}
+
+
+/*!
+ The event is passed in \a e.
+*/
+
+void Q3SpinWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!(e->state() & Qt::LeftButton))
+ return;
+
+ uint oldButtonDown = d->theButton;
+ if (oldButtonDown & 1 && !d->down.contains(e->pos())) {
+ d->stopTimer();
+ d->theButton = 0;
+ repaint(d->down);
+ } else if (oldButtonDown & 2 && !d->up.contains(e->pos())) {
+ d->stopTimer();
+ d->theButton = 0;
+ repaint(d->up);
+ } else if (!oldButtonDown && d->up.contains(e->pos()) && d->buttonDown & 2) {
+ d->startTimer(500);
+ d->theButton = 2;
+ repaint(d->up);
+ } else if (!oldButtonDown && d->down.contains(e->pos()) && d->buttonDown & 1) {
+ d->startTimer(500);
+ d->theButton = 1;
+ repaint(d->down);
+ }
+
+ if (!oldButtonDown && !d->buttonDown)
+ e->ignore();
+}
+
+
+/*!
+ The event is passed in \a e.
+*/
+#ifndef QT_NO_WHEELEVENT
+void Q3SpinWidget::wheelEvent(QWheelEvent *e)
+{
+ e->accept();
+ static float offset = 0;
+ static Q3SpinWidget* offset_owner = 0;
+ if (offset_owner != this) {
+ offset_owner = this;
+ offset = 0;
+ }
+ offset += -e->delta()/120;
+ if (QABS(offset) < 1)
+ return;
+ int ioff = int(offset);
+ int i;
+ for(i=0; i < QABS(ioff); i++)
+ offset > 0 ? stepDown() : stepUp();
+ offset -= ioff;
+}
+#endif
+
+/*!
+
+*/
+void Q3SpinWidget::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ QStyleOptionSpinBox opt = getStyleOption(this);
+
+ if (d->theButton & 1)
+ opt.activeSubControls = QStyle::SC_SpinBoxDown;
+ else if (d->theButton & 2)
+ opt.activeSubControls = QStyle::SC_SpinBoxUp;
+ else
+ opt.activeSubControls = QStyle::SC_None;
+ opt.rect = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxFrame, this);
+ opt.subControls = QStyle::SC_All;
+ style()->drawComplexControl(QStyle::CC_SpinBox, &opt, &p, this);
+}
+
+
+// ### What does the QEvent passed in contain? It used to be the previous style.
+/*!
+ The previous style is passed in \a ev.
+*/
+void Q3SpinWidget::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::StyleChange) {
+ arrange();
+ } else if(ev->type() == QEvent::ActivationChange) {
+ if (!isActiveWindow() && d->buttonDown) { //was active, but lost focus
+ d->stopTimer();
+ d->buttonDown = 0;
+ d->theButton = 0;
+ }
+ } else if(ev->type() == QEvent::EnabledChange) {
+ d->upEnabled = isEnabled();
+ d->downEnabled = isEnabled();
+ updateDisplay();
+ }
+ QWidget::changeEvent(ev);
+}
+
+/*!
+*/
+
+QRect Q3SpinWidget::upRect() const
+{
+ return d->up;
+}
+
+/*!
+*/
+
+QRect Q3SpinWidget::downRect() const
+{
+ return d->down;
+}
+
+/*!
+*/
+
+void Q3SpinWidget::updateDisplay()
+{
+ if (!isEnabled()) {
+ d->upEnabled = false;
+ d->downEnabled = false;
+ }
+ if (d->theButton & 1 && (d->downEnabled) == 0) {
+ d->theButton &= ~1;
+ d->buttonDown &= ~1;
+ }
+
+ if (d->theButton & 2 && (d->upEnabled) == 0) {
+ d->theButton &= ~2;
+ d->buttonDown &= ~2;
+ }
+ repaint();
+}
+
+/*!
+ Sets up-enabled to \a on.
+*/
+
+void Q3SpinWidget::setUpEnabled(bool on)
+{
+ if ((bool)d->upEnabled != on) {
+ d->upEnabled = on;
+ updateDisplay();
+ }
+}
+
+/*!
+*/
+
+bool Q3SpinWidget::isUpEnabled() const
+{
+ return d->upEnabled;
+}
+
+/*!
+ Sets down-enabled to \a on.
+*/
+
+void Q3SpinWidget::setDownEnabled(bool on)
+{
+ if ((bool)d->downEnabled != on) {
+ d->downEnabled = on;
+ updateDisplay();
+ }
+}
+
+/*!
+*/
+
+bool Q3SpinWidget::isDownEnabled() const
+{
+ return d->downEnabled;
+}
+
+/*!
+ Sets the button symbol to \a bs.
+*/
+
+void Q3SpinWidget::setButtonSymbols(ButtonSymbols bs)
+{
+ d->bsyms = bs;
+}
+
+/*!
+*/
+
+Q3SpinWidget::ButtonSymbols Q3SpinWidget::buttonSymbols() const
+{
+ return d->bsyms;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qt3support/widgets/q3titlebar.cpp b/src/qt3support/widgets/q3titlebar.cpp
new file mode 100644
index 0000000..df53364
--- /dev/null
+++ b/src/qt3support/widgets/q3titlebar.cpp
@@ -0,0 +1,645 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "qplatformdefs.h"
+
+#ifndef QT_NO_TITLEBAR
+
+#include "qapplication.h"
+#include "qcursor.h"
+#include "qdatetime.h"
+#include "qevent.h"
+#include "qimage.h"
+#include "qpainter.h"
+#include "qiodevice.h"
+#include "qpixmap.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+#include "qtooltip.h"
+#include "qdebug.h"
+#if defined(Q_WS_WIN)
+#include "qt_windows.h"
+#endif
+
+#include "private/qapplication_p.h"
+#include "private/q3titlebar_p.h"
+#include "private/qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3TitleBarPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(Q3TitleBar)
+public:
+ Q3TitleBarPrivate()
+ : toolTip(0), act(0), window(0), movable(1), pressed(0), autoraise(0), inevent(0)
+ {
+ }
+
+ Qt::WindowFlags flags;
+ QStyle::SubControl buttonDown;
+ QPoint moveOffset;
+ QToolTip *toolTip;
+ bool act :1;
+ QWidget* window;
+ bool movable :1;
+ bool pressed :1;
+ bool autoraise :1;
+ bool inevent : 1;
+
+ int titleBarState() const;
+ QStyleOptionTitleBar getStyleOption() const;
+ void readColors();
+};
+
+inline int Q3TitleBarPrivate::titleBarState() const
+{
+ uint state = window ? window->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
+ state |= uint(act ? QStyle::State_Active : QStyle::State_None);
+ return (int)state;
+}
+
+QStyleOptionTitleBar Q3TitleBarPrivate::getStyleOption() const
+{
+ Q_Q(const Q3TitleBar);
+ QStyleOptionTitleBar opt;
+ opt.init(q);
+ opt.text = q->windowTitle();
+ //################
+ QIcon icon = q->windowIcon();
+ QSize s = icon.actualSize(QSize(64, 64));
+ opt.icon = icon.pixmap(s);
+ opt.subControls = QStyle::SC_All;
+ opt.activeSubControls = QStyle::SC_None;
+ opt.titleBarState = titleBarState();
+ opt.titleBarFlags = flags;
+ return opt;
+}
+
+Q3TitleBar::Q3TitleBar(QWidget *w, QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*new Q3TitleBarPrivate, parent, Qt::WStyle_Customize | Qt::WStyle_NoBorder)
+{
+ Q_D(Q3TitleBar);
+ if (f == 0 && w)
+ f = w->windowFlags();
+ d->flags = f;
+ d->window = w;
+ d->buttonDown = QStyle::SC_None;
+ d->act = 0;
+ if (w) {
+ if (w->minimumSize() == w->maximumSize())
+ d->flags &= ~Qt::WindowMaximizeButtonHint;
+ setWindowTitle(w->windowTitle());
+ }
+
+ d->readColors();
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ setMouseTracking(true);
+ setAutoRaise(style()->styleHint(QStyle::SH_TitleBar_AutoRaise, 0, this));
+}
+
+void Q3TitleBar::setFakeWindowFlags(Qt::WindowFlags f)
+{
+ Q_D(Q3TitleBar);
+ d->flags = f;
+}
+
+Qt::WindowFlags Q3TitleBar::fakeWindowFlags() const
+{
+ Q_D(const Q3TitleBar);
+ return d->flags;
+}
+
+Q3TitleBar::~Q3TitleBar()
+{
+}
+
+QStyleOptionTitleBar Q3TitleBar::getStyleOption() const
+{
+ return d_func()->getStyleOption();
+}
+
+#ifdef Q_WS_WIN
+static inline QRgb colorref2qrgb(COLORREF col)
+{
+ return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
+}
+#endif
+
+void Q3TitleBarPrivate::readColors()
+{
+ Q_Q(Q3TitleBar);
+ QPalette pal = q->palette();
+
+ bool colorsInitialized = false;
+
+#ifdef Q_WS_WIN // ask system properties on windows
+#ifndef SPI_GETGRADIENTCAPTIONS
+#define SPI_GETGRADIENTCAPTIONS 0x1008
+#endif
+#ifndef COLOR_GRADIENTACTIVECAPTION
+#define COLOR_GRADIENTACTIVECAPTION 27
+#endif
+#ifndef COLOR_GRADIENTINACTIVECAPTION
+#define COLOR_GRADIENTINACTIVECAPTION 28
+#endif
+ if (QApplication::desktopSettingsAware()) {
+ pal.setColor(QPalette::Active, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)));
+ pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
+ pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ colorsInitialized = true;
+ BOOL gradient;
+ QT_WA({
+ SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
+ } , {
+ SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
+ });
+ if (gradient) {
+ pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
+ pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
+ } else {
+ pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
+ pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
+ }
+ }
+ }
+#endif // Q_WS_WIN
+ if (!colorsInitialized) {
+ pal.setColor(QPalette::Active, QPalette::Highlight,
+ pal.color(QPalette::Active, QPalette::Highlight));
+ pal.setColor(QPalette::Active, QPalette::Base,
+ pal.color(QPalette::Active, QPalette::Highlight));
+ pal.setColor(QPalette::Inactive, QPalette::Highlight,
+ pal.color(QPalette::Inactive, QPalette::Dark));
+ pal.setColor(QPalette::Inactive, QPalette::Base,
+ pal.color(QPalette::Inactive, QPalette::Dark));
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ pal.color(QPalette::Inactive, QPalette::Window));
+ }
+
+ q->setPalette(pal);
+ q->setActive(act);
+}
+
+void Q3TitleBar::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::ModifiedChange)
+ update();
+ QWidget::changeEvent(ev);
+}
+
+void Q3TitleBar::mousePressEvent(QMouseEvent *e)
+{
+ Q_D(Q3TitleBar);
+ if (!d->act)
+ emit doActivate();
+ if (e->button() == Qt::LeftButton) {
+ d->pressed = true;
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
+ e->pos(), this);
+ switch (ctrl) {
+ case QStyle::SC_TitleBarSysMenu:
+ if (d->flags & Qt::WindowSystemMenuHint) {
+ d->buttonDown = QStyle::SC_None;
+ static QTime *t = 0;
+ static Q3TitleBar *tc = 0;
+ if (!t)
+ t = new QTime;
+ if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
+ emit showOperationMenu();
+ t->start();
+ tc = this;
+ } else {
+ tc = 0;
+ emit doClose();
+ return;
+ }
+ }
+ break;
+
+ case QStyle::SC_TitleBarShadeButton:
+ case QStyle::SC_TitleBarUnshadeButton:
+ if (d->flags & Qt::WindowShadeButtonHint)
+ d->buttonDown = ctrl;
+ break;
+
+ case QStyle::SC_TitleBarNormalButton:
+ if (d->flags & Qt::WindowMinMaxButtonsHint)
+ d->buttonDown = ctrl;
+ break;
+
+ case QStyle::SC_TitleBarMinButton:
+ if (d->flags & Qt::WindowMinimizeButtonHint)
+ d->buttonDown = ctrl;
+ break;
+
+ case QStyle::SC_TitleBarMaxButton:
+ if (d->flags & Qt::WindowMaximizeButtonHint)
+ d->buttonDown = ctrl;
+ break;
+
+ case QStyle::SC_TitleBarCloseButton:
+ if (d->flags & Qt::WindowSystemMenuHint)
+ d->buttonDown = ctrl;
+ break;
+
+ case QStyle::SC_TitleBarLabel:
+ d->buttonDown = ctrl;
+ d->moveOffset = mapToParent(e->pos());
+ break;
+
+ default:
+ break;
+ }
+ repaint();
+ } else {
+ d->pressed = false;
+ }
+}
+
+void Q3TitleBar::contextMenuEvent(QContextMenuEvent *e)
+{
+ Q_D(Q3TitleBar);
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(),
+ this);
+ if(ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu) {
+ e->accept();
+ emit popupOperationMenu(e->globalPos());
+ } else {
+ e->ignore();
+ }
+}
+
+void Q3TitleBar::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_D(Q3TitleBar);
+ if (e->button() == Qt::LeftButton && d->pressed) {
+ e->accept();
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
+ e->pos(), this);
+ d->pressed = false;
+ if (ctrl == d->buttonDown) {
+ d->buttonDown = QStyle::SC_None;
+ repaint();
+ switch(ctrl) {
+ case QStyle::SC_TitleBarShadeButton:
+ case QStyle::SC_TitleBarUnshadeButton:
+ if(d->flags & Qt::WindowShadeButtonHint)
+ emit doShade();
+ break;
+
+ case QStyle::SC_TitleBarNormalButton:
+ if(d->flags & Qt::WindowMaximizeButtonHint)
+ emit doNormal();
+ break;
+
+ case QStyle::SC_TitleBarMinButton:
+ if(d->flags & Qt::WindowMinimizeButtonHint) {
+ if (d->window && d->window->isMinimized())
+ emit doNormal();
+ else
+ emit doMinimize();
+ }
+ break;
+
+ case QStyle::SC_TitleBarMaxButton:
+ if(d->flags & Qt::WindowMaximizeButtonHint) {
+ if(d->window && d->window->isMaximized())
+ emit doNormal();
+ else
+ emit doMaximize();
+ }
+ break;
+
+ case QStyle::SC_TitleBarCloseButton:
+ if(d->flags & Qt::WindowSystemMenuHint) {
+ d->buttonDown = QStyle::SC_None;
+ repaint();
+ emit doClose();
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else {
+ e->ignore();
+ }
+}
+
+void Q3TitleBar::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(Q3TitleBar);
+ e->accept();
+ switch (d->buttonDown) {
+ case QStyle::SC_None:
+ if(autoRaise())
+ repaint();
+ break;
+ case QStyle::SC_TitleBarSysMenu:
+ break;
+ case QStyle::SC_TitleBarShadeButton:
+ case QStyle::SC_TitleBarUnshadeButton:
+ case QStyle::SC_TitleBarNormalButton:
+ case QStyle::SC_TitleBarMinButton:
+ case QStyle::SC_TitleBarMaxButton:
+ case QStyle::SC_TitleBarCloseButton:
+ {
+ QStyle::SubControl last_ctrl = d->buttonDown;
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ d->buttonDown = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(), this);
+ if (d->buttonDown != last_ctrl)
+ d->buttonDown = QStyle::SC_None;
+ repaint();
+ d->buttonDown = last_ctrl;
+ }
+ break;
+
+ case QStyle::SC_TitleBarLabel:
+ if (d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed) {
+ if ((d->moveOffset - mapToParent(e->pos())).manhattanLength() >= 4) {
+ QPoint p = mapFromGlobal(e->globalPos());
+
+ QWidget *parent = d->window ? d->window->parentWidget() : 0;
+ if(parent && parent->inherits("Q3WorkspaceChild")) {
+ QWidget *workspace = parent->parentWidget();
+ p = workspace->mapFromGlobal(e->globalPos());
+ if (!workspace->rect().contains(p)) {
+ if (p.x() < 0)
+ p.rx() = 0;
+ if (p.y() < 0)
+ p.ry() = 0;
+ if (p.x() > workspace->width())
+ p.rx() = workspace->width();
+ if (p.y() > workspace->height())
+ p.ry() = workspace->height();
+ }
+ }
+
+ QPoint pp = p - d->moveOffset;
+ if (!parentWidget()->isMaximized())
+ parentWidget()->move(pp);
+ }
+ } else {
+ QStyle::SubControl last_ctrl = d->buttonDown;
+ d->buttonDown = QStyle::SC_None;
+ if(d->buttonDown != last_ctrl)
+ repaint();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Q3TitleBar::resizeEvent(QResizeEvent *r)
+{
+ QWidget::resizeEvent(r);
+ cutText();
+}
+
+bool Q3TitleBar::isTool() const
+{
+ return (d_func()->flags & Qt::WindowType_Mask) == Qt::Tool;
+}
+
+void Q3TitleBar::paintEvent(QPaintEvent *)
+{
+ Q_D(Q3TitleBar);
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ opt.subControls = QStyle::SC_TitleBarLabel;
+ opt.activeSubControls = d->buttonDown;
+ if (d->flags & Qt::WindowSystemMenuHint) {
+ opt.subControls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
+ if (d->window && (d->flags & Qt::WindowShadeButtonHint)) {
+ if (d->window->isMinimized())
+ opt.subControls |= QStyle::SC_TitleBarUnshadeButton;
+ else
+ opt.subControls |= QStyle::SC_TitleBarShadeButton;
+ }
+ if (d->window && (d->flags & Qt::WindowMinMaxButtonsHint)) {
+ if(d->window && d->window->isMinimized())
+ opt.subControls |= QStyle::SC_TitleBarNormalButton;
+ else
+ opt.subControls |= QStyle::SC_TitleBarMinButton;
+ }
+ if (d->window && (d->flags & Qt::WindowMaximizeButtonHint) && !d->window->isMaximized())
+ opt.subControls |= QStyle::SC_TitleBarMaxButton;
+ }
+ QStyle::SubControl under_mouse = QStyle::SC_None;
+
+ if (underMouse()) {
+ under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
+ mapFromGlobal(QCursor::pos()), this);
+ opt.activeSubControls |= under_mouse;
+ if (d->pressed)
+ opt.state |= QStyle::State_Sunken;
+ else if(autoRaise())
+ opt.state |= QStyle::State_MouseOver;
+ }
+
+ opt.palette.setCurrentColorGroup(usesActiveColor() ? QPalette::Active : QPalette::Inactive);
+
+ QPainter p(this);
+ if (!windowTitle().isEmpty())
+ opt.titleBarFlags |= Qt::WindowTitleHint;
+ style()->drawComplexControl(QStyle::CC_TitleBar, &opt, &p, this);
+}
+
+void Q3TitleBar::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ Q_D(Q3TitleBar);
+ if (e->button() != Qt::LeftButton) {
+ e->ignore();
+ return;
+ }
+ e->accept();
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ switch (style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(), this)) {
+ case QStyle::SC_TitleBarLabel:
+ emit doubleClicked();
+ break;
+
+ case QStyle::SC_TitleBarSysMenu:
+ if (d->flags & Qt::WStyle_SysMenu)
+ emit doClose();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Q3TitleBar::cutText()
+{
+ Q_D(Q3TitleBar);
+ QFontMetrics fm(font());
+ QStyleOptionTitleBar opt = d->getStyleOption();
+ int maxw = style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarLabel,
+ this).width();
+ if (!d->window)
+ return;
+
+ QString txt = d->window->windowTitle();
+ if (style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, this) && d->window
+ && d->window->isWindowModified())
+ txt += QLatin1String(" *");
+
+ QString cuttext = txt;
+ if (fm.width(txt + QLatin1Char('m')) > maxw) {
+ int i = txt.length();
+ int dotlength = fm.width(QLatin1String("..."));
+ while (i>0 && fm.width(txt.left(i)) + dotlength > maxw)
+ i--;
+ if(i != (int)txt.length())
+ cuttext = txt.left(i) + QLatin1String("...");
+ }
+
+ setWindowTitle(cuttext);
+}
+
+
+void Q3TitleBar::leaveEvent(QEvent *)
+{
+ if(autoRaise() && !d_func()->pressed)
+ repaint();
+}
+
+void Q3TitleBar::enterEvent(QEvent *)
+{
+ if(autoRaise() && !d_func()->pressed)
+ repaint();
+ QEvent e(QEvent::Leave);
+ QApplication::sendEvent(parentWidget(), &e);
+}
+
+void Q3TitleBar::setActive(bool active)
+{
+ Q_D(Q3TitleBar);
+ if (d->act == active)
+ return ;
+
+ d->act = active;
+ update();
+}
+
+bool Q3TitleBar::isActive() const
+{
+ return d_func()->act;
+}
+
+bool Q3TitleBar::usesActiveColor() const
+{
+ return (isActive() && isActiveWindow()) ||
+ (!window() && QWidget::window()->isActiveWindow());
+}
+
+QWidget *Q3TitleBar::window() const
+{
+ return d_func()->window;
+}
+
+bool Q3TitleBar::event(QEvent *e)
+{
+ Q_D(Q3TitleBar);
+ if (d->inevent)
+ return QWidget::event(e);
+ d->inevent = true;
+ if (e->type() == QEvent::ApplicationPaletteChange) {
+ d->readColors();
+ return true;
+ } else if (e->type() == QEvent::WindowActivate) {
+ setActive(d->act);
+ } else if (e->type() == QEvent::WindowDeactivate) {
+ bool wasActive = d->act;
+ setActive(false);
+ d->act = wasActive;
+ } else if (e->type() == QEvent::WindowIconChange) {
+ update();
+ } else if (e->type() == QEvent::WindowTitleChange) {
+ cutText();
+ update();
+ }
+
+ d->inevent = false;
+ return QWidget::event(e);
+}
+
+void Q3TitleBar::setMovable(bool b)
+{
+ d_func()->movable = b;
+}
+
+bool Q3TitleBar::isMovable() const
+{
+ return d_func()->movable;
+}
+
+void Q3TitleBar::setAutoRaise(bool b)
+{
+ d_func()->autoraise = b;
+}
+
+bool Q3TitleBar::autoRaise() const
+{
+ return d_func()->autoraise;
+}
+
+QSize Q3TitleBar::sizeHint() const
+{
+ ensurePolished();
+ QStyleOptionTitleBar opt = d_func()->getStyleOption();
+ QRect menur = style()->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarSysMenu, this);
+ return QSize(menur.width(), style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_TITLEBAR
diff --git a/src/qt3support/widgets/q3titlebar_p.h b/src/qt3support/widgets/q3titlebar_p.h
new file mode 100644
index 0000000..fc52f34
--- /dev/null
+++ b/src/qt3support/widgets/q3titlebar_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3TITLEBAR_P_H
+#define Q3TITLEBAR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qwidget.h"
+#include "qstyleoption.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_TITLEBAR)
+
+class QToolTip;
+class Q3TitleBarPrivate;
+class QPixmap;
+
+class Q_COMPAT_EXPORT Q3TitleBar : public QWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3TitleBar)
+ Q_PROPERTY(bool autoRaise READ autoRaise WRITE setAutoRaise)
+ Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
+
+public:
+ Q3TitleBar (QWidget *w, QWidget *parent, Qt::WindowFlags f = 0);
+ ~Q3TitleBar();
+
+ bool isActive() const;
+ bool usesActiveColor() const;
+
+ bool isMovable() const;
+ void setMovable(bool);
+
+ bool autoRaise() const;
+ void setAutoRaise(bool);
+
+ QWidget *window() const;
+ bool isTool() const;
+
+ QSize sizeHint() const;
+ QStyleOptionTitleBar getStyleOption() const;
+
+ // These flags are fake, stored in QTitleBarPrivate. They are not set as the widget's window flags.
+ void setFakeWindowFlags(Qt::WindowFlags f);
+ Qt::WindowFlags fakeWindowFlags() const;
+
+public Q_SLOTS:
+ void setActive(bool);
+
+Q_SIGNALS:
+ void doActivate();
+ void doNormal();
+ void doClose();
+ void doMaximize();
+ void doMinimize();
+ void doShade();
+ void showOperationMenu();
+ void popupOperationMenu(const QPoint&);
+ void doubleClicked();
+
+protected:
+ bool event(QEvent *);
+ void resizeEvent(QResizeEvent *);
+ void contextMenuEvent(QContextMenuEvent *);
+ void changeEvent(QEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void mouseDoubleClickEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void enterEvent(QEvent *e);
+ void leaveEvent(QEvent *e);
+ void paintEvent(QPaintEvent *p);
+
+ virtual void cutText();
+
+private:
+ Q_DISABLE_COPY(Q3TitleBar)
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif //Q3TITLEBAR_P_H
diff --git a/src/qt3support/widgets/q3toolbar.cpp b/src/qt3support/widgets/q3toolbar.cpp
new file mode 100644
index 0000000..dc0a9fd
--- /dev/null
+++ b/src/qt3support/widgets/q3toolbar.cpp
@@ -0,0 +1,840 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3toolbar.h"
+#ifndef QT_NO_TOOLBAR
+
+#include "q3mainwindow.h"
+#include "qapplication.h"
+#include "q3combobox.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qdrawutil.h"
+#include "qevent.h"
+#include "qframe.h"
+#include "qlayout.h"
+#include "qmap.h"
+#include "qpainter.h"
+#include "q3popupmenu.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+#include "qtoolbutton.h"
+#include "qtooltip.h"
+
+QT_BEGIN_NAMESPACE
+
+static const char * const arrow_v_xpm[] = {
+ "7 9 3 1",
+ " c None",
+ ". c #000000",
+ "+ c none",
+ ".+++++.",
+ "..+++..",
+ "+..+..+",
+ "++...++",
+ ".++.++.",
+ "..+++..",
+ "+..+..+",
+ "++...++",
+ "+++.+++"};
+
+static const char * const arrow_h_xpm[] = {
+ "9 7 3 1",
+ " c None",
+ ". c #000000",
+ "+ c none",
+ "..++..+++",
+ "+..++..++",
+ "++..++..+",
+ "+++..++..",
+ "++..++..+",
+ "+..++..++",
+ "..++..+++"};
+
+class Q3ToolBarExtensionWidget;
+
+class Q3ToolBarPrivate
+{
+public:
+ Q3ToolBarPrivate() : moving(false), checkingExtension(false) {
+ }
+
+ bool moving;
+ bool checkingExtension;
+ Q3ToolBarExtensionWidget *extension;
+ Q3PopupMenu *extensionPopup;
+
+ QMap<QAction *, QWidget *> actions;
+};
+
+
+class Q3ToolBarSeparator : public QWidget
+{
+ Q_OBJECT
+public:
+ Q3ToolBarSeparator(Qt::Orientation, Q3ToolBar *parent, const char* name=0);
+
+ QSize sizeHint() const;
+ Qt::Orientation orientation() const { return orient; }
+public slots:
+ void setOrientation(Qt::Orientation);
+protected:
+ void changeEvent(QEvent *);
+ void paintEvent(QPaintEvent *);
+
+private:
+ Qt::Orientation orient;
+};
+
+class Q3ToolBarExtensionWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Q3ToolBarExtensionWidget(QWidget *w);
+ void setOrientation(Qt::Orientation o);
+ QToolButton *button() const { return tb; }
+
+protected:
+ void resizeEvent(QResizeEvent *e) {
+ QWidget::resizeEvent(e);
+ layOut();
+ }
+
+private:
+ void layOut();
+ QToolButton *tb;
+ Qt::Orientation orient;
+
+};
+
+Q3ToolBarExtensionWidget::Q3ToolBarExtensionWidget(QWidget *w)
+ : QWidget(w, "qt_dockwidget_internal")
+{
+ tb = new QToolButton(this, "qt_toolbar_ext_button");
+ tb->setAutoRaise(true);
+ setOrientation(Qt::Horizontal);
+ setAutoFillBackground(true);
+}
+
+void Q3ToolBarExtensionWidget::setOrientation(Qt::Orientation o)
+{
+ orient = o;
+ if (orient == Qt::Horizontal)
+ tb->setIcon(QPixmap((const char **)arrow_h_xpm));
+ else
+ tb->setIcon(QPixmap((const char **)arrow_v_xpm));
+ layOut();
+}
+
+void Q3ToolBarExtensionWidget::layOut()
+{
+ tb->setGeometry(2, 2, width() - 4, height() - 4);
+}
+
+Q3ToolBarSeparator::Q3ToolBarSeparator(Qt::Orientation o , Q3ToolBar *parent,
+ const char* name)
+ : QWidget(parent, name)
+{
+ connect(parent, SIGNAL(orientationChanged(Qt::Orientation)),
+ this, SLOT(setOrientation(Qt::Orientation)));
+ setOrientation(o);
+ setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+}
+
+
+
+void Q3ToolBarSeparator::setOrientation(Qt::Orientation o)
+{
+ orient = o;
+}
+
+void Q3ToolBarSeparator::changeEvent(QEvent *ev)
+{
+ if(ev->type() == QEvent::StyleChange)
+ setOrientation(orient);
+ QWidget::changeEvent(ev);
+}
+
+static QStyleOption getStyleOption(const Q3ToolBarSeparator *tbs)
+{
+ QStyleOption opt(0);
+ opt.rect = tbs->rect();
+ opt.palette = tbs->palette();
+ if (tbs->orientation() == Qt::Horizontal)
+ opt.state = QStyle::State_Horizontal;
+ else
+ opt.state = QStyle::State_None;
+ return opt;
+}
+
+QSize Q3ToolBarSeparator::sizeHint() const
+{
+ QStyleOption opt = getStyleOption(this);
+ int extent = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, this);
+ if (orient == Qt::Horizontal)
+ return QSize(extent, 0);
+ else
+ return QSize(0, extent);
+}
+
+void Q3ToolBarSeparator::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ QStyleOption opt = getStyleOption(this);
+ style()->drawPrimitive(QStyle::PE_Q3DockWindowSeparator, &opt, &p, this);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "q3toolbar.moc"
+QT_END_INCLUDE_NAMESPACE
+
+
+/*!
+ \class Q3ToolBar
+ \brief The Q3ToolBar class provides a movable panel containing
+ widgets such as tool buttons.
+
+ \compat
+
+ A toolbar is a panel that contains a set of controls, usually
+ represented by small icons. It's purpose is to provide quick
+ access to frequently used commands or options. Within a
+ Q3MainWindow the user can drag toolbars within and between the
+ \link Q3DockArea dock areas\endlink. Toolbars can also be dragged
+ out of any dock area to float freely as top-level windows.
+
+ Q3ToolBar is a specialization of QDockWindow, and so provides all
+ the functionality of a QDockWindow.
+
+ To use Q3ToolBar you simply create a Q3ToolBar as a child of a
+ Q3MainWindow, create a number of QToolButton widgets (or other
+ widgets) in left to right (or top to bottom) order and call
+ addSeparator() when you want a separator. When a toolbar is
+ floated the caption used is the label given in the constructor
+ call. This can be changed with setLabel().
+
+ You may use most widgets within a toolbar, with QToolButton and
+ QComboBox being the most common. But note that the toolbar's
+ actions must be \l {Q3Action}s.
+
+ If you create a new widget on an already visible Q3ToolBar, this
+ widget will automatically become visible without needing a show()
+ call. (This differs from every other Qt widget container. We
+ recommend calling show() anyway since we hope to fix this anomaly
+ in a future release.)
+
+ Q3ToolBars, like QDockWindows, are located in \l{Q3DockArea}s or
+ float as top-level windows. Q3MainWindow provides four Q3DockAreas
+ (top, left, right and bottom). When you create a new toolbar (as
+ in the example above) as a child of a Q3MainWindow the toolbar will
+ be added to the top dock area. You can move it to another dock
+ area (or float it) by calling Q3MainWindow::moveDockWindow(). Dock
+ areas lay out their windows in lines.
+
+ If the main window is resized so that the area occupied by the
+ toolbar is too small to show all its widgets a little arrow button
+ (which looks like a right-pointing chevron, '&#187;') will appear
+ at the right or bottom of the toolbar depending on its
+ orientation. Clicking this button pops up a menu that shows the
+ 'overflowing' items. QToolButtons are represented in the menu using
+ their textLabel property, other QAbstractButton subclasses are represented
+ using their text property, and QComboBoxes are represented as submenus,
+ with the caption text being used in the submenu item.
+
+ Usually a toolbar will get precisely the space it needs. However,
+ with setHorizontalStretchable(), setVerticalStretchable() or
+ setStretchableWidget() you can tell the main window to expand the
+ toolbar to fill all available space in the specified orientation.
+
+ The toolbar arranges its buttons either horizontally or vertically
+ (see orientation() for details). Generally, Q3DockArea will set the
+ orientation correctly for you, but you can set it yourself with
+ setOrientation() and track any changes by connecting to the
+ orientationChanged() signal.
+
+ You can use the clear() method to remove all items from a toolbar.
+
+ \img qdockwindow.png Toolbar (dock window)
+ \caption A floating QToolbar (dock window)
+
+ \sa QToolButton Q3MainWindow
+*/
+
+/*!
+ Constructs an empty toolbar.
+
+ The toolbar is called \a name and is a child of \a parent and is
+ managed by \a parent. It is initially located in dock area \a dock
+ and is labeled \a label. If \a newLine is true the toolbar will be
+ placed on a new line in the dock area.
+*/
+
+Q3ToolBar::Q3ToolBar(const QString &label,
+ Q3MainWindow * parent, Qt::ToolBarDock dock,
+ bool newLine, const char * name)
+ : Q3DockWindow(InDock, parent, name, 0, true)
+{
+ mw = parent;
+ init();
+
+ if (parent)
+ parent->addToolBar(this, label, dock, newLine);
+}
+
+
+/*!
+ Constructs an empty horizontal toolbar.
+
+ The toolbar is called \a name and is a child of \a parent and is
+ managed by \a mainWindow. The \a label and \a newLine parameters
+ are passed straight to Q3MainWindow::addDockWindow(). \a name and
+ the widget flags \a f are passed on to the Q3DockWindow constructor.
+
+ Use this constructor if you want to create torn-off (undocked,
+ floating) toolbars or toolbars in the \link QStatusBar status
+ bar\endlink.
+*/
+
+Q3ToolBar::Q3ToolBar(const QString &label, Q3MainWindow * mainWindow,
+ QWidget * parent, bool newLine, const char * name,
+ Qt::WindowFlags f)
+ : Q3DockWindow(InDock, parent, name, f, true)
+{
+ mw = mainWindow;
+ init();
+
+ setParent(parent);
+
+ if (mainWindow)
+ mainWindow->addToolBar(this, label, Qt::DockUnmanaged, newLine);
+}
+
+
+/*!
+ \overload
+
+ Constructs an empty toolbar called \a name, with parent \a parent,
+ in its \a parent's top dock area, without any label and without
+ requiring a newline.
+*/
+
+Q3ToolBar::Q3ToolBar(Q3MainWindow * parent, const char * name)
+ : Q3DockWindow(InDock, parent, name, 0, true)
+{
+ mw = parent;
+ init();
+
+ if (parent)
+ parent->addToolBar(this, QString(), Qt::DockTop);
+}
+
+/*!
+ \internal
+
+ Common initialization code. Requires that \c mw and \c o are set.
+ Does not call Q3MainWindow::addDockWindow().
+*/
+void Q3ToolBar::init()
+{
+ d = new Q3ToolBarPrivate;
+ d->extension = 0;
+ d->extensionPopup = 0;
+ sw = 0;
+
+ setBackgroundRole(QPalette::Button);
+ setFocusPolicy(Qt::NoFocus);
+ setFrameStyle(QFrame::ToolBarPanel | QFrame::Raised);
+}
+
+/*!
+ Destructor.
+*/
+
+Q3ToolBar::~Q3ToolBar()
+{
+ delete d;
+}
+
+/*!
+ \reimp
+*/
+
+void Q3ToolBar::setOrientation(Qt::Orientation o)
+{
+ Q3DockWindow::setOrientation(o);
+ if (d->extension)
+ d->extension->setOrientation(o);
+ QObjectList childList = children();
+ for (int i = 0; i < childList.size(); ++i) {
+ Q3ToolBarSeparator* w = qobject_cast<Q3ToolBarSeparator*>(childList.at(i));
+ if (w)
+ w->setOrientation(o);
+ }
+}
+
+/*!
+ Adds a separator to the right/bottom of the toolbar.
+*/
+
+void Q3ToolBar::addSeparator()
+{
+ (void) new Q3ToolBarSeparator(orientation(), this, "toolbar separator");
+}
+
+/*!
+ \reimp
+*/
+
+void Q3ToolBar::styleChange(QStyle &oldStyle)
+{
+ Q3DockWindow::styleChange(oldStyle);
+}
+
+
+/*!
+ \reimp
+*/
+void Q3ToolBar::setVisible(bool visible)
+{
+ Q3DockWindow::setVisible(visible);
+ if (mw)
+ mw->triggerLayout(false);
+ if (visible)
+ checkForExtension(size());
+}
+
+/*!
+ Returns a pointer to the Q3MainWindow which manages this toolbar.
+*/
+
+Q3MainWindow * Q3ToolBar::mainWindow() const
+{
+ return mw;
+}
+
+
+/*!
+ Sets the widget \a w to be expanded if this toolbar is requested
+ to stretch.
+
+ The request to stretch might occur because Q3MainWindow
+ right-justifies the dock area the toolbar is in, or because this
+ toolbar's isVerticalStretchable() or isHorizontalStretchable() is
+ set to true.
+
+ If you call this function and the toolbar is not yet stretchable,
+ setStretchable() is called.
+
+ \sa Q3MainWindow::setRightJustification(), setVerticalStretchable(),
+ setHorizontalStretchable()
+*/
+
+void Q3ToolBar::setStretchableWidget(QWidget * w)
+{
+ sw = w;
+ boxLayout()->setStretchFactor(w, 1);
+
+ if (!isHorizontalStretchable() && !isVerticalStretchable()) {
+ if (orientation() == Qt::Horizontal)
+ setHorizontalStretchable(true);
+ else
+ setVerticalStretchable(true);
+ }
+}
+
+
+/*!
+ \reimp
+*/
+
+bool Q3ToolBar::event(QEvent * e)
+{
+ bool r = Q3DockWindow::event(e);
+ // After the event filters have dealt with it, do our stuff.
+ if (e->type() == QEvent::ChildInserted) {
+ QObject * child = ((QChildEvent*)e)->child();
+ if (child && child->isWidgetType() && !((QWidget*)child)->isWindow()
+ && child->parent() == this
+ && QLatin1String("qt_dockwidget_internal") != child->objectName()) {
+ boxLayout()->addWidget((QWidget*)child);
+ QLayoutItem *item = boxLayout()->itemAt(boxLayout()->indexOf((QWidget*)child));
+ if (QToolButton *button = qobject_cast<QToolButton*>(child)) {
+ item->setAlignment(Qt::AlignHCenter);
+ button->setFocusPolicy(Qt::NoFocus);
+ if (mw) {
+ QObject::connect(mw, SIGNAL(pixmapSizeChanged(bool)),
+ button, SLOT(setUsesBigPixmap(bool)));
+ button->setUsesBigPixmap(mw->usesBigPixmaps());
+ QObject::connect(mw, SIGNAL(usesTextLabelChanged(bool)),
+ child, SLOT(setUsesTextLabel(bool)));
+ button->setUsesTextLabel(mw->usesTextLabel());
+ }
+ button->setAutoRaise(true);
+ }
+ if (isVisible()) {
+ // toolbar compatibility: we auto show widgets that
+ // are not explicitly hidden
+ if (((QWidget*)child)->testAttribute(Qt::WA_WState_Hidden)
+ && !((QWidget*)child)->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ ((QWidget*)child)->show();
+ checkForExtension(size());
+ }
+ }
+ if (child && child->isWidgetType() && ((QWidget*)child) == sw)
+ boxLayout()->setStretchFactor((QWidget*)child, 1);
+ } else if (e->type() == QEvent::Show) {
+ layout()->activate();
+ } else if (e->type() == QEvent::LayoutHint && place() == OutsideDock) {
+ adjustSize();
+ }
+ return r;
+}
+
+
+/*!
+ \property Q3ToolBar::label
+ \brief the toolbar's label.
+
+ If the toolbar is floated the label becomes the toolbar window's
+ caption. There is no default label text.
+*/
+
+void Q3ToolBar::setLabel(const QString & label)
+{
+ l = label;
+ setWindowTitle(l);
+}
+
+QString Q3ToolBar::label() const
+{
+ return l;
+}
+
+
+/*!
+ Deletes all the toolbar's child widgets.
+*/
+
+void Q3ToolBar::clear()
+{
+ QObjectList childList = children();
+ d->extension = 0;
+ d->extensionPopup = 0; //they will both be destroyed by the following code
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *obj = childList.at(i);
+ if (obj->isWidgetType() && QLatin1String("qt_dockwidget_internal") != obj->objectName())
+ delete obj;
+ }
+}
+
+/*!
+ \internal
+*/
+
+QSize Q3ToolBar::minimumSize() const
+{
+ if (orientation() == Qt::Horizontal)
+ return QSize(0, Q3DockWindow::minimumSize().height());
+ return QSize(Q3DockWindow::minimumSize().width(), 0);
+}
+
+/*!
+ \reimp
+*/
+
+QSize Q3ToolBar::minimumSizeHint() const
+{
+ if (orientation() == Qt::Horizontal)
+ return QSize(0, Q3DockWindow::minimumSizeHint().height());
+ return QSize(Q3DockWindow::minimumSizeHint().width(), 0);
+}
+
+void Q3ToolBar::createPopup()
+{
+ if (!d->extensionPopup) {
+ d->extensionPopup = new Q3PopupMenu(this, "qt_dockwidget_internal");
+ connect(d->extensionPopup, SIGNAL(aboutToShow()), this, SLOT(createPopup()));
+ }
+
+ if (!d->extension) {
+ d->extension = new Q3ToolBarExtensionWidget(this);
+ d->extension->setOrientation(orientation());
+ d->extension->button()->setPopup(d->extensionPopup);
+ d->extension->button()->setPopupMode(QToolButton::InstantPopup);
+ }
+
+ d->extensionPopup->clear();
+
+ // delete submenus
+ QObjectList popups = d->extensionPopup->queryList("Q3PopupMenu", 0, false, true);
+ while (!popups.isEmpty())
+ delete popups.takeFirst();
+
+ QObjectList childlist = queryList("QWidget", 0, false, true);
+ bool hide = false;
+ bool doHide = false;
+ int id;
+ for (int i = 0; i < childlist.size(); ++i) {
+ QObject *obj = childlist.at(i);
+ if (!obj->isWidgetType() || obj == d->extension->button() || obj == d->extensionPopup
+ || QLatin1String("qt_dockwidget_internal") == obj->objectName()) {
+ continue;
+ }
+ int j = 2;
+ QWidget *w = (QWidget*)obj;
+ if (qobject_cast<Q3ComboBox*>(w))
+ j = 1;
+ hide = false;
+
+ const int padding = 4; // extra pixels added by the layout hierarchy
+ QPoint p(mapTo(this, w->geometry().bottomRight()));
+ if (orientation() == Qt::Horizontal) {
+ if ((p.x() > (doHide ? width() - d->extension->width() / j - padding : width() - padding))
+ || (p.x() > parentWidget()->width() - d->extension->width()))
+ hide = true;
+ } else {
+ if ((p.y() > (doHide ? height()- d->extension->height() / j - padding : height() - padding))
+ || (p.y() > parentWidget()->height() - d->extension->height()))
+ hide = true;
+ }
+ if (hide && w->isVisible()) {
+ doHide = true;
+ if (qobject_cast<QToolButton*>(w)) {
+ QToolButton *b = (QToolButton*)w;
+ QString s = b->textLabel();
+ if (s.isEmpty())
+ s = b->text();
+ if (b->popup() && b->popupDelay() == 0)
+ id = d->extensionPopup->insertItem(b->iconSet(), s, b->popup());
+ else
+ id = d->extensionPopup->insertItem(b->iconSet(), s, b, SLOT(click())) ;
+ if (b->isToggleButton())
+ d->extensionPopup->setItemChecked(id, b->isOn());
+ if (!b->isEnabled())
+ d->extensionPopup->setItemEnabled(id, false);
+ } else if (qobject_cast<QAbstractButton*>(w)) {
+ QAbstractButton *b = (QAbstractButton*)w;
+ QString s = b->text();
+ if (s.isEmpty())
+ s = QLatin1String("");
+ if (b->pixmap())
+ id = d->extensionPopup->insertItem(*b->pixmap(), s, b, SLOT(click()));
+ else
+ id = d->extensionPopup->insertItem(s, b, SLOT(click()));
+ if (b->isToggleButton())
+ d->extensionPopup->setItemChecked(id, b->isOn());
+ if (!b->isEnabled())
+ d->extensionPopup->setItemEnabled(id, false);
+#ifndef QT_NO_COMBOBOX
+ } else if (qobject_cast<Q3ComboBox*>(w)) {
+ Q3ComboBox *c = (Q3ComboBox*)w;
+ if (c->count() != 0) {
+ QString s = c->windowTitle();
+ if (s.isEmpty())
+ s = c->currentText();
+ int maxItems = 0;
+ Q3PopupMenu *cp = new Q3PopupMenu(d->extensionPopup);
+ cp->setEnabled(c->isEnabled());
+ d->extensionPopup->insertItem(s, cp);
+ connect(cp, SIGNAL(activated(int)), c, SLOT(internalActivate(int)));
+ for (int i = 0; i < c->count(); ++i) {
+ QString tmp = c->text(i);
+ cp->insertItem(tmp, i);
+ if (c->currentText() == tmp)
+ cp->setItemChecked(i, true);
+ if (!maxItems) {
+ if (cp->actions().count() == 10) {
+ int h = cp->sizeHint().height();
+ maxItems = QApplication::desktop()->height() * 10 / h;
+ }
+ } else if (cp->actions().count() >= maxItems - 1) {
+ Q3PopupMenu* sp = new Q3PopupMenu(d->extensionPopup);
+ cp->insertItem(tr("More..."), sp);
+ cp = sp;
+ connect(cp, SIGNAL(activated(int)), c, SLOT(internalActivate(int)));
+ }
+ }
+ }
+#endif //QT_NO_COMBOBOX
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+
+void Q3ToolBar::resizeEvent(QResizeEvent *e)
+{
+ Q3DockWindow::resizeEvent(e);
+ checkForExtension(e->size());
+}
+
+/*!
+ \internal
+
+ This function is called when an action is triggered. The relevant
+ information is passed in the event \a e.
+*/
+void Q3ToolBar::actionEvent(QActionEvent *e)
+{
+ if (e->type() == QEvent::ActionAdded) {
+ QAction *a = e->action();
+ QWidget *w;
+ if (a->isSeparator()) {
+ w = new Q3ToolBarSeparator(orientation(), this, "toolbar separator");
+ } else {
+ QToolButton* btn = new QToolButton(this);
+ btn->setDefaultAction(a);
+ w = btn;
+ }
+ d->actions.insert(a, w);
+ } else if (e->type() == QEvent::ActionRemoved) {
+ QAction *a = e->action();
+ delete d->actions.take(a);
+ }
+}
+
+
+void Q3ToolBar::checkForExtension(const QSize &sz)
+{
+ if (!isVisible())
+ return;
+
+ if (d->checkingExtension)
+ return;
+ d->checkingExtension = true;
+
+ bool tooSmall;
+ if (orientation() == Qt::Horizontal)
+ tooSmall = sz.width() < sizeHint().width();
+ else
+ tooSmall = sz.height() < sizeHint().height();
+
+ if (tooSmall) {
+ createPopup();
+ if (d->extensionPopup->actions().count()) {
+ // parentWidget()->width() used since the Q3ToolBar width
+ // will never be less than minimumSize()
+ if (orientation() == Qt::Horizontal)
+ d->extension->setGeometry((parentWidget() ? parentWidget()->width() : width()) - 20,
+ 1, 20, height() - 2);
+ else
+ d->extension->setGeometry(1, (parentWidget() ? parentWidget()->height() : height()) - 20,
+ width() - 2, 20);
+ d->extension->show();
+ d->extension->raise();
+ } else {
+ delete d->extension;
+ d->extension = 0;
+ delete d->extensionPopup;
+ d->extensionPopup = 0;
+ }
+ } else {
+ delete d->extension;
+ d->extension = 0;
+ delete d->extensionPopup;
+ d->extensionPopup = 0;
+ }
+ d->checkingExtension = false;
+}
+
+
+/*!
+ \internal
+*/
+
+void Q3ToolBar::setMinimumSize(int, int)
+{
+}
+
+/* from chaunsee:
+
+1. Tool Bars should contain only high-frequency functions. Avoid putting
+things like About and Exit on a tool bar unless they are frequent functions.
+
+2. All tool bar buttons must have some keyboard access method (it can be a
+menu or shortcut key or a function in a dialog box that can be accessed
+through the keyboard).
+
+3. Make tool bar functions as efficient as possible (the common example is to
+Print in Microsoft applications, it doesn't bring up the Print dialog box, it
+prints immediately to the default printer).
+
+4. Avoid turning tool bars into graphical menu bars. To me, a tool bar should
+be efficient. Once you make almost all the items in a tool bar into graphical
+pull-down menus, you start to lose efficiency.
+
+5. Make sure that adjacent icons are distinctive. There are some tool bars
+where you see a group of 4-5 icons that represent related functions, but they
+are so similar that you can't differentiate among them. These tool bars are
+often a poor attempt at a "common visual language".
+
+6. Use any de facto standard icons of your platform (for windows use the
+cut, copy and paste icons provided in dev kits rather than designing your
+own).
+
+7. Avoid putting a highly destructive tool bar button (delete database) by a
+safe, high-frequency button (Find) -- this will yield 1-0ff errors).
+
+8. Tooltips in many Microsoft products simply reiterate the menu text even
+when that is not explanatory. Consider making your tooltips slightly more
+verbose and explanatory than the corresponding menu item.
+
+9. Keep the tool bar as stable as possible when you click on different
+objects. Consider disabling tool bar buttons if they are used in most, but not
+all contexts.
+
+10. If you have multiple tool bars (like the Microsoft MMC snap-ins have),
+put the most stable tool bar to at the left with less stable ones to the
+right. This arrangement (stable to less stable) makes the tool bar somewhat
+more predictable.
+
+11. Keep a single tool bar to fewer than 20 items divided into 4-7 groups of
+items.
+*/
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qt3support/widgets/q3toolbar.h b/src/qt3support/widgets/q3toolbar.h
new file mode 100644
index 0000000..a1fc471
--- /dev/null
+++ b/src/qt3support/widgets/q3toolbar.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3TOOLBAR_H
+#define Q3TOOLBAR_H
+
+#include <Qt3Support/q3dockwindow.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_TOOLBAR
+
+class Q3MainWindow;
+class Q3ToolBarPrivate;
+
+class Q_COMPAT_EXPORT Q3ToolBar: public Q3DockWindow
+{
+ Q_OBJECT
+ Q_PROPERTY(QString label READ label WRITE setLabel)
+
+public:
+ Q3ToolBar(const QString &label,
+ Q3MainWindow *, Qt::ToolBarDock = Qt::DockTop,
+ bool newLine = false, const char* name=0);
+ Q3ToolBar(const QString &label, Q3MainWindow *, QWidget *,
+ bool newLine = false, const char* name=0, Qt::WindowFlags f = 0);
+ Q3ToolBar(Q3MainWindow* parent=0, const char* name=0);
+ ~Q3ToolBar();
+
+ void addSeparator();
+
+ void setVisible(bool visible);
+
+ Q3MainWindow * mainWindow() const;
+
+ virtual void setStretchableWidget(QWidget *);
+
+ bool event(QEvent * e);
+
+ virtual void setLabel(const QString &);
+ QString label() const;
+
+ virtual void clear();
+
+ QSize minimumSize() const;
+ QSize minimumSizeHint() const;
+
+ void setOrientation(Qt::Orientation o);
+ void setMinimumSize(int minw, int minh);
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+ void styleChange(QStyle &);
+ void actionEvent(QActionEvent *);
+
+private Q_SLOTS:
+ void createPopup();
+
+private:
+ void init();
+ void checkForExtension(const QSize &sz);
+ Q3ToolBarPrivate * d;
+ Q3MainWindow * mw;
+ QWidget * sw;
+ QString l;
+
+ friend class Q3MainWindow;
+ friend class Q3DockAreaLayout;
+
+private:
+ Q_DISABLE_COPY(Q3ToolBar)
+};
+
+#endif // QT_NO_TOOLBAR
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3TOOLBAR_H
diff --git a/src/qt3support/widgets/q3vbox.cpp b/src/qt3support/widgets/q3vbox.cpp
new file mode 100644
index 0000000..7a72051
--- /dev/null
+++ b/src/qt3support/widgets/q3vbox.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3vbox.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3VBox
+ \brief The Q3VBox widget provides vertical geometry management of
+ its child widgets.
+
+ \compat
+
+ All its child widgets will be placed vertically and sized
+ according to their sizeHint()s.
+
+ \img qvbox-m.png Q3VBox
+
+ \sa Q3HBox
+*/
+
+
+/*!
+ Constructs a vbox widget called \a name with parent \a parent and
+ widget flags \a f.
+ */
+Q3VBox::Q3VBox( QWidget *parent, const char *name, Qt::WindowFlags f )
+ :Q3HBox( false, parent, name, f )
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3vbox.h b/src/qt3support/widgets/q3vbox.h
new file mode 100644
index 0000000..c3b334c
--- /dev/null
+++ b/src/qt3support/widgets/q3vbox.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3VBOX_H
+#define Q3VBOX_H
+
+#include <Qt3Support/q3hbox.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3VBox : public Q3HBox
+{
+ Q_OBJECT
+public:
+ Q3VBox(QWidget* parent=0, const char* name=0, Qt::WindowFlags f=0);
+
+private:
+ Q_DISABLE_COPY(Q3VBox)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3VBOX_H
diff --git a/src/qt3support/widgets/q3vgroupbox.cpp b/src/qt3support/widgets/q3vgroupbox.cpp
new file mode 100644
index 0000000..b7c58a7
--- /dev/null
+++ b/src/qt3support/widgets/q3vgroupbox.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3vgroupbox.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Q3VGroupBox
+
+ \brief The Q3VGroupBox widget organizes widgets in a group with one
+ vertical column.
+
+ \compat
+
+ Q3VGroupBox is a convenience class that offers a thin layer on top
+ of Q3GroupBox. Think of it as a Q3VBox that offers a frame with a
+ title.
+
+ \sa Q3HGroupBox
+*/
+
+/*!
+ Constructs a horizontal group box with no title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+Q3VGroupBox::Q3VGroupBox( QWidget *parent, const char *name )
+ : Q3GroupBox( 1, Qt::Horizontal /* sic! */, parent, name )
+{
+}
+
+/*!
+ Constructs a horizontal group box with the title \a title.
+
+ The \a parent and \a name arguments are passed to the QWidget
+ constructor.
+*/
+
+Q3VGroupBox::Q3VGroupBox( const QString &title, QWidget *parent,
+ const char *name )
+ : Q3GroupBox( 1, Qt::Horizontal /* sic! */, title, parent, name )
+{
+}
+
+/*!
+ Destroys the horizontal group box, deleting its child widgets.
+*/
+Q3VGroupBox::~Q3VGroupBox()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3vgroupbox.h b/src/qt3support/widgets/q3vgroupbox.h
new file mode 100644
index 0000000..a0ec403
--- /dev/null
+++ b/src/qt3support/widgets/q3vgroupbox.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3VGROUPBOX_H
+#define Q3VGROUPBOX_H
+
+#include <Qt3Support/q3groupbox.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q_COMPAT_EXPORT Q3VGroupBox : public Q3GroupBox
+{
+ Q_OBJECT
+public:
+ Q3VGroupBox( QWidget* parent=0, const char* name=0 );
+ Q3VGroupBox( const QString &title, QWidget* parent=0, const char* name=0 );
+ ~Q3VGroupBox();
+
+private:
+ Q_DISABLE_COPY(Q3VGroupBox)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3VGROUPBOX_H
diff --git a/src/qt3support/widgets/q3whatsthis.cpp b/src/qt3support/widgets/q3whatsthis.cpp
new file mode 100644
index 0000000..6037be7
--- /dev/null
+++ b/src/qt3support/widgets/q3whatsthis.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3whatsthis.h"
+#ifndef QT_NO_WHATSTHIS
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qevent.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class Q3WhatsThis
+ \compat
+*/
+
+/*!
+ Constructs a new "What's This?" object for \a widget.
+*/
+Q3WhatsThis::Q3WhatsThis(QWidget *widget)
+ : QObject(widget)
+{
+ if (widget)
+ widget->installEventFilter(this);
+}
+
+/*!
+ Destroys the "What's This?" object.
+*/
+Q3WhatsThis::~Q3WhatsThis()
+{
+}
+
+/*!
+ \internal
+
+ Handles "What's This?" events.
+*/
+bool Q3WhatsThis::eventFilter(QObject *o, QEvent *e)
+{
+ if (o != parent() || !o->isWidgetType())
+ return false;
+
+ if (e->type() == QEvent::WhatsThis) {
+ QString s = text(static_cast<QHelpEvent*>(e)->pos());
+ if (!s.isEmpty())
+ QWhatsThis::showText(static_cast<QHelpEvent*>(e)->globalPos(), s, static_cast<QWidget*>(o));
+ } else if (e->type() == QEvent::QueryWhatsThis) {
+ QString s = text(static_cast<QHelpEvent*>(e)->pos());
+ if (s.isEmpty())
+ return false;
+ } else if (e->type() == QEvent::WhatsThisClicked) {
+ QString href = static_cast<QWhatsThisClickedEvent*>(e)->href();
+ if (clicked(href))
+ QWhatsThis::hideText();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+/*!
+ This virtual function returns the text for position \a pos in the
+ widget that this "What's This?" object documents. If there is no
+ "What's This?" text for the position, an empty string is returned.
+
+ The default implementation returns an empty string.
+*/
+QString Q3WhatsThis::text(const QPoint & /* pos */)
+{
+ if (parent() && parent()->isWidgetType())
+ return static_cast<QWidget*>(parent())->whatsThis();
+ return QString();
+}
+
+/*!
+ This virtual function is called when the user clicks inside the
+ "What's this?" window. \a href is the link the user clicked on, or
+ an empty string if there was no link.
+
+ If the function returns true (the default), the "What's this?"
+ window is closed, otherwise it remains visible.
+
+ The default implementation ignores \a href and returns true.
+*/
+bool Q3WhatsThis::clicked(const QString & /* href */)
+{
+ return true;
+}
+
+/*!
+ \fn void Q3WhatsThis::enterWhatsThisMode()
+
+ Enters "What's This?" mode and returns immediately.
+
+ Qt will install a special cursor and take over mouse input until
+ the user clicks somewhere. It then shows any help available and
+ ends "What's This?" mode. Finally, Qt removes the special cursor
+ and help window and then restores ordinary event processing, at
+ which point the left mouse button is no longer pressed.
+
+ The user can also use the Esc key to leave "What's This?" mode.
+
+ \sa inWhatsThisMode(), leaveWhatsThisMode()
+*/
+
+/*!
+ \fn bool Q3WhatsThis::inWhatsThisMode()
+
+ Returns true if the application is in "What's This?" mode;
+ otherwise returns false.
+
+ \sa enterWhatsThisMode(), leaveWhatsThisMode()
+*/
+
+/*!
+ \fn void Q3WhatsThis::add(QWidget *widget, const QString &text)
+
+ Adds \a text as "What's This?" help for \a widget. If the text is
+ rich text formatted (i.e. it contains markup) it will be rendered
+ with the default stylesheet QStyleSheet::defaultSheet().
+
+ The text is destroyed if the widget is later destroyed, so it need
+ not be explicitly removed.
+
+ \sa remove()
+*/
+
+/*!
+ \fn void Q3WhatsThis::remove(QWidget *widget)
+
+ Removes the "What's This?" help associated with the \a widget.
+ This happens automatically if the widget is destroyed.
+
+ \sa add()
+*/
+
+/*!
+ \fn void Q3WhatsThis::leaveWhatsThisMode(const QString& text = QString(), const QPoint& pos = QCursor::pos(), QWidget* widget = 0)
+
+ This function is used internally by widgets that support
+ QWidget::customWhatsThis(); applications do not usually call it.
+ An example of such a widget is Q3PopupMenu: menus still work
+ normally in "What's This?" mode but also provide help texts for
+ individual menu items.
+
+ If \a text is not empty, a "What's This?" help window is
+ displayed at the global screen position \a pos. If widget \a widget is
+ not 0 and has its own dedicated QWhatsThis object, this object
+ will receive clicked() messages when the user clicks on hyperlinks
+ inside the help text.
+
+ \sa inWhatsThisMode(), enterWhatsThisMode(), clicked()
+*/
+
+/*!
+ \fn void Q3WhatsThis::display(const QString &text, const QPoint &pos, QWidget *widget)
+
+ Display \a text in a help window at the global screen position \a
+ pos.
+
+ If widget \a widget is not 0 and has its own dedicated QWhatsThis
+ object, this object will receive clicked() messages when the user
+ clicks on hyperlinks inside the help text.
+
+ \sa clicked()
+*/
+
+/*!
+ Creates a QToolButton preconfigured to enter "What's This?" mode
+ when clicked. You will often use this with a tool bar as \a
+ parent:
+
+ \snippet doc/src/snippets/code/src_qt3support_widgets_q3whatsthis.cpp 0
+*/
+QToolButton *Q3WhatsThis::whatsThisButton(QWidget * parent)
+{
+ return QWhatsThis::whatsThisButton(parent);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_WHATSTHIS
diff --git a/src/qt3support/widgets/q3whatsthis.h b/src/qt3support/widgets/q3whatsthis.h
new file mode 100644
index 0000000..5080786
--- /dev/null
+++ b/src/qt3support/widgets/q3whatsthis.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3WHATSTHIS_H
+#define Q3WHATSTHIS_H
+
+#include <QtGui/qcursor.h>
+#include <QtGui/qwhatsthis.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+#ifndef QT_NO_WHATSTHIS
+
+class QToolButton;
+
+class Q_COMPAT_EXPORT Q3WhatsThis: public QObject
+{
+ Q_OBJECT
+public:
+ Q3WhatsThis(QWidget *);
+ ~Q3WhatsThis();
+ bool eventFilter(QObject *, QEvent *);
+
+ static inline void enterWhatsThisMode() { QWhatsThis::enterWhatsThisMode(); }
+ static inline bool inWhatsThisMode() { return QWhatsThis::inWhatsThisMode(); }
+
+ static inline void add(QWidget *w, const QString &s) { w->setWhatsThis(s); }
+ static inline void remove(QWidget *w) { w->setWhatsThis(QString()); }
+ static QToolButton * whatsThisButton(QWidget * parent);
+ static inline void leaveWhatsThisMode(const QString& text = QString(), const QPoint& pos = QCursor::pos(), QWidget* w = 0)
+ { QWhatsThis::showText(pos, text, w); }
+ static inline void display(const QString& text, const QPoint& pos = QCursor::pos(), QWidget* w = 0)
+ { QWhatsThis::showText(pos, text, w); }
+
+ virtual QString text(const QPoint &);
+ virtual bool clicked(const QString& href);
+
+};
+
+#endif // QT_NO_WHATSTHIS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3WHATSTHIS_H
diff --git a/src/qt3support/widgets/q3widgetstack.cpp b/src/qt3support/widgets/q3widgetstack.cpp
new file mode 100644
index 0000000..43263dc
--- /dev/null
+++ b/src/qt3support/widgets/q3widgetstack.cpp
@@ -0,0 +1,571 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 "q3widgetstack.h"
+#include "qlayout.h"
+#include "private/qlayoutengine_p.h"
+#include "qapplication.h"
+#include "qpainter.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt;
+
+class Q3WidgetStackPrivate {
+public:
+ class Invisible: public QWidget
+ {
+ public:
+ Invisible(Q3WidgetStack * parent): QWidget(parent, "qt_invisible_widgetstack")
+ {
+ setBackgroundMode(NoBackground);
+ }
+ const char * className() const
+ {
+ return "Q3WidgetStackPrivate::Invisible";
+ }
+ protected:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter(this).eraseRect(rect());
+ }
+ };
+
+ int nextNegativeID;
+ int nextPositiveID;
+};
+
+
+
+/*!
+ \class Q3WidgetStack
+ \brief The Q3WidgetStack class provides a stack of widgets of which
+ only the top widget is user-visible.
+
+ \compat
+
+ The application programmer can move any widget to the top of the
+ stack at any time using raiseWidget(), and add or remove widgets
+ using addWidget() and removeWidget(). It is not sufficient to pass
+ the widget stack as parent to a widget which should be inserted into
+ the widgetstack.
+
+ visibleWidget() is the \e get equivalent of raiseWidget(); it
+ returns a pointer to the widget that is currently at the top of
+ the stack.
+
+ Q3WidgetStack also provides the ability to manipulate widgets
+ through application-specified integer IDs. You can also translate
+ from widget pointers to IDs using id() and from IDs to widget
+ pointers using widget(). These numeric IDs are unique (per
+ Q3WidgetStack, not globally), but Q3WidgetStack does not attach any
+ additional meaning to them.
+
+ The default widget stack is frameless, but you can use the usual
+ Q3Frame functions (such as setFrameStyle()) to add a frame.
+
+ Q3WidgetStack provides a signal, aboutToShow(), which is emitted
+ just before a managed widget is shown.
+
+ \sa Q3TabDialog QTabWidget QTabBar Q3Frame
+*/
+
+
+/*!
+ Constructs an empty widget stack.
+
+ The \a parent, \a name and \a f arguments are passed to the Q3Frame
+ constructor.
+*/
+Q3WidgetStack::Q3WidgetStack(QWidget * parent, const char *name, Qt::WindowFlags f)
+ : Q3Frame(parent, name, f) //## merge constructors in 4.0
+{
+ init();
+}
+
+void Q3WidgetStack::init()
+{
+ d = new Q3WidgetStackPrivate();
+ d->nextNegativeID = -2;
+ d->nextPositiveID = 0;
+ dict = new Q3IntDict<QWidget>;
+ focusWidgets = 0;
+ topWidget = 0;
+ invisible = 0;
+ invisible = new Q3WidgetStackPrivate::Invisible(this);
+ invisible->hide();
+}
+
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+Q3WidgetStack::~Q3WidgetStack()
+{
+ delete focusWidgets;
+ delete d;
+ delete dict;
+}
+
+
+/*!
+ Adds widget \a w to this stack of widgets, with ID \a id.
+
+ If you pass an id \>= 0 this ID is used. If you pass an \a id of
+ -1 (the default), the widgets will be numbered automatically. If
+ you pass -2 a unique negative integer will be generated. No widget
+ has an ID of -1. Returns the ID or -1 on failure (e.g. \a w is 0).
+
+ If you pass an id that is already used, then a unique negative
+ integer will be generated to prevent two widgets having the same
+ id.
+
+ If \a w already exists in the stack the widget will be removed first.
+
+ If \a w is not a child of this Q3WidgetStack moves it using
+ reparent().
+*/
+
+int Q3WidgetStack::addWidget(QWidget * w, int id)
+{
+ if (!w || w == invisible || invisible == 0)
+ return -1;
+
+ // prevent duplicates
+ removeWidget(w);
+
+ if (id >= 0 && dict->find(id))
+ id = -2;
+ if (id < -1)
+ id = d->nextNegativeID--;
+ else if (id == -1)
+ id = d->nextPositiveID++;
+ else
+ d->nextPositiveID = qMax(d->nextPositiveID, id + 1);
+ // use id >= 0 as-is
+
+ dict->insert(id, w);
+
+ // preserve existing focus
+ QWidget * f = w->focusWidget();
+ while(f && f != w)
+ f = f->parentWidget();
+ if (f) {
+ if (!focusWidgets)
+ focusWidgets = new Q3PtrDict<QWidget>(17);
+ focusWidgets->replace(w, w->focusWidget());
+ }
+
+ w->hide();
+ if (w->parent() != this)
+ w->reparent(this, contentsRect().topLeft(), false);
+ w->setGeometry(contentsRect());
+ updateGeometry();
+ return id;
+}
+
+
+/*!
+ Removes widget \a w from this stack of widgets. Does not delete \a
+ w. If \a w is the currently visible widget, no other widget is
+ substituted.
+
+ \sa visibleWidget() raiseWidget()
+*/
+
+void Q3WidgetStack::removeWidget(QWidget * w)
+{
+ int i;
+ if (!w || (i = id(w)) == -1)
+ return ;
+
+ dict->take(i);
+ if (w == topWidget)
+ topWidget = 0;
+ if (dict->isEmpty())
+ invisible->hide(); // let background shine through again
+ updateGeometry();
+}
+
+
+/*!
+ Raises the widget with ID \a id to the top of the widget stack.
+
+ \sa visibleWidget()
+*/
+
+void Q3WidgetStack::raiseWidget(int id)
+{
+ if (id == -1)
+ return;
+ QWidget * w = dict->find(id);
+ if (w)
+ raiseWidget(w);
+}
+
+static bool isChildOf(QWidget* child, QWidget *parent)
+{
+ if (!child)
+ return false;
+ QObjectList list = parent->children();
+ for (int i = 0; i < list.size(); ++i) {
+ QObject *obj = list.at(i);
+ if (!obj->isWidgetType())
+ continue;
+ QWidget *widget = static_cast<QWidget *>(obj);
+ if (!widget->isWindow())
+ continue;
+ if (widget == child || isChildOf(child, widget))
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Raises widget \a w to the top of the widget stack.
+*/
+
+void Q3WidgetStack::raiseWidget(QWidget *w)
+{
+ if (!w || w == invisible || w->parent() != this || w == topWidget)
+ return;
+
+ if (id(w) == -1)
+ addWidget(w);
+ if (!isVisible()) {
+ topWidget = w;
+ return;
+ }
+
+ if (w->maximumSize().width() < invisible->width()
+ || w->maximumSize().height() < invisible->height())
+ invisible->setBackgroundMode(backgroundMode());
+ else if (invisible->backgroundMode() != NoBackground)
+ invisible->setBackgroundMode(NoBackground);
+
+ if (invisible->isHidden()) {
+ invisible->setGeometry(contentsRect());
+ invisible->lower();
+ invisible->show();
+ QApplication::sendPostedEvents(invisible, QEvent::ShowWindowRequest);
+ }
+
+ // try to move focus onto the incoming widget if focus
+ // was somewhere on the outgoing widget.
+ if (topWidget) {
+ QWidget * fw = window()->focusWidget();
+ if (topWidget->isAncestorOf(fw)) { // focus was on old page
+ // look for the best focus widget we can find
+ QWidget *p = w->focusWidget();
+ if (!p) {
+ // second best == first child widget in the focus chain
+ QWidget *i = fw;
+ while ((i = i->nextInFocusChain()) != fw) {
+ if (((i->focusPolicy() & Qt::TabFocus) == Qt::TabFocus)
+ && !i->focusProxy() && i->isVisibleTo(w) && i->isEnabled()
+ && w->isAncestorOf(i)) {
+ p = i;
+ break;
+ }
+ }
+ }
+ if (p)
+ p->setFocus();
+ } else {
+ // the focus wasn't on the old page, so we have to ensure focus doesn't go to
+ // the widget in the page that last had focus when we show the page again.
+ QWidget *oldfw = topWidget->focusWidget();
+ if (oldfw)
+ oldfw->clearFocus();
+ }
+ }
+
+ if (isVisible()) {
+ emit aboutToShow(w);
+ int i = id(w);
+ if (i != -1)
+ emit aboutToShow(i);
+ }
+
+ topWidget = w;
+
+ QObjectList c = children();
+ for (int i = 0; i < c.size(); ++i) {
+ QObject * o = c.at(i);
+ if (o->isWidgetType() && o != w && o != invisible)
+ static_cast<QWidget *>(o)->hide();
+ }
+
+ w->setGeometry(invisible->geometry());
+ w->show();
+}
+
+/*!
+ \reimp
+*/
+
+void Q3WidgetStack::frameChanged()
+{
+ Q3Frame::frameChanged();
+ setChildGeometries();
+}
+
+
+/*!
+ \internal
+*/
+
+void Q3WidgetStack::setFrameRect(const QRect & r)
+{
+ // ### this function used to be virtual in QFrame in Qt 3; it is no longer virtual in Qt 4
+ Q3Frame::setFrameRect(r);
+ setChildGeometries();
+}
+
+
+/*!
+ Fixes up the children's geometries.
+*/
+
+void Q3WidgetStack::setChildGeometries()
+{
+ invisible->setGeometry(contentsRect());
+ if (topWidget)
+ topWidget->setGeometry(invisible->geometry());
+}
+
+
+/*!
+ \reimp
+*/
+void Q3WidgetStack::setVisible(bool visible)
+{
+ if (visible) {
+ // Reimplemented in order to set the children's geometries
+ // appropriately and to pick the first widget as d->topWidget if no
+ // topwidget was defined
+ QObjectList c = children();
+ if (!isVisible() && !c.isEmpty()) {
+ for (int i = 0; i < c.size(); ++i) {
+ QObject * o = c.at(i);
+ if (o->isWidgetType()) {
+ if (!topWidget && o != invisible)
+ topWidget = static_cast<QWidget*>(o);
+ if (o == topWidget)
+ static_cast<QWidget *>(o)->show();
+ else
+ static_cast<QWidget *>(o)->hide();
+ }
+ }
+ setChildGeometries();
+ }
+ }
+ Q3Frame::setVisible(visible);
+}
+
+
+/*!
+ Returns the widget with ID \a id. Returns 0 if this widget stack
+ does not manage a widget with ID \a id.
+
+ \sa id() addWidget()
+*/
+
+QWidget * Q3WidgetStack::widget(int id) const
+{
+ return id != -1 ? dict->find(id) : 0;
+}
+
+
+/*!
+ Returns the ID of the \a widget. Returns -1 if \a widget is 0 or
+ is not being managed by this widget stack.
+
+ \sa widget() addWidget()
+*/
+
+int Q3WidgetStack::id(QWidget * widget) const
+{
+ if (!widget)
+ return -1;
+
+ Q3IntDictIterator<QWidget> it(*dict);
+ while (it.current() && it.current() != widget)
+ ++it;
+ return it.current() == widget ? it.currentKey() : -1;
+}
+
+
+/*!
+ Returns the currently visible widget (the one at the top of the
+ stack), or 0 if nothing is currently being shown.
+
+ \sa aboutToShow() id() raiseWidget()
+*/
+
+QWidget * Q3WidgetStack::visibleWidget() const
+{
+ return topWidget;
+}
+
+
+/*!
+ \fn void Q3WidgetStack::aboutToShow(int id)
+
+ This signal is emitted just before a managed widget is shown if
+ that managed widget has an ID != -1. The \a id parameter is the numeric
+ ID of the widget.
+
+ If you call visibleWidget() in a slot connected to aboutToShow(),
+ the widget it returns is the one that is currently visible, not
+ the one that is about to be shown.
+*/
+
+
+/*!
+ \fn void Q3WidgetStack::aboutToShow(QWidget *widget)
+
+ \overload
+
+ This signal is emitted just before a managed widget is shown. The
+ argument is a pointer to the \a widget.
+
+ If you call visibleWidget() in a slot connected to aboutToShow(),
+ the widget returned is the one that is currently visible, not the
+ one that is about to be shown.
+*/
+
+
+/*!
+ \reimp
+*/
+
+void Q3WidgetStack::resizeEvent(QResizeEvent * e)
+{
+ Q3Frame::resizeEvent(e);
+ setChildGeometries();
+}
+
+
+/*!
+ \reimp
+*/
+
+QSize Q3WidgetStack::sizeHint() const
+{
+ constPolish();
+
+ QSize size(0, 0);
+
+ Q3IntDictIterator<QWidget> it(*dict);
+ QWidget *w;
+
+ while ((w = it.current()) != 0) {
+ ++it;
+ QSize sh = w->sizeHint();
+ if (w->sizePolicy().horData() == QSizePolicy::Ignored)
+ sh.rwidth() = 0;
+ if (w->sizePolicy().verData() == QSizePolicy::Ignored)
+ sh.rheight() = 0;
+#ifndef QT_NO_LAYOUT
+ size = size.expandedTo(sh).expandedTo(qSmartMinSize(w));
+#endif
+ }
+ if (size.isNull())
+ size = QSize(128, 64);
+ size += QSize(2*frameWidth(), 2*frameWidth());
+ return size;
+}
+
+
+/*!
+ \reimp
+*/
+QSize Q3WidgetStack::minimumSizeHint() const
+{
+ constPolish();
+
+ QSize size(0, 0);
+
+ Q3IntDictIterator<QWidget> it(*dict);
+ QWidget *w;
+
+ while ((w = it.current()) != 0) {
+ ++it;
+ QSize sh = w->minimumSizeHint();
+ if (w->sizePolicy().horData() == QSizePolicy::Ignored)
+ sh.rwidth() = 0;
+ if (w->sizePolicy().verData() == QSizePolicy::Ignored)
+ sh.rheight() = 0;
+#ifndef QT_NO_LAYOUT
+ size = size.expandedTo(sh).expandedTo(w->minimumSize());
+#endif
+ }
+ if (size.isNull())
+ size = QSize(64, 32);
+ size += QSize(2*frameWidth(), 2*frameWidth());
+ return size;
+}
+
+/*!
+ \reimp
+*/
+void Q3WidgetStack::childEvent(QChildEvent *e)
+{
+ if (e->child()->isWidgetType() && e->removed())
+ removeWidget((QWidget *) e->child());
+}
+
+
+/*!
+ \reimp
+*/
+bool Q3WidgetStack::event(QEvent* e)
+{
+ if (e->type() == QEvent::LayoutRequest || e->type() == QEvent::LayoutHint )
+ updateGeometry(); // propgate layout hints to parent
+ return Q3Frame::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qt3support/widgets/q3widgetstack.h b/src/qt3support/widgets/q3widgetstack.h
new file mode 100644
index 0000000..e63830f
--- /dev/null
+++ b/src/qt3support/widgets/q3widgetstack.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module 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 Q3WIDGETSTACK_H
+#define Q3WIDGETSTACK_H
+
+#include <Qt3Support/q3frame.h>
+#include <Qt3Support/q3intdict.h>
+#include <Qt3Support/q3ptrdict.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3SupportLight)
+
+class Q3WidgetStackPrivate;
+
+
+class Q_COMPAT_EXPORT Q3WidgetStack: public Q3Frame
+{
+ Q_OBJECT
+public:
+ Q3WidgetStack(QWidget* parent, const char* name=0, Qt::WindowFlags f=0);
+
+ ~Q3WidgetStack();
+
+ int addWidget(QWidget *, int = -1);
+ void removeWidget(QWidget *);
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+ void setVisible(bool visible);
+
+ QWidget * widget(int) const;
+ int id(QWidget *) const;
+
+ QWidget * visibleWidget() const;
+
+ void setFrameRect(const QRect &);
+
+Q_SIGNALS:
+ void aboutToShow(int);
+ void aboutToShow(QWidget *);
+
+public Q_SLOTS:
+ void raiseWidget(int);
+ void raiseWidget(QWidget *);
+
+protected:
+ void frameChanged();
+ void resizeEvent(QResizeEvent *);
+ bool event(QEvent* e);
+
+ virtual void setChildGeometries();
+ void childEvent(QChildEvent *);
+
+private:
+ void init();
+
+ Q3WidgetStackPrivate * d;
+ Q3IntDict<QWidget> * dict;
+ Q3PtrDict<QWidget> * focusWidgets;
+ QWidget * topWidget;
+ QWidget * invisible;
+
+ Q_DISABLE_COPY(Q3WidgetStack)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q3WIDGETSTACK_H
diff --git a/src/qt3support/widgets/widgets.pri b/src/qt3support/widgets/widgets.pri
new file mode 100644
index 0000000..9bd6fb4
--- /dev/null
+++ b/src/qt3support/widgets/widgets.pri
@@ -0,0 +1,58 @@
+# Qt compat module
+
+HEADERS += \
+ widgets/q3action.h \
+ widgets/q3buttongroup.h \
+ widgets/q3datetimeedit.h \
+ widgets/q3dockarea.h \
+ widgets/q3dockwindow.h \
+ widgets/q3frame.h \
+ widgets/q3vbox.h \
+ widgets/q3vgroupbox.h \
+ widgets/q3hbox.h \
+ widgets/q3hgroupbox.h \
+ widgets/q3grid.h \
+ widgets/q3gridview.h \
+ widgets/q3groupbox.h \
+ widgets/q3header.h \
+ widgets/q3mainwindow.h \
+ widgets/q3mainwindow_p.h \
+ widgets/q3progressbar.h \
+ widgets/q3scrollview.h \
+ widgets/q3titlebar_p.h \
+ widgets/q3toolbar.h \
+ widgets/q3whatsthis.h \
+ widgets/q3widgetstack.h \
+ widgets/q3button.h \
+ widgets/q3rangecontrol.h \
+ widgets/q3popupmenu.h \
+ widgets/q3combobox.h
+
+SOURCES += \
+ widgets/q3action.cpp \
+ widgets/q3buttongroup.cpp \
+ widgets/q3datetimeedit.cpp \
+ widgets/q3dockarea.cpp \
+ widgets/q3dockwindow.cpp \
+ widgets/q3frame.cpp \
+ widgets/q3vbox.cpp \
+ widgets/q3vgroupbox.cpp \
+ widgets/q3hbox.cpp \
+ widgets/q3hgroupbox.cpp \
+ widgets/q3grid.cpp \
+ widgets/q3gridview.cpp \
+ widgets/q3groupbox.cpp \
+ widgets/q3header.cpp \
+ widgets/q3mainwindow.cpp \
+ widgets/q3progressbar.cpp \
+ widgets/q3scrollview.cpp \
+ widgets/q3titlebar.cpp \
+ widgets/q3toolbar.cpp \
+ widgets/q3whatsthis.cpp \
+ widgets/q3widgetstack.cpp \
+ widgets/q3button.cpp \
+ widgets/q3rangecontrol.cpp \
+ widgets/q3spinwidget.cpp \
+ widgets/q3popupmenu.cpp \
+ widgets/q3combobox.cpp
+