summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/kernel.pri246
-rw-r--r--src/widgets/kernel/mac.pri4
-rw-r--r--src/widgets/kernel/qaction.cpp1520
-rw-r--r--src/widgets/kernel/qaction.h264
-rw-r--r--src/widgets/kernel/qaction_p.h144
-rw-r--r--src/widgets/kernel/qactiongroup.cpp422
-rw-r--r--src/widgets/kernel/qactiongroup.h112
-rw-r--r--src/widgets/kernel/qapplication.cpp5687
-rw-r--r--src/widgets/kernel/qapplication.h422
-rw-r--r--src/widgets/kernel/qapplication_p.h626
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp431
-rw-r--r--src/widgets/kernel/qbackingstore.cpp1665
-rw-r--r--src/widgets/kernel/qbackingstore_p.h278
-rw-r--r--src/widgets/kernel/qboxlayout.cpp1550
-rw-r--r--src/widgets/kernel/qboxlayout.h173
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp76
-rw-r--r--src/widgets/kernel/qdesktopwidget.h110
-rw-r--r--src/widgets/kernel/qdesktopwidget.qdoc269
-rw-r--r--src/widgets/kernel/qdesktopwidget_qpa.cpp174
-rw-r--r--src/widgets/kernel/qdesktopwidget_qpa_p.h81
-rw-r--r--src/widgets/kernel/qformlayout.cpp2079
-rw-r--r--src/widgets/kernel/qformlayout.h163
-rw-r--r--src/widgets/kernel/qgesture.cpp1118
-rw-r--r--src/widgets/kernel/qgesture.h328
-rw-r--r--src/widgets/kernel/qgesture_p.h245
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp721
-rw-r--r--src/widgets/kernel/qgesturemanager_p.h151
-rw-r--r--src/widgets/kernel/qgesturerecognizer.cpp240
-rw-r--r--src/widgets/kernel/qgesturerecognizer.h102
-rw-r--r--src/widgets/kernel/qgridlayout.cpp1889
-rw-r--r--src/widgets/kernel/qgridlayout.h176
-rw-r--r--src/widgets/kernel/qguieventdispatcher_glib.cpp224
-rw-r--r--src/widgets/kernel/qguieventdispatcher_glib_p.h79
-rw-r--r--src/widgets/kernel/qguiplatformplugin.cpp298
-rw-r--r--src/widgets/kernel/qguiplatformplugin_p.h126
-rw-r--r--src/widgets/kernel/qicon.cpp1165
-rw-r--r--src/widgets/kernel/qicon.h143
-rw-r--r--src/widgets/kernel/qicon_p.h139
-rw-r--r--src/widgets/kernel/qiconengine.cpp324
-rw-r--r--src/widgets/kernel/qiconengine.h104
-rw-r--r--src/widgets/kernel/qiconengineplugin.cpp171
-rw-r--r--src/widgets/kernel/qiconengineplugin.h104
-rw-r--r--src/widgets/kernel/qiconloader.cpp573
-rw-r--r--src/widgets/kernel/qiconloader_p.h192
-rw-r--r--src/widgets/kernel/qlayout.cpp1632
-rw-r--r--src/widgets/kernel/qlayout.h245
-rw-r--r--src/widgets/kernel/qlayout_p.h101
-rw-r--r--src/widgets/kernel/qlayoutengine.cpp436
-rw-r--r--src/widgets/kernel/qlayoutengine_p.h140
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp834
-rw-r--r--src/widgets/kernel/qlayoutitem.h182
-rw-r--r--src/widgets/kernel/qsizepolicy.h244
-rw-r--r--src/widgets/kernel/qsizepolicy.qdoc529
-rw-r--r--src/widgets/kernel/qsoftkeymanager.cpp319
-rw-r--r--src/widgets/kernel/qsoftkeymanager_common_p.h86
-rw-r--r--src/widgets/kernel/qsoftkeymanager_p.h115
-rw-r--r--src/widgets/kernel/qsound.cpp367
-rw-r--r--src/widgets/kernel/qsound.h90
-rw-r--r--src/widgets/kernel/qsound_p.h100
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp543
-rw-r--r--src/widgets/kernel/qstackedlayout.h115
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp595
-rw-r--r--src/widgets/kernel/qstandardgestures_p.h117
-rw-r--r--src/widgets/kernel/qt_gui_pch.h85
-rw-r--r--src/widgets/kernel/qtooltip.cpp623
-rw-r--r--src/widgets/kernel/qtooltip.h84
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp777
-rw-r--r--src/widgets/kernel/qwhatsthis.h88
-rw-r--r--src/widgets/kernel/qwidget.cpp12677
-rw-r--r--src/widgets/kernel/qwidget.h1091
-rw-r--r--src/widgets/kernel/qwidget_p.h1034
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp824
-rw-r--r--src/widgets/kernel/qwidgetaction.cpp287
-rw-r--r--src/widgets/kernel/qwidgetaction.h91
-rw-r--r--src/widgets/kernel/qwidgetaction_p.h77
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp188
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h83
-rw-r--r--src/widgets/kernel/symbian.pri7
-rw-r--r--src/widgets/kernel/win.pri4
-rw-r--r--src/widgets/kernel/x11.pri4
80 files changed, 49922 insertions, 0 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
new file mode 100644
index 0000000000..d085bff146
--- /dev/null
+++ b/src/widgets/kernel/kernel.pri
@@ -0,0 +1,246 @@
+# Qt kernel module
+
+# Only used on platforms with CONFIG += precompile_header
+PRECOMPILED_HEADER = kernel/qt_gui_pch.h
+
+
+KERNEL_P= kernel
+HEADERS += \
+ kernel/qaction.h \
+ kernel/qaction_p.h \
+ kernel/qactiongroup.h \
+ kernel/qapplication.h \
+ kernel/qapplication_p.h \
+ kernel/qbackingstore_p.h \
+ kernel/qboxlayout.h \
+ kernel/qdesktopwidget.h \
+ kernel/qformlayout.h \
+ kernel/qgridlayout.h \
+ kernel/qicon.h \
+ kernel/qicon_p.h \
+ kernel/qiconloader_p.h \
+ kernel/qiconengine.h \
+ kernel/qiconengineplugin.h \
+ kernel/qlayout.h \
+ kernel/qlayout_p.h \
+ kernel/qlayoutengine_p.h \
+ kernel/qlayoutitem.h \
+ kernel/qsizepolicy.h \
+ kernel/qstackedlayout.h \
+ kernel/qtooltip.h \
+ kernel/qwhatsthis.h \
+ kernel/qwidget.h \
+ kernel/qwidget_p.h \
+ kernel/qwidgetaction.h \
+ kernel/qwidgetaction_p.h \
+ kernel/qgesture.h \
+ kernel/qgesture_p.h \
+ kernel/qstandardgestures_p.h \
+ kernel/qgesturerecognizer.h \
+ kernel/qgesturemanager_p.h \
+ kernel/qsoftkeymanager_p.h \
+ kernel/qsoftkeymanager_common_p.h \
+ kernel/qguiplatformplugin_p.h
+
+SOURCES += \
+ kernel/qaction.cpp \
+ kernel/qactiongroup.cpp \
+ kernel/qapplication.cpp \
+ kernel/qbackingstore.cpp \
+ kernel/qboxlayout.cpp \
+ kernel/qformlayout.cpp \
+ kernel/qgridlayout.cpp \
+ kernel/qicon.cpp \
+ kernel/qiconloader.cpp \
+ kernel/qiconengine.cpp \
+ kernel/qiconengineplugin.cpp \
+ kernel/qlayout.cpp \
+ kernel/qlayoutengine.cpp \
+ kernel/qlayoutitem.cpp \
+ kernel/qstackedlayout.cpp \
+ kernel/qtooltip.cpp \
+ kernel/qwhatsthis.cpp \
+ kernel/qwidget.cpp \
+ kernel/qwidgetaction.cpp \
+ kernel/qgesture.cpp \
+ kernel/qstandardgestures.cpp \
+ kernel/qgesturerecognizer.cpp \
+ kernel/qgesturemanager.cpp \
+ kernel/qsoftkeymanager.cpp \
+ kernel/qdesktopwidget.cpp \
+ kernel/qguiplatformplugin.cpp \
+ kernel/qwidgetsvariant.cpp
+
+win32 {
+ DEFINES += QT_NO_DIRECTDRAW
+
+ HEADERS += \
+ kernel/qwinnativepangesturerecognizer_win_p.h
+
+ SOURCES += \
+ kernel/qapplication_win.cpp \
+ kernel/qclipboard_win.cpp \
+ kernel/qcursor_win.cpp \
+ kernel/qdesktopwidget_win.cpp \
+ kernel/qdnd_win.cpp \
+ kernel/qmime_win.cpp \
+ kernel/qsound_win.cpp \
+ kernel/qwidget_win.cpp \
+ kernel/qole_win.cpp \
+ kernel/qkeymapper_win.cpp \
+ kernel/qwinnativepangesturerecognizer_win.cpp
+
+ !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
+}
+
+symbian {
+ exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h): DEFINES += QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H
+
+ SOURCES += \
+ kernel/qapplication_s60.cpp \
+ kernel/qeventdispatcher_s60.cpp \
+ kernel/qwidget_s60.cpp \
+ kernel/qcursor_s60.cpp \
+ kernel/qdesktopwidget_s60.cpp \
+ kernel/qkeymapper_s60.cpp\
+ kernel/qclipboard_s60.cpp\
+ kernel/qdnd_s60.cpp \
+ kernel/qsound_s60.cpp
+
+ HEADERS += \
+ kernel/qt_s60_p.h \
+ kernel/qeventdispatcher_s60_p.h
+
+ LIBS += -lbafl -lestor
+
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+ INCLUDEPATH += ../3rdparty/s60
+
+ contains(QT_CONFIG, s60) {
+ SOURCES += kernel/qsoftkeymanager_s60.cpp
+ HEADERS += kernel/qsoftkeymanager_s60_p.h
+ }
+}
+
+
+unix:x11 {
+ INCLUDEPATH += ../3rdparty/xorg
+ HEADERS += \
+ kernel/qx11embed_x11.h \
+ kernel/qx11info_x11.h \
+ kernel/qkde_p.h
+
+ SOURCES += \
+ kernel/qapplication_x11.cpp \
+ kernel/qclipboard_x11.cpp \
+ kernel/qcursor_x11.cpp \
+ kernel/qdnd_x11.cpp \
+ kernel/qdesktopwidget_x11.cpp \
+ kernel/qmotifdnd_x11.cpp \
+ kernel/qsound_x11.cpp \
+ kernel/qwidget_x11.cpp \
+ kernel/qwidgetcreate_x11.cpp \
+ kernel/qx11embed_x11.cpp \
+ kernel/qx11info_x11.cpp \
+ kernel/qkeymapper_x11.cpp \
+ kernel/qkde.cpp
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qguieventdispatcher_glib.cpp
+ HEADERS += \
+ kernel/qguieventdispatcher_glib_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
+ }
+ SOURCES += \
+ kernel/qeventdispatcher_x11.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_x11_p.h
+}
+
+!qpa {
+ HEADERS += \
+ kernel/qsound.h \
+ kernel/qsound_p.h
+
+ SOURCES += \
+ kernel/qsound.cpp
+}
+
+qpa {
+ HEADERS += \
+ kernel/qdesktopwidget_qpa_p.h \
+ kernel/qwidgetwindow_qpa_p.h \
+
+ SOURCES += \
+ kernel/qapplication_qpa.cpp \
+ kernel/qdesktopwidget_qpa.cpp \
+ kernel/qwidget_qpa.cpp \
+ kernel/qwidgetwindow_qpa.cpp \
+}
+
+!qpa:!x11:mac {
+ SOURCES += \
+ kernel/qclipboard_mac.cpp \
+ kernel/qmime_mac.cpp \
+ kernel/qt_mac.cpp \
+ kernel/qkeymapper_mac.cpp
+
+ OBJECTIVE_HEADERS += \
+ qcocoawindow_mac_p.h \
+ qcocoapanel_mac_p.h \
+ qcocoawindowdelegate_mac_p.h \
+ qcocoaview_mac_p.h \
+ qcocoaapplication_mac_p.h \
+ qcocoaapplicationdelegate_mac_p.h \
+ qmacgesturerecognizer_mac_p.h \
+ qmultitouch_mac_p.h \
+ qcocoasharedwindowmethods_mac_p.h \
+ qcocoaintrospection_p.h
+
+ OBJECTIVE_SOURCES += \
+ kernel/qcursor_mac.mm \
+ kernel/qdnd_mac.mm \
+ kernel/qsound_mac.mm \
+ kernel/qapplication_mac.mm \
+ kernel/qwidget_mac.mm \
+ kernel/qcocoapanel_mac.mm \
+ kernel/qcocoaview_mac.mm \
+ kernel/qcocoawindow_mac.mm \
+ kernel/qcocoawindowdelegate_mac.mm \
+ kernel/qcocoamenuloader_mac.mm \
+ kernel/qcocoaapplication_mac.mm \
+ kernel/qcocoaapplicationdelegate_mac.mm \
+ kernel/qt_cocoa_helpers_mac.mm \
+ kernel/qdesktopwidget_mac.mm \
+ kernel/qeventdispatcher_mac.mm \
+ kernel/qcocoawindowcustomthemeframe_mac.mm \
+ kernel/qmacgesturerecognizer_mac.mm \
+ kernel/qmultitouch_mac.mm \
+ kernel/qcocoaintrospection_mac.mm
+
+ HEADERS += \
+ kernel/qt_cocoa_helpers_mac_p.h \
+ kernel/qcocoaapplication_mac_p.h \
+ kernel/qcocoaapplicationdelegate_mac_p.h \
+ kernel/qeventdispatcher_mac_p.h
+
+ MENU_NIB.files = mac/qt_menu.nib
+ MENU_NIB.path = Resources
+ MENU_NIB.version = Versions
+ QMAKE_BUNDLE_DATA += MENU_NIB
+ RESOURCES += mac/macresources.qrc
+
+ LIBS_PRIVATE += -framework AppKit
+}
+
+wince*: {
+ HEADERS += \
+ ../corelib/kernel/qfunctions_wince.h \
+ kernel/qguifunctions_wince.h
+
+ SOURCES += \
+ ../corelib/kernel/qfunctions_wince.cpp \
+ kernel/qguifunctions_wince.cpp
+}
diff --git a/src/widgets/kernel/mac.pri b/src/widgets/kernel/mac.pri
new file mode 100644
index 0000000000..df457dd166
--- /dev/null
+++ b/src/widgets/kernel/mac.pri
@@ -0,0 +1,4 @@
+!x11:!qpa:mac {
+ LIBS_PRIVATE += -framework Carbon -lz
+ *-mwerks:INCLUDEPATH += compat
+}
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
new file mode 100644
index 0000000000..69e9889e08
--- /dev/null
+++ b/src/widgets/kernel/qaction.cpp
@@ -0,0 +1,1520 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaction.h"
+#include "qactiongroup.h"
+
+#ifndef QT_NO_ACTION
+#include "qaction_p.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qlist.h"
+#include "qdebug.h"
+#include <private/qshortcutmap_p.h>
+#include <private/qapplication_p.h>
+#include <private/qmenu_p.h>
+
+#define QAPP_CHECK(functionName) \
+ if (!qApp) { \
+ qWarning("QAction: Initialize QApplication before calling '" functionName "'."); \
+ return; \
+ }
+
+QT_BEGIN_NAMESPACE
+
+/*
+ internal: guesses a descriptive text from a text suited for a menu entry
+ */
+static QString qt_strippedText(QString s)
+{
+ s.remove( QString::fromLatin1("...") );
+ int i = 0;
+ while (i < s.size()) {
+ ++i;
+ if (s.at(i-1) != QLatin1Char('&'))
+ continue;
+ if (i < s.size() && s.at(i) == QLatin1Char('&'))
+ ++i;
+ s.remove(i-1,1);
+ }
+ return s.trimmed();
+}
+
+
+QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
+ visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
+ forceEnabledInSoftkeys(false), menuActionSoftkeys(false),
+ iconVisibleInMenu(-1),
+ menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::NoSoftKey),
+ priority(QAction::NormalPriority)
+{
+#ifdef QT3_SUPPORT
+ static int qt_static_action_id = -1;
+ param = id = --qt_static_action_id;
+ act_signal = 0;
+#endif
+#ifndef QT_NO_SHORTCUT
+ shortcutId = 0;
+ shortcutContext = Qt::WindowShortcut;
+ autorepeat = true;
+#endif
+}
+
+QActionPrivate::~QActionPrivate()
+{
+}
+
+bool QActionPrivate::showStatusText(QWidget *widget, const QString &str)
+{
+#ifdef QT_NO_STATUSTIP
+ Q_UNUSED(widget);
+ Q_UNUSED(str);
+#else
+ if(QObject *object = widget ? widget : parent) {
+ QStatusTipEvent tip(str);
+ QApplication::sendEvent(object, &tip);
+ return true;
+ }
+#endif
+ return false;
+}
+
+void QActionPrivate::sendDataChanged()
+{
+ Q_Q(QAction);
+ QActionEvent e(QEvent::ActionChanged, q);
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *w = widgets.at(i);
+ QApplication::sendEvent(w, &e);
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ for (int i = 0; i < graphicsWidgets.size(); ++i) {
+ QGraphicsWidget *w = graphicsWidgets.at(i);
+ QApplication::sendEvent(w, &e);
+ }
+#endif
+ QApplication::sendEvent(q, &e);
+
+ emit q->changed();
+}
+
+#ifndef QT_NO_SHORTCUT
+void QActionPrivate::redoGrab(QShortcutMap &map)
+{
+ Q_Q(QAction);
+ if (shortcutId)
+ map.removeShortcut(shortcutId, q);
+ if (shortcut.isEmpty())
+ return;
+ shortcutId = map.addShortcut(q, shortcut, shortcutContext);
+ if (!enabled)
+ map.setShortcutEnabled(false, shortcutId, q);
+ if (!autorepeat)
+ map.setShortcutAutoRepeat(false, shortcutId, q);
+}
+
+void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
+{
+ Q_Q(QAction);
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
+ map.removeShortcut(id, q);
+ }
+ alternateShortcutIds.clear();
+ if (alternateShortcuts.isEmpty())
+ return;
+ for(int i = 0; i < alternateShortcuts.count(); ++i) {
+ const QKeySequence& alternate = alternateShortcuts.at(i);
+ if (!alternate.isEmpty())
+ alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext));
+ else
+ alternateShortcutIds.append(0);
+ }
+ if (!enabled) {
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
+ map.setShortcutEnabled(false, id, q);
+ }
+ }
+ if (!autorepeat) {
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
+ map.setShortcutAutoRepeat(false, id, q);
+ }
+ }
+}
+
+void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
+{
+ Q_Q(QAction);
+ if (shortcutId)
+ map.setShortcutEnabled(enable, shortcutId, q);
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
+ map.setShortcutEnabled(enable, id, q);
+ }
+}
+#endif // QT_NO_SHORTCUT
+
+
+/*!
+ \class QAction
+ \brief The QAction class provides an abstract user interface
+ action that can be inserted into widgets.
+
+ \ingroup mainwindow-classes
+
+
+ \omit
+ * parent and widget are different
+ * parent does not define context
+ \endomit
+
+ In applications many common commands can be invoked via menus,
+ toolbar buttons, and keyboard shortcuts. Since the user expects
+ each command to be performed in the same way, regardless of the
+ user interface used, it is useful to represent each command as
+ an \e action.
+
+ Actions can be added to menus and toolbars, and will
+ automatically keep them in sync. For example, in a word processor,
+ if the user presses a Bold toolbar button, the Bold menu item
+ will automatically be checked.
+
+ Actions can be created as independent objects, but they may
+ also be created during the construction of menus; the QMenu class
+ contains convenience functions for creating actions suitable for
+ use as menu items.
+
+ A QAction may contain an icon, menu text, a shortcut, status text,
+ "What's This?" text, and a tooltip. Most of these can be set in
+ the constructor. They can also be set independently with
+ setIcon(), setText(), setIconText(), setShortcut(),
+ setStatusTip(), setWhatsThis(), and setToolTip(). For menu items,
+ it is possible to set an individual font with setFont().
+
+ Actions are added to widgets using QWidget::addAction() or
+ QGraphicsWidget::addAction(). Note that an action must be added to a
+ widget before it can be used; this is also true when the shortcut should
+ be global (i.e., Qt::ApplicationShortcut as Qt::ShortcutContext).
+
+ Once a QAction has been created it should be added to the relevant
+ menu and toolbar, then connected to the slot which will perform
+ the action. For example:
+
+ \snippet examples/mainwindows/application/mainwindow.cpp 19
+ \codeline
+ \snippet examples/mainwindows/application/mainwindow.cpp 28
+ \snippet examples/mainwindows/application/mainwindow.cpp 31
+
+ We recommend that actions are created as children of the window
+ they are used in. In most cases actions will be children of
+ the application's main window.
+
+ \sa QMenu, QToolBar, {Application Example}
+*/
+
+/*!
+ \fn void QAction::trigger()
+
+ This is a convenience slot that calls activate(Trigger).
+*/
+
+/*!
+ \fn void QAction::hover()
+
+ This is a convenience slot that calls activate(Hover).
+*/
+
+/*!
+ \enum QAction::MenuRole
+
+ This enum describes how an action should be moved into the application menu on Mac OS X.
+
+ \value NoRole This action should not be put into the application menu
+ \value TextHeuristicRole This action should be put in the application menu based on the action's text
+ as described in the QMenuBar documentation.
+ \value ApplicationSpecificRole This action should be put in the application menu with an application specific role
+ \value AboutQtRole This action matches handles the "About Qt" menu item.
+ \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
+ the menu item will be set to "About <application name>". The application name is fetched from the
+ \c{Info.plist} file in the application's bundle (See \l{Deploying an Application on Mac OS X}).
+ \value PreferencesRole This action should be placed where the "Preferences..." menu item is in the application menu.
+ \value QuitRole This action should be placed where the Quit menu item is in the application menu.
+
+ Setting this value only has effect on items that are in the immediate menus
+ of the menubar, not the submenus of those menus. For example, if you have
+ File menu in your menubar and the File menu has a submenu, setting the
+ MenuRole for the actions in that submenu have no effect. They will never be moved.
+*/
+
+/*! \since 4.6
+
+ \enum QAction::SoftKeyRole
+
+ This enum describes how an action should be placed in the softkey bar. Currently this enum only
+ has an effect on the Symbian platform.
+
+ \value NoSoftKey This action should not be used as a softkey
+ \value PositiveSoftKey This action is used to describe a softkey with a positive or non-destructive
+ role such as Ok, Select, or Options.
+ \value NegativeSoftKey This action is used to describe a soft ey with a negative or destructive role
+ role such as Cancel, Discard, or Close.
+ \value SelectSoftKey This action is used to describe a role that selects a particular item or widget
+ in the application.
+
+ Actions with a softkey role defined are only visible in the softkey bar when the widget containing
+ the action has focus. If no widget currently has focus, the softkey framework will traverse up the
+ widget parent hierarchy looking for a widget containing softkey actions.
+ */
+
+/*!
+ Constructs an action with \a parent. If \a parent is an action
+ group the action will be automatically inserted into the group.
+*/
+QAction::QAction(QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+
+/*!
+ Constructs an action with some \a text and \a parent. If \a
+ parent is an action group the action will be automatically
+ inserted into the group.
+
+ The action uses a stripped version of \a text (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 will be used for
+ tooltips unless you specify a different text using
+ setToolTip().
+
+*/
+QAction::QAction(const QString &text, QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->text = text;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Constructs an action with an \a icon and some \a text and \a
+ parent. If \a parent is an action group the action will be
+ automatically inserted into the group.
+
+ The action uses a stripped version of \a text (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 will be used for
+ tooltips unless you specify a different text using
+ setToolTip().
+*/
+QAction::QAction(const QIcon &icon, const QString &text, QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->icon = icon;
+ d->text = text;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ \internal
+*/
+QAction::QAction(QActionPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QAction);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Returns the parent widget.
+*/
+QWidget *QAction::parentWidget() const
+{
+ QObject *ret = parent();
+ while (ret && !ret->isWidgetType())
+ ret = ret->parent();
+ return (QWidget*)ret;
+}
+
+/*!
+ \since 4.2
+ Returns a list of widgets this action has been added to.
+
+ \sa QWidget::addAction(), associatedGraphicsWidgets()
+*/
+QList<QWidget *> QAction::associatedWidgets() const
+{
+ Q_D(const QAction);
+ return d->widgets;
+}
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ \since 4.5
+ Returns a list of widgets this action has been added to.
+
+ \sa QWidget::addAction(), associatedWidgets()
+*/
+QList<QGraphicsWidget *> QAction::associatedGraphicsWidgets() const
+{
+ Q_D(const QAction);
+ return d->graphicsWidgets;
+}
+#endif
+
+#ifndef QT_NO_SHORTCUT
+/*!
+ \property QAction::shortcut
+ \brief the action's primary shortcut key
+
+ Valid keycodes for this property can be found in \l Qt::Key and
+ \l Qt::Modifier. There is no default shortcut key.
+*/
+void QAction::setShortcut(const QKeySequence &shortcut)
+{
+ QAPP_CHECK("setShortcut");
+
+ Q_D(QAction);
+ if (d->shortcut == shortcut)
+ return;
+
+ d->shortcut = shortcut;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+/*!
+ \since 4.2
+
+ Sets \a shortcuts as the list of shortcuts that trigger the
+ action. The first element of the list is the primary shortcut.
+
+ \sa shortcut
+*/
+void QAction::setShortcuts(const QList<QKeySequence> &shortcuts)
+{
+ Q_D(QAction);
+
+ QList <QKeySequence> listCopy = shortcuts;
+
+ QKeySequence primary;
+ if (!listCopy.isEmpty())
+ primary = listCopy.takeFirst();
+
+ if (d->shortcut == primary && d->alternateShortcuts == listCopy)
+ return;
+
+ QAPP_CHECK("setShortcuts");
+
+ d->shortcut = primary;
+ d->alternateShortcuts = listCopy;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+/*!
+ \since 4.2
+
+ Sets a platform dependent list of shortcuts based on the \a key.
+ The result of calling this function will depend on the currently running platform.
+ Note that more than one shortcut can assigned by this action.
+ If only the primary shortcut is required, use setShortcut instead.
+
+ \sa QKeySequence::keyBindings()
+*/
+void QAction::setShortcuts(QKeySequence::StandardKey key)
+{
+ QList <QKeySequence> list = QKeySequence::keyBindings(key);
+ setShortcuts(list);
+}
+
+/*!
+ Returns the primary shortcut.
+
+ \sa setShortcuts()
+*/
+QKeySequence QAction::shortcut() const
+{
+ Q_D(const QAction);
+ return d->shortcut;
+}
+
+/*!
+ \since 4.2
+
+ Returns the list of shortcuts, with the primary shortcut as
+ the first element of the list.
+
+ \sa setShortcuts()
+*/
+QList<QKeySequence> QAction::shortcuts() const
+{
+ Q_D(const QAction);
+ QList <QKeySequence> shortcuts;
+ if (!d->shortcut.isEmpty())
+ shortcuts << d->shortcut;
+ if (!d->alternateShortcuts.isEmpty())
+ shortcuts << d->alternateShortcuts;
+ return shortcuts;
+}
+
+/*!
+ \property QAction::shortcutContext
+ \brief the context for the action's shortcut
+
+ Valid values for this property can be found in \l Qt::ShortcutContext.
+ The default value is Qt::WindowShortcut.
+*/
+void QAction::setShortcutContext(Qt::ShortcutContext context)
+{
+ Q_D(QAction);
+ if (d->shortcutContext == context)
+ return;
+ QAPP_CHECK("setShortcutContext");
+ d->shortcutContext = context;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+Qt::ShortcutContext QAction::shortcutContext() const
+{
+ Q_D(const QAction);
+ return d->shortcutContext;
+}
+
+/*!
+ \property QAction::autoRepeat
+ \brief whether the action can auto repeat
+ \since 4.2
+
+ If true, the action will auto repeat when the keyboard shortcut
+ combination is held down, provided that keyboard auto repeat is
+ enabled on the system.
+ The default value is true.
+*/
+void QAction::setAutoRepeat(bool on)
+{
+ Q_D(QAction);
+ if (d->autorepeat == on)
+ return;
+ QAPP_CHECK("setAutoRepeat");
+ d->autorepeat = on;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+bool QAction::autoRepeat() const
+{
+ Q_D(const QAction);
+ return d->autorepeat;
+}
+#endif // QT_NO_SHORTCUT
+
+/*!
+ \property QAction::font
+ \brief the action's font
+
+ The font property is used to render the text set on the
+ QAction. The font will can be considered a hint as it will not be
+ consulted in all cases based upon application and style.
+
+ By default, this property contains the application's default font.
+
+ \sa QAction::setText() QStyle
+*/
+void QAction::setFont(const QFont &font)
+{
+ Q_D(QAction);
+ if (d->font == font)
+ return;
+
+ d->fontSet = true;
+ d->font = font;
+ d->sendDataChanged();
+}
+
+QFont QAction::font() const
+{
+ Q_D(const QAction);
+ return d->font;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(const QString &text, const QKeySequence &shortcut, QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->text = text;
+ setShortcut(shortcut);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
+ QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->text = text;
+ setShortcut(shortcut);
+ d->icon = icon;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+#endif
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+QAction::~QAction()
+{
+ Q_D(QAction);
+ for (int i = d->widgets.size()-1; i >= 0; --i) {
+ QWidget *w = d->widgets.at(i);
+ w->removeAction(this);
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ for (int i = d->graphicsWidgets.size()-1; i >= 0; --i) {
+ QGraphicsWidget *w = d->graphicsWidgets.at(i);
+ w->removeAction(this);
+ }
+#endif
+ if (d->group)
+ d->group->removeAction(this);
+#ifndef QT_NO_SHORTCUT
+ if (d->shortcutId && qApp) {
+ qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this);
+ for(int i = 0; i < d->alternateShortcutIds.count(); ++i) {
+ const int id = d->alternateShortcutIds.at(i);
+ qApp->d_func()->shortcutMap.removeShortcut(id, this);
+ }
+ }
+#endif
+}
+
+/*!
+ Sets this action group to \a group. The action will be automatically
+ added to the group's list of actions.
+
+ Actions within the group will be mutually exclusive.
+
+ \sa QActionGroup, QAction::actionGroup()
+*/
+void QAction::setActionGroup(QActionGroup *group)
+{
+ Q_D(QAction);
+ if(group == d->group)
+ return;
+
+ if(d->group)
+ d->group->removeAction(this);
+ d->group = group;
+ if(group)
+ group->addAction(this);
+}
+
+/*!
+ Returns the action group for this action. If no action group manages
+ this action then 0 will be returned.
+
+ \sa QActionGroup, QAction::setActionGroup()
+*/
+QActionGroup *QAction::actionGroup() const
+{
+ Q_D(const QAction);
+ return d->group;
+}
+
+
+/*!
+ \property QAction::icon
+ \brief the action's icon
+
+ In toolbars, the icon is used as the tool button icon; in menus,
+ it is displayed to the left of the menu text. There is no default
+ icon.
+
+ On Symbian the icons which are passed to softkeys, i.e. to actions with
+ softkey role, need to have pixmap alpha channel correctly set otherwise
+ drawing artifacts will appear when softkey is pressed down.
+
+ If a null icon (QIcon::isNull() is passed into this function,
+ the icon of the action is cleared.
+*/
+void QAction::setIcon(const QIcon &icon)
+{
+ Q_D(QAction);
+ d->icon = icon;
+ d->sendDataChanged();
+}
+
+QIcon QAction::icon() const
+{
+ Q_D(const QAction);
+ return d->icon;
+}
+
+#ifndef QT_NO_MENU
+/*!
+ Returns the menu contained by this action. Actions that contain
+ menus can be used to create menu items with submenus, or inserted
+ into toolbars to create buttons with popup menus.
+
+ \sa QMenu::addAction()
+*/
+QMenu *QAction::menu() const
+{
+ Q_D(const QAction);
+ return d->menu;
+}
+
+/*!
+ Sets the menu contained by this action to the specified \a menu.
+*/
+void QAction::setMenu(QMenu *menu)
+{
+ Q_D(QAction);
+ if (d->menu)
+ d->menu->d_func()->setOverrideMenuAction(0); //we reset the default action of any previous menu
+ d->menu = menu;
+ if (menu)
+ menu->d_func()->setOverrideMenuAction(this);
+ d->sendDataChanged();
+}
+#endif // QT_NO_MENU
+
+/*!
+ If \a b is true then this action will be considered a separator.
+
+ How a separator is represented depends on the widget it is inserted
+ into. Under most circumstances the text, submenu, and icon will be
+ ignored for separator actions.
+
+ \sa QAction::isSeparator()
+*/
+void QAction::setSeparator(bool b)
+{
+ Q_D(QAction);
+ if (d->separator == b)
+ return;
+
+ d->separator = b;
+ d->sendDataChanged();
+}
+
+/*!
+ Returns true if this action is a separator action; otherwise it
+ returns false.
+
+ \sa QAction::setSeparator()
+*/
+bool QAction::isSeparator() const
+{
+ Q_D(const QAction);
+ return d->separator;
+}
+
+/*!
+ \property QAction::text
+ \brief the action's descriptive text
+
+ If the action is added to a menu, the menu option will consist of
+ the icon (if there is one), the text, and the shortcut (if there
+ is one). If the text is not explicitly set in the constructor, or
+ by using setText(), the action's description icon text will be
+ used as text. There is no default text.
+
+ \sa iconText
+*/
+void QAction::setText(const QString &text)
+{
+ Q_D(QAction);
+ if (d->text == text)
+ return;
+
+ d->text = text;
+ d->sendDataChanged();
+}
+
+QString QAction::text() const
+{
+ Q_D(const QAction);
+ QString s = d->text;
+ if(s.isEmpty()) {
+ s = d->iconText;
+ s.replace(QLatin1Char('&'), QLatin1String("&&"));
+ }
+ return s;
+}
+
+
+
+
+
+/*!
+ \property QAction::iconText
+ \brief the action's descriptive icon text
+
+ If QToolBar::toolButtonStyle is set to a value that permits text to
+ be displayed, the text defined held in this property appears as a
+ label in the relevant tool button.
+
+ It also serves as the default text in menus and tooltips if the action
+ has not been defined with setText() or setToolTip(), and will
+ also be used in toolbar buttons if no icon has been defined using setIcon().
+
+ If the icon text is not explicitly set, the action's normal text will be
+ used for the icon text.
+
+ By default, this property contains an empty string.
+
+ \sa setToolTip(), setStatusTip()
+*/
+void QAction::setIconText(const QString &text)
+{
+ Q_D(QAction);
+ if (d->iconText == text)
+ return;
+
+ d->iconText = text;
+ d->sendDataChanged();
+}
+
+QString QAction::iconText() const
+{
+ Q_D(const QAction);
+ if (d->iconText.isEmpty())
+ return qt_strippedText(d->text);
+ return d->iconText;
+}
+
+/*!
+ \property QAction::toolTip
+ \brief the action's tooltip
+
+ This text is used for the tooltip. If no tooltip is specified,
+ the action's text is used.
+
+ By default, this property contains the action's text.
+
+ \sa setStatusTip() setShortcut()
+*/
+void QAction::setToolTip(const QString &tooltip)
+{
+ Q_D(QAction);
+ if (d->tooltip == tooltip)
+ return;
+
+ d->tooltip = tooltip;
+ d->sendDataChanged();
+}
+
+QString QAction::toolTip() const
+{
+ Q_D(const QAction);
+ if (d->tooltip.isEmpty()) {
+ if (!d->text.isEmpty())
+ return qt_strippedText(d->text);
+ return qt_strippedText(d->iconText);
+ }
+ return d->tooltip;
+}
+
+/*!
+ \property QAction::statusTip
+ \brief the action's status tip
+
+ The status tip is displayed on all status bars provided by the
+ action's top-level parent widget.
+
+ By default, this property contains an empty string.
+
+ \sa setToolTip() showStatusText()
+*/
+void QAction::setStatusTip(const QString &statustip)
+{
+ Q_D(QAction);
+ if (d->statustip == statustip)
+ return;
+
+ d->statustip = statustip;
+ d->sendDataChanged();
+}
+
+QString QAction::statusTip() const
+{
+ Q_D(const QAction);
+ return d->statustip;
+}
+
+/*!
+ \property QAction::whatsThis
+ \brief the action's "What's This?" help text
+
+ The "What's This?" text is used to provide a brief description of
+ the action. The text may contain rich text. There is no default
+ "What's This?" text.
+
+ \sa QWhatsThis Q3StyleSheet
+*/
+void QAction::setWhatsThis(const QString &whatsthis)
+{
+ Q_D(QAction);
+ if (d->whatsthis == whatsthis)
+ return;
+
+ d->whatsthis = whatsthis;
+ d->sendDataChanged();
+}
+
+QString QAction::whatsThis() const
+{
+ Q_D(const QAction);
+ return d->whatsthis;
+}
+
+/*!
+ \enum QAction::Priority
+ \since 4.6
+
+ This enum defines priorities for actions in user interface.
+
+ \value LowPriority The action should not be prioritized in
+ the user interface.
+
+ \value NormalPriority
+
+ \value HighPriority The action should be prioritized in
+ the user interface.
+
+ \sa priority
+*/
+
+
+/*!
+ \property QAction::priority
+ \since 4.6
+
+ \brief the actions's priority in the user interface.
+
+ This property can be set to indicate how the action should be prioritized
+ in the user interface.
+
+ For instance, when toolbars have the Qt::ToolButtonTextBesideIcon
+ mode set, then actions with LowPriority will not show the text
+ labels.
+*/
+void QAction::setPriority(Priority priority)
+{
+ Q_D(QAction);
+ if (d->priority == priority)
+ return;
+
+ d->priority = priority;
+ d->sendDataChanged();
+}
+
+QAction::Priority QAction::priority() const
+{
+ Q_D(const QAction);
+ return d->priority;
+}
+
+/*!
+ \property QAction::checkable
+ \brief whether the action is a checkable action
+
+ A checkable action is one which has an on/off state. For example,
+ in a word processor, a Bold toolbar button may be 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.
+ By default, this property 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
+ QActionGroup with the QActionGroup::exclusive property set to
+ true.
+
+ \sa QAction::setChecked()
+*/
+void QAction::setCheckable(bool b)
+{
+ Q_D(QAction);
+ if (d->checkable == b)
+ return;
+
+ d->checkable = b;
+ d->checked = false;
+ d->sendDataChanged();
+}
+
+bool QAction::isCheckable() const
+{
+ Q_D(const QAction);
+ return d->checkable;
+}
+
+/*!
+ \fn void QAction::toggle()
+
+ This is a convenience function for the \l checked property.
+ Connect to it to change the checked state to its opposite state.
+*/
+void QAction::toggle()
+{
+ Q_D(QAction);
+ setChecked(!d->checked);
+}
+
+/*!
+ \property QAction::checked
+ \brief whether the action is checked.
+
+ Only checkable actions can be checked. By default, this is false
+ (the action is unchecked).
+
+ \sa checkable
+*/
+void QAction::setChecked(bool b)
+{
+ Q_D(QAction);
+ if (!d->checkable || d->checked == b)
+ return;
+
+ QPointer<QAction> guard(this);
+ d->checked = b;
+ d->sendDataChanged();
+ if (guard)
+ emit toggled(b);
+}
+
+bool QAction::isChecked() const
+{
+ Q_D(const QAction);
+ return d->checked;
+}
+
+/*!
+ \fn void QAction::setDisabled(bool b)
+
+ This is a convenience function for the \l enabled property, that
+ is useful for signals--slots connections. If \a b is true the
+ action is disabled; otherwise it is enabled.
+*/
+
+/*!
+ \property QAction::enabled
+ \brief whether the action is enabled
+
+ Disabled actions cannot be chosen by the user. They do not
+ disappear from menus or toolbars, but they are displayed in a way
+ which indicates that they are unavailable. For example, they might
+ be displayed using only shades of gray.
+
+ \gui{What's This?} help on disabled actions is still available, provided
+ that the QAction::whatsThis property is set.
+
+ An action will be disabled when all widgets to which it is added
+ (with QWidget::addAction()) are disabled or not visible. When an
+ action is disabled, it is not possible to trigger it through its
+ shortcut.
+
+ By default, this property is true (actions are enabled).
+
+ \sa text
+*/
+void QAction::setEnabled(bool b)
+{
+ Q_D(QAction);
+ if (b == d->enabled && b != d->forceDisabled)
+ return;
+ d->forceDisabled = !b;
+ if (b && (!d->visible || (d->group && !d->group->isEnabled())))
+ return;
+ QAPP_CHECK("setEnabled");
+ d->enabled = b;
+#ifndef QT_NO_SHORTCUT
+ d->setShortcutEnabled(b, qApp->d_func()->shortcutMap);
+#endif
+ d->sendDataChanged();
+}
+
+bool QAction::isEnabled() const
+{
+ Q_D(const QAction);
+ return d->enabled;
+}
+
+/*!
+ \property QAction::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.
+
+ By default, this property is true (actions are visible).
+*/
+void QAction::setVisible(bool b)
+{
+ Q_D(QAction);
+ if (b == d->visible && b != d->forceInvisible)
+ return;
+ QAPP_CHECK("setVisible");
+ d->forceInvisible = !b;
+ d->visible = b;
+ d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ;
+#ifndef QT_NO_SHORTCUT
+ d->setShortcutEnabled(d->enabled, qApp->d_func()->shortcutMap);
+#endif
+ d->sendDataChanged();
+}
+
+
+bool QAction::isVisible() const
+{
+ Q_D(const QAction);
+ return d->visible;
+}
+
+/*!
+ \reimp
+*/
+bool
+QAction::event(QEvent *e)
+{
+#ifndef QT_NO_SHORTCUT
+ if (e->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+ Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()),
+ "QAction::event",
+ "Received shortcut event from incorrect shortcut");
+ if (se->isAmbiguous())
+ qWarning("QAction::eventFilter: Ambiguous shortcut overload: %s", QString(se->key()).toLatin1().constData());
+ else
+ activate(Trigger);
+ return true;
+ }
+#endif
+ return QObject::event(e);
+}
+
+/*!
+ Returns the user data as set in QAction::setData.
+
+ \sa setData()
+*/
+QVariant
+QAction::data() const
+{
+ Q_D(const QAction);
+ return d->userData;
+}
+
+/*!
+ \fn void QAction::setData(const QVariant &userData)
+
+ Sets the action's internal data to the given \a userData.
+
+ \sa data()
+*/
+void
+QAction::setData(const QVariant &data)
+{
+ Q_D(QAction);
+ d->userData = data;
+ d->sendDataChanged();
+}
+
+
+/*!
+ Updates the relevant status bar for the \a widget specified by sending a
+ QStatusTipEvent to its parent widget. Returns true if an event was sent;
+ otherwise returns false.
+
+ If a null widget is specified, the event is sent to the action's parent.
+
+ \sa statusTip
+*/
+bool
+QAction::showStatusText(QWidget *widget)
+{
+ return d_func()->showStatusText(widget, statusTip());
+}
+
+/*!
+ Sends the relevant signals for ActionEvent \a event.
+
+ Action based widgets use this API to cause the QAction
+ to emit signals as well as emitting their own.
+*/
+void QAction::activate(ActionEvent event)
+{
+ Q_D(QAction);
+ if(event == Trigger) {
+ QObject *guard = this;
+ QMetaObject::addGuard(&guard);
+ if(d->checkable) {
+ // the checked action of an exclusive group cannot be unchecked
+ if (d->checked && (d->group && d->group->isExclusive()
+ && d->group->checkedAction() == this)) {
+ if (guard)
+ emit triggered(true);
+ QMetaObject::removeGuard(&guard);
+ return;
+ }
+ setChecked(!d->checked);
+ }
+ if (guard)
+ emit triggered(d->checked);
+#ifdef QT3_SUPPORT
+ if (guard)
+ emit activated(d->param);
+#endif
+ QMetaObject::removeGuard(&guard);
+ } else if(event == Hover) {
+ emit hovered();
+ }
+}
+
+/*!
+ \fn void QAction::triggered(bool checked)
+
+ This signal is emitted when an action is activated by the user;
+ for example, when the user clicks a menu option, toolbar button,
+ or presses an action's shortcut key combination, or when trigger()
+ was called. Notably, it is \e not emitted when setChecked() or
+ toggle() is called.
+
+ If the action is checkable, \a checked is true if the action is
+ checked, or false if the action is unchecked.
+
+ \sa QAction::activate(), QAction::toggled(), checked
+*/
+
+/*!
+ \fn void QAction::toggled(bool checked)
+
+ This signal is emitted whenever a checkable action changes its
+ isChecked() status. This can be the result of a user interaction,
+ or because setChecked() was called.
+
+ \a checked is true if the action is checked, or false if the
+ action is unchecked.
+
+ \sa QAction::activate(), QAction::triggered(), checked
+*/
+
+/*!
+ \fn void QAction::hovered()
+
+ This signal is emitted when an action is highlighted by the user;
+ for example, when the user pauses with the cursor over a menu option,
+ toolbar button, or presses an action's shortcut key combination.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QAction::changed()
+
+ This signal is emitted when an action has changed. If you
+ are only interested in actions in a given widget, you can
+ watch for QWidget::actionEvent() sent with an
+ QEvent::ActionChanged.
+
+ \sa QWidget::actionEvent()
+*/
+
+/*!
+ \enum QAction::ActionEvent
+
+ This enum type is used when calling QAction::activate()
+
+ \value Trigger this will cause the QAction::triggered() signal to be emitted.
+
+ \value Hover this will cause the QAction::hovered() signal to be emitted.
+*/
+
+/*!
+ \fn void QAction::setMenuText(const QString &text)
+
+ Use setText() instead.
+*/
+
+/*!
+ \fn QString QAction::menuText() const
+
+ Use text() instead.
+*/
+
+/*!
+ \fn bool QAction::isOn() const
+
+ Use isChecked() instead.
+*/
+
+/*!
+ \fn void QAction::setOn(bool b)
+
+ Use setChecked() instead.
+*/
+
+/*!
+ \fn bool QAction::isToggleAction() const
+
+ Use isCheckable() instead.
+*/
+
+/*!
+ \fn void QAction::setToggleAction(bool b)
+
+ Use setCheckable() instead.
+*/
+
+/*!
+ \fn void QAction::setIconSet(const QIcon &i)
+
+ Use setIcon() instead.
+*/
+
+/*!
+ \fn bool QAction::addTo(QWidget *w)
+
+ Use QWidget::addAction() instead.
+
+ \oldcode
+ action->addTo(widget);
+ \newcode
+ widget->addAction(action);
+ \endcode
+*/
+
+/*!
+ \fn bool QAction::removeFrom(QWidget *w)
+
+ Use QWidget::removeAction() instead.
+
+ \oldcode
+ action->removeFrom(widget);
+ \newcode
+ widget->removeAction(action);
+ \endcode
+*/
+
+/*!
+ \fn void QAction::setAccel(const QKeySequence &shortcut)
+
+ Use setShortcut() instead.
+*/
+
+/*!
+ \fn QIcon QAction::iconSet() const
+
+ Use icon() instead.
+*/
+
+/*!
+ \fn QKeySequence QAction::accel() const
+
+ Use shortcut() instead.
+*/
+
+/*!
+ \fn void QAction::activated(int i);
+
+ Use triggered() instead.
+*/
+
+
+/*!
+ \property QAction::menuRole
+ \brief the action's menu role
+ \since 4.2
+
+ This indicates what role the action serves in the application menu on Mac
+ OS X. By default all action have the TextHeuristicRole, which means that
+ the action is added based on its text (see QMenuBar for more information).
+
+ The menu role can only be changed before the actions are put into the menu
+ bar in Mac OS X (usually just before the first application window is
+ shown).
+*/
+void QAction::setMenuRole(MenuRole menuRole)
+{
+ Q_D(QAction);
+ if (d->menuRole == menuRole)
+ return;
+
+ d->menuRole = menuRole;
+ d->sendDataChanged();
+}
+
+QAction::MenuRole QAction::menuRole() const
+{
+ Q_D(const QAction);
+ return d->menuRole;
+}
+
+/*!
+ \property QAction::softKeyRole
+ \brief the action's softkey role
+ \since 4.6
+
+ This indicates what type of role this action describes in the softkey framework
+ on platforms where such a framework is supported. Currently this is only
+ supported on the Symbian platform.
+
+ The softkey role can be changed any time.
+*/
+void QAction::setSoftKeyRole(SoftKeyRole softKeyRole)
+{
+ Q_D(QAction);
+ if (d->softKeyRole == softKeyRole)
+ return;
+
+ d->softKeyRole = softKeyRole;
+ d->sendDataChanged();
+}
+
+QAction::SoftKeyRole QAction::softKeyRole() const
+{
+ Q_D(const QAction);
+ return d->softKeyRole;
+}
+
+/*!
+ \property QAction::iconVisibleInMenu
+ \brief Whether or not an action should show an icon in a menu
+ \since 4.4
+
+ In some applications, it may make sense to have actions with icons in the
+ toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it
+ is false, it is not shown.
+
+ The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
+ is set for the application. Explicitly settings this property overrides
+ the presence (or abscence) of the attribute.
+
+ For example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qaction.cpp 0
+
+ \sa QAction::icon QApplication::setAttribute()
+*/
+void QAction::setIconVisibleInMenu(bool visible)
+{
+ Q_D(QAction);
+ if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
+ int oldValue = d->iconVisibleInMenu;
+ d->iconVisibleInMenu = visible;
+ // Only send data changed if we really need to.
+ if (oldValue != -1
+ || (oldValue == -1
+ && visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))) {
+ d->sendDataChanged();
+ }
+ }
+}
+
+bool QAction::isIconVisibleInMenu() const
+{
+ Q_D(const QAction);
+ if (d->iconVisibleInMenu == -1) {
+ return !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus);
+ }
+ return d->iconVisibleInMenu;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qaction.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h
new file mode 100644
index 0000000000..856fd92f10
--- /dev/null
+++ b/src/widgets/kernel/qaction.h
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTION_H
+#define QACTION_H
+
+#include <QtGui/qkeysequence.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qicon.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QMenu;
+class QActionGroup;
+class QActionPrivate;
+class QGraphicsWidget;
+
+class Q_GUI_EXPORT QAction : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAction)
+
+ Q_ENUMS(MenuRole)
+ Q_ENUMS(SoftKeyRole)
+ Q_ENUMS(Priority)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
+ Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
+ Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
+#ifndef QT_NO_SHORTCUT
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
+ Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
+#endif
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
+ Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
+ Q_PROPERTY(SoftKeyRole softKeyRole READ softKeyRole WRITE setSoftKeyRole NOTIFY changed)
+ Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority)
+
+public:
+ enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
+ AboutRole, PreferencesRole, QuitRole };
+ enum SoftKeyRole {
+ NoSoftKey, PositiveSoftKey, NegativeSoftKey, SelectSoftKey };
+ enum Priority { LowPriority = 0,
+ NormalPriority = 128,
+ HighPriority = 256};
+ explicit QAction(QObject* parent);
+ QAction(const QString &text, QObject* parent);
+ QAction(const QIcon &icon, const QString &text, QObject* parent);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QAction(QObject* parent, const char* name);
+ QT3_SUPPORT_CONSTRUCTOR QAction(const QString &text, const QKeySequence &shortcut,
+ QObject* parent, const char* name);
+ QT3_SUPPORT_CONSTRUCTOR QAction(const QIcon &icon, const QString &text,
+ const QKeySequence &shortcut,
+ QObject* parent, const char* name);
+#endif
+ ~QAction();
+
+ void setActionGroup(QActionGroup *group);
+ QActionGroup *actionGroup() const;
+ void setIcon(const QIcon &icon);
+ QIcon icon() const;
+
+ void setText(const QString &text);
+ QString text() const;
+
+ void setIconText(const QString &text);
+ QString iconText() const;
+
+ void setToolTip(const QString &tip);
+ QString toolTip() const;
+
+ void setStatusTip(const QString &statusTip);
+ QString statusTip() const;
+
+ void setWhatsThis(const QString &what);
+ QString whatsThis() const;
+
+ void setPriority(Priority priority);
+ Priority priority() const;
+
+#ifndef QT_NO_MENU
+ QMenu *menu() const;
+ void setMenu(QMenu *menu);
+#endif
+
+ void setSeparator(bool b);
+ bool isSeparator() const;
+
+#ifndef QT_NO_SHORTCUT
+ void setShortcut(const QKeySequence &shortcut);
+ QKeySequence shortcut() const;
+
+ void setShortcuts(const QList<QKeySequence> &shortcuts);
+ void setShortcuts(QKeySequence::StandardKey);
+ QList<QKeySequence> shortcuts() const;
+
+ void setShortcutContext(Qt::ShortcutContext context);
+ Qt::ShortcutContext shortcutContext() const;
+
+ void setAutoRepeat(bool);
+ bool autoRepeat() const;
+#endif
+
+ void setFont(const QFont &font);
+ QFont font() const;
+
+ void setCheckable(bool);
+ bool isCheckable() const;
+
+ QVariant data() const;
+ void setData(const QVariant &var);
+
+ bool isChecked() const;
+
+ bool isEnabled() const;
+
+ bool isVisible() const;
+
+ enum ActionEvent { Trigger, Hover };
+ void activate(ActionEvent event);
+ bool showStatusText(QWidget *widget=0);
+
+ void setMenuRole(MenuRole menuRole);
+ MenuRole menuRole() const;
+
+ void setSoftKeyRole(SoftKeyRole softKeyRole);
+ SoftKeyRole softKeyRole() const;
+
+ void setIconVisibleInMenu(bool visible);
+ bool isIconVisibleInMenu() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setMenuText(const QString &text) { setText(text); }
+ inline QT3_SUPPORT QString menuText() const { return text(); }
+ inline QT3_SUPPORT bool isOn() const { return isChecked(); }
+ inline QT3_SUPPORT bool isToggleAction() const { return isCheckable(); }
+ inline QT3_SUPPORT void setToggleAction(bool b) { setCheckable(b); }
+ inline QT3_SUPPORT void setIconSet(const QIcon &i) { setIcon(i); }
+ inline QT3_SUPPORT QIcon iconSet() const { return icon(); }
+ inline QT3_SUPPORT bool addTo(QWidget *w) { w->addAction(this); return true; }
+ inline QT3_SUPPORT bool removeFrom(QWidget *w) { w->removeAction(this); return true; }
+ inline QT3_SUPPORT void setAccel(const QKeySequence &shortcut) { setShortcut(shortcut); }
+ inline QT3_SUPPORT QKeySequence accel() const { return shortcut(); }
+#endif
+
+ QWidget *parentWidget() const;
+
+ QList<QWidget *> associatedWidgets() const;
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsWidget *> associatedGraphicsWidgets() const; // ### suboptimal
+#endif
+
+protected:
+ bool event(QEvent *);
+ QAction(QActionPrivate &dd, QObject *parent);
+
+public Q_SLOTS:
+#ifdef QT3_SUPPORT
+ inline QT_MOC_COMPAT void setOn(bool b) { setChecked(b); }
+#endif
+ void trigger() { activate(Trigger); }
+ void hover() { activate(Hover); }
+ void setChecked(bool);
+ void toggle();
+ void setEnabled(bool);
+ inline void setDisabled(bool b) { setEnabled(!b); }
+ void setVisible(bool);
+
+Q_SIGNALS:
+ void changed();
+ void triggered(bool checked = false);
+ void hovered();
+ void toggled(bool);
+#ifdef QT3_SUPPORT
+ QT_MOC_COMPAT void activated(int = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QAction)
+
+#ifdef QT3_SUPPORT
+ friend class QMenuItem;
+#endif
+ friend class QGraphicsWidget;
+ friend class QWidget;
+ friend class QActionGroup;
+ friend class QMenu;
+ friend class QMenuPrivate;
+ friend class QMenuBar;
+ friend class QShortcutMap;
+ friend class QToolButton;
+#ifdef Q_WS_MAC
+ friend void qt_mac_clear_status_text(QAction *action);
+#endif
+};
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtGui/qactiongroup.h>
+QT_END_INCLUDE_NAMESPACE
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACTION_H
diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h
new file mode 100644
index 0000000000..f3154f90c1
--- /dev/null
+++ b/src/widgets/kernel/qaction_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTION_P_H
+#define QACTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qaction.h"
+#include "QtGui/qmenu.h"
+#include "private/qgraphicswidget_p.h"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACTION
+
+#ifdef QT3_SUPPORT
+class QMenuItemEmitter;
+#endif
+
+class QShortcutMap;
+
+class Q_AUTOTEST_EXPORT QActionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAction)
+public:
+ QActionPrivate();
+ ~QActionPrivate();
+
+ static QActionPrivate *get(QAction *q)
+ {
+ return q->d_func();
+ }
+
+ bool showStatusText(QWidget *w, const QString &str);
+
+ QPointer<QActionGroup> group;
+ QString text;
+ QString iconText;
+ QIcon icon;
+ QString tooltip;
+ QString statustip;
+ QString whatsthis;
+#ifndef QT_NO_SHORTCUT
+ QKeySequence shortcut;
+ QList<QKeySequence> alternateShortcuts;
+#endif
+ QVariant userData;
+#ifndef QT_NO_SHORTCUT
+ int shortcutId;
+ QList<int> alternateShortcutIds;
+ Qt::ShortcutContext shortcutContext;
+ uint autorepeat : 1;
+#endif
+ QFont font;
+ QPointer<QMenu> menu;
+ uint enabled : 1, forceDisabled : 1;
+ uint visible : 1, forceInvisible : 1;
+ uint checkable : 1;
+ uint checked : 1;
+ uint separator : 1;
+ uint fontSet : 1;
+
+ //for soft keys management
+ uint forceEnabledInSoftkeys : 1;
+ uint menuActionSoftkeys : 1;
+ int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
+
+ QAction::MenuRole menuRole;
+ QAction::SoftKeyRole softKeyRole;
+ QAction::Priority priority;
+
+ QList<QWidget *> widgets;
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsWidget *> graphicsWidgets;
+#endif
+#ifndef QT_NO_SHORTCUT
+ void redoGrab(QShortcutMap &map);
+ void redoGrabAlternate(QShortcutMap &map);
+ void setShortcutEnabled(bool enable, QShortcutMap &map);
+
+ static QShortcutMap *globalMap;
+#endif // QT_NO_SHORTCUT
+
+#ifdef QT3_SUPPORT //for menubar/menu compat
+ QMenuItemEmitter *act_signal;
+ int id, param;
+#endif
+ void sendDataChanged();
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QACTION_P_H
diff --git a/src/widgets/kernel/qactiongroup.cpp b/src/widgets/kernel/qactiongroup.cpp
new file mode 100644
index 0000000000..95ea8afab7
--- /dev/null
+++ b/src/widgets/kernel/qactiongroup.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qactiongroup.h"
+
+#ifndef QT_NO_ACTION
+
+#include "qaction_p.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qlist.h"
+
+QT_BEGIN_NAMESPACE
+
+class QActionGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QActionGroup)
+public:
+ QActionGroupPrivate() : exclusive(1), enabled(1), visible(1) { }
+ QList<QAction *> actions;
+ QPointer<QAction> current;
+ uint exclusive : 1;
+ uint enabled : 1;
+ uint visible : 1;
+
+private:
+ void _q_actionTriggered(); //private slot
+ void _q_actionChanged(); //private slot
+ void _q_actionHovered(); //private slot
+};
+
+void QActionGroupPrivate::_q_actionChanged()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error");
+ if(exclusive) {
+ if (action->isChecked()) {
+ if (action != current) {
+ if(current)
+ current->setChecked(false);
+ current = action;
+ }
+ } else if (action == current) {
+ current = 0;
+ }
+ }
+}
+
+void QActionGroupPrivate::_q_actionTriggered()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionTriggered", "internal error");
+ emit q->triggered(action);
+ emit q->selected(action);
+}
+
+void QActionGroupPrivate::_q_actionHovered()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionHovered", "internal error");
+ emit q->hovered(action);
+}
+
+/*!
+ \class QActionGroup
+ \brief The QActionGroup class groups actions together.
+
+ \ingroup mainwindow-classes
+
+ In some situations it is useful to group actions together. For
+ example, if you have a \gui{Left Align} action, a \gui{Right
+ Align} action, a \gui{Justify} action, and a \gui{Center} action,
+ only one of these actions should be active at any one time. One
+ simple way of achieving this is to group the actions together in
+ an action group.
+
+ Here's a example (from the \l{mainwindows/menus}{Menus} example):
+
+ \snippet examples/mainwindows/menus/mainwindow.cpp 6
+
+ Here we create a new action group. Since the action group is
+ exclusive by default, only one of the actions in the group is
+ checked at any one time.
+
+ \img qactiongroup-align.png Alignment options in a QMenu
+
+ A QActionGroup emits an triggered() signal when one of its
+ actions is chosen. Each action in an action group emits its
+ triggered() signal as usual.
+
+ As stated above, an action group is \l exclusive by default; it
+ ensures that only one checkable action is active at any one time.
+ If you want to group checkable actions without making them
+ exclusive, you can turn of exclusiveness by calling
+ setExclusive(false).
+
+ Actions can be added to an action group using addAction(), but it
+ is usually more convenient to specify a group when creating
+ actions; this ensures that actions are automatically created with
+ a parent. Actions can be visually separated from each other by
+ adding a separator action to the group; create an action and use
+ QAction's \l {QAction::}{setSeparator()} function to make it
+ considered a separator. Action groups are added to widgets with
+ the QWidget::addActions() function.
+
+ \sa QAction
+*/
+
+/*!
+ Constructs an action group for the \a parent object.
+
+ The action group is exclusive by default. Call setExclusive(false)
+ to make the action group non-exclusive.
+*/
+QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
+{
+}
+
+/*!
+ Destroys the action group.
+*/
+QActionGroup::~QActionGroup()
+{
+}
+
+/*!
+ \fn QAction *QActionGroup::addAction(QAction *action)
+
+ Adds the \a action to this group, and returns it.
+
+ Normally an action is added to a group by creating it with the
+ group as its parent, so this function is not usually used.
+
+ \sa QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(QAction* a)
+{
+ Q_D(QActionGroup);
+ if(!d->actions.contains(a)) {
+ d->actions.append(a);
+ QObject::connect(a, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+ QObject::connect(a, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+ QObject::connect(a, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
+ }
+ if(!a->d_func()->forceDisabled) {
+ a->setEnabled(d->enabled);
+ a->d_func()->forceDisabled = false;
+ }
+ if(!a->d_func()->forceInvisible) {
+ a->setVisible(d->visible);
+ a->d_func()->forceInvisible = false;
+ }
+ if(a->isChecked())
+ d->current = a;
+ QActionGroup *oldGroup = a->d_func()->group;
+ if(oldGroup != this) {
+ if (oldGroup)
+ oldGroup->removeAction(a);
+ a->d_func()->group = this;
+ }
+ return a;
+}
+
+/*!
+ Creates and returns an action with \a text. The newly created
+ action is a child of this action 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 QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(const QString &text)
+{
+ return new QAction(text, this);
+}
+
+/*!
+ Creates and returns an action with \a text and an \a icon. The
+ newly created action is a child of this action group.
+
+ Normally an action is added to a group by creating it with the
+ group as its parent, so this function is not usually used.
+
+ \sa QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(const QIcon &icon, const QString &text)
+{
+ return new QAction(icon, text, this);
+}
+
+/*!
+ Removes the \a action from this group. The action will have no
+ parent as a result.
+
+ \sa QAction::setActionGroup()
+*/
+void QActionGroup::removeAction(QAction *action)
+{
+ Q_D(QActionGroup);
+ if (d->actions.removeAll(action)) {
+ if (action == d->current)
+ d->current = 0;
+ QObject::disconnect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+ QObject::disconnect(action, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+ QObject::disconnect(action, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
+ action->d_func()->group = 0;
+ }
+}
+
+/*!
+ Returns the list of this groups's actions. This may be empty.
+*/
+QList<QAction*> QActionGroup::actions() const
+{
+ Q_D(const QActionGroup);
+ return d->actions;
+}
+
+/*!
+ \property QActionGroup::exclusive
+ \brief whether the action group does exclusive checking
+
+ If exclusive is true, only one checkable action in the action group
+ can ever be active at any time. If the user chooses another
+ checkable action in the group, the one they chose becomes active and
+ the one that was active becomes inactive.
+
+ \sa QAction::checkable
+*/
+void QActionGroup::setExclusive(bool b)
+{
+ Q_D(QActionGroup);
+ d->exclusive = b;
+}
+
+bool QActionGroup::isExclusive() const
+{
+ Q_D(const QActionGroup);
+ return d->exclusive;
+}
+
+/*!
+ \fn void QActionGroup::setDisabled(bool b)
+
+ This is a convenience function for the \l enabled property, that
+ is useful for signals--slots connections. If \a b is true the
+ action group is disabled; otherwise it is enabled.
+*/
+
+/*!
+ \property QActionGroup::enabled
+ \brief whether the action group is enabled
+
+ Each action in the group will be enabled or disabled unless it
+ has been explicitly disabled.
+
+ \sa QAction::setEnabled()
+*/
+void QActionGroup::setEnabled(bool b)
+{
+ Q_D(QActionGroup);
+ d->enabled = b;
+ for(QList<QAction*>::const_iterator it = d->actions.constBegin(); it != d->actions.constEnd(); ++it) {
+ if(!(*it)->d_func()->forceDisabled) {
+ (*it)->setEnabled(b);
+ (*it)->d_func()->forceDisabled = false;
+ }
+ }
+}
+
+bool QActionGroup::isEnabled() const
+{
+ Q_D(const QActionGroup);
+ return d->enabled;
+}
+
+/*!
+ Returns the currently checked action in the group, or 0 if none
+ are checked.
+*/
+QAction *QActionGroup::checkedAction() const
+{
+ Q_D(const QActionGroup);
+ return d->current;
+}
+
+/*!
+ \property QActionGroup::visible
+ \brief whether the action group is visible
+
+ Each action in the action group will match the visible state of
+ this group unless it has been explicitly hidden.
+
+ \sa QAction::setEnabled()
+*/
+void QActionGroup::setVisible(bool b)
+{
+ Q_D(QActionGroup);
+ d->visible = b;
+ for(QList<QAction*>::Iterator it = d->actions.begin(); it != d->actions.end(); ++it) {
+ if(!(*it)->d_func()->forceInvisible) {
+ (*it)->setVisible(b);
+ (*it)->d_func()->forceInvisible = false;
+ }
+ }
+}
+
+bool QActionGroup::isVisible() const
+{
+ Q_D(const QActionGroup);
+ return d->visible;
+}
+
+/*!
+ \fn void QActionGroup::triggered(QAction *action)
+
+ This signal is emitted when the given \a action in the action
+ group is activated by the user; for example, when the user clicks
+ a menu option, toolbar button, or presses an action's shortcut key
+ combination.
+
+ Connect to this signal for command actions.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QActionGroup::hovered(QAction *action)
+
+ This signal is emitted when the given \a action in the action
+ group is highlighted by the user; for example, when the user
+ pauses with the cursor over a menu option, toolbar button, or
+ presses an action's shortcut key combination.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QActionGroup::add(QAction* a)
+
+ Use addAction() instead.
+*/
+
+/*!
+ \fn void QActionGroup::addSeparator()
+
+ Normally you add a separator to the menus or widgets to which
+ actions are added, so this function is very rarely needed.
+
+ \oldcode
+ actionGroup->addSeparator();
+ \newcode
+ QAction *separator = new QAction(this);
+ separator->setSeparator(true);
+ actionGroup->addAction(separator);
+ \endcode
+*/
+
+/*!
+ \fn bool QActionGroup::addTo(QWidget *widget)
+
+ \oldcode
+ actionGroup->addTo(widget);
+ \newcode
+ widget->addActions(actionGroup->actions());
+ \endcode
+*/
+
+/*!
+ \fn void QActionGroup::selected(QAction *action);
+
+ Use triggered() instead.
+
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qactiongroup.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qactiongroup.h b/src/widgets/kernel/qactiongroup.h
new file mode 100644
index 0000000000..88f4fe8eac
--- /dev/null
+++ b/src/widgets/kernel/qactiongroup.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIONGROUP_H
+#define QACTIONGROUP_H
+
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QActionGroupPrivate;
+
+class Q_GUI_EXPORT QActionGroup : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QActionGroup)
+
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+
+public:
+ explicit QActionGroup(QObject* parent);
+ ~QActionGroup();
+
+ QAction *addAction(QAction* a);
+ QAction *addAction(const QString &text);
+ QAction *addAction(const QIcon &icon, const QString &text);
+ void removeAction(QAction *a);
+ QList<QAction*> actions() const;
+
+ QAction *checkedAction() const;
+ bool isExclusive() const;
+ bool isEnabled() const;
+ bool isVisible() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void add(QAction* a) { addAction(a); }
+ inline QT3_SUPPORT void addSeparator()
+ { QAction *act = new QAction(this); act->setSeparator(true); addAction(act); }
+ inline QT3_SUPPORT bool addTo(QWidget *w) { w->addActions(actions()); return true; }
+#endif
+
+public Q_SLOTS:
+ void setEnabled(bool);
+ inline void setDisabled(bool b) { setEnabled(!b); }
+ void setVisible(bool);
+ void setExclusive(bool);
+
+Q_SIGNALS:
+ void triggered(QAction *);
+ QT_MOC_COMPAT void selected(QAction *);
+ void hovered(QAction *);
+
+private:
+ Q_DISABLE_COPY(QActionGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
+ Q_PRIVATE_SLOT(d_func(), void _q_actionChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_actionHovered())
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACTIONGROUP_H
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
new file mode 100644
index 0000000000..2044cf78ce
--- /dev/null
+++ b/src/widgets/kernel/qapplication.cpp
@@ -0,0 +1,5687 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qabstracteventdispatcher.h"
+#include "qaccessible.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qdir.h"
+#include "qevent.h"
+#include "qfile.h"
+#include "qfileinfo.h"
+#include "qgraphicsscene.h"
+#include "qhash.h"
+#include "qset.h"
+#include "qlayout.h"
+#include "qsessionmanager.h"
+#include "qstyle.h"
+#include "qstylefactory.h"
+#include "qtextcodec.h"
+#include "qtranslator.h"
+#include "qvariant.h"
+#include "qwidget.h"
+#include "private/qdnd_p.h"
+#include "qcolormap.h"
+#include "qdebug.h"
+#include "private/qstylesheetstyle_p.h"
+#include "private/qstyle_p.h"
+#include "qmessagebox.h"
+#include <QtGui/qgraphicsproxywidget.h>
+
+#include "qinputcontext.h"
+#include "private/qkeymapper_p.h"
+
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN)
+#include "qinputcontextfactory.h"
+#endif
+
+#include "qguiplatformplugin_p.h"
+
+#include <qthread.h>
+#include <private/qthread_p.h>
+
+#include <private/qfont_p.h>
+
+#include <stdlib.h>
+
+#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
+#include <link.h>
+#endif
+
+#include "qapplication_p.h"
+#include "private/qevent_p.h"
+#include "qwidget_p.h"
+
+#include "qapplication.h"
+
+#include "qgesture.h"
+#include "private/qgesturemanager_p.h"
+
+#ifndef QT_NO_LIBRARY
+#include "qlibrary.h"
+#endif
+
+#ifdef Q_WS_WINCE
+#include "qdatetime.h"
+#include "qguifunctions_wince.h"
+extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
+#endif
+
+#include "qdatetime.h"
+
+#ifdef QT_MAC_USE_COCOA
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+//#define ALIEN_DEBUG
+
+#if defined(Q_OS_SYMBIAN)
+#include "qt_s60_p.h"
+#endif
+
+static void initResources()
+{
+#if defined(Q_WS_WINCE)
+ Q_INIT_RESOURCE_EXTERN(qstyle_wince)
+ Q_INIT_RESOURCE(qstyle_wince);
+#elif defined(Q_OS_SYMBIAN)
+ Q_INIT_RESOURCE_EXTERN(qstyle_s60)
+ Q_INIT_RESOURCE(qstyle_s60);
+#else
+ Q_INIT_RESOURCE_EXTERN(qstyle)
+ Q_INIT_RESOURCE(qstyle);
+#endif
+ Q_INIT_RESOURCE_EXTERN(qmessagebox)
+ Q_INIT_RESOURCE(qmessagebox);
+#if !defined(QT_NO_PRINTDIALOG)
+ Q_INIT_RESOURCE_EXTERN(qprintdialog)
+ Q_INIT_RESOURCE(qprintdialog);
+#endif
+
+}
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT void qt_call_post_routines();
+
+QApplication::Type qt_appType=QApplication::Tty;
+QApplicationPrivate *QApplicationPrivate::self = 0;
+
+QInputContext *QApplicationPrivate::inputContext = 0;
+
+bool QApplicationPrivate::quitOnLastWindowClosed = true;
+
+#ifdef Q_WS_WINCE
+int QApplicationPrivate::autoMaximizeThreshold = -1;
+bool QApplicationPrivate::autoSipEnabled = false;
+#else
+bool QApplicationPrivate::autoSipEnabled = true;
+#endif
+
+QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags)
+ : QApplicationPrivateBase(argc, argv, flags)
+{
+ application_type = type;
+ qt_appType = type;
+
+#ifndef QT_NO_SESSIONMANAGER
+ is_session_restored = false;
+#endif
+
+ quitOnLastWindowClosed = true;
+
+#ifdef QT3_SUPPORT
+ qt_compat_used = 0;
+ qt_compat_resolved = 0;
+ qt_tryAccelEvent = 0;
+ qt_tryComposeUnicode = 0;
+ qt_dispatchAccelEvent = 0;
+#endif
+#if defined(Q_WS_QWS) && !defined(QT_NO_DIRECTPAINTER)
+ directPainters = 0;
+#endif
+
+#ifndef QT_NO_GESTURES
+ gestureManager = 0;
+ gestureWidget = 0;
+#endif // QT_NO_GESTURES
+
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ move_cursor = 0;
+ copy_cursor = 0;
+ link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ ignore_cursor = 0;
+#endif
+
+ if (!self)
+ self = this;
+}
+
+QApplicationPrivate::~QApplicationPrivate()
+{
+ if (self == this)
+ self = 0;
+}
+
+/*!
+ \class QApplication
+ \brief The QApplication class manages the GUI application's control
+ flow and main settings.
+
+ QApplication contains the main event loop, where all events from the window
+ system and other sources are processed and dispatched. It also handles the
+ application's initialization, finalization, and provides session
+ management. In addition, QApplication handles most of the system-wide and
+ application-wide settings.
+
+ For any GUI application using Qt, there is precisely \bold one QApplication
+ object, no matter whether the application has 0, 1, 2 or more windows at
+ any given time. For non-GUI Qt applications, use QCoreApplication instead,
+ as it does not depend on the \l QtGui library.
+
+ The QApplication object is accessible through the instance() function that
+ returns a pointer equivalent to the global qApp pointer.
+
+ QApplication's main areas of responsibility are:
+ \list
+ \o It initializes the application with the user's desktop settings
+ such as palette(), font() and doubleClickInterval(). It keeps
+ track of these properties in case the user changes the desktop
+ globally, for example through some kind of control panel.
+
+ \o It performs event handling, meaning that it receives events
+ from the underlying window system and dispatches them to the
+ relevant widgets. By using sendEvent() and postEvent() you can
+ send your own events to widgets.
+
+ \o It parses common command line arguments and sets its internal
+ state accordingly. See the \l{QApplication::QApplication()}
+ {constructor documentation} below for more details.
+
+ \o It defines the application's look and feel, which is
+ encapsulated in a QStyle object. This can be changed at runtime
+ with setStyle().
+
+ \o It specifies how the application is to allocate colors. See
+ setColorSpec() for details.
+
+ \o It provides localization of strings that are visible to the
+ user via translate().
+
+ \o It provides some magical objects like the desktop() and the
+ clipboard().
+
+ \o It knows about the application's windows. You can ask which
+ widget is at a certain position using widgetAt(), get a list of
+ topLevelWidgets() and closeAllWindows(), etc.
+
+ \o It manages the application's mouse cursor handling, see
+ setOverrideCursor()
+
+ \o On the X window system, it provides functions to flush and sync
+ the communication stream, see flushX() and syncX().
+
+ \o It provides support for sophisticated \l{Session Management}
+ {session management}. This makes it possible for applications
+ to terminate gracefully when the user logs out, to cancel a
+ shutdown process if termination isn't possible and even to
+ preserve the entire application's state for a future session.
+ See isSessionRestored(), sessionId() and commitData() and
+ saveState() for details.
+ \endlist
+
+ Since the QApplication object does so much initialization, it \e{must} be
+ created before any other objects related to the user interface are created.
+ QApplication also deals with common command line arguments. Hence, it is
+ usually a good idea to create it \e before any interpretation or
+ modification of \c argv is done in the application itself.
+
+ \table
+ \header
+ \o{2,1} Groups of functions
+
+ \row
+ \o System settings
+ \o desktopSettingsAware(),
+ setDesktopSettingsAware(),
+ cursorFlashTime(),
+ setCursorFlashTime(),
+ doubleClickInterval(),
+ setDoubleClickInterval(),
+ setKeyboardInputInterval(),
+ wheelScrollLines(),
+ setWheelScrollLines(),
+ palette(),
+ setPalette(),
+ font(),
+ setFont(),
+ fontMetrics().
+
+ \row
+ \o Event handling
+ \o exec(),
+ processEvents(),
+ exit(),
+ quit().
+ sendEvent(),
+ postEvent(),
+ sendPostedEvents(),
+ removePostedEvents(),
+ hasPendingEvents(),
+ notify(),
+ macEventFilter(),
+ qwsEventFilter(),
+ x11EventFilter(),
+ x11ProcessEvent(),
+ winEventFilter().
+
+ \row
+ \o GUI Styles
+ \o style(),
+ setStyle().
+
+ \row
+ \o Color usage
+ \o colorSpec(),
+ setColorSpec(),
+ qwsSetCustomColors().
+
+ \row
+ \o Text handling
+ \o installTranslator(),
+ removeTranslator()
+ translate().
+
+ \row
+ \o Widgets
+ \o allWidgets(),
+ topLevelWidgets(),
+ desktop(),
+ activePopupWidget(),
+ activeModalWidget(),
+ clipboard(),
+ focusWidget(),
+ activeWindow(),
+ widgetAt().
+
+ \row
+ \o Advanced cursor handling
+ \o overrideCursor(),
+ setOverrideCursor(),
+ restoreOverrideCursor().
+
+ \row
+ \o X Window System synchronization
+ \o flushX(),
+ syncX().
+
+ \row
+ \o Session management
+ \o isSessionRestored(),
+ sessionId(),
+ commitData(),
+ saveState().
+
+ \row
+ \o Miscellaneous
+ \o closeAllWindows(),
+ startingUp(),
+ closingDown(),
+ type().
+ \endtable
+
+ \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings
+*/
+
+/*!
+ \enum QApplication::Type
+
+ \value Tty a console application
+ \value GuiClient a GUI client application
+ \value GuiServer a GUI server application (for Qt for Embedded Linux)
+*/
+
+/*!
+ \enum QApplication::ColorSpec
+
+ \value NormalColor the default color allocation policy
+ \value CustomColor the same as NormalColor for X11; allocates colors
+ to a palette on demand under Windows
+ \value ManyColor the right choice for applications that use thousands of
+ colors
+
+ See setColorSpec() for full details.
+*/
+
+/*!
+ \fn QWidget *QApplication::topLevelAt(const QPoint &point)
+
+ Returns the top-level widget at the given \a point; returns 0 if
+ there is no such widget.
+*/
+
+/*!
+ \fn QWidget *QApplication::topLevelAt(int x, int y)
+
+ \overload
+
+ Returns the top-level widget at the point (\a{x}, \a{y}); returns
+ 0 if there is no such widget.
+*/
+
+
+/*
+ The qt_init() and qt_cleanup() functions are implemented in the
+ qapplication_xyz.cpp file.
+*/
+
+void qt_init(QApplicationPrivate *priv, int type
+#ifdef Q_WS_X11
+ , Display *display = 0, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0
+#endif
+ );
+void qt_cleanup();
+
+Qt::MouseButtons QApplicationPrivate::mouse_buttons = Qt::NoButton;
+Qt::KeyboardModifiers QApplicationPrivate::modifier_buttons = Qt::NoModifier;
+
+QStyle *QApplicationPrivate::app_style = 0; // default application style
+QString QApplicationPrivate::styleOverride; // style override
+
+#ifndef QT_NO_STYLE_STYLESHEET
+QString QApplicationPrivate::styleSheet; // default application stylesheet
+#endif
+QPointer<QWidget> QApplicationPrivate::leaveAfterRelease = 0;
+
+int QApplicationPrivate::app_cspec = QApplication::NormalColor;
+QPalette *QApplicationPrivate::sys_pal = 0; // default system palette
+QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer
+
+#ifndef Q_WS_QPA
+Q_GLOBAL_STATIC(QMutex, applicationFontMutex)
+QFont *QApplicationPrivate::app_font = 0; // default application font
+#endif
+QFont *QApplicationPrivate::sys_font = 0; // default system font
+QFont *QApplicationPrivate::set_font = 0; // default font set by programmer
+
+QIcon *QApplicationPrivate::app_icon = 0;
+QWidget *QApplicationPrivate::main_widget = 0; // main application widget
+QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input focus
+QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show()
+QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus
+bool QApplicationPrivate::obey_desktop_settings = true; // use winsys resources
+int QApplicationPrivate::cursor_flash_time = 1000; // text caret flash time
+int QApplicationPrivate::mouse_double_click_time = 400; // mouse dbl click limit
+int QApplicationPrivate::keyboard_input_time = 400; // keyboard input interval
+#ifndef QT_NO_WHEELEVENT
+int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll
+#endif
+bool qt_is_gui_used;
+bool Q_GUI_EXPORT qt_tab_all_widgets = true;
+bool qt_in_tab_key_event = false;
+int qt_antialiasing_threshold = -1;
+static int drag_time = 500;
+#ifndef QT_GUI_DRAG_DISTANCE
+#define QT_GUI_DRAG_DISTANCE 4
+#endif
+#ifdef Q_OS_SYMBIAN
+// The screens are a bit too small to for your thumb when using only 4 pixels drag distance.
+static int drag_distance = 12; //XXX move to qplatformdefs.h
+#else
+static int drag_distance = QT_GUI_DRAG_DISTANCE;
+#endif
+QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut
+bool QApplicationPrivate::animate_ui = true;
+bool QApplicationPrivate::animate_menu = false;
+bool QApplicationPrivate::fade_menu = false;
+bool QApplicationPrivate::animate_combo = false;
+bool QApplicationPrivate::animate_tooltip = false;
+bool QApplicationPrivate::fade_tooltip = false;
+bool QApplicationPrivate::animate_toolbox = false;
+bool QApplicationPrivate::widgetCount = false;
+bool QApplicationPrivate::load_testability = false;
+QString QApplicationPrivate::qmljs_debug_arguments;
+#ifdef QT_KEYPAD_NAVIGATION
+# ifdef Q_OS_SYMBIAN
+Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
+# else
+Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadTabOrder;
+# endif
+QWidget *QApplicationPrivate::oldEditFocus = 0;
+#endif
+
+bool qt_tabletChokeMouse = false;
+
+inline bool QApplicationPrivate::isAlien(QWidget *widget)
+{
+ if (!widget)
+ return false;
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ return !widget->isWindow()
+# ifdef Q_BACKINGSTORE_SUBSURFACES
+ && !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface)
+# endif
+ ;
+#else
+ return !widget->internalWinId();
+#endif
+}
+
+// ######## move to QApplicationPrivate
+// Default application palettes and fonts (per widget type)
+Q_GLOBAL_STATIC(PaletteHash, app_palettes)
+PaletteHash *qt_app_palettes_hash()
+{
+ return app_palettes();
+}
+
+Q_GLOBAL_STATIC(FontHash, app_fonts)
+FontHash *qt_app_fonts_hash()
+{
+ return app_fonts();
+}
+
+QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus
+
+QDesktopWidget *qt_desktopWidget = 0; // root window widgets
+#if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
+QClipboard *qt_clipboard = 0; // global clipboard object
+#endif
+QWidgetList * qt_modal_stack=0; // stack of modal widgets
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::process_cmdline()
+{
+ // process platform-indep command line
+ if (!qt_is_gui_used || !argc)
+ return;
+
+ int i, j;
+
+ j = 1;
+ for (i=1; i<argc; i++) { // if you add anything here, modify QCoreApplication::arguments()
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg = argv[i];
+ arg = arg;
+ QString s;
+ if (arg == "-qdevel" || arg == "-qdebug") {
+ // obsolete argument
+ } else if (arg.indexOf("-qmljsdebugger=", 0) != -1) {
+ qmljs_debug_arguments = QString::fromLocal8Bit(arg.right(arg.length() - 15));
+ } else if (arg.indexOf("-style=", 0) != -1) {
+ s = QString::fromLocal8Bit(arg.right(arg.length() - 7).toLower());
+ } else if (arg == "-style" && i < argc-1) {
+ s = QString::fromLocal8Bit(argv[++i]).toLower();
+#ifndef QT_NO_SESSIONMANAGER
+ } else if (arg == "-session" && i < argc-1) {
+ ++i;
+ if (argv[i] && *argv[i]) {
+ session_id = QString::fromLatin1(argv[i]);
+ int p = session_id.indexOf(QLatin1Char('_'));
+ if (p >= 0) {
+ session_key = session_id.mid(p +1);
+ session_id = session_id.left(p);
+ }
+ is_session_restored = true;
+ }
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+ } else if (arg == "-stylesheet" && i < argc -1) {
+ styleSheet = QLatin1String("file:///");
+ styleSheet.append(QString::fromLocal8Bit(argv[++i]));
+ } else if (arg.indexOf("-stylesheet=") != -1) {
+ styleSheet = QLatin1String("file:///");
+ styleSheet.append(QString::fromLocal8Bit(arg.right(arg.length() - 12)));
+#endif
+ } else if (qstrcmp(arg, "-widgetcount") == 0) {
+ widgetCount = true;
+ } else if (qstrcmp(arg, "-testability") == 0) {
+ load_testability = true;
+ } else {
+ argv[j++] = argv[i];
+ }
+ if (!s.isEmpty()) {
+ if (app_style) {
+ delete app_style;
+ app_style = 0;
+ }
+ styleOverride = s;
+ }
+ }
+
+ if(j < argc) {
+ argv[j] = 0;
+ argc = j;
+ }
+}
+
+/*!
+ Initializes the window system and constructs an application object with
+ \a argc command line arguments in \a argv.
+
+ \warning The data referred to by \a argc and \a argv must stay valid for
+ the entire lifetime of the QApplication object. In addition, \a argc must
+ be greater than zero and \a argv must contain at least one valid character
+ string.
+
+ The global \c qApp pointer refers to this application object. Only one
+ application object should be created.
+
+ This application object must be constructed before any \l{QPaintDevice}
+ {paint devices} (including widgets, pixmaps, bitmaps etc.).
+
+ \note \a argc and \a argv might be changed as Qt removes command line
+ arguments that it recognizes.
+
+ Qt debugging options (not available if Qt was compiled without the QT_DEBUG
+ flag defined):
+ \list
+ \o -nograb, tells Qt that it must never grab the mouse or the
+ keyboard.
+ \o -dograb (only under X11), running under a debugger can cause an
+ implicit -nograb, use -dograb to override.
+ \o -sync (only under X11), switches to synchronous mode for
+ debugging.
+ \endlist
+
+ See \l{Debugging Techniques} for a more detailed explanation.
+
+ All Qt programs automatically support the following command line options:
+ \list
+ \o -style= \e style, sets the application GUI style. Possible values
+ are \c motif, \c windows, and \c platinum. If you compiled Qt with
+ additional styles or have additional styles as plugins these will
+ be available to the \c -style command line option.
+ \o -style \e style, is the same as listed above.
+ \o -stylesheet= \e stylesheet, sets the application \l styleSheet. The
+ value must be a path to a file that contains the Style Sheet.
+ \note Relative URLs in the Style Sheet file are relative to the
+ Style Sheet file's path.
+ \o -stylesheet \e stylesheet, is the same as listed above.
+ \o -session= \e session, restores the application from an earlier
+ \l{Session Management}{session}.
+ \o -session \e session, is the same as listed above.
+ \o -widgetcount, prints debug message at the end about number of
+ widgets left undestroyed and maximum number of widgets existed at
+ the same time
+ \o -reverse, sets the application's layout direction to
+ Qt::RightToLeft
+ \o -qmljsdebugger=, activates the QML/JS debugger with a specified port.
+ The value must be of format port:1234[,block], where block is optional
+ and will make the application wait until a debugger connects to it.
+ \endlist
+
+ The X11 version of Qt supports some traditional X11 command line options:
+ \list
+ \o -display \e display, sets the X display (default is $DISPLAY).
+ \o -geometry \e geometry, sets the client geometry of the first window
+ that is shown.
+ \o -fn or \c -font \e font, defines the application font. The font
+ should be specified using an X logical font description. Note that
+ this option is ignored when Qt is built with fontconfig support enabled.
+ \o -bg or \c -background \e color, sets the default background color
+ and an application palette (light and dark shades are calculated).
+ \o -fg or \c -foreground \e color, sets the default foreground color.
+ \o -btn or \c -button \e color, sets the default button color.
+ \o -name \e name, sets the application name.
+ \o -title \e title, sets the application title.
+ \o -visual \c TrueColor, forces the application to use a TrueColor
+ visual on an 8-bit display.
+ \o -ncols \e count, limits the number of colors allocated in the color
+ cube on an 8-bit display, if the application is using the
+ QApplication::ManyColor color specification. If \e count is 216
+ then a 6x6x6 color cube is used (i.e. 6 levels of red, 6 of green,
+ and 6 of blue); for other values, a cube approximately proportional
+ to a 2x3x1 cube is used.
+ \o -cmap, causes the application to install a private color map on an
+ 8-bit display.
+ \o -im, sets the input method server (equivalent to setting the
+ XMODIFIERS environment variable)
+ \o -inputstyle, defines how the input is inserted into the given
+ widget, e.g., \c onTheSpot makes the input appear directly in the
+ widget, while \c overTheSpot makes the input appear in a box
+ floating over the widget and is not inserted until the editing is
+ done.
+ \endlist
+
+ \section1 X11 Notes
+
+ If QApplication fails to open the X11 display, it will terminate
+ the process. This behavior is consistent with most X11
+ applications.
+
+ \sa arguments()
+*/
+
+QApplication::QApplication(int &argc, char **argv)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, int _internal)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GuiClient, _internal))
+{ Q_D(QApplication); d->construct(); }
+
+
+/*!
+ Constructs an application object with \a argc command line arguments in
+ \a argv. If \a GUIenabled is true, a GUI application is constructed,
+ otherwise a non-GUI (console) application is created.
+
+ \warning The data referred to by \a argc and \a argv must stay valid for
+ the entire lifetime of the QApplication object. In addition, \a argc must
+ be greater than zero and \a argv must contain at least one valid character
+ string.
+
+ Set \a GUIenabled to false for programs without a graphical user interface
+ that should be able to run without a window system.
+
+ On X11, the window system is initialized if \a GUIenabled is true. If
+ \a GUIenabled is false, the application does not connect to the X server.
+ On Windows and Mac OS, currently the window system is always initialized,
+ regardless of the value of GUIenabled. This may change in future versions
+ of Qt.
+
+ The following example shows how to create an application that uses a
+ graphical interface when available.
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 0
+*/
+
+QApplication::QApplication(int &argc, char **argv, bool GUIenabled )
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, 0x040000))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, _internal))
+{ Q_D(QApplication); d->construct();}
+
+
+
+/*!
+ Constructs an application object with \a argc command line arguments in
+ \a argv.
+
+ \warning The data referred to by \a argc and \a argv must stay valid for
+ the entire lifetime of the QApplication object. In addition, \a argc must
+ be greater than zero and \a argv must contain at least one valid character
+ string.
+
+ With Qt for Embedded Linux, passing QApplication::GuiServer for \a type
+ makes this application the server (equivalent to running with the
+ \c -qws option).
+*/
+QApplication::QApplication(int &argc, char **argv, Type type)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, type, 0x040000))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, Type type , int _internal)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, type, _internal))
+{ Q_D(QApplication); d->construct(); }
+
+#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
+static int qt_matchLibraryName(dl_phdr_info *info, size_t, void *data)
+{
+ const char *name = static_cast<const char *>(data);
+ return strstr(info->dlpi_name, name) != 0;
+}
+#endif
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::construct(
+#ifdef Q_WS_X11
+ Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap
+#endif
+ )
+{
+ initResources();
+
+ qt_is_gui_used = (qt_appType != QApplication::Tty);
+ process_cmdline();
+
+ // Must be called before initialize()
+ qt_init(this, qt_appType
+#ifdef Q_WS_X11
+ , dpy, visual, cmap
+#endif
+ );
+ initialize();
+ eventDispatcher->startingUp();
+
+#ifdef QT_EVAL
+ extern void qt_gui_eval_init(uint);
+ qt_gui_eval_init(application_type);
+#endif
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+ symbianInit();
+#endif
+
+#ifndef QT_NO_LIBRARY
+ if(load_testability) {
+ QLibrary testLib(QLatin1String("qttestability"));
+ if (testLib.load()) {
+ typedef void (*TasInitialize)(void);
+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
+#ifdef Q_OS_SYMBIAN
+ // resolving method by name does not work on Symbian OS so need to use ordinal
+ if(!initFunction) {
+ initFunction = (TasInitialize)testLib.resolve("1");
+ }
+#endif
+ if (initFunction) {
+ initFunction();
+ } else {
+ qCritical("Library qttestability resolve failed!");
+ }
+ } else {
+ qCritical("Library qttestability load failed!");
+ }
+ }
+
+ //make sure the plugin is loaded
+ if (qt_is_gui_used)
+ qt_guiPlatformPlugin();
+#endif
+}
+
+#if defined(Q_WS_X11)
+// ### a string literal is a cont char*
+// ### using it as a char* is wrong and could lead to segfaults
+// ### if aargv is modified someday
+// ########## make it work with argc == argv == 0
+static int aargc = 1;
+static char *aargv[] = { (char*)"unknown", 0 };
+
+/*!
+ \fn QApplication::QApplication(Display* display, Qt::HANDLE visual, Qt::HANDLE colormap)
+
+ Creates an application, given an already open display \a display. If
+ \a visual and \a colormap are non-zero, the application will use those
+ values as the default Visual and Colormap contexts.
+
+ \warning Qt only supports TrueColor visuals at depths higher than 8
+ bits-per-pixel.
+
+ This function is only available on X11.
+*/
+QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
+ : QApplicationBase(*new QApplicationPrivate(aargc, aargv, GuiClient, 0x040000))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+}
+
+QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
+ : QApplicationBase(*new QApplicationPrivate(aargc, aargv, GuiClient, _internal))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+ QApplicationPrivate::app_compile_version = _internal;
+}
+
+/*!
+ \fn QApplication::QApplication(Display *display, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap)
+
+ Creates an application, given an already open \a display and using \a argc
+ command line arguments in \a argv. If \a visual and \a colormap are
+ non-zero, the application will use those values as the default Visual
+ and Colormap contexts.
+
+ \warning Qt only supports TrueColor visuals at depths higher than 8
+ bits-per-pixel.
+
+ This function is only available on X11.
+*/
+QApplication::QApplication(Display *dpy, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+}
+
+QApplication::QApplication(Display *dpy, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
+ : QApplicationBase(*new QApplicationPrivate(argc, argv, GuiClient, _internal))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+ QApplicationPrivate::app_compile_version = _internal;
+}
+
+#endif // Q_WS_X11
+
+extern void qInitDrawhelperAsm();
+extern void qInitImageConversions();
+extern int qRegisterGuiVariant();
+extern int qUnregisterGuiVariant();
+#ifndef QT_NO_STATEMACHINE
+extern int qRegisterGuiStateMachine();
+extern int qUnregisterGuiStateMachine();
+#endif
+
+/*!
+ \fn void QApplicationPrivate::initialize()
+
+ Initializes the QApplication object, called from the constructors.
+*/
+void QApplicationPrivate::initialize()
+{
+ QWidgetPrivate::mapper = new QWidgetMapper;
+ QWidgetPrivate::allWidgets = new QWidgetSet;
+
+ if (qt_appType != QApplication::Tty)
+ (void) QApplication::style(); // trigger creation of application style
+ // trigger registering of QVariant's GUI types
+ qRegisterGuiVariant();
+#ifndef QT_NO_STATEMACHINE
+ // trigger registering of QStateMachine's GUI types
+ qRegisterGuiStateMachine();
+#endif
+
+ is_app_running = true; // no longer starting up
+
+ Q_Q(QApplication);
+#ifndef QT_NO_SESSIONMANAGER
+ // connect to the session manager
+ session_manager = new QSessionManager(q, session_id, session_key);
+#endif
+
+ if (qgetenv("QT_USE_NATIVE_WINDOWS").toInt() > 0)
+ q->setAttribute(Qt::AA_NativeWindows);
+
+#ifdef Q_WS_WINCE
+#ifdef QT_AUTO_MAXIMIZE_THRESHOLD
+ autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD;
+#else
+ if (qt_wince_is_mobile())
+ autoMaximizeThreshold = 50;
+ else
+ autoMaximizeThreshold = -1;
+#endif //QT_AUTO_MAXIMIZE_THRESHOLD
+#endif //Q_WS_WINCE
+
+ // Set up which span functions should be used in raster engine...
+ qInitDrawhelperAsm();
+ // and QImage conversion functions
+ qInitImageConversions();
+
+#ifndef QT_NO_WHEELEVENT
+ QApplicationPrivate::wheel_scroll_lines = 3;
+#endif
+
+ if (qt_is_gui_used)
+ initializeMultitouch();
+}
+
+/*!
+ Returns the type of application (\l Tty, GuiClient, or
+ GuiServer). The type is set when constructing the QApplication
+ object.
+*/
+QApplication::Type QApplication::type()
+{
+ return qt_appType;
+}
+
+/*****************************************************************************
+ Functions returning the active popup and modal widgets.
+ *****************************************************************************/
+
+/*!
+ Returns the active popup widget.
+
+ A popup widget is a special top-level widget that sets the \c
+ Qt::WType_Popup widget flag, e.g. the QMenu widget. When the application
+ opens a popup widget, all events are sent to the popup. Normal widgets and
+ modal widgets cannot be accessed before the popup widget is closed.
+
+ Only other popup widgets may be opened when a popup widget is shown. The
+ popup widgets are organized in a stack. This function returns the active
+ popup widget at the top of the stack.
+
+ \sa activeModalWidget(), topLevelWidgets()
+*/
+
+QWidget *QApplication::activePopupWidget()
+{
+ return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ?
+ QApplicationPrivate::popupWidgets->last() : 0;
+}
+
+
+/*!
+ Returns the active modal widget.
+
+ A modal widget is a special top-level widget which is a subclass of QDialog
+ that specifies the modal parameter of the constructor as true. A modal
+ widget must be closed before the user can continue with other parts of the
+ program.
+
+ Modal widgets are organized in a stack. This function returns the active
+ modal widget at the top of the stack.
+
+ \sa activePopupWidget(), topLevelWidgets()
+*/
+
+QWidget *QApplication::activeModalWidget()
+{
+ return qt_modal_stack && !qt_modal_stack->isEmpty() ? qt_modal_stack->first() : 0;
+}
+
+/*!
+ Cleans up any window system resources that were allocated by this
+ application. Sets the global variable \c qApp to 0.
+*/
+
+QApplication::~QApplication()
+{
+ Q_D(QApplication);
+
+#if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
+ // flush clipboard contents
+ if (qt_clipboard) {
+ QEvent event(QEvent::Clipboard);
+ QApplication::sendEvent(qt_clipboard, &event);
+ }
+#endif
+
+ //### this should probable be done even later
+ qt_call_post_routines();
+
+ // kill timers before closing down the dispatcher
+ d->toolTipWakeUp.stop();
+ d->toolTipFallAsleep.stop();
+
+#if !defined(Q_WS_QPA)
+ d->eventDispatcher->closingDown();
+ d->eventDispatcher = 0;
+#endif
+ QApplicationPrivate::is_app_closing = true;
+ QApplicationPrivate::is_app_running = false;
+
+ delete QWidgetPrivate::mapper;
+ QWidgetPrivate::mapper = 0;
+
+ // delete all widgets
+ if (QWidgetPrivate::allWidgets) {
+ QWidgetSet *mySet = QWidgetPrivate::allWidgets;
+ QWidgetPrivate::allWidgets = 0;
+ for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (!w->parent()) // window
+ w->destroy(true, true);
+ }
+ delete mySet;
+ }
+
+ delete qt_desktopWidget;
+ qt_desktopWidget = 0;
+
+#if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
+ delete qt_clipboard;
+ qt_clipboard = 0;
+#endif
+
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ delete d->move_cursor; d->move_cursor = 0;
+ delete d->copy_cursor; d->copy_cursor = 0;
+ delete d->link_cursor; d->link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ delete d->ignore_cursor; d->ignore_cursor = 0;
+#endif
+
+ delete QApplicationPrivate::app_pal;
+ QApplicationPrivate::app_pal = 0;
+ delete QApplicationPrivate::sys_pal;
+ QApplicationPrivate::sys_pal = 0;
+ delete QApplicationPrivate::set_pal;
+ QApplicationPrivate::set_pal = 0;
+ app_palettes()->clear();
+
+#ifndef Q_WS_QPA
+ {
+ QMutexLocker locker(applicationFontMutex());
+ delete QApplicationPrivate::app_font;
+ QApplicationPrivate::app_font = 0;
+ }
+#endif
+
+ delete QApplicationPrivate::sys_font;
+ QApplicationPrivate::sys_font = 0;
+ delete QApplicationPrivate::set_font;
+ QApplicationPrivate::set_font = 0;
+ app_fonts()->clear();
+
+ delete QApplicationPrivate::app_style;
+ QApplicationPrivate::app_style = 0;
+ delete QApplicationPrivate::app_icon;
+ QApplicationPrivate::app_icon = 0;
+
+#ifndef QT_NO_DRAGANDDROP
+ if (qt_is_gui_used)
+ delete QDragManager::self();
+#endif
+
+ d->cleanupMultitouch();
+
+ qt_cleanup();
+
+ if (QApplicationPrivate::widgetCount)
+ qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances);
+#ifndef QT_NO_SESSIONMANAGER
+ delete d->session_manager;
+ d->session_manager = 0;
+#endif //QT_NO_SESSIONMANAGER
+
+ QApplicationPrivate::obey_desktop_settings = true;
+ QApplicationPrivate::cursor_flash_time = 1000;
+ QApplicationPrivate::mouse_double_click_time = 400;
+ QApplicationPrivate::keyboard_input_time = 400;
+
+ drag_time = 500;
+ drag_distance = 4;
+ QApplicationPrivate::app_strut = QSize(0, 0);
+ QApplicationPrivate::animate_ui = true;
+ QApplicationPrivate::animate_menu = false;
+ QApplicationPrivate::fade_menu = false;
+ QApplicationPrivate::animate_combo = false;
+ QApplicationPrivate::animate_tooltip = false;
+ QApplicationPrivate::fade_tooltip = false;
+ QApplicationPrivate::widgetCount = false;
+
+#ifndef QT_NO_STATEMACHINE
+ // trigger unregistering of QStateMachine's GUI types
+ qUnregisterGuiStateMachine();
+#endif
+ // trigger unregistering of QVariant's GUI types
+ qUnregisterGuiVariant();
+}
+
+
+/*!
+ \fn QWidget *QApplication::widgetAt(const QPoint &point)
+
+ Returns the widget at global screen position \a point, or 0 if there is no
+ Qt widget there.
+
+ This function can be slow.
+
+ \sa QCursor::pos(), QWidget::grabMouse(), QWidget::grabKeyboard()
+*/
+QWidget *QApplication::widgetAt(const QPoint &p)
+{
+ QWidget *window = QApplication::topLevelAt(p);
+ if (!window)
+ return 0;
+
+ QWidget *child = 0;
+
+ if (!window->testAttribute(Qt::WA_TransparentForMouseEvents))
+ child = window->childAt(window->mapFromGlobal(p));
+
+ if (child)
+ return child;
+
+ if (window->testAttribute(Qt::WA_TransparentForMouseEvents)) {
+ //shoot a hole in the widget and try once again,
+ //suboptimal on Qt for Embedded Linux where we do
+ //know the stacking order of the toplevels.
+ int x = p.x();
+ int y = p.y();
+ QRegion oldmask = window->mask();
+ QPoint wpoint = window->mapFromGlobal(QPoint(x, y));
+ QRegion newmask = (oldmask.isEmpty() ? QRegion(window->rect()) : oldmask)
+ - QRegion(wpoint.x(), wpoint.y(), 1, 1);
+ window->setMask(newmask);
+ QWidget *recurse = 0;
+ if (QApplication::topLevelAt(p) != window) // verify recursion will terminate
+ recurse = widgetAt(x, y);
+ if (oldmask.isEmpty())
+ window->clearMask();
+ else
+ window->setMask(oldmask);
+ return recurse;
+ }
+ return window;
+}
+
+/*!
+ \fn QWidget *QApplication::widgetAt(int x, int y)
+
+ \overload
+
+ Returns the widget at global screen position (\a x, \a y), or 0 if there is
+ no Qt widget there.
+*/
+
+/*!
+ \fn void QApplication::setArgs(int argc, char **argv)
+ \internal
+*/
+
+
+
+/*!
+ \internal
+*/
+bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
+{
+ if ((event->type() == QEvent::UpdateRequest
+#ifdef QT3_SUPPORT
+ || event->type() == QEvent::LayoutHint
+#endif
+ || event->type() == QEvent::LayoutRequest
+ || event->type() == QEvent::Resize
+ || event->type() == QEvent::Move
+ || event->type() == QEvent::LanguageChange
+ || event->type() == QEvent::UpdateSoftKeys
+ || event->type() == QEvent::InputMethod)) {
+ for (int i = 0; i < postedEvents->size(); ++i) {
+ const QPostEvent &cur = postedEvents->at(i);
+ if (cur.receiver != receiver || cur.event == 0 || cur.event->type() != event->type())
+ continue;
+ if (cur.event->type() == QEvent::LayoutRequest
+#ifdef QT3_SUPPORT
+ || cur.event->type() == QEvent::LayoutHint
+#endif
+ || cur.event->type() == QEvent::UpdateRequest) {
+ ;
+ } else if (cur.event->type() == QEvent::Resize) {
+ ((QResizeEvent *)(cur.event))->s = ((QResizeEvent *)event)->s;
+ } else if (cur.event->type() == QEvent::Move) {
+ ((QMoveEvent *)(cur.event))->p = ((QMoveEvent *)event)->p;
+ } else if (cur.event->type() == QEvent::LanguageChange) {
+ ;
+ } else if (cur.event->type() == QEvent::UpdateSoftKeys) {
+ ;
+ } else if ( cur.event->type() == QEvent::InputMethod ) {
+ *(QInputMethodEvent *)(cur.event) = *(QInputMethodEvent *)event;
+ } else {
+ continue;
+ }
+ delete event;
+ return true;
+ }
+ return false;
+ }
+ return QApplicationBase::compressEvent(event, receiver, postedEvents);
+}
+
+/*!
+ \property QApplication::styleSheet
+ \brief the application style sheet
+ \since 4.2
+
+ By default, this property returns an empty string unless the user specifies
+ the \c{-stylesheet} option on the command line when running the application.
+
+ \sa QWidget::setStyle(), {Qt Style Sheets}
+*/
+
+/*!
+ \property QApplication::autoMaximizeThreshold
+ \since 4.4
+ \brief defines a threshold for auto maximizing widgets
+
+ \bold{The auto maximize threshold is only available as part of Qt for
+ Windows CE.}
+
+ This property defines a threshold for the size of a window as a percentage
+ of the screen size. If the minimum size hint of a window exceeds the
+ threshold, calling show() will cause the window to be maximized
+ automatically.
+
+ Setting the threshold to 100 or greater means that the widget will always
+ be maximized. Alternatively, setting the threshold to 50 means that the
+ widget will be maximized only if the vertical minimum size hint is at least
+ 50% of the vertical screen size.
+
+ Setting the threshold to -1 disables the feature.
+
+ On Windows CE the default is -1 (i.e., it is disabled).
+ On Windows Mobile the default is 40.
+*/
+
+/*!
+ \property QApplication::autoSipEnabled
+ \since 4.5
+ \brief toggles automatic SIP (software input panel) visibility
+
+ Set this property to \c true to automatically display the SIP when entering
+ widgets that accept keyboard input. This property only affects widgets with
+ the WA_InputMethodEnabled attribute set, and is typically used to launch
+ a virtual keyboard on devices which have very few or no keys.
+
+ \bold{ The property only has an effect on platforms which use software input
+ panels, such as Windows CE and Symbian.}
+
+ The default is platform dependent.
+*/
+
+#ifdef Q_WS_WINCE
+void QApplication::setAutoMaximizeThreshold(const int threshold)
+{
+ QApplicationPrivate::autoMaximizeThreshold = threshold;
+}
+
+int QApplication::autoMaximizeThreshold() const
+{
+ return QApplicationPrivate::autoMaximizeThreshold;
+}
+#endif
+
+void QApplication::setAutoSipEnabled(const bool enabled)
+{
+ QApplicationPrivate::autoSipEnabled = enabled;
+}
+
+bool QApplication::autoSipEnabled() const
+{
+ return QApplicationPrivate::autoSipEnabled;
+}
+
+#ifndef QT_NO_STYLE_STYLESHEET
+
+QString QApplication::styleSheet() const
+{
+ return QApplicationPrivate::styleSheet;
+}
+
+void QApplication::setStyleSheet(const QString& styleSheet)
+{
+ QApplicationPrivate::styleSheet = styleSheet;
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style);
+ if (styleSheet.isEmpty()) { // application style sheet removed
+ if (!proxy)
+ return; // there was no stylesheet before
+ setStyle(proxy->base);
+ } else if (proxy) { // style sheet update, just repolish
+ proxy->repolish(qApp);
+ } else { // stylesheet set the first time
+ QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style);
+ QApplicationPrivate::app_style->setParent(newProxy);
+ setStyle(newProxy);
+ }
+}
+
+#endif // QT_NO_STYLE_STYLESHEET
+
+/*!
+ Returns the application's style object.
+
+ \sa setStyle(), QStyle
+*/
+QStyle *QApplication::style()
+{
+ if (QApplicationPrivate::app_style)
+ return QApplicationPrivate::app_style;
+ if (!qt_is_gui_used) {
+ Q_ASSERT(!"No style available in non-gui applications!");
+ return 0;
+ }
+
+ if (!QApplicationPrivate::app_style) {
+ // Compile-time search for default style
+ //
+ QString style;
+#ifdef QT_BUILD_INTERNAL
+ QString envStyle = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE"));
+#else
+ QString envStyle;
+#endif
+ if (!QApplicationPrivate::styleOverride.isEmpty()) {
+ style = QApplicationPrivate::styleOverride;
+ } else if (!envStyle.isEmpty()) {
+ style = envStyle;
+ } else {
+ style = QApplicationPrivate::desktopStyleKey();
+ }
+
+ QStyle *&app_style = QApplicationPrivate::app_style;
+ app_style = QStyleFactory::create(style);
+ if (!app_style) {
+ QStringList styles = QStyleFactory::keys();
+ for (int i = 0; i < styles.size(); ++i) {
+ if ((app_style = QStyleFactory::create(styles.at(i))))
+ break;
+ }
+ }
+ if (!app_style) {
+ Q_ASSERT(!"No styles available!");
+ return 0;
+ }
+ }
+ // take ownership of the style
+ QApplicationPrivate::app_style->setParent(qApp);
+
+ if (!QApplicationPrivate::sys_pal)
+ QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
+ if (QApplicationPrivate::set_pal) // repolish set palette with the new style
+ QApplication::setPalette(*QApplicationPrivate::set_pal);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!QApplicationPrivate::styleSheet.isEmpty()) {
+ qApp->setStyleSheet(QApplicationPrivate::styleSheet);
+ } else
+#endif
+ QApplicationPrivate::app_style->polish(qApp);
+
+ return QApplicationPrivate::app_style;
+}
+
+/*!
+ Sets the application's GUI style to \a style. Ownership of the style object
+ is transferred to QApplication, so QApplication will delete the style
+ object on application exit or when a new style is set and the old style is
+ still the parent of the application object.
+
+ Example usage:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 1
+
+ When switching application styles, the color palette is set back to the
+ initial colors or the system defaults. This is necessary since certain
+ styles have to adapt the color palette to be fully style-guide compliant.
+
+ Setting the style before a palette has been se, i.e., before creating
+ QApplication, will cause the application to use QStyle::standardPalette()
+ for the palette.
+
+ \warning Qt style sheets are currently not supported for custom QStyle
+ subclasses. We plan to address this in some future release.
+
+ \sa style(), QStyle, setPalette(), desktopSettingsAware()
+*/
+void QApplication::setStyle(QStyle *style)
+{
+ if (!style || style == QApplicationPrivate::app_style)
+ return;
+
+ QWidgetList all = allWidgets();
+
+ // clean up the old style
+ if (QApplicationPrivate::app_style) {
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (!(w->windowType() == Qt::Desktop) && // except desktop
+ w->testAttribute(Qt::WA_WState_Polished)) { // has been polished
+ QApplicationPrivate::app_style->unpolish(w);
+ }
+ }
+ }
+ QApplicationPrivate::app_style->unpolish(qApp);
+ }
+
+ QStyle *old = QApplicationPrivate::app_style; // save
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) {
+ // we have a stylesheet already and a new style is being set
+ QStyleSheetStyle *newProxy = new QStyleSheetStyle(style);
+ style->setParent(newProxy);
+ QApplicationPrivate::app_style = newProxy;
+ } else
+#endif // QT_NO_STYLE_STYLESHEET
+ QApplicationPrivate::app_style = style;
+ QApplicationPrivate::app_style->setParent(qApp); // take ownership
+
+ // take care of possible palette requirements of certain gui
+ // styles. Do it before polishing the application since the style
+ // might call QApplication::setPalette() itself
+ if (QApplicationPrivate::set_pal) {
+ QApplication::setPalette(*QApplicationPrivate::set_pal);
+ } else if (QApplicationPrivate::sys_pal) {
+ QApplicationPrivate::initializeWidgetPaletteHash();
+ QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
+ } else if (!QApplicationPrivate::sys_pal) {
+ // Initialize the sys_pal if it hasn't happened yet...
+ QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
+ }
+
+ // initialize the application with the new style
+ QApplicationPrivate::app_style->polish(qApp);
+
+ // re-polish existing widgets if necessary
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ for (QWidgetList::ConstIterator it1 = all.constBegin(); it1 != all.constEnd(); ++it1) {
+ register QWidget *w = *it1;
+ if (w->windowType() != Qt::Desktop && w->testAttribute(Qt::WA_WState_Polished)) {
+ if (w->style() == QApplicationPrivate::app_style)
+ QApplicationPrivate::app_style->polish(w); // repolish
+#ifndef QT_NO_STYLE_STYLESHEET
+ else
+ w->setStyleSheet(w->styleSheet()); // touch
+#endif
+ }
+ }
+
+ for (QWidgetList::ConstIterator it2 = all.constBegin(); it2 != all.constEnd(); ++it2) {
+ register QWidget *w = *it2;
+ if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) {
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(w, &e);
+#ifdef QT3_SUPPORT
+ if (old)
+ w->styleChange(*old);
+#endif
+ w->update();
+ }
+ }
+ }
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) {
+ oldProxy->deref();
+ } else
+#endif
+ if (old && old->parent() == qApp) {
+ delete old;
+ }
+
+ if (QApplicationPrivate::focus_widget) {
+ QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason);
+ QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in);
+ QApplicationPrivate::focus_widget->update();
+ }
+}
+
+/*!
+ \overload
+
+ Requests a QStyle object for \a style from the QStyleFactory.
+
+ The string must be one of the QStyleFactory::keys(), typically one of
+ "windows", "motif", "cde", "plastique", "windowsxp", or "macintosh". Style
+ names are case insensitive.
+
+ Returns 0 if an unknown \a style is passed, otherwise the QStyle object
+ returned is set as the application's GUI style.
+
+ \warning To ensure that the application's style is set correctly, it is
+ best to call this function before the QApplication constructor, if
+ possible.
+*/
+QStyle* QApplication::setStyle(const QString& style)
+{
+ QStyle *s = QStyleFactory::create(style);
+ if (!s)
+ return 0;
+
+ setStyle(s);
+ return s;
+}
+
+/*!
+ Returns the color specification.
+
+ \sa QApplication::setColorSpec()
+*/
+
+int QApplication::colorSpec()
+{
+ return QApplicationPrivate::app_cspec;
+}
+
+/*!
+ Sets the color specification for the application to \a spec.
+
+ The color specification controls how the application allocates colors when
+ run on a display with a limited amount of colors, e.g. 8 bit / 256 color
+ displays.
+
+ The color specification must be set before you create the QApplication
+ object.
+
+ The options are:
+ \list
+ \o QApplication::NormalColor. This is the default color allocation
+ strategy. Use this option if your application uses buttons, menus,
+ texts and pixmaps with few colors. With this option, the
+ application uses system global colors. This works fine for most
+ applications under X11, but on the Windows platform, it may cause
+ dithering of non-standard colors.
+ \o QApplication::CustomColor. Use this option if your application
+ needs a small number of custom colors. On X11, this option is the
+ same as NormalColor. On Windows, Qt creates a Windows palette, and
+ allocates colors to it on demand.
+ \o QApplication::ManyColor. Use this option if your application is
+ very color hungry, e.g., it requires thousands of colors. \br
+ Under X11 the effect is:
+ \list
+ \o For 256-color displays which have at best a 256 color true
+ color visual, the default visual is used, and colors are
+ allocated from a color cube. The color cube is the 6x6x6
+ (216 color) "Web palette" (the red, green, and blue
+ components always have one of the following values: 0x00,
+ 0x33, 0x66, 0x99, 0xCC, or 0xFF), but the number of colors
+ can be changed by the \e -ncols option. The user can force
+ the application to use the true color visual with the
+ \l{QApplication::QApplication()}{-visual} option.
+ \o For 256-color displays which have a true color visual with
+ more than 256 colors, use that visual. Silicon Graphics X
+ servers this feature, for example. They provide an 8 bit
+ visual by default but can deliver true color when asked.
+ \endlist
+ On Windows, Qt creates a Windows palette, and fills it with a color
+ cube.
+ \endlist
+
+ Be aware that the CustomColor and ManyColor choices may lead to colormap
+ flashing: The foreground application gets (most) of the available colors,
+ while the background windows will look less attractive.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 2
+
+ \sa colorSpec()
+*/
+
+void QApplication::setColorSpec(int spec)
+{
+ if (qApp)
+ qWarning("QApplication::setColorSpec: This function must be "
+ "called before the QApplication object is created");
+ QApplicationPrivate::app_cspec = spec;
+}
+
+/*!
+ \property QApplication::globalStrut
+ \brief the minimum size that any GUI element that the user can interact
+ with should have
+
+ For example, no button should be resized to be smaller than the global
+ strut size. The strut size should be considered when reimplementing GUI
+ controls that may be used on touch-screens or similar I/O devices.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 3
+
+ By default, this property contains a QSize object with zero width and height.
+*/
+QSize QApplication::globalStrut()
+{
+ return QApplicationPrivate::app_strut;
+}
+
+void QApplication::setGlobalStrut(const QSize& strut)
+{
+ QApplicationPrivate::app_strut = strut;
+}
+
+
+/*!
+ \fn QPalette QApplication::palette(const QWidget* widget)
+ \overload
+
+ If a \a widget is passed, the default palette for the widget's class is
+ returned. This may or may not be the application palette. In most cases
+ there is no special palette for certain types of widgets, but one notable
+ exception is the popup menu under Windows, if the user has defined a
+ special background color for menus in the display settings.
+
+ \sa setPalette(), QWidget::palette()
+*/
+QPalette QApplication::palette(const QWidget* w)
+{
+ PaletteHash *hash = app_palettes();
+ if (w && hash && hash->size()) {
+ QHash<QByteArray, QPalette>::ConstIterator it = hash->constFind(w->metaObject()->className());
+ if (it != hash->constEnd())
+ return *it;
+ for (it = hash->constBegin(); it != hash->constEnd(); ++it) {
+ if (w->inherits(it.key()))
+ return it.value();
+ }
+ }
+ return palette();
+}
+
+/*!
+ \overload
+
+ Returns the palette for widgets of the given \a className.
+
+ \sa setPalette(), QWidget::palette()
+*/
+QPalette QApplication::palette(const char *className)
+{
+ if (!QApplicationPrivate::app_pal)
+ palette();
+ PaletteHash *hash = app_palettes();
+ if (className && hash && hash->size()) {
+ QHash<QByteArray, QPalette>::ConstIterator it = hash->constFind(className);
+ if (it != hash->constEnd())
+ return *it;
+ }
+ return *QApplicationPrivate::app_pal;
+}
+
+void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash)
+{
+ QPalette pal = palette;
+
+ if (QApplicationPrivate::app_style)
+ QApplicationPrivate::app_style->polish(pal); // NB: non-const reference
+
+ bool all = false;
+ PaletteHash *hash = app_palettes();
+ if (!className) {
+ if (QApplicationPrivate::app_pal && pal.isCopyOf(*QApplicationPrivate::app_pal))
+ return;
+ if (!QApplicationPrivate::app_pal)
+ QApplicationPrivate::app_pal = new QPalette(pal);
+ else
+ *QApplicationPrivate::app_pal = pal;
+ if (hash && hash->size()) {
+ all = true;
+ if (clearWidgetPaletteHash)
+ hash->clear();
+ }
+ } else if (hash) {
+ hash->insert(className, pal);
+ }
+
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ // Send ApplicationPaletteChange to qApp itself, and to the widgets.
+ QEvent e(QEvent::ApplicationPaletteChange);
+ QApplication::sendEvent(QApplication::instance(), &e);
+
+ QWidgetList wids = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = wids.constBegin(); it != wids.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (all || (!className && w->isWindow()) || w->inherits(className)) // matching class
+ QApplication::sendEvent(w, &e);
+ }
+
+ // Send to all scenes as well.
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
+ for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
+ it != scenes.constEnd(); ++it) {
+ QApplication::sendEvent(*it, &e);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ if (!className && (!QApplicationPrivate::sys_pal || !palette.isCopyOf(*QApplicationPrivate::sys_pal))) {
+ if (!QApplicationPrivate::set_pal)
+ QApplicationPrivate::set_pal = new QPalette(palette);
+ else
+ *QApplicationPrivate::set_pal = palette;
+ }
+}
+
+/*!
+ Changes the default application palette to \a palette.
+
+ If \a className is passed, the change applies only to widgets that inherit
+ \a className (as reported by QObject::inherits()). If \a className is left
+ 0, the change affects all widgets, thus overriding any previously set class
+ specific palettes.
+
+ The palette may be changed according to the current GUI style in
+ QStyle::polish().
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ When using style sheets, the palette of a widget can be customized using
+ the "color", "background-color", "selection-color",
+ "selection-background-color" and "alternate-background-color".
+
+ \note Some styles do not use the palette for all drawing, for instance, if
+ they make use of native theme engines. This is the case for the Windows XP,
+ Windows Vista, and Mac OS X styles.
+
+ \sa QWidget::setPalette(), palette(), QStyle::polish()
+*/
+
+void QApplication::setPalette(const QPalette &palette, const char* className)
+{
+ QApplicationPrivate::setPalette_helper(palette, className, /*clearWidgetPaletteHash=*/ true);
+}
+
+
+
+void QApplicationPrivate::setSystemPalette(const QPalette &pal)
+{
+ QPalette adjusted;
+
+#if 0
+ // adjust the system palette to avoid dithering
+ QColormap cmap = QColormap::instance();
+ if (cmap.depths() > 4 && cmap.depths() < 24) {
+ for (int g = 0; g < QPalette::NColorGroups; g++)
+ for (int i = 0; i < QPalette::NColorRoles; i++) {
+ QColor color = pal.color((QPalette::ColorGroup)g, (QPalette::ColorRole)i);
+ color = cmap.colorAt(cmap.pixel(color));
+ adjusted.setColor((QPalette::ColorGroup)g, (QPalette::ColorRole) i, color);
+ }
+ }
+#else
+ adjusted = pal;
+#endif
+
+ if (!sys_pal)
+ sys_pal = new QPalette(adjusted);
+ else
+ *sys_pal = adjusted;
+
+
+ if (!QApplicationPrivate::set_pal)
+ QApplication::setPalette(*sys_pal);
+}
+
+/*!
+ Returns the default application font.
+
+ \sa fontMetrics(), QWidget::font()
+*/
+QFont QApplication::font()
+{
+#ifndef Q_WS_QPA
+ QMutexLocker locker(applicationFontMutex());
+ if (!QApplicationPrivate::app_font)
+ QApplicationPrivate::app_font = new QFont(QLatin1String("Helvetica"));
+ return *QApplicationPrivate::app_font;
+#else
+ return QGuiApplication::font();
+#endif
+}
+
+/*!
+ \overload
+
+ Returns the default font for the \a widget.
+
+ \sa fontMetrics(), QWidget::setFont()
+*/
+
+QFont QApplication::font(const QWidget *widget)
+{
+ FontHash *hash = app_fonts();
+
+#ifdef Q_WS_MAC
+ // short circuit for small and mini controls
+ if (widget->testAttribute(Qt::WA_MacSmallSize)) {
+ return hash->value("QSmallFont");
+ } else if (widget->testAttribute(Qt::WA_MacMiniSize)) {
+ return hash->value("QMiniFont");
+ }
+#endif
+ if (widget && hash && hash->size()) {
+ QHash<QByteArray, QFont>::ConstIterator it =
+ hash->constFind(widget->metaObject()->className());
+ if (it != hash->constEnd())
+ return it.value();
+ for (it = hash->constBegin(); it != hash->constEnd(); ++it) {
+ if (widget->inherits(it.key()))
+ return it.value();
+ }
+ }
+ return font();
+}
+
+/*!
+ \overload
+
+ Returns the font for widgets of the given \a className.
+
+ \sa setFont(), QWidget::font()
+*/
+QFont QApplication::font(const char *className)
+{
+ FontHash *hash = app_fonts();
+ if (className && hash && hash->size()) {
+ QHash<QByteArray, QFont>::ConstIterator it = hash->constFind(className);
+ if (it != hash->constEnd())
+ return *it;
+ }
+ return font();
+}
+
+
+/*!
+ Changes the default application font to \a font. If \a className is passed,
+ the change applies only to classes that inherit \a className (as reported
+ by QObject::inherits()).
+
+ On application start-up, the default font depends on the window system. It
+ can vary depending on both the window system version and the locale. This
+ function lets you override the default font; but overriding may be a bad
+ idea because, for example, some locales need extra large fonts to support
+ their special characters.
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ The font of an application can be customized using the "font" style sheet
+ property. To set a bold font for all QPushButtons, set the application
+ styleSheet() as "QPushButton { font: bold }"
+
+ \sa font(), fontMetrics(), QWidget::setFont()
+*/
+
+void QApplication::setFont(const QFont &font, const char *className)
+{
+ bool all = false;
+ FontHash *hash = app_fonts();
+ if (!className) {
+#ifndef Q_WS_QPA
+ QMutexLocker locker(applicationFontMutex());
+ if (!QApplicationPrivate::app_font)
+ QApplicationPrivate::app_font = new QFont(font);
+ else
+ *QApplicationPrivate::app_font = font;
+#else
+ QGuiApplication::setFont(font);
+#endif
+ if (hash && hash->size()) {
+ all = true;
+ hash->clear();
+ }
+ } else if (hash) {
+ hash->insert(className, font);
+ }
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ // Send ApplicationFontChange to qApp itself, and to the widgets.
+ QEvent e(QEvent::ApplicationFontChange);
+ QApplication::sendEvent(QApplication::instance(), &e);
+
+ QWidgetList wids = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = wids.constBegin(); it != wids.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (all || (!className && w->isWindow()) || w->inherits(className)) // matching class
+ sendEvent(w, &e);
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Send to all scenes as well.
+ QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
+ for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
+ it != scenes.constEnd(); ++it) {
+ QApplication::sendEvent(*it, &e);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ if (!className && (!QApplicationPrivate::sys_font || !font.isCopyOf(*QApplicationPrivate::sys_font))) {
+ if (!QApplicationPrivate::set_font)
+ QApplicationPrivate::set_font = new QFont(font);
+ else
+ *QApplicationPrivate::set_font = font;
+ }
+}
+
+/*! \internal
+*/
+void QApplicationPrivate::setSystemFont(const QFont &font)
+{
+ if (!sys_font)
+ sys_font = new QFont(font);
+ else
+ *sys_font = font;
+
+ if (!QApplicationPrivate::set_font)
+ QApplication::setFont(*sys_font);
+}
+
+/*! \internal
+*/
+QString QApplicationPrivate::desktopStyleKey()
+{
+ return qt_guiPlatformPlugin()->styleName();
+}
+
+/*!
+ \property QApplication::windowIcon
+ \brief the default window icon
+
+ \sa QWidget::setWindowIcon(), {Setting the Application Icon}
+*/
+QIcon QApplication::windowIcon()
+{
+ return QApplicationPrivate::app_icon ? *QApplicationPrivate::app_icon : QIcon();
+}
+
+void QApplication::setWindowIcon(const QIcon &icon)
+{
+ if (!QApplicationPrivate::app_icon)
+ QApplicationPrivate::app_icon = new QIcon();
+ *QApplicationPrivate::app_icon = icon;
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+#ifdef Q_WS_MAC
+ void qt_mac_set_app_icon(const QPixmap &); //qapplication_mac.cpp
+ QSize size = QApplicationPrivate::app_icon->actualSize(QSize(128, 128));
+ qt_mac_set_app_icon(QApplicationPrivate::app_icon->pixmap(size));
+#endif
+ QEvent e(QEvent::ApplicationWindowIconChange);
+ QWidgetList all = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (w->isWindow())
+ sendEvent(w, &e);
+ }
+ }
+}
+
+/*!
+ Returns a list of the top-level widgets (windows) in the application.
+
+ \note Some of the top-level widgets may be hidden, for example a tooltip if
+ no tooltip is currently shown.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 4
+
+ \sa allWidgets(), QWidget::isWindow(), QWidget::isHidden()
+*/
+QWidgetList QApplication::topLevelWidgets()
+{
+ QWidgetList list;
+ QWidgetList all = allWidgets();
+
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ QWidget *w = *it;
+ if (w->isWindow() && w->windowType() != Qt::Desktop)
+ list.append(w);
+ }
+ return list;
+}
+
+/*!
+ Returns a list of all the widgets in the application.
+
+ The list is empty (QList::isEmpty()) if there are no widgets.
+
+ \note Some of the widgets may be hidden.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 5
+
+ \sa topLevelWidgets(), QWidget::isVisible()
+*/
+
+QWidgetList QApplication::allWidgets()
+{
+ if (QWidgetPrivate::allWidgets)
+ return QWidgetPrivate::allWidgets->toList();
+ return QWidgetList();
+}
+
+/*!
+ Returns the application widget that has the keyboard input focus, or 0 if
+ no widget in this application has the focus.
+
+ \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
+*/
+
+QWidget *QApplication::focusWidget()
+{
+ return QApplicationPrivate::focus_widget;
+}
+
+void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
+{
+#ifndef QT_NO_GRAPHICSVIEW
+ if (focus && focus->window()->graphicsProxyWidget())
+ return;
+#endif
+
+ hidden_focus_widget = 0;
+
+ if (focus != focus_widget) {
+ if (focus && focus->isHidden()) {
+ hidden_focus_widget = focus;
+ return;
+ }
+
+ if (focus && (reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
+ && qt_in_tab_key_event)
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ else if (focus && reason == Qt::ShortcutFocusReason) {
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ }
+ QWidget *prev = focus_widget;
+ focus_widget = focus;
+#ifndef QT_NO_IM
+ if (prev && ((reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
+ && prev->testAttribute(Qt::WA_InputMethodEnabled))
+ // Do reset the input context, in case the new focus widget won't accept keyboard input
+ // or it is not created fully yet.
+ || (focus_widget && (!focus_widget->testAttribute(Qt::WA_InputMethodEnabled)
+ || !focus_widget->testAttribute(Qt::WA_WState_Created))))) {
+ QInputContext *qic = prev->inputContext();
+ if(qic) {
+ qic->reset();
+ qic->setFocusWidget(0);
+ }
+ }
+#endif //QT_NO_IM
+
+ if(focus_widget)
+ focus_widget->d_func()->setFocus_sys();
+
+ if (reason != Qt::NoFocusReason) {
+
+ //send events
+ if (prev) {
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled()) {
+ if (prev->hasEditFocus() && reason != Qt::PopupFocusReason
+#ifdef Q_OS_SYMBIAN
+ && reason != Qt::ActiveWindowFocusReason
+#endif
+ )
+ prev->setEditFocus(false);
+ }
+#endif
+#ifndef QT_NO_IM
+ if (focus) {
+ QInputContext *prevIc;
+ prevIc = prev->inputContext();
+ if (prevIc && prevIc != focus->inputContext()) {
+ QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel);
+ QApplication::sendEvent(prev, &closeSIPEvent);
+ }
+ }
+#endif
+ QFocusEvent out(QEvent::FocusOut, reason);
+ QPointer<QWidget> that = prev;
+ QApplication::sendEvent(prev, &out);
+ if (that)
+ QApplication::sendEvent(that->style(), &out);
+ }
+ if(focus && QApplicationPrivate::focus_widget == focus) {
+#ifndef QT_NO_IM
+ if (focus->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *qic = focus->inputContext();
+ if (qic && focus->testAttribute(Qt::WA_WState_Created)
+ && focus->isEnabled())
+ qic->setFocusWidget(focus);
+ }
+#endif //QT_NO_IM
+ QFocusEvent in(QEvent::FocusIn, reason);
+ QPointer<QWidget> that = focus;
+ QApplication::sendEvent(focus, &in);
+ if (that)
+ QApplication::sendEvent(that->style(), &in);
+ }
+ emit qApp->focusChanged(prev, focus_widget);
+ }
+ }
+}
+
+
+/*!
+ Returns the application top-level window that has the keyboard input focus,
+ or 0 if no application window has the focus. There might be an
+ activeWindow() even if there is no focusWidget(), for example if no widget
+ in that window accepts key events.
+
+ \sa QWidget::setFocus(), QWidget::hasFocus(), focusWidget()
+*/
+
+QWidget *QApplication::activeWindow()
+{
+ return QApplicationPrivate::active_window;
+}
+
+/*!
+ Returns display (screen) font metrics for the application font.
+
+ \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
+*/
+
+QFontMetrics QApplication::fontMetrics()
+{
+ return desktop()->fontMetrics();
+}
+
+
+/*!
+ Closes all top-level windows.
+
+ This function is particularly useful for applications with many top-level
+ windows. It could, for example, be connected to a \gui{Exit} entry in the
+ \gui{File} menu:
+
+ \snippet examples/mainwindows/mdi/mainwindow.cpp 0
+
+ The windows are closed in random order, until one window does not accept
+ the close event. The application quits when the last window was
+ successfully closed; this can be turned off by setting
+ \l quitOnLastWindowClosed to false.
+
+ \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(),
+ QWidget::closeEvent(), lastWindowClosed(), quit(), topLevelWidgets(),
+ QWidget::isWindow()
+*/
+void QApplication::closeAllWindows()
+{
+ bool did_close = true;
+ QWidget *w;
+ while ((w = activeModalWidget()) && did_close) {
+ if (!w->isVisible() || w->data->is_closing)
+ break;
+ did_close = w->close();
+ }
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; did_close && i < list.size(); ++i) {
+ w = list.at(i);
+ if (w->isVisible()
+ && w->windowType() != Qt::Desktop
+ && !w->data->is_closing) {
+ did_close = w->close();
+ list = QApplication::topLevelWidgets();
+ i = -1;
+ }
+ }
+}
+
+/*!
+ Displays a simple message box about Qt. The message includes the version
+ number of Qt being used by the application.
+
+ This is useful for inclusion in the \gui Help menu of an application, as
+ shown in the \l{mainwindows/menus}{Menus} example.
+
+ This function is a convenience slot for QMessageBox::aboutQt().
+*/
+void QApplication::aboutQt()
+{
+#ifndef QT_NO_MESSAGEBOX
+ QMessageBox::aboutQt(
+#ifdef Q_WS_MAC
+ 0
+#else
+ activeWindow()
+#endif // Q_WS_MAC
+ );
+#endif // QT_NO_MESSAGEBOX
+}
+
+
+/*!
+ \fn void QApplication::lastWindowClosed()
+
+ This signal is emitted from QApplication::exec() when the last visible
+ primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose
+ attribute set is closed.
+
+ By default,
+
+ \list
+ \o this attribute is set for all widgets except transient windows such
+ as splash screens, tool windows, and popup menus
+
+ \o QApplication implicitly quits when this signal is emitted.
+ \endlist
+
+ This feature can be turned off by setting \l quitOnLastWindowClosed to
+ false.
+
+ \sa QWidget::close()
+*/
+
+/*!
+ \since 4.1
+ \fn void QApplication::focusChanged(QWidget *old, QWidget *now)
+
+ This signal is emitted when the widget that has keyboard focus changed from
+ \a old to \a now, i.e., because the user pressed the tab-key, clicked into
+ a widget or changed the active window. Both \a old and \a now can be the
+ null-pointer.
+
+ The signal is emitted after both widget have been notified about the change
+ through QFocusEvent.
+
+ \sa QWidget::setFocus(), QWidget::clearFocus(), Qt::FocusReason
+*/
+
+
+#ifndef QT_NO_TRANSLATION
+#if defined(Q_WS_MAC)
+static const char *application_menu_strings[] = {
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1")
+ };
+QString qt_mac_applicationmenu_string(int type)
+{
+ QString menuString = QString::fromLatin1(application_menu_strings[type]);
+ QString translated = qApp->translate("QMenuBar", application_menu_strings[type]);
+ if (translated != menuString)
+ return translated;
+ else
+ return qApp->translate("MAC_APPLICATION_MENU",
+ application_menu_strings[type]);
+}
+#endif
+#endif
+
+/*!\reimp
+
+*/
+bool QApplication::event(QEvent *e)
+{
+ Q_D(QApplication);
+ if(e->type() == QEvent::Close) {
+#if defined(Q_OS_SYMBIAN)
+ // In order to have proper application-exit effects on Symbian, certain
+ // native APIs have to be called _before_ closing/destroying the widgets.
+ bool effectStarted = qt_beginFullScreenEffect();
+#endif
+ QCloseEvent *ce = static_cast<QCloseEvent*>(e);
+ ce->accept();
+ closeAllWindows();
+
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) &&
+ (!(w->windowType() == Qt::Dialog) || !w->parentWidget())) {
+ ce->ignore();
+ break;
+ }
+ }
+ if (ce->isAccepted()) {
+ return true;
+ } else {
+#if defined(Q_OS_SYMBIAN)
+ if (effectStarted)
+ qt_abortFullScreenEffect();
+#endif
+ }
+#ifndef Q_OS_WIN
+ } else if (e->type() == QEvent::LocaleChange) {
+ // on Windows the event propagation is taken care by the
+ // WM_SETTINGCHANGE event handler.
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (!(w->windowType() == Qt::Desktop)) {
+ if (!w->testAttribute(Qt::WA_SetLocale))
+ w->d_func()->setLocale_helper(QLocale(), true);
+ }
+ }
+#endif
+ } else if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ Q_ASSERT(te != 0);
+ if (te->timerId() == d->toolTipWakeUp.timerId()) {
+ d->toolTipWakeUp.stop();
+ if (d->toolTipWidget) {
+ QWidget *w = d->toolTipWidget->window();
+ // show tooltip if WA_AlwaysShowToolTips is set, or if
+ // any ancestor of d->toolTipWidget is the active
+ // window
+ bool showToolTip = w->testAttribute(Qt::WA_AlwaysShowToolTips);
+ while (w && !showToolTip) {
+ showToolTip = w->isActiveWindow();
+ w = w->parentWidget();
+ w = w ? w->window() : 0;
+ }
+ if (showToolTip) {
+ QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
+ QApplication::sendEvent(d->toolTipWidget, &e);
+ if (e.isAccepted())
+ d->toolTipFallAsleep.start(2000, this);
+ }
+ }
+ } else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
+ d->toolTipFallAsleep.stop();
+ }
+ }
+ return QApplicationBase::event(e);
+
+ if(e->type() == QEvent::LanguageChange) {
+#if defined(QT_MAC_USE_COCOA)
+ qt_mac_post_retranslateAppMenu();
+#endif
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (!(w->windowType() == Qt::Desktop))
+ postEvent(w, new QEvent(QEvent::LanguageChange));
+ }
+ }
+
+}
+#if !defined(Q_WS_X11)
+
+// The doc and X implementation of this function is in qapplication_x11.cpp
+
+void QApplication::syncX() {} // do nothing
+
+#endif
+
+void QApplicationPrivate::notifyLayoutDirectionChange()
+{
+ Q_Q(QApplication);
+ QWidgetList list = q->topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ QEvent ev(QEvent::ApplicationLayoutDirectionChange);
+ q->sendEvent(w, &ev);
+ }
+}
+
+
+/*!
+ \fn Qt::WindowsVersion QApplication::winVersion()
+
+ Use \l QSysInfo::WindowsVersion instead.
+*/
+
+/*!
+ \fn void QApplication::setActiveWindow(QWidget* active)
+
+ Sets the active window to the \a active widget in response to a system
+ event. The function is called from the platform specific event handlers.
+
+ \warning This function does \e not set the keyboard focus to the active
+ widget. Call QWidget::activateWindow() instead.
+
+ It sets the activeWindow() and focusWidget() attributes and sends proper
+ \l{QEvent::WindowActivate}{WindowActivate}/\l{QEvent::WindowDeactivate}
+ {WindowDeactivate} and \l{QEvent::FocusIn}{FocusIn}/\l{QEvent::FocusOut}
+ {FocusOut} events to all appropriate widgets. The window will then be
+ painted in active state (e.g. cursors in line edits will blink), and it
+ will have tool tips enabled.
+
+ \sa activeWindow(), QWidget::activateWindow()
+*/
+void QApplication::setActiveWindow(QWidget* act)
+{
+ QWidget* window = act?act->window():0;
+
+ if (QApplicationPrivate::active_window == window)
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (window && window->graphicsProxyWidget()) {
+ // Activate the proxy's view->viewport() ?
+ return;
+ }
+#endif
+
+ QWidgetList toBeActivated;
+ QWidgetList toBeDeactivated;
+
+ if (QApplicationPrivate::active_window) {
+ if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) {
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && w->isActiveWindow())
+ toBeDeactivated.append(w);
+ }
+ } else {
+ toBeDeactivated.append(QApplicationPrivate::active_window);
+ }
+ }
+
+#if !defined(Q_WS_MAC)
+ QWidget *previousActiveWindow = QApplicationPrivate::active_window;
+#endif
+ QApplicationPrivate::active_window = window;
+
+ if (QApplicationPrivate::active_window) {
+ if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) {
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && w->isActiveWindow())
+ toBeActivated.append(w);
+ }
+ } else {
+ toBeActivated.append(QApplicationPrivate::active_window);
+ }
+
+ }
+
+ // first the activation/deactivation events
+ QEvent activationChange(QEvent::ActivationChange);
+ QEvent windowActivate(QEvent::WindowActivate);
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+
+#if !defined(Q_WS_MAC)
+ if (!previousActiveWindow) {
+ QEvent appActivate(QEvent::ApplicationActivate);
+ sendSpontaneousEvent(qApp, &appActivate);
+ }
+#endif
+
+ for (int i = 0; i < toBeActivated.size(); ++i) {
+ QWidget *w = toBeActivated.at(i);
+ sendSpontaneousEvent(w, &windowActivate);
+ sendSpontaneousEvent(w, &activationChange);
+ }
+
+#ifdef QT_MAC_USE_COCOA
+ // In case the user clicked on a child window, we need to
+ // reestablish the stacking order of the window so
+ // it pops in front of other child windows in cocoa:
+ qt_cocoaStackChildWindowOnTopOfOtherChildren(window);
+#endif
+
+ for(int i = 0; i < toBeDeactivated.size(); ++i) {
+ QWidget *w = toBeDeactivated.at(i);
+ sendSpontaneousEvent(w, &windowDeactivate);
+ sendSpontaneousEvent(w, &activationChange);
+ }
+
+#if !defined(Q_WS_MAC)
+ if (!QApplicationPrivate::active_window) {
+ QEvent appDeactivate(QEvent::ApplicationDeactivate);
+ sendSpontaneousEvent(qApp, &appDeactivate);
+ }
+#endif
+
+ if (QApplicationPrivate::popupWidgets == 0) { // !inPopupMode()
+ // then focus events
+ if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
+ QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
+ } else if (QApplicationPrivate::active_window) {
+ QWidget *w = QApplicationPrivate::active_window->focusWidget();
+ if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
+ w->setFocus(Qt::ActiveWindowFocusReason);
+ else {
+ w = QApplicationPrivate::focusNextPrevChild_helper(QApplicationPrivate::active_window, true);
+ if (w) {
+ w->setFocus(Qt::ActiveWindowFocusReason);
+ } else {
+ // If the focus widget is not in the activate_window, clear the focus
+ w = QApplicationPrivate::focus_widget;
+ if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus)
+ QApplicationPrivate::setFocusWidget(QApplicationPrivate::active_window, Qt::ActiveWindowFocusReason);
+ else if (!QApplicationPrivate::active_window->isAncestorOf(w))
+ QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
+ }
+ }
+ }
+ }
+}
+
+/*!internal
+ * Helper function that returns the new focus widget, but does not set the focus reason.
+ * Returns 0 if a new focus widget could not be found.
+ * Shared with QGraphicsProxyWidgetPrivate::findFocusChild()
+*/
+QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next)
+{
+ uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
+
+ QWidget *f = toplevel->focusWidget();
+ if (!f)
+ f = toplevel;
+
+ QWidget *w = f;
+ QWidget *test = f->d_func()->focus_next;
+ while (test && test != f) {
+ if ((test->focusPolicy() & focus_flag) == focus_flag
+ && !(test->d_func()->extra && test->d_func()->extra->focus_proxy)
+ && test->isVisibleTo(toplevel) && test->isEnabled()
+ && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
+ && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) {
+ w = test;
+ if (next)
+ break;
+ }
+ test = test->d_func()->focus_next;
+ }
+ if (w == f) {
+ if (qt_in_tab_key_event) {
+ w->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ w->update();
+ }
+ return 0;
+ }
+ return w;
+}
+
+/*!
+ \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave)
+ \internal
+
+ Creates the proper Enter/Leave event when widget \a enter is entered and
+ widget \a leave is left.
+ */
+void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
+#if 0
+ if (leave) {
+ QEvent e(QEvent::Leave);
+ QApplication::sendEvent(leave, & e);
+ }
+ if (enter) {
+ QEvent e(QEvent::Enter);
+ QApplication::sendEvent(enter, & e);
+ }
+ return;
+#endif
+
+ QWidget* w ;
+ if ((!enter && !leave) || (enter == leave))
+ return;
+#ifdef ALIEN_DEBUG
+ qDebug() << "QApplicationPrivate::dispatchEnterLeave, ENTER:" << enter << "LEAVE:" << leave;
+#endif
+ QWidgetList leaveList;
+ QWidgetList enterList;
+
+ bool sameWindow = leave && enter && leave->window() == enter->window();
+ if (leave && !sameWindow) {
+ w = leave;
+ do {
+ leaveList.append(w);
+ } while (!w->isWindow() && (w = w->parentWidget()));
+ }
+ if (enter && !sameWindow) {
+ w = enter;
+ do {
+ enterList.prepend(w);
+ } while (!w->isWindow() && (w = w->parentWidget()));
+ }
+ if (sameWindow) {
+ int enterDepth = 0;
+ int leaveDepth = 0;
+ w = enter;
+ while (!w->isWindow() && (w = w->parentWidget()))
+ enterDepth++;
+ w = leave;
+ while (!w->isWindow() && (w = w->parentWidget()))
+ leaveDepth++;
+ QWidget* wenter = enter;
+ QWidget* wleave = leave;
+ while (enterDepth > leaveDepth) {
+ wenter = wenter->parentWidget();
+ enterDepth--;
+ }
+ while (leaveDepth > enterDepth) {
+ wleave = wleave->parentWidget();
+ leaveDepth--;
+ }
+ while (!wenter->isWindow() && wenter != wleave) {
+ wenter = wenter->parentWidget();
+ wleave = wleave->parentWidget();
+ }
+
+ w = leave;
+ while (w != wleave) {
+ leaveList.append(w);
+ w = w->parentWidget();
+ }
+ w = enter;
+ while (w != wenter) {
+ enterList.prepend(w);
+ w = w->parentWidget();
+ }
+ }
+
+ QEvent leaveEvent(QEvent::Leave);
+ for (int i = 0; i < leaveList.size(); ++i) {
+ w = leaveList.at(i);
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
+ if (leaveAfterRelease == w)
+ leaveAfterRelease = 0;
+#endif
+ QApplication::sendEvent(w, &leaveEvent);
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
+ Q_ASSERT(instance());
+ QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
+ qApp->d_func()->notify_helper(w, &he);
+ }
+ }
+ }
+ QPoint posEnter = QCursor::pos();
+ QEvent enterEvent(QEvent::Enter);
+ for (int i = 0; i < enterList.size(); ++i) {
+ w = enterList.at(i);
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ QApplication::sendEvent(w, &enterEvent);
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
+ QHoverEvent he(QEvent::HoverEnter, w->mapFromGlobal(posEnter), QPoint(-1, -1));
+ qApp->d_func()->notify_helper(w, &he);
+ }
+ }
+ }
+
+#ifndef QT_NO_CURSOR
+ // Update cursor for alien/graphics widgets.
+
+ const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen)));
+#if defined(Q_WS_X11) || defined(Q_WS_QPA)
+ //Whenever we leave an alien widget on X11, we need to reset its nativeParentWidget()'s cursor.
+ // This is not required on Windows as the cursor is reset on every single mouse move.
+ QWidget *parentOfLeavingCursor = 0;
+ for (int i = 0; i < leaveList.size(); ++i) {
+ w = leaveList.at(i);
+ if (!isAlien(w))
+ break;
+ if (w->testAttribute(Qt::WA_SetCursor)) {
+ QWidget *parent = w->parentWidget();
+ while (parent && parent->d_func()->data.in_destructor)
+ parent = parent->parentWidget();
+ parentOfLeavingCursor = parent;
+ //continue looping, we need to find the downest alien widget with a cursor.
+ // (downest on the screen)
+ }
+ }
+ //check that we will not call qt_x11_enforce_cursor twice with the same native widget
+ if (parentOfLeavingCursor && (!enterOnAlien
+ || parentOfLeavingCursor->effectiveWinId() != enter->effectiveWinId())) {
+#ifndef QT_NO_GRAPHICSVIEW
+ if (!parentOfLeavingCursor->window()->graphicsProxyWidget())
+#endif
+ {
+#if defined(Q_WS_X11)
+ qt_x11_enforce_cursor(parentOfLeavingCursor,true);
+#elif defined(Q_WS_QPA)
+ if (enter == QApplication::desktop()) {
+ qt_qpa_set_cursor(enter, true);
+ } else {
+ qt_qpa_set_cursor(parentOfLeavingCursor, true);
+ }
+#endif
+ }
+ }
+#endif
+ if (enterOnAlien) {
+ QWidget *cursorWidget = enter;
+ while (!cursorWidget->isWindow() && !cursorWidget->isEnabled())
+ cursorWidget = cursorWidget->parentWidget();
+
+ if (!cursorWidget)
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (cursorWidget->window()->graphicsProxyWidget()) {
+ QWidgetPrivate::nearestGraphicsProxyWidget(cursorWidget)->setCursor(cursorWidget->cursor());
+ } else
+#endif
+ {
+#if defined(Q_WS_WIN)
+ qt_win_set_cursor(cursorWidget, true);
+#elif defined(Q_WS_X11)
+ qt_x11_enforce_cursor(cursorWidget, true);
+#elif defined(Q_OS_SYMBIAN)
+ qt_symbian_set_cursor(cursorWidget, true);
+#elif defined(Q_WS_QPA)
+ qt_qpa_set_cursor(cursorWidget, true);
+#endif
+ }
+ }
+#endif
+}
+
+/* exported for the benefit of testing tools */
+Q_GUI_EXPORT bool qt_tryModalHelper(QWidget *widget, QWidget **rettop)
+{
+ return QApplicationPrivate::tryModalHelper(widget, rettop);
+}
+
+/*! \internal
+ Returns true if \a widget is blocked by a modal window.
+ */
+bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
+{
+ widget = widget->window();
+ if (!modalState())
+ return false;
+ if (QApplication::activePopupWidget() == widget)
+ return false;
+
+#if 0
+ for (int i = 0; i < qt_modal_stack->size(); ++i) {
+ QWidget *modalWidget = qt_modal_stack->at(i);
+
+ {
+ // check if the active modal widget is our widget or a parent of our widget
+ QWidget *w = widget;
+ while (w) {
+ if (w == modalWidget)
+ return false;
+ w = w->parentWidget();
+ }
+#ifdef Q_WS_WIN
+ if ((widget->testAttribute(Qt::WA_WState_Created) || widget->data->winid)
+ && (modalWidget->testAttribute(Qt::WA_WState_Created) || modalWidget->data->winid)
+ && IsChild(modalWidget->data->winid, widget->data->winid))
+ return false;
+#endif
+ }
+
+ Qt::WindowModality windowModality = modalWidget->windowModality();
+ if (windowModality == Qt::NonModal) {
+ // determine the modality type if it hasn't been set on the
+ // modalWidget, this normally happens when waiting for a
+ // native dialog. use WindowModal if we are the child of a
+ // group leader; otherwise use ApplicationModal.
+ QWidget *m = modalWidget;
+ while (m && !m->testAttribute(Qt::WA_GroupLeader)) {
+ m = m->parentWidget();
+ if (m)
+ m = m->window();
+ }
+ windowModality = (m && m->testAttribute(Qt::WA_GroupLeader))
+ ? Qt::WindowModal
+ : Qt::ApplicationModal;
+ }
+
+ switch (windowModality) {
+ case Qt::ApplicationModal:
+ {
+ QWidget *groupLeaderForWidget = widget;
+ while (groupLeaderForWidget && !groupLeaderForWidget->testAttribute(Qt::WA_GroupLeader))
+ groupLeaderForWidget = groupLeaderForWidget->parentWidget();
+
+ if (groupLeaderForWidget) {
+ // if \a widget has WA_GroupLeader, it can only be blocked by ApplicationModal children
+ QWidget *m = modalWidget;
+ while (m && m != groupLeaderForWidget && !m->testAttribute(Qt::WA_GroupLeader))
+ m = m->parentWidget();
+ if (m == groupLeaderForWidget)
+ return true;
+ } else if (modalWidget != widget) {
+ return true;
+ }
+ break;
+ }
+ case Qt::WindowModal:
+ {
+ QWidget *w = widget;
+ do {
+ QWidget *m = modalWidget;
+ do {
+ if (m == w)
+ return true;
+ m = m->parentWidget();
+ if (m)
+ m = m->window();
+ } while (m);
+ w = w->parentWidget();
+ if (w)
+ w = w->window();
+ } while (w);
+ break;
+ }
+ default:
+ Q_ASSERT_X(false, "QApplication", "internal error, a modal widget cannot be modeless");
+ break;
+ }
+ }
+#endif
+ return false;
+}
+
+/*!\internal
+ */
+void QApplicationPrivate::enterModal(QWidget *widget)
+{
+ QSet<QWidget*> blocked;
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (window->windowType() != Qt::Tool && isBlockedByModal(window))
+ blocked.insert(window);
+ }
+
+ enterModal_sys(widget);
+
+ windows = QApplication::topLevelWidgets();
+ QEvent e(QEvent::WindowBlocked);
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (!blocked.contains(window) && window->windowType() != Qt::Tool && isBlockedByModal(window))
+ QApplication::sendEvent(window, &e);
+ }
+}
+
+/*!\internal
+ */
+void QApplicationPrivate::leaveModal(QWidget *widget)
+{
+ QSet<QWidget*> blocked;
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (window->windowType() != Qt::Tool && isBlockedByModal(window))
+ blocked.insert(window);
+ }
+
+ leaveModal_sys(widget);
+
+ windows = QApplication::topLevelWidgets();
+ QEvent e(QEvent::WindowUnblocked);
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if(blocked.contains(window) && window->windowType() != Qt::Tool && !isBlockedByModal(window))
+ QApplication::sendEvent(window, &e);
+ }
+}
+
+
+
+/*!\internal
+
+ Called from qapplication_\e{platform}.cpp, returns true
+ if the widget should accept the event.
+ */
+bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
+{
+ QWidget *top = QApplication::activeModalWidget();
+ if (rettop)
+ *rettop = top;
+
+ // the active popup widget always gets the input event
+ if (QApplication::activePopupWidget())
+ return true;
+
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ top = QApplicationPrivate::tryModalHelper_sys(top);
+ if (rettop)
+ *rettop = top;
+#endif
+
+ return !isBlockedByModal(widget->window());
+}
+
+/*
+ \internal
+*/
+QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint &globalPos,
+ QPoint &pos, QEvent::Type type,
+ Qt::MouseButtons buttons, QWidget *buttonDown,
+ QWidget *alienWidget)
+{
+ Q_ASSERT(candidate);
+
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ if (((type == QEvent::MouseMove && buttons) || (type == QEvent::MouseButtonRelease))
+ && !buttonDown && !mouseGrabber) {
+ return 0;
+ }
+
+ if (alienWidget && alienWidget->internalWinId())
+ alienWidget = 0;
+
+ QWidget *receiver = candidate;
+
+ if (!mouseGrabber)
+ mouseGrabber = (buttonDown && !isBlockedByModal(buttonDown)) ? buttonDown : alienWidget;
+
+ if (mouseGrabber && mouseGrabber != candidate) {
+ receiver = mouseGrabber;
+ pos = receiver->mapFromGlobal(globalPos);
+#ifdef ALIEN_DEBUG
+ qDebug() << " ** receiver adjusted to:" << receiver << "pos:" << pos;
+#endif
+ }
+
+ return receiver;
+
+}
+
+/*
+ \internal
+*/
+bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
+ QWidget *alienWidget, QWidget *nativeWidget,
+ QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous)
+{
+ Q_ASSERT(receiver);
+ Q_ASSERT(event);
+ Q_ASSERT(nativeWidget);
+ Q_ASSERT(buttonDown);
+
+ if (alienWidget && !isAlien(alienWidget))
+ alienWidget = 0;
+
+ QPointer<QWidget> receiverGuard = receiver;
+ QPointer<QWidget> nativeGuard = nativeWidget;
+ QPointer<QWidget> alienGuard = alienWidget;
+ QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
+
+ const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen);
+
+ if (*buttonDown) {
+ if (!graphicsWidget) {
+ // Register the widget that shall receive a leave event
+ // after the last button is released.
+ if ((alienWidget || !receiver->internalWinId()) && !leaveAfterRelease && !QWidget::mouseGrabber())
+ leaveAfterRelease = *buttonDown;
+ if (event->type() == QEvent::MouseButtonRelease && !event->buttons())
+ *buttonDown = 0;
+ }
+ } else if (lastMouseReceiver) {
+ // Dispatch enter/leave if we move:
+ // 1) from an alien widget to another alien widget or
+ // from a native widget to an alien widget (first OR case)
+ // 2) from an alien widget to a native widget (second OR case)
+ if ((alienWidget && alienWidget != lastMouseReceiver)
+ || (isAlien(lastMouseReceiver) && !alienWidget)) {
+ if (activePopupWidget) {
+ if (!QWidget::mouseGrabber())
+ dispatchEnterLeave(alienWidget ? alienWidget : nativeWidget, lastMouseReceiver);
+ } else {
+ dispatchEnterLeave(receiver, lastMouseReceiver);
+ }
+
+ }
+ }
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QApplicationPrivate::sendMouseEvent: receiver:" << receiver
+ << "pos:" << event->pos() << "alien" << alienWidget << "button down"
+ << *buttonDown << "last" << lastMouseReceiver << "leave after release"
+ << leaveAfterRelease;
+#endif
+
+ // We need this quard in case someone opens a modal dialog / popup. If that's the case
+ // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
+ const bool wasLeaveAfterRelease = leaveAfterRelease != 0;
+ bool result;
+ if (spontaneous)
+ result = QApplication::sendSpontaneousEvent(receiver, event);
+ else
+ result = QApplication::sendEvent(receiver, event);
+
+ if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
+ && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
+ // Dispatch enter/leave if:
+ // 1) the mouse grabber is an alien widget
+ // 2) the button is released on an alien widget
+ QWidget *enter = 0;
+ if (nativeGuard)
+ enter = alienGuard ? alienWidget : nativeWidget;
+ else // The receiver is typically deleted on mouse release with drag'n'drop.
+ enter = QApplication::widgetAt(event->globalPos());
+ dispatchEnterLeave(enter, leaveAfterRelease);
+ leaveAfterRelease = 0;
+ lastMouseReceiver = enter;
+ } else if (!wasLeaveAfterRelease) {
+ if (activePopupWidget) {
+ if (!QWidget::mouseGrabber())
+ lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : 0);
+ } else {
+ lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPos());
+ }
+ }
+
+ return result;
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
+/*
+ This function should only be called when the widget changes visibility, i.e.
+ when the \a widget is shown, hidden or deleted. This function does nothing
+ if the widget is a top-level or native, i.e. not an alien widget. In that
+ case enter/leave events are genereated by the underlying windowing system.
+*/
+extern QPointer<QWidget> qt_last_mouse_receiver;
+extern QWidget *qt_button_down;
+void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
+{
+#ifndef QT_NO_CURSOR
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ if (!widget || widget->isWindow())
+ return;
+#else
+ if (!widget || widget->internalWinId() || widget->isWindow())
+ return;
+#endif
+ const bool widgetInShow = widget->isVisible() && !widget->data->in_destructor;
+ if (!widgetInShow && widget != qt_last_mouse_receiver)
+ return; // Widget was not under the cursor when it was hidden/deleted.
+
+ if (widgetInShow && widget->parentWidget()->data->in_show)
+ return; // Ingore recursive show.
+
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ if (mouseGrabber && mouseGrabber != widget)
+ return; // Someone else has the grab; enter/leave should not occur.
+
+ QWidget *tlw = widget->window();
+ if (tlw->data->in_destructor || tlw->data->is_closing)
+ return; // Closing down the business.
+
+ if (widgetInShow && (!qt_last_mouse_receiver || qt_last_mouse_receiver->window() != tlw))
+ return; // Mouse cursor not inside the widget's top-level.
+
+ const QPoint globalPos(QCursor::pos());
+ QPoint pos = tlw->mapFromGlobal(globalPos);
+
+ // Find the current widget under the mouse. If this function was called from
+ // the widget's destructor, we have to make sure childAt() doesn't take into
+ // account widgets that are about to be destructed.
+ QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(pos, widget->data->in_destructor);
+ if (!widgetUnderCursor)
+ widgetUnderCursor = tlw;
+ else
+ pos = widgetUnderCursor->mapFrom(tlw, pos);
+
+ if (widgetInShow && widgetUnderCursor != widget && !widget->isAncestorOf(widgetUnderCursor))
+ return; // Mouse cursor not inside the widget or any of its children.
+
+ if (widget->data->in_destructor && qt_button_down == widget)
+ qt_button_down = 0;
+
+ // Send enter/leave events followed by a mouse move on the entered widget.
+ QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
+ sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
+#endif // QT_NO_CURSOR
+}
+#endif // Q_WS_WIN || Q_WS_X11 || Q_WS_MAC
+
+/*!
+ Returns the desktop widget (also called the root window).
+
+ The desktop may be composed of multiple screens, so it would be incorrect,
+ for example, to attempt to \e center some widget in the desktop's geometry.
+ QDesktopWidget has various functions for obtaining useful geometries upon
+ the desktop, such as QDesktopWidget::screenGeometry() and
+ QDesktopWidget::availableGeometry().
+
+ On X11, it is also possible to draw on the desktop.
+*/
+QDesktopWidget *QApplication::desktop()
+{
+ if (!qt_desktopWidget || // not created yet
+ !(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away
+ qt_desktopWidget = new QDesktopWidget();
+ }
+ return qt_desktopWidget;
+}
+
+#if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
+/*!
+ Returns a pointer to the application global clipboard.
+
+ \note The QApplication object should already be constructed before
+ accessing the clipboard.
+*/
+QClipboard *QApplication::clipboard()
+{
+ if (qt_clipboard == 0) {
+ if (!qApp) {
+ qWarning("QApplication: Must construct a QApplication before accessing a QClipboard");
+ return 0;
+ }
+ qt_clipboard = new QClipboard(0);
+ }
+ return qt_clipboard;
+}
+#endif // Q_WS_QPA && QT_NO_CLIPBOARD
+/*!
+ Sets whether Qt should use the system's standard colors, fonts, etc., to
+ \a on. By default, this is true.
+
+ This function must be called before creating the QApplication object, like
+ this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 6
+
+ \sa desktopSettingsAware()
+*/
+void QApplication::setDesktopSettingsAware(bool on)
+{
+ QApplicationPrivate::obey_desktop_settings = on;
+}
+
+/*!
+ Returns true if Qt is set to use the system's standard colors, fonts, etc.;
+ otherwise returns false. The default is true.
+
+ \sa setDesktopSettingsAware()
+*/
+bool QApplication::desktopSettingsAware()
+{
+ return QApplicationPrivate::obey_desktop_settings;
+}
+
+/*!
+ Returns the current state of the modifier keys on the keyboard. The current
+ state is updated sychronously as the event queue is emptied of events that
+ will spontaneously change the keyboard state (QEvent::KeyPress and
+ QEvent::KeyRelease events).
+
+ It should be noted this may not reflect the actual keys held on the input
+ device at the time of calling but rather the modifiers as last reported in
+ one of the above events. If no keys are being held Qt::NoModifier is
+ returned.
+
+ \sa mouseButtons()
+*/
+
+Qt::KeyboardModifiers QApplication::keyboardModifiers()
+{
+ return QApplicationPrivate::modifier_buttons;
+}
+
+/*!
+ Returns the current state of the buttons on the mouse. The current state is
+ updated syncronously as the event queue is emptied of events that will
+ spontaneously change the mouse state (QEvent::MouseButtonPress and
+ QEvent::MouseButtonRelease events).
+
+ It should be noted this may not reflect the actual buttons held on the
+ input device at the time of calling but rather the mouse buttons as last
+ reported in one of the above events. If no mouse buttons are being held
+ Qt::NoButton is returned.
+
+ \sa keyboardModifiers()
+*/
+
+Qt::MouseButtons QApplication::mouseButtons()
+{
+ return QApplicationPrivate::mouse_buttons;
+}
+
+/*!
+ \fn bool QApplication::isSessionRestored() const
+
+ Returns true if the application has been restored from an earlier
+ \l{Session Management}{session}; otherwise returns false.
+
+ \sa sessionId(), commitData(), saveState()
+*/
+
+
+/*!
+ \fn QString QApplication::sessionId() const
+
+ Returns the current \l{Session Management}{session's} identifier.
+
+ If the application has been restored from an earlier session, this
+ identifier is the same as it was in that previous session. The session
+ identifier is guaranteed to be unique both for different applications
+ and for different instances of the same application.
+
+ \sa isSessionRestored(), sessionKey(), commitData(), saveState()
+*/
+
+/*!
+ \fn QString QApplication::sessionKey() const
+
+ Returns the session key in the current \l{Session Management}{session}.
+
+ If the application has been restored from an earlier session, this key is
+ the same as it was when the previous session ended.
+
+ The session key changes with every call of commitData() or saveState().
+
+ \sa isSessionRestored(), sessionId(), commitData(), saveState()
+*/
+#ifndef QT_NO_SESSIONMANAGER
+bool QApplication::isSessionRestored() const
+{
+ Q_D(const QApplication);
+ return d->is_session_restored;
+}
+
+QString QApplication::sessionId() const
+{
+ Q_D(const QApplication);
+ return d->session_id;
+}
+
+QString QApplication::sessionKey() const
+{
+ Q_D(const QApplication);
+ return d->session_key;
+}
+#endif
+
+
+
+/*!
+ \since 4.2
+ \fn void QApplication::commitDataRequest(QSessionManager &manager)
+
+ This signal deals with \l{Session Management}{session management}. It is
+ emitted when the QSessionManager wants the application to commit all its
+ data.
+
+ Usually this means saving all open files, after getting permission from
+ the user. Furthermore you may want to provide a means by which the user
+ can cancel the shutdown.
+
+ You should not exit the application within this signal. Instead,
+ the session manager may or may not do this afterwards, depending on the
+ context.
+
+ \warning Within this signal, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details and example
+ usage.
+
+ \note You should use Qt::DirectConnection when connecting to this signal.
+
+ \sa isSessionRestored(), sessionId(), saveState(), {Session Management}
+*/
+
+/*!
+ This function deals with \l{Session Management}{session management}. It is
+ invoked when the QSessionManager wants the application to commit all its
+ data.
+
+ Usually this means saving all open files, after getting permission from the
+ user. Furthermore you may want to provide a means by which the user can
+ cancel the shutdown.
+
+ You should not exit the application within this function. Instead, the
+ session manager may or may not do this afterwards, depending on the
+ context.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details and example
+ usage.
+
+ The default implementation requests interaction and sends a close event to
+ all visible top-level widgets. If any event was rejected, the shutdown is
+ canceled.
+
+ \sa isSessionRestored(), sessionId(), saveState(), {Session Management}
+*/
+#ifndef QT_NO_SESSIONMANAGER
+void QApplication::commitData(QSessionManager& manager )
+{
+ emit commitDataRequest(manager);
+ if (manager.allowsInteraction()) {
+ QWidgetList done;
+ QWidgetList list = QApplication::topLevelWidgets();
+ bool cancelled = false;
+ for (int i = 0; !cancelled && i < list.size(); ++i) {
+ QWidget* w = list.at(i);
+ if (w->isVisible() && !done.contains(w)) {
+ cancelled = !w->close();
+ if (!cancelled)
+ done.append(w);
+ list = QApplication::topLevelWidgets();
+ i = -1;
+ }
+ }
+ if (cancelled)
+ manager.cancel();
+ }
+}
+
+/*!
+ \since 4.2
+ \fn void QApplication::saveStateRequest(QSessionManager &manager)
+
+ This signal deals with \l{Session Management}{session management}. It is
+ invoked when the \l{QSessionManager}{session manager} wants the application
+ to preserve its state for a future session.
+
+ For example, a text editor would create a temporary file that includes the
+ current contents of its edit buffers, the location of the cursor and other
+ aspects of the current editing session.
+
+ You should never exit the application within this signal. Instead, the
+ session manager may or may not do this afterwards, depending on the
+ context. Futhermore, most session managers will very likely request a saved
+ state immediately after the application has been started. This permits the
+ session manager to learn about the application's restart policy.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details.
+
+ \note You should use Qt::DirectConnection when connecting to this signal.
+
+ \sa isSessionRestored(), sessionId(), commitData(), {Session Management}
+*/
+
+/*!
+ This function deals with \l{Session Management}{session management}. It is
+ invoked when the \l{QSessionManager}{session manager} wants the application
+ to preserve its state for a future session.
+
+ For example, a text editor would create a temporary file that includes the
+ current contents of its edit buffers, the location of the cursor and other
+ aspects of the current editing session.
+
+ You should never exit the application within this function. Instead, the
+ session manager may or may not do this afterwards, depending on the
+ context. Futhermore, most session managers will very likely request a saved
+ state immediately after the application has been started. This permits the
+ session manager to learn about the application's restart policy.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details.
+
+ \sa isSessionRestored(), sessionId(), commitData(), {Session Management}
+*/
+
+void QApplication::saveState(QSessionManager &manager)
+{
+ emit saveStateRequest(manager);
+}
+#endif //QT_NO_SESSIONMANAGER
+/*
+ Sets the time after which a drag should start to \a ms ms.
+
+ \sa startDragTime()
+*/
+
+void QApplication::setStartDragTime(int ms)
+{
+ drag_time = ms;
+}
+
+/*!
+ \property QApplication::startDragTime
+ \brief the time in milliseconds that a mouse button must be held down
+ before a drag and drop operation will begin
+
+ If you support drag and drop in your application, and want to start a drag
+ and drop operation after the user has held down a mouse button for a
+ certain amount of time, you should use this property's value as the delay.
+
+ Qt also uses this delay internally, e.g. in QTextEdit and QLineEdit, for
+ starting a drag.
+
+ The default value is 500 ms.
+
+ \sa startDragDistance(), {Drag and Drop}
+*/
+
+int QApplication::startDragTime()
+{
+ return drag_time;
+}
+
+/*
+ Sets the distance after which a drag should start to \a l pixels.
+
+ \sa startDragDistance()
+*/
+
+void QApplication::setStartDragDistance(int l)
+{
+ drag_distance = l;
+}
+
+/*!
+ \property QApplication::startDragDistance
+
+ If you support drag and drop in your application, and want to start a drag
+ and drop operation after the user has moved the cursor a certain distance
+ with a button held down, you should use this property's value as the
+ minimum distance required.
+
+ For example, if the mouse position of the click is stored in \c startPos
+ and the current position (e.g. in the mouse move event) is \c currentPos,
+ you can find out if a drag should be started with code like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 7
+
+ Qt uses this value internally, e.g. in QFileDialog.
+
+ The default value is 4 pixels.
+
+ \sa startDragTime() QPoint::manhattanLength() {Drag and Drop}
+*/
+
+int QApplication::startDragDistance()
+{
+ return drag_distance;
+}
+
+/*!
+ \fn void QApplication::setReverseLayout(bool reverse)
+
+ Use setLayoutDirection() instead.
+*/
+
+/*!
+ \fn void QApplication::reverseLayout()
+
+ Use layoutDirection() instead.
+*/
+
+
+/*!
+ \obsolete
+
+ Strips out vertical alignment flags and transforms an alignment \a align
+ of Qt::AlignLeft into Qt::AlignLeft or Qt::AlignRight according to the
+ language used.
+*/
+
+#ifdef QT3_SUPPORT
+Qt::Alignment QApplication::horizontalAlignment(Qt::Alignment align)
+{
+ return QGuiApplicationPrivate::visualAlignment(layoutDirection(), align);
+}
+#endif
+
+/*!
+ Enters the main event loop and waits until exit() is called, then returns
+ the value that was set to exit() (which is 0 if exit() is called via
+ quit()).
+
+ It is necessary to call this function to start event handling. The main
+ event loop receives events from the window system and dispatches these to
+ the application widgets.
+
+ Generally, no user interaction can take place before calling exec(). As a
+ special case, modal widgets like QMessageBox can be used before calling
+ exec(), because modal widgets call exec() to start a local event loop.
+
+ To make your application perform idle processing, i.e., executing a special
+ function whenever there are no pending events, use a QTimer with 0 timeout.
+ More advanced idle processing schemes can be achieved using processEvents().
+
+ We recommend that you connect clean-up code to the
+ \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
+ application's \c{main()} function. This is because, on some platforms the
+ QApplication::exec() call may not return. For example, on the Windows
+ platform, when the user logs off, the system terminates the process after Qt
+ closes all top-level windows. Hence, there is \e{no guarantee} that the
+ application will have time to exit its event loop and execute code at the
+ end of the \c{main()} function, after the QApplication::exec() call.
+
+ \sa quitOnLastWindowClosed, quit(), exit(), processEvents(),
+ QCoreApplication::exec()
+*/
+int QApplication::exec()
+{
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::setRootObject(qApp);
+#endif
+ return QApplicationBase::exec();
+}
+
+/*! \reimp
+ */
+bool QApplication::notify(QObject *receiver, QEvent *e)
+{
+ Q_D(QApplication);
+ // no events are delivered after ~QCoreApplication() has started
+ if (QApplicationPrivate::is_app_closing)
+ return true;
+
+ if (receiver == 0) { // serious error
+ qWarning("QApplication::notify: Unexpected null receiver");
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ d->checkReceiverThread(receiver);
+#endif
+
+ // capture the current mouse/keyboard state
+ if(e->spontaneous()) {
+ if (e->type() == QEvent::KeyPress
+ || e->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ QApplicationPrivate::modifier_buttons = ke->modifiers();
+ } else if(e->type() == QEvent::MouseButtonPress
+ || e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QApplicationPrivate::modifier_buttons = me->modifiers();
+ if(me->type() == QEvent::MouseButtonPress)
+ QApplicationPrivate::mouse_buttons |= me->button();
+ else
+ QApplicationPrivate::mouse_buttons &= ~me->button();
+ }
+#if !defined(QT_NO_WHEELEVENT) || !defined(QT_NO_TABLETEVENT)
+ else if (false
+# ifndef QT_NO_WHEELEVENT
+ || e->type() == QEvent::Wheel
+# endif
+# ifndef QT_NO_TABLETEVENT
+ || e->type() == QEvent::TabletMove
+ || e->type() == QEvent::TabletPress
+ || e->type() == QEvent::TabletRelease
+# endif
+ ) {
+ QInputEvent *ie = static_cast<QInputEvent*>(e);
+ QApplicationPrivate::modifier_buttons = ie->modifiers();
+ }
+#endif // !QT_NO_WHEELEVENT || !QT_NO_TABLETEVENT
+ }
+
+#ifndef QT_NO_GESTURES
+ // walk through parents and check for gestures
+ if (d->gestureManager) {
+ switch (e->type()) {
+ case QEvent::Paint:
+ case QEvent::MetaCall:
+ case QEvent::DeferredDelete:
+ case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave:
+ case QEvent::Drop: case QEvent::DragResponse:
+ case QEvent::ChildAdded: case QEvent::ChildPolished:
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ case QEvent::ChildInserted:
+ case QEvent::LayoutHint:
+#endif
+ case QEvent::ChildRemoved:
+ case QEvent::UpdateRequest:
+ case QEvent::UpdateLater:
+ case QEvent::AccessibilityPrepare:
+ case QEvent::LocaleChange:
+ case QEvent::Style:
+ case QEvent::IconDrag:
+ case QEvent::StyleChange:
+ case QEvent::AccessibilityHelp:
+ case QEvent::AccessibilityDescription:
+ case QEvent::GraphicsSceneDragEnter:
+ case QEvent::GraphicsSceneDragMove:
+ case QEvent::GraphicsSceneDragLeave:
+ case QEvent::GraphicsSceneDrop:
+ case QEvent::DynamicPropertyChange:
+ case QEvent::NetworkReplyUpdated:
+ break;
+ default:
+ if (receiver->isWidgetType()) {
+ if (d->gestureManager->filterEvent(static_cast<QWidget *>(receiver), e))
+ return true;
+ } else {
+ // a special case for events that go to QGesture objects.
+ // We pass the object to the gesture manager and it'll figure
+ // out if it's QGesture or not.
+ if (d->gestureManager->filterEvent(receiver, e))
+ return true;
+ }
+ }
+ }
+#endif // QT_NO_GESTURES
+
+ // User input and window activation makes tooltips sleep
+ switch (e->type()) {
+ case QEvent::Wheel:
+ case QEvent::ActivationChange:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::FocusOut:
+ case QEvent::FocusIn:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ d->toolTipFallAsleep.stop();
+ // fall-through
+ case QEvent::Leave:
+ d->toolTipWakeUp.stop();
+ default:
+ break;
+ }
+
+ bool res = false;
+ if (!receiver->isWidgetType()) {
+ res = d->notify_helper(receiver, e);
+ } else switch (e->type()) {
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ case QEvent::Accel:
+ {
+ if (d->use_compat()) {
+ QKeyEvent* key = static_cast<QKeyEvent*>(e);
+ res = d->notify_helper(receiver, e);
+
+ if (!res && !key->isAccepted())
+ res = d->qt_dispatchAccelEvent(static_cast<QWidget *>(receiver), key);
+
+ // next lines are for compatibility with Qt <= 3.0.x: old
+ // QAccel was listening on toplevel widgets
+ if (!res && !key->isAccepted() && !static_cast<QWidget *>(receiver)->isWindow())
+ res = d->notify_helper(static_cast<QWidget *>(receiver)->window(), e);
+ }
+ break;
+ }
+#endif //QT3_SUPPORT && !QT_NO_SHORTCUT
+ case QEvent::ShortcutOverride:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ {
+ bool isWidget = receiver->isWidgetType();
+ bool isGraphicsWidget = false;
+#ifndef QT_NO_GRAPHICSVIEW
+ isGraphicsWidget = !isWidget && qobject_cast<QGraphicsWidget *>(receiver);
+#endif
+ if (!isWidget && !isGraphicsWidget) {
+ res = d->notify_helper(receiver, e);
+ break;
+ }
+
+ QKeyEvent* key = static_cast<QKeyEvent*>(e);
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ if (d->use_compat() && d->qt_tryComposeUnicode(static_cast<QWidget*>(receiver), key))
+ break;
+#endif
+ if (key->type()==QEvent::KeyPress) {
+#ifndef QT_NO_SHORTCUT
+ // Try looking for a Shortcut before sending key events
+ if ((res = qApp->d_func()->shortcutMap.tryShortcutEvent(receiver, key)))
+ return res;
+#endif
+ qt_in_tab_key_event = (key->key() == Qt::Key_Backtab
+ || key->key() == Qt::Key_Tab
+ || key->key() == Qt::Key_Left
+ || key->key() == Qt::Key_Up
+ || key->key() == Qt::Key_Right
+ || key->key() == Qt::Key_Down);
+ }
+ bool def = key->isAccepted();
+ QPointer<QObject> pr = receiver;
+ while (receiver) {
+ if (def)
+ key->accept();
+ else
+ key->ignore();
+ res = d->notify_helper(receiver, e);
+ QWidget *w = isWidget ? static_cast<QWidget *>(receiver) : 0;
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsWidget *gw = isGraphicsWidget ? static_cast<QGraphicsWidget *>(receiver) : 0;
+#endif
+
+ if ((res && key->isAccepted())
+ /*
+ QLineEdit will emit a signal on Key_Return, but
+ ignore the event, and sometimes the connected
+ slot deletes the QLineEdit (common in itemview
+ delegates), so we have to check if the widget
+ was destroyed even if the event was ignored (to
+ prevent a crash)
+
+ note that we don't have to reset pw while
+ propagating (because the original receiver will
+ be destroyed if one of its ancestors is)
+ */
+ || !pr
+ || (isWidget && (w->isWindow() || !w->parentWidget()))
+#ifndef QT_NO_GRAPHICSVIEW
+ || (isGraphicsWidget && (gw->isWindow() || !gw->parentWidget()))
+#endif
+ ) {
+ break;
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ receiver = w ? (QObject *)w->parentWidget() : (QObject *)gw->parentWidget();
+#else
+ receiver = w->parentWidget();
+#endif
+ }
+ qt_in_tab_key_event = false;
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+
+ QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
+ QPoint relpos = mouse->pos();
+
+ if (e->spontaneous()) {
+#ifndef QT_NO_IM
+ QInputContext *ic = w->inputContext();
+ if (ic
+ && w->testAttribute(Qt::WA_InputMethodEnabled)
+ && ic->filterEvent(mouse))
+ return true;
+#endif
+
+ if (e->type() == QEvent::MouseButtonPress) {
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
+ }
+
+ // ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms
+ // like Mac OS X (probably others too), can optimize their views by not
+ // dispatching mouse move events. We have attributes to control hover,
+ // and mouse tracking, but as long as we are deciding to implement this
+ // feature without choice of opting-in or out, you ALWAYS have to have
+ // tracking enabled. Therefore, the other properties give a false sense of
+ // performance enhancement.
+ if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) {
+ d->toolTipWidget = w;
+ d->toolTipPos = relpos;
+ d->toolTipGlobalPos = mouse->globalPos();
+ d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive()?20:700, this);
+ }
+ }
+
+ bool eventAccepted = mouse->isAccepted();
+
+ QPointer<QWidget> pw = w;
+ while (w) {
+ QMouseEvent me(mouse->type(), relpos, mouse->globalPos(), mouse->button(), mouse->buttons(),
+ mouse->modifiers());
+ me.spont = mouse->spontaneous();
+ // throw away any mouse-tracking-only mouse events
+ if (!w->hasMouseTracking()
+ && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
+ // but still send them through all application event filters (normally done by notify_helper)
+ for (int i = 0; i < d->eventFilters.size(); ++i) {
+ register QObject *obj = d->eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != w->d_func()->threadData) {
+ qWarning("QApplication: Object event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(w, w == receiver ? mouse : &me))
+ break;
+ }
+ res = true;
+ } else {
+ w->setAttribute(Qt::WA_NoMouseReplay, false);
+ res = d->notify_helper(w, w == receiver ? mouse : &me);
+ e->spont = false;
+ }
+ eventAccepted = (w == receiver ? mouse : &me)->isAccepted();
+ if (res && eventAccepted)
+ break;
+ if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+
+ mouse->setAccepted(eventAccepted);
+
+ if (e->type() == QEvent::MouseMove) {
+ if (!pw)
+ break;
+
+ w = static_cast<QWidget *>(receiver);
+ relpos = mouse->pos();
+ QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
+ while (w) {
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
+ QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff);
+ d->notify_helper(w, &he);
+ }
+ if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ }
+
+ d->hoverGlobalPos = mouse->globalPos();
+ }
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
+ QPoint relpos = wheel->pos();
+ bool eventAccepted = wheel->isAccepted();
+
+ if (e->spontaneous()) {
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::WheelFocus,
+ Qt::MouseFocusReason);
+ }
+
+ while (w) {
+ QWheelEvent we(relpos, wheel->globalPos(), wheel->delta(), wheel->buttons(),
+ wheel->modifiers(), wheel->orientation());
+ we.spont = wheel->spontaneous();
+ res = d->notify_helper(w, w == receiver ? wheel : &we);
+ eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted();
+ e->spont = false;
+ if ((res && eventAccepted)
+ || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ wheel->setAccepted(eventAccepted);
+ }
+ break;
+#endif
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QContextMenuEvent *context = static_cast<QContextMenuEvent*>(e);
+ QPoint relpos = context->pos();
+ bool eventAccepted = context->isAccepted();
+ while (w) {
+ QContextMenuEvent ce(context->reason(), relpos, context->globalPos(), context->modifiers());
+ ce.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? context : &ce);
+ eventAccepted = ((w == receiver) ? context : &ce)->isAccepted();
+ e->spont = false;
+
+ if ((res && eventAccepted)
+ || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ context->setAccepted(eventAccepted);
+ }
+ break;
+#endif // QT_NO_CONTEXTMENU
+#ifndef QT_NO_TABLETEVENT
+ case QEvent::TabletMove:
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
+ QPoint relpos = tablet->pos();
+ bool eventAccepted = tablet->isAccepted();
+ while (w) {
+ QTabletEvent te(tablet->type(), relpos, tablet->globalPos(),
+ tablet->hiResGlobalPos(), tablet->device(), tablet->pointerType(),
+ tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
+ tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
+ tablet->modifiers(), tablet->uniqueId());
+ te.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? tablet : &te);
+ eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
+ e->spont = false;
+ if ((res && eventAccepted)
+ || w->isWindow()
+ || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ tablet->setAccepted(eventAccepted);
+ qt_tabletChokeMouse = tablet->isAccepted();
+ }
+ break;
+#endif // QT_NO_TABLETEVENT
+
+#if !defined(QT_NO_TOOLTIP) || !defined(QT_NO_WHATSTHIS)
+ case QEvent::ToolTip:
+ case QEvent::WhatsThis:
+ case QEvent::QueryWhatsThis:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QHelpEvent *help = static_cast<QHelpEvent*>(e);
+ QPoint relpos = help->pos();
+ bool eventAccepted = help->isAccepted();
+ while (w) {
+ QHelpEvent he(help->type(), relpos, help->globalPos());
+ he.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? help : &he);
+ e->spont = false;
+ eventAccepted = (w == receiver ? help : &he)->isAccepted();
+ if ((res && eventAccepted) || w->isWindow())
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ help->setAccepted(eventAccepted);
+ }
+ break;
+#endif
+#if !defined(QT_NO_STATUSTIP) || !defined(QT_NO_WHATSTHIS)
+ case QEvent::StatusTip:
+ case QEvent::WhatsThisClicked:
+ {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ while (w) {
+ res = d->notify_helper(w, e);
+ if ((res && e->isAccepted()) || w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ }
+ break;
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter: {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(e);
+#ifdef Q_WS_MAC
+ // HIView has a slight difference in how it delivers events to children and parents
+ // It will not give a leave to a child's parent when it enters a child.
+ QWidget *currentTarget = QDragManager::self()->currentTarget();
+ if (currentTarget) {
+ // Assume currentTarget did not get a leave
+ QDragLeaveEvent event;
+ QApplication::sendEvent(currentTarget, &event);
+ }
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ // QGraphicsProxyWidget handles its own propagation,
+ // and we must not change QDragManagers currentTarget.
+ QWExtra *extra = w->window()->d_func()->extra;
+ if (extra && extra->proxyWidget) {
+ res = d->notify_helper(w, dragEvent);
+ break;
+ }
+#endif
+ while (w) {
+ if (w->isEnabled() && w->acceptDrops()) {
+ res = d->notify_helper(w, dragEvent);
+ if (res && dragEvent->isAccepted()) {
+ QDragManager::self()->setCurrentTarget(w);
+ break;
+ }
+ }
+ if (w->isWindow())
+ break;
+ dragEvent->p = w->mapToParent(dragEvent->p);
+ w = w->parentWidget();
+ }
+ }
+ break;
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ case QEvent::DragLeave: {
+ QWidget* w = static_cast<QWidget *>(receiver);
+#ifndef QT_NO_GRAPHICSVIEW
+ // QGraphicsProxyWidget handles its own propagation,
+ // and we must not change QDragManagers currentTarget.
+ QWExtra *extra = w->window()->d_func()->extra;
+ bool isProxyWidget = extra && extra->proxyWidget;
+ if (!isProxyWidget)
+#endif
+ w = QDragManager::self()->currentTarget();
+
+ if (!w) {
+#ifdef Q_WS_MAC
+ // HIView has a slight difference in how it delivers events to children and parents
+ // It will not give an enter to a child's parent when it leaves the child.
+ if (e->type() == QEvent::DragLeave)
+ break;
+ // Assume that w did not get an enter.
+ QDropEvent *dropEvent = static_cast<QDropEvent *>(e);
+ QDragEnterEvent dragEnterEvent(dropEvent->pos(), dropEvent->possibleActions(),
+ dropEvent->mimeData(), dropEvent->mouseButtons(),
+ dropEvent->keyboardModifiers());
+ QApplication::sendEvent(receiver, &dragEnterEvent);
+ w = QDragManager::self()->currentTarget();
+ if (!w)
+#endif
+ break;
+ }
+ if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
+ QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
+ QWidget *origReciver = static_cast<QWidget *>(receiver);
+ while (origReciver && w != origReciver) {
+ dragEvent->p = origReciver->mapToParent(dragEvent->p);
+ origReciver = origReciver->parentWidget();
+ }
+ }
+ res = d->notify_helper(w, e);
+ if (e->type() != QEvent::DragMove
+#ifndef QT_NO_GRAPHICSVIEW
+ && !isProxyWidget
+#endif
+ )
+ QDragManager::self()->setCurrentTarget(0, e->type() == QEvent::Drop);
+ }
+ break;
+#endif
+ case QEvent::TouchBegin:
+ // Note: TouchUpdate and TouchEnd events are never propagated
+ {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
+ bool eventAccepted = touchEvent->isAccepted();
+ if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) {
+ // give the widget focus if the focus policy allows it
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
+ }
+
+ while (widget) {
+ // first, try to deliver the touch event
+ bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
+ touchEvent->setWidget(widget);
+ touchEvent->setAccepted(acceptTouchEvents);
+ QWeakPointer<QWidget> p = widget;
+ res = acceptTouchEvents && d->notify_helper(widget, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ if (p.isNull()) {
+ // widget was deleted
+ widget = 0;
+ } else {
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted);
+ }
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first widget to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
+ d->widgetForTouchPointId[touchPoint.id()] = widget;
+ }
+ break;
+ } else if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
+ break;
+ }
+ QPoint offset = widget->pos();
+ widget = widget->parentWidget();
+ touchEvent->setWidget(widget);
+ for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) {
+ QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i];
+ QRectF rect = pt.rect();
+ rect.moveCenter(offset);
+ pt.d->rect = rect;
+ pt.d->startPos = pt.startPos() + offset;
+ pt.d->lastPos = pt.lastPos() + offset;
+ }
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ break;
+ }
+ case QEvent::RequestSoftwareInputPanel:
+ case QEvent::CloseSoftwareInputPanel:
+#ifndef QT_NO_IM
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QInputContext *ic = w->inputContext();
+ if (ic && ic->filterEvent(e)) {
+ break;
+ }
+ }
+#endif
+ res = d->notify_helper(receiver, e);
+ break;
+
+#ifndef QT_NO_GESTURES
+ case QEvent::NativeGesture:
+ {
+ // only propagate the first gesture event (after the GID_BEGIN)
+ QWidget *w = static_cast<QWidget *>(receiver);
+ while (w) {
+ e->ignore();
+ res = d->notify_helper(w, e);
+ if ((res && e->isAccepted()) || w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ break;
+ }
+ case QEvent::Gesture:
+ case QEvent::GestureOverride:
+ {
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(e);
+ QList<QGesture *> allGestures = gestureEvent->gestures();
+
+ bool eventAccepted = gestureEvent->isAccepted();
+ bool wasAccepted = eventAccepted;
+ while (w) {
+ // send only gestures the widget expects
+ QList<QGesture *> gestures;
+ QWidgetPrivate *wd = w->d_func();
+ for (int i = 0; i < allGestures.size();) {
+ QGesture *g = allGestures.at(i);
+ Qt::GestureType type = g->gestureType();
+ QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
+ wd->gestureContext.find(type);
+ bool deliver = contextit != wd->gestureContext.end() &&
+ (g->state() == Qt::GestureStarted || w == receiver ||
+ (contextit.value() & Qt::ReceivePartialGestures));
+ if (deliver) {
+ allGestures.removeAt(i);
+ gestures.append(g);
+ } else {
+ ++i;
+ }
+ }
+ if (!gestures.isEmpty()) { // we have gestures for this w
+ QGestureEvent ge(gestures);
+ ge.t = gestureEvent->t;
+ ge.spont = gestureEvent->spont;
+ ge.m_accept = wasAccepted;
+ ge.d_func()->accepted = gestureEvent->d_func()->accepted;
+ res = d->notify_helper(w, &ge);
+ gestureEvent->spont = false;
+ eventAccepted = ge.isAccepted();
+ for (int i = 0; i < gestures.size(); ++i) {
+ QGesture *g = gestures.at(i);
+ // Ignore res [event return value] because handling of multiple gestures
+ // packed into a single QEvent depends on not consuming the event
+ if (eventAccepted || ge.isAccepted(g)) {
+ // if the gesture was accepted, mark the target widget for it
+ gestureEvent->d_func()->targetWidgets[g->gestureType()] = w;
+ gestureEvent->setAccepted(g, true);
+ } else {
+ // if the gesture was explicitly ignored by the application,
+ // put it back so a parent can get it
+ allGestures.append(g);
+ }
+ }
+ }
+ if (allGestures.isEmpty()) // everything delivered
+ break;
+ if (w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ foreach (QGesture *g, allGestures)
+ gestureEvent->setAccepted(g, false);
+ gestureEvent->m_accept = false; // to make sure we check individual gestures
+ } else {
+ res = d->notify_helper(receiver, e);
+ }
+ break;
+ }
+#endif // QT_NO_GESTURES
+#ifdef QT_MAC_USE_COCOA
+ case QEvent::Enter:
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ if (w->testAttribute(Qt::WA_AcceptTouchEvents))
+ qt_widget_private(w)->registerTouchWindow(true);
+ }
+ res = d->notify_helper(receiver, e);
+ break;
+ case QEvent::Leave:
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ if (w->testAttribute(Qt::WA_AcceptTouchEvents))
+ qt_widget_private(w)->registerTouchWindow(false);
+ }
+ res = d->notify_helper(receiver, e);
+ break;
+#endif
+ default:
+ res = d->notify_helper(receiver, e);
+ break;
+ }
+
+ return res;
+}
+
+bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
+{
+ // send to all application event filters
+ if (sendThroughApplicationEventFilters(receiver, e))
+ return true;
+
+ if (receiver->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+
+#if !defined(Q_WS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+ // toggle HasMouse widget state on enter and leave
+ if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
+ widget->setAttribute(Qt::WA_UnderMouse, true);
+ else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
+ widget->setAttribute(Qt::WA_UnderMouse, false);
+#endif
+
+ if (QLayout *layout=widget->d_func()->layout) {
+ layout->widgetEvent(e);
+ }
+ }
+
+ // send to all receiver event filters
+ if (sendThroughObjectEventFilters(receiver, e))
+ return true;
+
+ // deliver the event
+ bool consumed = receiver->event(e);
+ e->spont = false;
+ return consumed;
+}
+
+
+/*!
+ \class QSessionManager
+ \brief The QSessionManager class provides access to the session manager.
+
+ A session manager in a desktop environment (in which Qt GUI applications
+ live) keeps track of a session, which is a group of running applications,
+ each of which has a particular state. The state of an application contains
+ (most notably) the documents the application has open and the position and
+ size of its windows.
+
+ The session manager is used to save the session, e.g., when the machine is
+ shut down, and to restore a session, e.g., when the machine is started up.
+ We recommend that you use QSettings to save an application's settings,
+ for example, window positions, recently used files, etc. When the
+ application is restarted by the session manager, you can restore the
+ settings.
+
+ QSessionManager provides an interface between the application and the
+ session manager so that the program can work well with the session manager.
+ In Qt, session management requests for action are handled by the two
+ virtual functions QApplication::commitData() and QApplication::saveState().
+ Both provide a reference to a session manager object as argument, to allow
+ the application to communicate with the session manager. The session
+ manager can only be accessed through these functions.
+
+ No user interaction is possible \e unless the application gets explicit
+ permission from the session manager. You ask for permission by calling
+ allowsInteraction() or, if it is really urgent, allowsErrorInteraction().
+ Qt does not enforce this, but the session manager may.
+
+ You can try to abort the shutdown process by calling cancel(). The default
+ commitData() function does this if some top-level window rejected its
+ closeEvent().
+
+ For sophisticated session managers provided on Unix/X11, QSessionManager
+ offers further possibilities to fine-tune an application's session
+ management behavior: setRestartCommand(), setDiscardCommand(),
+ setRestartHint(), setProperty(), requestPhase2(). See the respective
+ function descriptions for further details.
+
+ \sa QApplication, {Session Management}
+*/
+
+/*! \enum QSessionManager::RestartHint
+
+ This enum type defines the circumstances under which this application wants
+ to be restarted by the session manager. The current values are:
+
+ \value RestartIfRunning If the application is still running when the
+ session is shut down, it wants to be restarted
+ at the start of the next session.
+
+ \value RestartAnyway The application wants to be started at the
+ start of the next session, no matter what.
+ (This is useful for utilities that run just
+ after startup and then quit.)
+
+ \value RestartImmediately The application wants to be started immediately
+ whenever it is not running.
+
+ \value RestartNever The application does not want to be restarted
+ automatically.
+
+ The default hint is \c RestartIfRunning.
+*/
+
+
+/*!
+ \fn QString QSessionManager::sessionId() const
+
+ Returns the identifier of the current session.
+
+ If the application has been restored from an earlier session, this
+ identifier is the same as it was in the earlier session.
+
+ \sa sessionKey(), QApplication::sessionId()
+*/
+
+/*!
+ \fn QString QSessionManager::sessionKey() const
+
+ Returns the session key in the current session.
+
+ If the application has been restored from an earlier session, this key is
+ the same as it was when the previous session ended.
+
+ The session key changes with every call of commitData() or saveState().
+
+ \sa sessionId(), QApplication::sessionKey()
+*/
+
+/*!
+ \fn void* QSessionManager::handle() const
+
+ \internal
+*/
+
+/*!
+ \fn bool QSessionManager::allowsInteraction()
+
+ Asks the session manager for permission to interact with the user. Returns
+ true if interaction is permitted; otherwise returns false.
+
+ The rationale behind this mechanism is to make it possible to synchronize
+ user interaction during a shutdown. Advanced session managers may ask all
+ applications simultaneously to commit their data, resulting in a much
+ faster shutdown.
+
+ When the interaction is completed we strongly recommend releasing the user
+ interaction semaphore with a call to release(). This way, other
+ applications may get the chance to interact with the user while your
+ application is still busy saving data. (The semaphore is implicitly
+ released when the application exits.)
+
+ If the user decides to cancel the shutdown process during the interaction
+ phase, you must tell the session manager that this has happened by calling
+ cancel().
+
+ Here's an example of how an application's QApplication::commitData() might
+ be implemented:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 8
+
+ If an error occurred within the application while saving its data, you may
+ want to try allowsErrorInteraction() instead.
+
+ \sa QApplication::commitData(), release(), cancel()
+*/
+
+
+/*!
+ \fn bool QSessionManager::allowsErrorInteraction()
+
+ Returns true if error interaction is permitted; otherwise returns false.
+
+ This is similar to allowsInteraction(), but also enables the application to
+ tell the user about any errors that occur. Session managers may give error
+ interaction requests higher priority, which means that it is more likely
+ that an error interaction is permitted. However, you are still not
+ guaranteed that the session manager will allow interaction.
+
+ \sa allowsInteraction(), release(), cancel()
+*/
+
+/*!
+ \fn void QSessionManager::release()
+
+ Releases the session manager's interaction semaphore after an interaction
+ phase.
+
+ \sa allowsInteraction(), allowsErrorInteraction()
+*/
+
+/*!
+ \fn void QSessionManager::cancel()
+
+ Tells the session manager to cancel the shutdown process. Applications
+ should not call this function without asking the user first.
+
+ \sa allowsInteraction(), allowsErrorInteraction()
+*/
+
+/*!
+ \fn void QSessionManager::setRestartHint(RestartHint hint)
+
+ Sets the application's restart hint to \a hint. On application startup, the
+ hint is set to \c RestartIfRunning.
+
+ \note These flags are only hints, a session manager may or may not respect
+ them.
+
+ We recommend setting the restart hint in QApplication::saveState() because
+ most session managers perform a checkpoint shortly after an application's
+ startup.
+
+ \sa restartHint()
+*/
+
+/*!
+ \fn QSessionManager::RestartHint QSessionManager::restartHint() const
+
+ Returns the application's current restart hint. The default is
+ \c RestartIfRunning.
+
+ \sa setRestartHint()
+*/
+
+/*!
+ \fn void QSessionManager::setRestartCommand(const QStringList& command)
+
+ If the session manager is capable of restoring sessions it will execute
+ \a command in order to restore the application. The command defaults to
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 9
+
+ The \c -session option is mandatory; otherwise QApplication cannot tell
+ whether it has been restored or what the current session identifier is.
+ See QApplication::isSessionRestored() and QApplication::sessionId() for
+ details.
+
+ If your application is very simple, it may be possible to store the entire
+ application state in additional command line options. This is usually a
+ very bad idea because command lines are often limited to a few hundred
+ bytes. Instead, use QSettings, temporary files, or a database for this
+ purpose. By marking the data with the unique sessionId(), you will be able
+ to restore the application in a future session.
+
+ \sa restartCommand(), setDiscardCommand(), setRestartHint()
+*/
+
+/*!
+ \fn QStringList QSessionManager::restartCommand() const
+
+ Returns the currently set restart command.
+
+ To iterate over the list, you can use the \l foreach pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 10
+
+ \sa setRestartCommand(), restartHint()
+*/
+
+/*!
+ \fn void QSessionManager::setDiscardCommand(const QStringList& list)
+
+ Sets the discard command to the given \a list.
+
+ \sa discardCommand(), setRestartCommand()
+*/
+
+
+/*!
+ \fn QStringList QSessionManager::discardCommand() const
+
+ Returns the currently set discard command.
+
+ To iterate over the list, you can use the \l foreach pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 11
+
+ \sa setDiscardCommand(), restartCommand(), setRestartCommand()
+*/
+
+/*!
+ \fn void QSessionManager::setManagerProperty(const QString &name, const QString &value)
+ \overload
+
+ Low-level write access to the application's identification and state
+ records are kept in the session manager.
+
+ The property called \a name has its value set to the string \a value.
+*/
+
+/*!
+ \fn void QSessionManager::setManagerProperty(const QString& name,
+ const QStringList& value)
+
+ Low-level write access to the application's identification and state record
+ are kept in the session manager.
+
+ The property called \a name has its value set to the string list \a value.
+*/
+
+/*!
+ \fn bool QSessionManager::isPhase2() const
+
+ Returns true if the session manager is currently performing a second
+ session management phase; otherwise returns false.
+
+ \sa requestPhase2()
+*/
+
+/*!
+ \fn void QSessionManager::requestPhase2()
+
+ Requests a second session management phase for the application. The
+ application may then return immediately from the QApplication::commitData()
+ or QApplication::saveState() function, and they will be called again once
+ most or all other applications have finished their session management.
+
+ The two phases are useful for applications such as the X11 window manager
+ that need to store information about another application's windows and
+ therefore have to wait until these applications have completed their
+ respective session management tasks.
+
+ \note If another application has requested a second phase it may get called
+ before, simultaneously with, or after your application's second phase.
+
+ \sa isPhase2()
+*/
+
+/*****************************************************************************
+ Stubbed session management support
+ *****************************************************************************/
+#ifndef QT_NO_SESSIONMANAGER
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+
+#if defined(Q_OS_WINCE)
+HRESULT qt_CoCreateGuid(GUID* guid)
+{
+ // We will use the following information to create the GUID
+ // 1. absolute path to application
+ wchar_t tempFilename[MAX_PATH];
+ if (!GetModuleFileName(0, tempFilename, MAX_PATH))
+ return S_FALSE;
+ unsigned int hash = qHash(QString::fromWCharArray(tempFilename));
+ guid->Data1 = hash;
+ // 2. creation time of file
+ QFileInfo info(QString::fromWCharArray(tempFilename));
+ guid->Data2 = qHash(info.created().toTime_t());
+ // 3. current system time
+ guid->Data3 = qHash(QDateTime::currentDateTime().toTime_t());
+ return S_OK;
+}
+#if !defined(OLE32_MCOMGUID) || defined(QT_WINCE_FORCE_CREATE_GUID)
+#define CoCreateGuid qt_CoCreateGuid
+#endif
+
+#endif
+
+class QSessionManagerPrivate : public QObjectPrivate
+{
+public:
+ QStringList restartCommand;
+ QStringList discardCommand;
+ QString sessionId;
+ QString sessionKey;
+ QSessionManager::RestartHint restartHint;
+};
+
+QSessionManager* qt_session_manager_self = 0;
+QSessionManager::QSessionManager(QApplication * app, QString &id, QString &key)
+ : QObject(*new QSessionManagerPrivate, app)
+{
+ Q_D(QSessionManager);
+ setObjectName(QLatin1String("qt_sessionmanager"));
+ qt_session_manager_self = this;
+#if defined(Q_WS_WIN)
+ wchar_t guidstr[40];
+ GUID guid;
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ id = QString::fromWCharArray(guidstr);
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ key = QString::fromWCharArray(guidstr);
+#endif
+ d->sessionId = id;
+ d->sessionKey = key;
+ d->restartHint = RestartIfRunning;
+}
+
+QSessionManager::~QSessionManager()
+{
+ qt_session_manager_self = 0;
+}
+
+QString QSessionManager::sessionId() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionId;
+}
+
+QString QSessionManager::sessionKey() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionKey;
+}
+
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC)
+void* QSessionManager::handle() const
+{
+ return 0;
+}
+#endif
+
+#if !defined(Q_WS_WIN)
+bool QSessionManager::allowsInteraction()
+{
+ return true;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ return true;
+}
+void QSessionManager::release()
+{
+}
+
+void QSessionManager::cancel()
+{
+}
+#endif
+
+
+void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
+{
+ Q_D(QSessionManager);
+ d->restartHint = hint;
+}
+
+QSessionManager::RestartHint QSessionManager::restartHint() const
+{
+ Q_D(const QSessionManager);
+ return d->restartHint;
+}
+
+void QSessionManager::setRestartCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->restartCommand = command;
+}
+
+QStringList QSessionManager::restartCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->restartCommand;
+}
+
+void QSessionManager::setDiscardCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->discardCommand = command;
+}
+
+QStringList QSessionManager::discardCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->discardCommand;
+}
+
+void QSessionManager::setManagerProperty(const QString&, const QString&)
+{
+}
+
+void QSessionManager::setManagerProperty(const QString&, const QStringList&)
+{
+}
+
+bool QSessionManager::isPhase2() const
+{
+ return false;
+}
+
+void QSessionManager::requestPhase2()
+{
+}
+
+#endif
+#endif // QT_NO_SESSIONMANAGER
+
+/*!
+ \typedef QApplication::ColorMode
+ \compat
+
+ Use ColorSpec instead.
+*/
+
+/*!
+ \fn Qt::MacintoshVersion QApplication::macVersion()
+
+ Use QSysInfo::MacintoshVersion instead.
+*/
+
+/*!
+ \fn QApplication::ColorMode QApplication::colorMode()
+
+ Use colorSpec() instead, and use ColorSpec as the enum type.
+*/
+
+/*!
+ \fn void QApplication::setColorMode(ColorMode mode)
+
+ Use setColorSpec() instead, and pass a ColorSpec value instead.
+*/
+
+/*!
+ \fn bool QApplication::hasGlobalMouseTracking()
+
+ This feature does not exist anymore. This function always returns true
+ in Qt 4.
+*/
+
+/*!
+ \fn void QApplication::setGlobalMouseTracking(bool dummy)
+
+ This function does nothing in Qt 4. The \a dummy parameter is ignored.
+*/
+
+/*!
+ \fn void QApplication::flushX()
+
+ Use flush() instead.
+*/
+
+/*!
+ \fn void QApplication::setWinStyleHighlightColor(const QColor &c)
+
+ Use the palette instead.
+
+ \oldcode
+ app.setWinStyleHighlightColor(color);
+ \newcode
+ QPalette palette(QApplication::palette());
+ palette.setColor(QPalette::Highlight, color);
+ QApplication::setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QApplication::setPalette(const QPalette &pal, bool b, const char* className = 0)
+
+ Use the two-argument overload instead.
+*/
+
+/*!
+ \fn void QApplication::setFont(const QFont &font, bool b, const char* className = 0)
+
+ Use the two-argument overload instead.
+*/
+
+/*!
+ \fn const QColor &QApplication::winStyleHighlightColor()
+
+ Use QApplication::palette().color(QPalette::Active, QPalette::Highlight) instead.
+*/
+
+/*!
+ \fn QWidget *QApplication::widgetAt(int x, int y, bool child)
+
+ Use the two-argument widgetAt() overload to get the child widget. To get
+ the top-level widget do this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 12
+*/
+
+/*!
+ \fn QWidget *QApplication::widgetAt(const QPoint &point, bool child)
+
+ Use the single-argument widgetAt() overload to get the child widget. To get
+ the top-level widget do this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 13
+*/
+
+#ifdef QT3_SUPPORT
+QWidget *QApplication::mainWidget()
+{
+ return QApplicationPrivate::main_widget;
+}
+#endif
+bool QApplicationPrivate::inPopupMode() const
+{
+ return QApplicationPrivate::popupWidgets != 0;
+}
+
+/*!
+ \property QApplication::quitOnLastWindowClosed
+
+ \brief whether the application implicitly quits when the last window is
+ closed.
+
+ The default is true.
+
+ If this property is true, the applications quits when the last visible
+ primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose
+ attribute set is closed. By default this attribute is set for all widgets
+ except for sub-windows. Refer to \l{Qt::WindowType} for a detailed list of
+ Qt::Window objects.
+
+ \sa quit(), QWidget::close()
+ */
+
+void QApplication::setQuitOnLastWindowClosed(bool quit)
+{
+ QApplicationPrivate::quitOnLastWindowClosed = quit;
+}
+
+bool QApplication::quitOnLastWindowClosed()
+{
+ return QApplicationPrivate::quitOnLastWindowClosed;
+}
+
+void QApplicationPrivate::emitLastWindowClosed()
+{
+ if (qApp && qApp->d_func()->in_exec) {
+ if (QApplicationPrivate::quitOnLastWindowClosed) {
+ // get ready to quit, this event might be removed if the
+ // event loop is re-entered, however
+ QApplication::postEvent(qApp, new QEvent(QEvent::Quit));
+ }
+ emit qApp->lastWindowClosed();
+ }
+}
+
+/*! \variable QApplication::NormalColors
+ \compat
+
+ Use \l NormalColor instead.
+*/
+
+/*! \variable QApplication::CustomColors
+ \compat
+
+ Use \l CustomColor instead.
+*/
+
+#ifdef QT_KEYPAD_NAVIGATION
+/*!
+ Sets the kind of focus navigation Qt should use to \a mode.
+
+ This feature is available in Qt for Embedded Linux, Symbian and Windows CE
+ only.
+
+ \note On Windows CE this feature is disabled by default for touch device
+ mkspecs. To enable keypad navigation, build Qt with
+ QT_KEYPAD_NAVIGATION defined.
+
+ \note On Symbian, setting the mode to Qt::NavigationModeCursorAuto will enable a
+ virtual mouse cursor on non touchscreen devices, which is controlled
+ by the cursor keys if there is no analog pointer device.
+ On other platforms and on touchscreen devices, it has the same
+ meaning as Qt::NavigationModeNone.
+
+ \since 4.6
+
+ \sa keypadNavigationEnabled()
+*/
+void QApplication::setNavigationMode(Qt::NavigationMode mode)
+{
+#ifdef Q_OS_SYMBIAN
+ QApplicationPrivate::setNavigationMode(mode);
+#else
+ QApplicationPrivate::navigationMode = mode;
+#endif
+}
+
+/*!
+ Returns what kind of focus navigation Qt is using.
+
+ This feature is available in Qt for Embedded Linux, Symbian and Windows CE
+ only.
+
+ \note On Windows CE this feature is disabled by default for touch device
+ mkspecs. To enable keypad navigation, build Qt with
+ QT_KEYPAD_NAVIGATION defined.
+
+ \note On Symbian, the default mode is Qt::NavigationModeNone for touch
+ devices, and Qt::NavigationModeKeypadDirectional.
+
+ \since 4.6
+
+ \sa keypadNavigationEnabled()
+*/
+Qt::NavigationMode QApplication::navigationMode()
+{
+ return QApplicationPrivate::navigationMode;
+}
+
+/*!
+ Sets whether Qt should use focus navigation suitable for use with a
+ minimal keypad.
+
+ This feature is available in Qt for Embedded Linux, Symbian and Windows CE
+ only.
+
+ \note On Windows CE this feature is disabled by default for touch device
+ mkspecs. To enable keypad navigation, build Qt with
+ QT_KEYPAD_NAVIGATION defined.
+
+ \deprecated
+
+ \sa setNavigationMode()
+*/
+void QApplication::setKeypadNavigationEnabled(bool enable)
+{
+ if (enable) {
+#ifdef Q_OS_SYMBIAN
+ QApplication::setNavigationMode(Qt::NavigationModeKeypadDirectional);
+#else
+ QApplication::setNavigationMode(Qt::NavigationModeKeypadTabOrder);
+#endif
+ }
+ else {
+ QApplication::setNavigationMode(Qt::NavigationModeNone);
+ }
+}
+
+/*!
+ Returns true if Qt is set to use keypad navigation; otherwise returns
+ false. The default value is true on Symbian, but false on other platforms.
+
+ This feature is available in Qt for Embedded Linux, Symbian and Windows CE
+ only.
+
+ \note On Windows CE this feature is disabled by default for touch device
+ mkspecs. To enable keypad navigation, build Qt with
+ QT_KEYPAD_NAVIGATION defined.
+
+ \deprecated
+
+ \sa navigationMode()
+*/
+bool QApplication::keypadNavigationEnabled()
+{
+ return QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadTabOrder ||
+ QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadDirectional;
+}
+#endif
+
+/*!
+ \fn void QApplication::alert(QWidget *widget, int msec)
+ \since 4.3
+
+ Causes an alert to be shown for \a widget if the window is not the active
+ window. The alert is shown for \a msec miliseconds. If \a msec is zero (the
+ default), then the alert is shown indefinitely until the window becomes
+ active again.
+
+ Currently this function does nothing on Qt for Embedded Linux.
+
+ On Mac OS X, this works more at the application level and will cause the
+ application icon to bounce in the dock.
+
+ On Windows, this causes the window's taskbar entry to flash for a time. If
+ \a msec is zero, the flashing will stop and the taskbar entry will turn a
+ different color (currently orange).
+
+ On X11, this will cause the window to be marked as "demands attention", the
+ window must not be hidden (i.e. not have hide() called on it, but be
+ visible in some sort of way) in order for this to work.
+*/
+
+/*!
+ \property QApplication::cursorFlashTime
+ \brief the text cursor's flash (blink) time in milliseconds
+
+ The flash time is the time required to display, invert and restore the
+ caret display. Usually the text cursor is displayed for half the cursor
+ flash time, then hidden for the same amount of time, but this may vary.
+
+ The default value on X11 is 1000 milliseconds. On Windows, the
+ \gui{Control Panel} value is used and setting this property sets the cursor
+ flash time for all applications.
+
+ We recommend that widgets do not cache this value as it may change at any
+ time if the user changes the global desktop settings.
+*/
+
+/*!
+ \property QApplication::doubleClickInterval
+ \brief the time limit in milliseconds that distinguishes a double click
+ from two consecutive mouse clicks
+
+ The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
+ operating system's value is used. However, on Windows and Symbian OS,
+ calling this function sets the double click interval for all applications.
+*/
+
+/*!
+ \property QApplication::keyboardInputInterval
+ \brief the time limit in milliseconds that distinguishes a key press
+ from two consecutive key presses
+ \since 4.2
+
+ The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
+ operating system's value is used.
+*/
+
+/*!
+ \property QApplication::wheelScrollLines
+ \brief the number of lines to scroll a widget, when the
+ mouse wheel is rotated.
+
+ If the value exceeds the widget's number of visible lines, the widget
+ should interpret the scroll operation as a single \e{page up} or
+ \e{page down}. If the widget is an \l{QAbstractItemView}{item view class},
+ then the result of scrolling one \e line depends on the setting of the
+ widget's \l{QAbstractItemView::verticalScrollMode()}{scroll mode}. Scroll
+ one \e line can mean \l{QAbstractItemView::ScrollPerItem}{scroll one item}
+ or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}.
+
+ By default, this property has a value of 3.
+*/
+
+/*!
+ \fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+
+ Enables the UI effect \a effect if \a enable is true, otherwise the effect
+ will not be used.
+
+ \note All effects are disabled on screens running at less than 16-bit color
+ depth.
+
+ \sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
+*/
+
+/*!
+ \fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+
+ Returns true if \a effect is enabled; otherwise returns false.
+
+ By default, Qt will try to use the desktop settings. To prevent this, call
+ setDesktopSettingsAware(false).
+
+ \note All effects are disabled on screens running at less than 16-bit color
+ depth.
+
+ \sa setEffectEnabled(), Qt::UIEffect
+*/
+
+/*!
+ \fn QWidget *QApplication::mainWidget()
+
+ Returns the main application widget, or 0 if there is no main widget.
+*/
+
+/*!
+ \fn void QApplication::setMainWidget(QWidget *mainWidget)
+
+ Sets the application's main widget to \a mainWidget.
+
+ In most respects the main widget is like any other widget, except that if
+ it is closed, the application exits. QApplication does \e not take
+ ownership of the \a mainWidget, so if you create your main widget on the
+ heap you must delete it yourself.
+
+ You need not have a main widget; connecting lastWindowClosed() to quit()
+ is an alternative.
+
+ On X11, this function also resizes and moves the main widget according
+ to the \e -geometry command-line option, so you should set the default
+ geometry (using \l QWidget::setGeometry()) before calling setMainWidget().
+
+ \sa mainWidget(), exec(), quit()
+*/
+
+/*!
+ \fn void QApplication::beep()
+
+ Sounds the bell, using the default volume and sound. The function is \e not
+ available in Qt for Embedded Linux.
+*/
+
+/*!
+ \fn void QApplication::setOverrideCursor(const QCursor &cursor)
+
+ Sets the application override cursor to \a cursor.
+
+ Application override cursors are intended for showing the user that the
+ application is in a special state, for example during an operation that
+ might take some time.
+
+ This cursor will be displayed in all the application's widgets until
+ restoreOverrideCursor() or another setOverrideCursor() is called.
+
+ Application cursors are stored on an internal stack. setOverrideCursor()
+ pushes the cursor onto the stack, and restoreOverrideCursor() pops the
+ active cursor off the stack. changeOverrideCursor() changes the curently
+ active application override cursor.
+
+ Every setOverrideCursor() must eventually be followed by a corresponding
+ restoreOverrideCursor(), otherwise the stack will never be emptied.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication_x11.cpp 0
+
+ \sa overrideCursor(), restoreOverrideCursor(), changeOverrideCursor(),
+ QWidget::setCursor()
+*/
+
+/*!
+ \fn void QApplication::restoreOverrideCursor()
+
+ Undoes the last setOverrideCursor().
+
+ If setOverrideCursor() has been called twice, calling
+ restoreOverrideCursor() will activate the first cursor set. Calling this
+ function a second time restores the original widgets' cursors.
+
+ \sa setOverrideCursor(), overrideCursor()
+*/
+
+/*!
+ \macro qApp
+ \relates QApplication
+
+ A global pointer referring to the unique application object. It is
+ equivalent to the pointer returned by the QCoreApplication::instance()
+ function except that, in GUI applications, it is a pointer to a
+ QApplication instance.
+
+ Only one application object can be created.
+
+ \sa QCoreApplication::instance()
+*/
+
+#ifndef QT_NO_IM
+// ************************************************************************
+// Input Method support
+// ************************************************************************
+
+/*!
+ This function replaces the QInputContext instance used by the application
+ with \a inputContext.
+
+ Qt takes ownership of the given \a inputContext.
+
+ \sa inputContext()
+*/
+void QApplication::setInputContext(QInputContext *inputContext)
+{
+ if (inputContext == QApplicationPrivate::inputContext)
+ return;
+ if (!inputContext) {
+ qWarning("QApplication::setInputContext: called with 0 input context");
+ return;
+ }
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = inputContext;
+ QApplicationPrivate::inputContext->setParent(this);
+}
+
+/*!
+ Returns the QInputContext instance used by the application.
+
+ \sa setInputContext()
+*/
+QInputContext *QApplication::inputContext() const
+{
+ Q_D(const QApplication);
+ Q_UNUSED(d);// only static members being used.
+ if (QApplicationPrivate::is_app_closing)
+ return d->inputContext;
+#ifdef Q_WS_X11
+ if (!X11)
+ return 0;
+ if (!d->inputContext) {
+ QApplication *that = const_cast<QApplication *>(this);
+ QInputContext *qic = QInputContextFactory::create(X11->default_im, that);
+ // fallback to default X Input Method.
+ if (!qic)
+ qic = QInputContextFactory::create(QLatin1String("xim"), that);
+ that->d_func()->inputContext = qic;
+ }
+#elif defined(Q_OS_SYMBIAN)
+ if (!d->inputContext) {
+ QApplication *that = const_cast<QApplication *>(this);
+ const QStringList keys = QInputContextFactory::keys();
+ // Try hbim and coefep first, then try others.
+ if (keys.contains(QLatin1String("hbim"))) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("hbim"), that);
+ } else if (keys.contains(QLatin1String("coefep"))) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("coefep"), that);
+ } else {
+ for (int c = 0; c < keys.size() && !d->inputContext; ++c) {
+ that->d_func()->inputContext = QInputContextFactory::create(keys[c], that);
+ }
+ }
+ }
+#endif
+ return d->inputContext;
+}
+#endif // QT_NO_IM
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{
+ return QApplicationBase::sendSpontaneousEvent(receiver, event);
+}
+
+
+void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason)
+{
+ QWidget *focusWidget = widget;
+ while (focusWidget) {
+ if (focusWidget->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
+ focusWidget->setFocus(focusReason);
+ break;
+ }
+ if (focusWidget->isWindow())
+ break;
+ focusWidget = focusWidget->parentWidget();
+ }
+}
+
+bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
+{
+ QWidget *f = w;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if ((w->focusPolicy() & policy) != policy)
+ return false;
+ if (w != f && (f->focusPolicy() & policy) != policy)
+ return false;
+ return true;
+}
+
+/*! \fn QDecoration &QApplication::qwsDecoration()
+ Return the QWSDecoration used for decorating windows.
+
+ \warning This method is non-portable. It is only available in
+ Qt for Embedded Linux.
+
+ \sa QDecoration
+*/
+
+/*!
+ \fn void QApplication::qwsSetDecoration(QDecoration *decoration)
+
+ Sets the QDecoration derived class to use for decorating the
+ windows used by Qt for Embedded Linux to the \a decoration
+ specified.
+
+ This method is non-portable. It is only available in Qt for Embedded Linux.
+
+ \sa QDecoration
+*/
+
+/*! \fn QDecoration* QApplication::qwsSetDecoration(const QString &decoration)
+ \overload
+
+ Requests a QDecoration object for \a decoration from the
+ QDecorationFactory.
+
+ The string must be one of the QDecorationFactory::keys(). Keys are case
+ insensitive.
+
+ A later call to the QApplication constructor will override the requested
+ style when a "-style" option is passed in as a commandline parameter.
+
+ Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object
+ returned is set as the application's GUI style.
+*/
+
+/*!
+ \fn bool QApplication::qwsEventFilter(QWSEvent *event)
+
+ This virtual function is only implemented under Qt for Embedded Linux.
+
+ If you create an application that inherits QApplication and
+ reimplement this function, you get direct access to all QWS (Q
+ Window System) events that the are received from the QWS master
+ process. The events are passed in the \a event parameter.
+
+ Return true if you want to stop the event from being processed.
+ Return false for normal event dispatching. The default
+ implementation returns false.
+*/
+
+/*! \fn void QApplication::qwsSetCustomColors(QRgb *colorTable, int start, int numColors)
+ Set Qt for Embedded Linux custom color table.
+
+ Qt for Embedded Linux on 8-bpp displays allocates a standard 216 color cube.
+ The remaining 40 colors may be used by setting a custom color
+ table in the QWS master process before any clients connect.
+
+ \a colorTable is an array of up to 40 custom colors. \a start is
+ the starting index (0-39) and \a numColors is the number of colors
+ to be set (1-40).
+
+ This method is non-portable. It is available \e only in
+ Qt for Embedded Linux.
+
+ \note The custom colors will not be used by the default screen
+ driver. To make use of the new colors, implement a custom screen
+ driver, or use QDirectPainter.
+*/
+
+/*! \fn int QApplication::qwsProcessEvent(QWSEvent* event)
+ \internal
+*/
+
+/*! \fn int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
+ \internal
+*/
+
+/*! \fn int QApplication::x11ProcessEvent(XEvent* event)
+ This function does the core processing of individual X
+ \a{event}s, normally by dispatching Qt events to the right
+ destination.
+
+ It returns 1 if the event was consumed by special handling, 0 if
+ the \a event was consumed by normal handling, and -1 if the \a
+ event was for an unrecognized widget.
+
+ \sa x11EventFilter()
+*/
+
+/*!
+ \fn bool QApplication::x11EventFilter(XEvent *event)
+
+ \warning This virtual function is only implemented under X11.
+
+ If you create an application that inherits QApplication and
+ reimplement this function, you get direct access to all X events
+ that the are received from the X server. The events are passed in
+ the \a event parameter.
+
+ Return true if you want to stop the event from being processed.
+ Return false for normal event dispatching. The default
+ implementation returns false.
+
+ It is only the directly addressed messages that are filtered.
+ You must install an event filter directly on the event
+ dispatcher, which is returned by
+ QAbstractEventDispatcher::instance(), to handle system wide
+ messages.
+
+ \sa x11ProcessEvent()
+*/
+
+/*! \fn void QApplication::winFocus(QWidget *widget, bool gotFocus)
+ \internal
+ \since 4.1
+
+ If \a gotFocus is true, \a widget will become the active window.
+ Otherwise the active window is reset to 0.
+*/
+
+/*! \fn void QApplication::winMouseButtonUp()
+ \internal
+ */
+
+/*! \fn void QApplication::syncX()
+ Synchronizes with the X server in the X11 implementation.
+ This normally takes some time. Does nothing on other platforms.
+*/
+
+void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+{
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i];
+
+ // preserve the sub-pixel resolution
+ QRectF rect = touchPoint.screenRect();
+ const QPointF screenPos = rect.center();
+ const QPointF delta = screenPos - screenPos.toPoint();
+
+ rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta);
+ touchPoint.d->rect = rect;
+ if (touchPoint.state() == Qt::TouchPointPressed) {
+ touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
+ touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
+ }
+ }
+}
+
+void QApplicationPrivate::initializeMultitouch()
+{
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+
+ initializeMultitouch_sys();
+}
+
+void QApplicationPrivate::cleanupMultitouch()
+{
+ cleanupMultitouch_sys();
+
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+}
+
+int QApplicationPrivate::findClosestTouchPointId(const QPointF &screenPos)
+{
+ int closestTouchPointId = -1;
+ qreal closestDistance = qreal(0.);
+ foreach (const QTouchEvent::TouchPoint &touchPoint, appCurrentTouchPoints) {
+ qreal distance = QLineF(screenPos, touchPoint.screenPos()).length();
+ if (closestTouchPointId == -1 || distance < closestDistance) {
+ closestTouchPointId = touchPoint.id();
+ closestDistance = distance;
+ }
+ }
+ return closestTouchPointId;
+}
+
+void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints)
+{
+ QApplicationPrivate *d = self;
+ typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
+ QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
+
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint touchPoint = touchPoints.at(i);
+ // explicitly detach from the original touch point that we got, so even
+ // if the touchpoint structs are reused, we will make a copy that we'll
+ // deliver to the user (which might want to store the struct for later use).
+ touchPoint.d = touchPoint.d->detach();
+
+ // update state
+ QWeakPointer<QWidget> widget;
+ switch (touchPoint.state()) {
+ case Qt::TouchPointPressed:
+ {
+ if (deviceType == QTouchEvent::TouchPad) {
+ // on touch-pads, send all touch points to the same widget
+ widget = d->widgetForTouchPointId.isEmpty()
+ ? QWeakPointer<QWidget>()
+ : d->widgetForTouchPointId.constBegin().value();
+ }
+
+ if (!widget) {
+ // determine which widget this event will go to
+ if (!window)
+ window = QApplication::topLevelAt(touchPoint.screenPos().toPoint());
+ if (!window)
+ continue;
+ widget = window->childAt(window->mapFromGlobal(touchPoint.screenPos().toPoint()));
+ if (!widget)
+ widget = window;
+ }
+
+ if (deviceType == QTouchEvent::TouchScreen) {
+ int closestTouchPointId = d->findClosestTouchPointId(touchPoint.screenPos());
+ QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId).data();
+ if (closestWidget
+ && (widget.data()->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget.data()))) {
+ widget = closestWidget;
+ }
+ }
+
+ d->widgetForTouchPointId[touchPoint.id()] = widget;
+ touchPoint.d->startScreenPos = touchPoint.screenPos();
+ touchPoint.d->lastScreenPos = touchPoint.screenPos();
+ touchPoint.d->startNormalizedPos = touchPoint.normalizedPos();
+ touchPoint.d->lastNormalizedPos = touchPoint.normalizedPos();
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.d->pressure = qreal(1.);
+
+ d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
+ break;
+ }
+ case Qt::TouchPointReleased:
+ {
+ widget = d->widgetForTouchPointId.take(touchPoint.id());
+ if (!widget)
+ continue;
+
+ QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.take(touchPoint.id());
+ touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos();
+ touchPoint.d->lastScreenPos = previousTouchPoint.screenPos();
+ touchPoint.d->startPos = previousTouchPoint.startPos();
+ touchPoint.d->lastPos = previousTouchPoint.pos();
+ touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos();
+ touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos();
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.d->pressure = qreal(0.);
+ break;
+ }
+ default:
+ widget = d->widgetForTouchPointId.value(touchPoint.id());
+ if (!widget)
+ continue;
+
+ Q_ASSERT(d->appCurrentTouchPoints.contains(touchPoint.id()));
+ QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.value(touchPoint.id());
+ touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos();
+ touchPoint.d->lastScreenPos = previousTouchPoint.screenPos();
+ touchPoint.d->startPos = previousTouchPoint.startPos();
+ touchPoint.d->lastPos = previousTouchPoint.pos();
+ touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos();
+ touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos();
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.d->pressure = qreal(1.);
+ d->appCurrentTouchPoints[touchPoint.id()] = touchPoint;
+ break;
+ }
+ Q_ASSERT(widget.data() != 0);
+
+ // make the *scene* functions return the same as the *screen* functions
+ touchPoint.d->sceneRect = touchPoint.screenRect();
+ touchPoint.d->startScenePos = touchPoint.startScreenPos();
+ touchPoint.d->lastScenePos = touchPoint.lastScreenPos();
+
+ StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget.data()];
+ maskAndPoints.first |= touchPoint.state();
+ if (touchPoint.isPrimary())
+ maskAndPoints.first |= Qt::TouchPointPrimary;
+ maskAndPoints.second.append(touchPoint);
+ }
+
+ if (widgetsNeedingEvents.isEmpty())
+ return;
+
+ QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
+ const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QWidget *widget = it.key();
+ if (!QApplicationPrivate::tryModalHelper(widget, 0))
+ continue;
+
+ QEvent::Type eventType;
+ switch (it.value().first & Qt::TouchPointStateMask) {
+ case Qt::TouchPointPressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ eventType = QEvent::TouchEnd;
+ break;
+ case Qt::TouchPointStationary:
+ // don't send the event if nothing changed
+ continue;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QTouchEvent touchEvent(eventType,
+ deviceType,
+ QApplication::keyboardModifiers(),
+ it.value().first,
+ it.value().second);
+ updateTouchPointsForWidget(widget, &touchEvent);
+
+ switch (touchEvent.type()) {
+ case QEvent::TouchBegin:
+ {
+ // if the TouchBegin handler recurses, we assume that means the event
+ // has been implicitly accepted and continue to send touch events
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
+ (void ) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ break;
+ }
+ default:
+ if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) {
+ if (touchEvent.type() == QEvent::TouchEnd)
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
+ (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ }
+ break;
+ }
+ }
+}
+
+Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints)
+{
+ QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints);
+}
+
+#ifndef QT_NO_GESTURES
+QGestureManager* QGestureManager::instance()
+{
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ if (!qAppPriv)
+ return 0;
+ if (!qAppPriv->gestureManager)
+ qAppPriv->gestureManager = new QGestureManager(qApp);
+ return qAppPriv->gestureManager;
+}
+#endif // QT_NO_GESTURES
+
+QString QApplicationPrivate::qmljsDebugArgumentsString()
+{
+ return qmljs_debug_arguments;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qapplication.cpp"
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
new file mode 100644
index 0000000000..3a5f02f144
--- /dev/null
+++ b/src/widgets/kernel/qapplication.h
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAPPLICATION_H
+#define QAPPLICATION_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qcursor.h>
+#ifdef QT_INCLUDE_COMPAT
+# include <QtGui/qdesktopwidget.h>
+#endif
+#ifdef QT3_SUPPORT
+# include <QtGui/qwidget.h>
+# include <QtGui/qpalette.h>
+#endif
+#ifdef Q_WS_QWS
+# include <QtGui/qrgb.h>
+# include <QtGui/qtransportauth_qws.h>
+#endif
+#ifdef Q_WS_QPA
+# include <QtGui/qguiapplication.h>
+#endif
+
+QT_BEGIN_HEADER
+
+#if defined(Q_OS_SYMBIAN)
+class CApaApplication;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QSessionManager;
+class QDesktopWidget;
+class QStyle;
+class QEventLoop;
+class QIcon;
+class QInputContext;
+template <typename T> class QList;
+class QLocale;
+#if defined(Q_WS_QWS)
+class QDecoration;
+#elif defined(Q_WS_QPA)
+class QPlatformNativeInterface;
+#endif
+#if defined(Q_OS_SYMBIAN)
+class QSymbianEvent;
+#endif
+
+class QApplication;
+class QApplicationPrivate;
+#if defined(qApp)
+#undef qApp
+#endif
+#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
+
+#ifdef Q_WS_QPA
+#define QApplicationBase QGuiApplication
+#else
+#define QApplicationBase QCoreApplication
+#endif
+
+class Q_GUI_EXPORT QApplication : public QApplicationBase
+{
+ Q_OBJECT
+ Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon)
+ Q_PROPERTY(int cursorFlashTime READ cursorFlashTime WRITE setCursorFlashTime)
+ Q_PROPERTY(int doubleClickInterval READ doubleClickInterval WRITE setDoubleClickInterval)
+ Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval)
+#ifndef QT_NO_WHEELEVENT
+ Q_PROPERTY(int wheelScrollLines READ wheelScrollLines WRITE setWheelScrollLines)
+#endif
+ Q_PROPERTY(QSize globalStrut READ globalStrut WRITE setGlobalStrut)
+ Q_PROPERTY(int startDragTime READ startDragTime WRITE setStartDragTime)
+ Q_PROPERTY(int startDragDistance READ startDragDistance WRITE setStartDragDistance)
+ Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed)
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
+#endif
+#ifdef Q_WS_WINCE
+ Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
+#endif
+ Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
+
+public:
+ enum Type { Tty, GuiClient, GuiServer };
+
+#ifdef Q_OS_SYMBIAN
+ typedef CApaApplication * (*QS60MainApplicationFactory)();
+#endif
+
+#ifndef qdoc
+ QApplication(int &argc, char **argv, int = ApplicationFlags);
+ QApplication(int &argc, char **argv, bool GUIenabled, int = ApplicationFlags);
+ QApplication(int &argc, char **argv, Type, int = ApplicationFlags);
+#if defined(Q_WS_X11)
+ QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = ApplicationFlags);
+ QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = ApplicationFlags);
+#endif
+#if defined(Q_OS_SYMBIAN)
+ QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = ApplicationFlags);
+#endif
+#endif
+ virtual ~QApplication();
+
+ static Type type();
+
+ static QStyle *style();
+ static void setStyle(QStyle*);
+ static QStyle *setStyle(const QString&);
+ enum ColorSpec { NormalColor=0, CustomColor=1, ManyColor=2 };
+ static int colorSpec();
+ static void setColorSpec(int);
+ // ### Qt4 compatibility, remove?
+ static inline void setGraphicsSystem(const QString &) {}
+
+ using QGuiApplication::palette;
+ static QPalette palette(const QWidget *);
+ static QPalette palette(const char *className);
+ static void setPalette(const QPalette &, const char* className = 0);
+ static QFont font();
+ static QFont font(const QWidget*);
+ static QFont font(const char *className);
+ static void setFont(const QFont &, const char* className = 0);
+ static QFontMetrics fontMetrics();
+
+ static void setWindowIcon(const QIcon &icon);
+ static QIcon windowIcon();
+
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QWidget *mainWidget();
+ static QT3_SUPPORT void setMainWidget(QWidget *);
+#endif
+
+ static QWidgetList allWidgets();
+ static QWidgetList topLevelWidgets();
+
+ static QDesktopWidget *desktop();
+
+ static QWidget *activePopupWidget();
+ static QWidget *activeModalWidget();
+#if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
+ static QClipboard *clipboard();
+#endif
+ static QWidget *focusWidget();
+
+ static QWidget *activeWindow();
+ static void setActiveWindow(QWidget* act);
+
+ static QWidget *widgetAt(const QPoint &p);
+ static inline QWidget *widgetAt(int x, int y) { return widgetAt(QPoint(x, y)); }
+ static QWidget *topLevelAt(const QPoint &p);
+ static inline QWidget *topLevelAt(int x, int y) { return topLevelAt(QPoint(x, y)); }
+
+ static void syncX();
+ static void beep();
+ static void alert(QWidget *widget, int duration = 0);
+
+ static Qt::KeyboardModifiers keyboardModifiers();
+ static Qt::MouseButtons mouseButtons();
+
+ static void setDesktopSettingsAware(bool);
+ static bool desktopSettingsAware();
+
+ static void setCursorFlashTime(int);
+ static int cursorFlashTime();
+
+ static void setDoubleClickInterval(int);
+ static int doubleClickInterval();
+
+ static void setKeyboardInputInterval(int);
+ static int keyboardInputInterval();
+
+#ifndef QT_NO_WHEELEVENT
+ static void setWheelScrollLines(int);
+ static int wheelScrollLines();
+#endif
+ static void setGlobalStrut(const QSize &);
+ static QSize globalStrut();
+
+ static void setStartDragTime(int ms);
+ static int startDragTime();
+ static void setStartDragDistance(int l);
+ static int startDragDistance();
+
+ static bool isEffectEnabled(Qt::UIEffect);
+ static void setEffectEnabled(Qt::UIEffect, bool enable = true);
+
+#if defined(Q_WS_MAC)
+ virtual bool macEventFilter(EventHandlerCallRef, EventRef);
+#endif
+#if defined(Q_WS_X11)
+ virtual bool x11EventFilter(XEvent *);
+ virtual int x11ClientMessage(QWidget*, XEvent*, bool passive_only);
+ int x11ProcessEvent(XEvent*);
+#endif
+#if defined(Q_OS_SYMBIAN)
+ int symbianProcessEvent(const QSymbianEvent *event);
+ virtual bool symbianEventFilter(const QSymbianEvent *event);
+#endif
+#if defined(Q_WS_QWS)
+ virtual bool qwsEventFilter(QWSEvent *);
+ int qwsProcessEvent(QWSEvent*);
+ void qwsSetCustomColors(QRgb *colortable, int start, int numColors);
+#ifndef QT_NO_QWS_MANAGER
+ static QDecoration &qwsDecoration();
+ static void qwsSetDecoration(QDecoration *);
+ static QDecoration *qwsSetDecoration(const QString &decoration);
+#endif
+#endif
+
+#if defined(Q_WS_QPA)
+ static QPlatformNativeInterface *platformNativeInterface();
+#endif
+
+
+#if defined(Q_WS_WIN)
+ void winFocus(QWidget *, bool);
+ static void winMouseButtonUp();
+#endif
+#ifndef QT_NO_SESSIONMANAGER
+ // session management
+ bool isSessionRestored() const;
+ QString sessionId() const;
+ QString sessionKey() const;
+ virtual void commitData(QSessionManager& sm);
+ virtual void saveState(QSessionManager& sm);
+#endif
+
+#ifndef QT_NO_IM
+ void setInputContext(QInputContext *);
+ QInputContext *inputContext() const;
+#endif
+
+ static int exec();
+ bool notify(QObject *, QEvent *);
+
+
+ static void setQuitOnLastWindowClosed(bool quit);
+ static bool quitOnLastWindowClosed();
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static Q_DECL_DEPRECATED void setKeypadNavigationEnabled(bool);
+ static bool keypadNavigationEnabled();
+ static void setNavigationMode(Qt::NavigationMode mode);
+ static Qt::NavigationMode navigationMode();
+#endif
+
+Q_SIGNALS:
+ void lastWindowClosed();
+ void focusChanged(QWidget *old, QWidget *now);
+#ifndef QT_NO_SESSIONMANAGER
+ void commitDataRequest(QSessionManager &sessionManager);
+ void saveStateRequest(QSessionManager &sessionManager);
+#endif
+
+public:
+ QString styleSheet() const;
+public Q_SLOTS:
+#ifndef QT_NO_STYLE_STYLESHEET
+ void setStyleSheet(const QString& sheet);
+#endif
+#ifdef Q_WS_WINCE
+ void setAutoMaximizeThreshold(const int threshold);
+ int autoMaximizeThreshold() const;
+#endif
+ void setAutoSipEnabled(const bool enabled);
+ bool autoSipEnabled() const;
+ static void closeAllWindows();
+ static void aboutQt();
+
+protected:
+#if defined(Q_WS_QWS)
+ void setArgs(int, char **);
+#endif
+ bool event(QEvent *);
+ bool compressEvent(QEvent *, QObject *receiver, QPostEventList *);
+
+#ifdef QT3_SUPPORT
+public:
+ static inline QT3_SUPPORT void setReverseLayout(bool b) { setLayoutDirection(b?Qt::RightToLeft:Qt::LeftToRight); }
+ static inline bool QT3_SUPPORT reverseLayout() { return layoutDirection() == Qt::RightToLeft; }
+ static QT3_SUPPORT Qt::Alignment horizontalAlignment(Qt::Alignment align);
+ typedef int ColorMode;
+ enum { NormalColors = NormalColor, CustomColors = CustomColor };
+ static inline QT3_SUPPORT ColorMode colorMode() { return static_cast<ColorMode>(colorSpec()); }
+ static inline QT3_SUPPORT void setColorMode(ColorMode mode) { setColorSpec(int(mode)); }
+#if defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN)
+ static QT3_SUPPORT Qt::WindowsVersion winVersion() { return (Qt::WindowsVersion)QSysInfo::WindowsVersion; }
+#endif
+#if defined(Q_OS_MAC)
+ static QT3_SUPPORT Qt::MacintoshVersion macVersion() { return (Qt::MacintoshVersion)QSysInfo::MacintoshVersion; }
+#endif
+# ifndef QT_NO_CURSOR
+ inline static QT3_SUPPORT void setOverrideCursor(const QCursor &cursor, bool replace)
+ { if (replace) changeOverrideCursor(cursor); else setOverrideCursor(cursor); }
+# endif
+ inline static QT3_SUPPORT bool hasGlobalMouseTracking() {return true;}
+ inline static QT3_SUPPORT void setGlobalMouseTracking(bool) {}
+ inline static QT3_SUPPORT void flushX() { flush(); }
+ static inline QT3_SUPPORT void setWinStyleHighlightColor(const QColor &c) {
+ QPalette p(palette());
+ p.setColor(QPalette::Highlight, c);
+ setPalette(p);
+ }
+ static inline QT3_SUPPORT const QColor &winStyleHighlightColor()
+ { return palette().color(QPalette::Active, QPalette::Highlight); }
+ static inline QT3_SUPPORT void setPalette(const QPalette &pal, bool, const char* className = 0)
+ { setPalette(pal, className); }
+ static inline QT3_SUPPORT void setFont(const QFont &font, bool, const char* className = 0)
+ { setFont(font, className); }
+
+ static inline QT3_SUPPORT QWidget *widgetAt(int x, int y, bool child)
+ { QWidget *w = widgetAt(x, y); return child ? w : (w ? w->window() : 0); }
+ static inline QT3_SUPPORT QWidget *widgetAt(const QPoint &p, bool child)
+ { QWidget *w = widgetAt(p); return child ? w : (w ? w->window() : 0); }
+#endif // QT3_SUPPORT
+
+#if defined(Q_INTERNAL_QAPP_SRC) || defined(qdoc)
+ QApplication(int &argc, char **argv);
+ QApplication(int &argc, char **argv, bool GUIenabled);
+ QApplication(int &argc, char **argv, Type);
+#if defined(Q_WS_X11)
+ QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0);
+ QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
+#endif
+#if defined(Q_OS_SYMBIAN) || defined(qdoc)
+ QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv);
+#endif
+#endif
+
+private:
+ Q_DISABLE_COPY(QApplication)
+ Q_DECLARE_PRIVATE(QApplication)
+
+ friend class QGraphicsWidget;
+ friend class QGraphicsItem;
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend class QWidgetWindow;
+ friend class QETWidget;
+ friend class Q3AccelManager;
+ friend class QTranslator;
+ friend class QWidgetAnimator;
+#ifndef QT_NO_SHORTCUT
+ friend class QShortcut;
+ friend class QLineEdit;
+ friend class QTextControl;
+#endif
+ friend class QAction;
+
+#if defined(Q_WS_QWS)
+ friend class QInputContext;
+ friend class QWSDirectPainterSurface;
+ friend class QDirectPainter;
+ friend class QDirectPainterPrivate;
+#endif
+#ifndef QT_NO_GESTURES
+ friend class QGestureManager;
+#endif
+
+#if defined(Q_WS_MAC) || defined(Q_WS_X11)
+ Q_PRIVATE_SLOT(d_func(), void _q_alertTimeOut())
+#endif
+#if defined(QT_RX71_MULTITOUCH)
+ Q_PRIVATE_SLOT(d_func(), void _q_readRX71MultiTouchEvents())
+#endif
+#if defined(Q_OS_SYMBIAN)
+ Q_PRIVATE_SLOT(d_func(), void _q_aboutToQuit())
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAPPLICATION_H
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
new file mode 100644
index 0000000000..a089a6ba40
--- /dev/null
+++ b/src/widgets/kernel/qapplication_p.h
@@ -0,0 +1,626 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAPPLICATION_P_H
+#define QAPPLICATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qapplication.h"
+#include "QtGui/qevent.h"
+#include "QtGui/qfont.h"
+#include "QtGui/qcursor.h"
+#include "QtGui/qregion.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qtranslator.h"
+#include "QtCore/qbasictimer.h"
+#include "QtCore/qhash.h"
+#include "QtCore/qpointer.h"
+#include "private/qcoreapplication_p.h"
+#include "QtGui/private/qshortcutmap_p.h"
+#include <private/qthread_p.h>
+#include "QtCore/qpoint.h"
+#include <QTime>
+#ifdef Q_OS_SYMBIAN
+#include <w32std.h>
+#endif
+#ifdef Q_WS_QPA
+#include <QWindowSystemInterface>
+#include "private/qwindowsysteminterface_qpa_p.h"
+#include "QtGui/qplatformintegration_qpa.h"
+#include "QtGui/private/qguiapplication_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QClipboard;
+class QGraphicsScene;
+class QInputContext;
+class QObject;
+class QWidget;
+class QSocketNotifier;
+#ifndef QT_NO_GESTURES
+class QGestureManager;
+#endif
+
+extern bool qt_is_gui_used;
+#ifndef QT_NO_CLIPBOARD
+extern QClipboard *qt_clipboard;
+#endif
+
+#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) || defined(Q_OS_WINCE)
+extern QSysInfo::WinVersion qt_winver;
+enum { QT_TABLET_NPACKETQSIZE = 128 };
+# ifdef Q_OS_WINCE
+ extern DWORD qt_cever;
+# endif
+#elif defined (Q_OS_MAC)
+extern QSysInfo::MacVersion qt_macver;
+#endif
+#if defined(Q_WS_QWS)
+class QWSManager;
+class QDirectPainter;
+struct QWSServerCleaner { ~QWSServerCleaner(); };
+#endif
+
+#ifndef QT_NO_TABLET
+struct QTabletDeviceData
+{
+#ifndef Q_WS_MAC
+ int minPressure;
+ int maxPressure;
+ int minTanPressure;
+ int maxTanPressure;
+ int minX, maxX, minY, maxY, minZ, maxZ;
+ inline QPointF scaleCoord(int coordX, int coordY, int outOriginX, int outExtentX,
+ int outOriginY, int outExtentY) const;
+#endif
+
+#if defined(Q_WS_X11) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
+ QPointer<QWidget> widgetToGetPress;
+#endif
+
+#ifdef Q_WS_X11
+ int deviceType;
+ enum {
+ TOTAL_XINPUT_EVENTS = 64
+ };
+ void *device;
+ int eventCount;
+ long unsigned int eventList[TOTAL_XINPUT_EVENTS]; // XEventClass is in fact a long unsigned int
+
+ int xinput_motion;
+ int xinput_key_press;
+ int xinput_key_release;
+ int xinput_button_press;
+ int xinput_button_release;
+ int xinput_proximity_in;
+ int xinput_proximity_out;
+#elif defined(Q_WS_WIN)
+ qint64 llId;
+ int currentDevice;
+ int currentPointerType;
+#elif defined(Q_WS_MAC)
+ quint64 tabletUniqueID;
+ int tabletDeviceType;
+ int tabletPointerType;
+ int capabilityMask;
+#endif
+};
+
+static inline int sign(int x)
+{
+ return x >= 0 ? 1 : -1;
+}
+
+#ifndef Q_WS_MAC
+inline QPointF QTabletDeviceData::scaleCoord(int coordX, int coordY,
+ int outOriginX, int outExtentX,
+ int outOriginY, int outExtentY) const
+{
+ QPointF ret;
+
+ if (sign(outExtentX) == sign(maxX))
+ ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX);
+ else
+ ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX - minX)))
+ + outOriginX);
+
+ if (sign(outExtentY) == sign(maxY))
+ ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY);
+ else
+ ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY - minY)))
+ + outOriginY);
+
+ return ret;
+}
+#endif
+
+typedef QList<QTabletDeviceData> QTabletDeviceDataList;
+QTabletDeviceDataList *qt_tablet_devices();
+# if defined(Q_WS_MAC)
+typedef QHash<int, QTabletDeviceData> QMacTabletHash;
+QMacTabletHash *qt_mac_tablet_hash();
+# endif
+#endif
+
+#ifdef QT3_SUPPORT
+extern "C" {
+ typedef bool (*Ptrqt_tryAccelEvent)(QWidget *w, QKeyEvent *e);
+ typedef bool (*Ptrqt_tryComposeUnicode)(QWidget *w, QKeyEvent *e);
+ typedef bool (*Ptrqt_dispatchAccelEvent)(QWidget *w, QKeyEvent *e);
+}
+#endif
+
+#if defined(Q_WS_WIN)
+typedef BOOL (WINAPI *PtrRegisterTouchWindow)(HWND, ULONG);
+typedef BOOL (WINAPI *PtrGetTouchInputInfo)(HANDLE, UINT, PVOID, int);
+typedef BOOL (WINAPI *PtrCloseTouchInputHandle)(HANDLE);
+
+#ifndef QT_NO_GESTURES
+typedef BOOL (WINAPI *PtrGetGestureInfo)(HANDLE, PVOID);
+typedef BOOL (WINAPI *PtrGetGestureExtraArgs)(HANDLE, UINT, PBYTE);
+typedef BOOL (WINAPI *PtrCloseGestureInfoHandle)(HANDLE);
+typedef BOOL (WINAPI *PtrSetGestureConfig)(HWND, DWORD, UINT, PVOID, UINT);
+typedef BOOL (WINAPI *PtrGetGestureConfig)(HWND, DWORD, DWORD, PUINT, PVOID, UINT);
+
+typedef BOOL (WINAPI *PtrBeginPanningFeedback)(HWND);
+typedef BOOL (WINAPI *PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL);
+typedef BOOL (WINAPI *PtrEndPanningFeedback)(HWND, BOOL);
+
+#ifndef WM_GESTURE
+# define WM_GESTURE 0x0119
+
+# define GID_BEGIN 1
+# define GID_END 2
+# define GID_ZOOM 3
+# define GID_PAN 4
+# define GID_ROTATE 5
+# define GID_TWOFINGERTAP 6
+# define GID_ROLLOVER 7
+
+typedef struct tagGESTUREINFO
+{
+ UINT cbSize;
+ DWORD dwFlags;
+ DWORD dwID;
+ HWND hwndTarget;
+ POINTS ptsLocation;
+ DWORD dwInstanceID;
+ DWORD dwSequenceID;
+ ULONGLONG ullArguments;
+ UINT cbExtraArgs;
+} GESTUREINFO;
+
+# define GC_PAN 0x00000001
+# define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002
+# define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004
+
+# define GC_ZOOM 0x00000001
+# define GC_ROTATE 0x00000001
+
+typedef struct tagGESTURECONFIG
+{
+ DWORD dwID;
+ DWORD dwWant;
+ DWORD dwBlock;
+} GESTURECONFIG;
+
+# define GID_ROTATE_ANGLE_FROM_ARGUMENT(arg) ((((double)(arg) / 65535.0) * 4.0 * 3.14159265) - 2.0*3.14159265)
+
+#endif // WM_GESTURE
+
+#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
+#undef GID_ZOOM
+#define GID_ZOOM 0xf000
+#undef GID_ROTATE
+#define GID_ROTATE 0xf001
+#undef GID_TWOFINGERTAP
+#define GID_TWOFINGERTAP 0xf002
+#undef GID_ROLLOVER
+#define GID_ROLLOVER 0xf003
+#endif
+
+#endif // QT_NO_GESTURES
+
+#endif // Q_WS_WIN
+
+class QScopedLoopLevelCounter
+{
+ QThreadData *threadData;
+public:
+ QScopedLoopLevelCounter(QThreadData *threadData)
+ : threadData(threadData)
+ { ++threadData->loopLevel; }
+ ~QScopedLoopLevelCounter()
+ { --threadData->loopLevel; }
+};
+
+typedef QHash<QByteArray, QFont> FontHash;
+FontHash *qt_app_fonts_hash();
+
+typedef QHash<QByteArray, QPalette> PaletteHash;
+PaletteHash *qt_app_palettes_hash();
+
+#ifdef Q_WS_QPA
+#define QApplicationPrivateBase QGuiApplicationPrivate
+#else
+#define QApplicationPrivateBase QCoreApplicationPrivate
+#endif
+
+class Q_GUI_EXPORT QApplicationPrivate : public QApplicationPrivateBase
+{
+ Q_DECLARE_PUBLIC(QApplication)
+public:
+ QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags);
+ ~QApplicationPrivate();
+
+ virtual void notifyLayoutDirectionChange();
+
+#if defined(Q_WS_X11)
+#ifndef QT_NO_SETTINGS
+ static bool x11_apply_settings();
+#endif
+ static void reset_instance_pointer();
+#elif defined(Q_WS_QWS)
+ static bool qws_apply_settings();
+ static QWidget *findWidget(const QObjectList&, const QPoint &, bool rec);
+#endif
+ static bool quitOnLastWindowClosed;
+ static void emitLastWindowClosed();
+#ifdef Q_WS_WINCE
+ static int autoMaximizeThreshold;
+#endif
+ static bool autoSipEnabled;
+ static QString desktopStyleKey();
+
+
+ void createEventDispatcher();
+ QString appName() const;
+ static void dispatchEnterLeave(QWidget *enter, QWidget *leave);
+
+ //modality
+ static void enterModal(QWidget*);
+ static void leaveModal(QWidget*);
+ static void enterModal_sys(QWidget*);
+ static void leaveModal_sys(QWidget*);
+ static bool isBlockedByModal(QWidget *widget);
+ static bool modalState();
+ static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0);
+#ifdef Q_WS_MAC
+ static QWidget *tryModalHelper_sys(QWidget *top);
+ bool canQuit();
+#endif
+
+ bool notify_helper(QObject *receiver, QEvent * e);
+
+ void construct(
+#ifdef Q_WS_X11
+ Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0
+#endif
+ );
+ void initialize();
+ void process_cmdline();
+
+#if defined(Q_WS_X11)
+ static void x11_initialize_style();
+#endif
+
+ bool inPopupMode() const;
+ void closePopup(QWidget *popup);
+ void openPopup(QWidget *popup);
+ static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
+ static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next);
+
+#ifndef QT_NO_SESSIONMANAGER
+ QSessionManager *session_manager;
+ QString session_id;
+ QString session_key;
+ bool is_session_restored;
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Maintain a list of all scenes to ensure font and palette propagation to
+ // all scenes.
+ QList<QGraphicsScene *> scene_list;
+#endif
+
+ QBasicTimer toolTipWakeUp, toolTipFallAsleep;
+ QPoint toolTipPos, toolTipGlobalPos, hoverGlobalPos;
+ QPointer<QWidget> toolTipWidget;
+#ifndef QT_NO_SHORTCUT
+ QShortcutMap shortcutMap;
+#endif
+
+#ifdef QT3_SUPPORT
+ bool qt_compat_used;
+ bool qt_compat_resolved;
+ Ptrqt_tryAccelEvent qt_tryAccelEvent;
+ Ptrqt_tryComposeUnicode qt_tryComposeUnicode;
+ Ptrqt_dispatchAccelEvent qt_dispatchAccelEvent;
+
+ bool use_compat() {
+ return qt_tryAccelEvent
+ && qt_tryComposeUnicode
+ && qt_dispatchAccelEvent;
+ }
+#endif
+ static QInputContext *inputContext;
+
+ static Qt::MouseButtons mouse_buttons;
+ static Qt::KeyboardModifiers modifier_buttons;
+
+ static QSize app_strut;
+ static QWidgetList *popupWidgets;
+ static QStyle *app_style;
+ static int app_cspec;
+ static QPalette *sys_pal;
+ static QPalette *set_pal;
+
+private:
+#ifndef Q_WS_QPA
+ static QFont *app_font; // private for a reason! Always use QApplication::font() instead!
+#endif
+public:
+ static QFont *sys_font;
+ static QFont *set_font;
+ static QWidget *main_widget;
+ static QWidget *focus_widget;
+ static QWidget *hidden_focus_widget;
+ static QWidget *active_window;
+ static QIcon *app_icon;
+ static bool obey_desktop_settings;
+ static int cursor_flash_time;
+ static int mouse_double_click_time;
+ static int keyboard_input_time;
+#ifndef QT_NO_WHEELEVENT
+ static int wheel_scroll_lines;
+#endif
+
+ static bool animate_ui;
+ static bool animate_menu;
+ static bool animate_tooltip;
+ static bool animate_combo;
+ static bool fade_menu;
+ static bool fade_tooltip;
+ static bool animate_toolbox;
+ static bool widgetCount; // Coupled with -widgetcount switch
+ static bool load_testability; // Coupled with -testability switch
+ static QString qmljs_debug_arguments; // a string containing arguments for js/qml debugging.
+ static QString qmljsDebugArgumentsString(); // access string from other libraries
+
+#ifdef Q_WS_MAC
+ static bool native_modal_dialog_active;
+#endif
+
+ static void setSystemPalette(const QPalette &pal);
+ static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash);
+ static void initializeWidgetPaletteHash();
+ static void setSystemFont(const QFont &font);
+
+#if defined(Q_WS_X11)
+ static void applyX11SpecificCommandLineArguments(QWidget *main_widget);
+#elif defined(Q_WS_QWS)
+ static void applyQWSSpecificCommandLineArguments(QWidget *main_widget);
+#endif
+
+#ifdef Q_WS_MAC
+ static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
+ static OSStatus globalAppleEventProcessor(const AppleEvent *, AppleEvent *, long);
+ static OSStatus tabletProximityCallback(EventHandlerCallRef, EventRef, void *);
+#ifdef QT_MAC_USE_COCOA
+ static void qt_initAfterNSAppStarted();
+ static void setupAppleEvents();
+#endif
+ static bool qt_mac_apply_settings();
+#endif
+
+#ifdef Q_WS_QWS
+ QPointer<QWSManager> last_manager;
+ QWSServerCleaner qwsServerCleaner;
+# ifndef QT_NO_DIRECTPAINTER
+ QMap<WId, QDirectPainter *> *directPainters;
+# endif
+ QRect maxWindowRect(const QScreen *screen) const { return maxWindowRects[screen]; }
+ void setMaxWindowRect(const QScreen *screen, int screenNo, const QRect &rect);
+ void setScreenTransformation(QScreen *screen, int screenNo, int transformation);
+#endif
+
+ static QApplicationPrivate *instance() { return self; }
+
+ static QString styleOverride;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static QWidget *oldEditFocus;
+ static Qt::NavigationMode navigationMode;
+#endif
+
+#if defined(Q_WS_MAC) || defined(Q_WS_X11)
+ void _q_alertTimeOut();
+ QHash<QWidget *, QTimer *> alertTimerHash;
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+ static QString styleSheet;
+#endif
+ static QPointer<QWidget> leaveAfterRelease;
+ static QWidget *pickMouseReceiver(QWidget *candidate, const QPoint &globalPos, QPoint &pos,
+ QEvent::Type type, Qt::MouseButtons buttons,
+ QWidget *buttonDown, QWidget *alienWidget);
+ static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
+ QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous = true);
+#ifdef Q_OS_SYMBIAN
+ static void setNavigationMode(Qt::NavigationMode mode);
+ static TUint resolveS60ScanCode(TInt scanCode, TUint keysym);
+ QSet<WId> nativeWindows;
+
+ int symbianProcessWsEvent(const QSymbianEvent *symbianEvent);
+ int symbianHandleCommand(const QSymbianEvent *symbianEvent);
+ int symbianResourceChange(const QSymbianEvent *symbianEvent);
+
+ void _q_aboutToQuit();
+#endif
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
+ void sendSyntheticEnterLeave(QWidget *widget);
+#endif
+
+#ifndef QT_NO_GESTURES
+ QGestureManager *gestureManager;
+ QWidget *gestureWidget;
+#endif
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ QPixmap *move_cursor;
+ QPixmap *copy_cursor;
+ QPixmap *link_cursor;
+#endif
+#if defined(Q_WS_WIN)
+ QPixmap *ignore_cursor;
+#endif
+
+ QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId;
+ QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
+ static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+ void initializeMultitouch();
+ void initializeMultitouch_sys();
+ void cleanupMultitouch();
+ void cleanupMultitouch_sys();
+ int findClosestTouchPointId(const QPointF &screenPos);
+ void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
+ void removeTouchPoint(int touchPointId);
+ static void translateRawTouchEvent(QWidget *widget,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints);
+
+#if defined(Q_WS_WIN)
+ static bool HasTouchSupport;
+ static PtrRegisterTouchWindow RegisterTouchWindow;
+ static PtrGetTouchInputInfo GetTouchInputInfo;
+ static PtrCloseTouchInputHandle CloseTouchInputHandle;
+
+ QHash<DWORD, int> touchInputIDToTouchPointID;
+ bool translateTouchEvent(const MSG &msg);
+
+#ifndef QT_NO_GESTURES
+ PtrGetGestureInfo GetGestureInfo;
+ PtrGetGestureExtraArgs GetGestureExtraArgs;
+ PtrCloseGestureInfoHandle CloseGestureInfoHandle;
+ PtrSetGestureConfig SetGestureConfig;
+ PtrGetGestureConfig GetGestureConfig;
+ PtrBeginPanningFeedback BeginPanningFeedback;
+ PtrUpdatePanningFeedback UpdatePanningFeedback;
+ PtrEndPanningFeedback EndPanningFeedback;
+#endif // QT_NO_GESTURES
+#endif
+
+#ifdef QT_RX71_MULTITOUCH
+ bool hasRX71MultiTouch;
+
+ struct RX71TouchPointState {
+ QSocketNotifier *socketNotifier;
+ QTouchEvent::TouchPoint touchPoint;
+
+ int minX, maxX, scaleX;
+ int minY, maxY, scaleY;
+ int minZ, maxZ;
+ };
+ QList<RX71TouchPointState> allRX71TouchPoints;
+
+ bool readRX71MultiTouchEvents(int deviceNumber);
+ void fakeMouseEventFromRX71TouchEvent();
+ void _q_readRX71MultiTouchEvents();
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+ int pressureSupported;
+ int maxTouchPressure;
+ QList<QTouchEvent::TouchPoint> appAllTouchPoints;
+
+ bool useTranslucentEGLSurfaces;
+#endif
+
+private:
+#ifdef Q_WS_QWS
+ QMap<const QScreen*, QRect> maxWindowRects;
+#endif
+
+#ifdef Q_OS_SYMBIAN
+ QHash<TInt, TUint> scanCodeCache;
+#endif
+
+ static QApplicationPrivate *self;
+
+ static void giveFocusAccordingToFocusPolicy(QWidget *w,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason);
+ static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
+
+
+ static bool isAlien(QWidget *);
+};
+
+Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints);
+
+#if defined(Q_WS_WIN)
+ extern void qt_win_set_cursor(QWidget *, bool);
+#elif defined(Q_WS_X11)
+ extern void qt_x11_enforce_cursor(QWidget *, bool);
+ extern void qt_x11_enforce_cursor(QWidget *);
+#elif defined(Q_OS_SYMBIAN)
+ extern void qt_symbian_set_cursor(QWidget *, bool);
+#else
+ extern void qt_qpa_set_cursor(QWidget * w, bool force);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QAPPLICATION_P_H
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
new file mode 100644
index 0000000000..f3e033c787
--- /dev/null
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -0,0 +1,431 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication_p.h"
+#include "qcolormap.h"
+#include "qpixmapcache.h"
+#if !defined(QT_NO_GLIB)
+#include "private/qeventdispatcher_glib_qpa_p.h"
+#endif
+#include "private/qeventdispatcher_qpa_p.h"
+#ifndef QT_NO_CURSOR
+#include "private/qcursor_p.h"
+#endif
+
+#include "private/qwidget_p.h"
+#include "private/qevent_p.h"
+
+#include "qgenericpluginfactory_qpa.h"
+#include "private/qplatformintegrationfactory_qpa_p.h"
+#include <qdesktopwidget.h>
+
+#include <qinputcontext.h>
+#include <QPlatformCursor>
+#include <qdebug.h>
+#include <QWindowSystemInterface>
+#include "private/qwindowsysteminterface_qpa_p.h"
+#include <QPlatformIntegration>
+
+#include "qdesktopwidget_qpa_p.h"
+#include "qwidgetwindow_qpa_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QString appName;
+static QString appFont;
+
+QString QApplicationPrivate::appName() const
+{
+ return QT_PREPEND_NAMESPACE(appName);
+}
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ QGuiApplicationPrivate::createEventDispatcher();
+}
+
+static bool qt_try_modal(QWidget *widget, QEvent::Type type)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ bool block_event = false;
+ bool paint_event = false;
+
+ switch (type) {
+#if 0
+ case QEvent::Focus:
+ if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
+ break;
+ // drop through
+#endif
+ case QEvent::MouseButtonPress: // disallow mouse/key events
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ block_event = true;
+ break;
+ default:
+ break;
+ }
+
+ if ((block_event || paint_event) && top->parentWidget() == 0)
+ top->raise();
+
+ return !block_event;
+}
+
+
+
+void QApplicationPrivate::enterModal_sys(QWidget *)
+{
+#if 0
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+#endif
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *)
+{
+#if 0
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ }
+ }
+ app_do_modal = qt_modal_stack != 0;
+#endif
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return false;
+#if 0
+ return app_do_modal;
+#endif
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ Q_Q(QApplication);
+ if (!popupWidgets)
+ return;
+ popupWidgets->removeAll(popup);
+
+//###
+// if (popup == qt_popup_down) {
+// qt_button_down = 0;
+// qt_popup_down = 0;
+// }
+
+ if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+
+ //### replay mouse event?
+
+ //### transfer/release mouse grab
+
+ //### transfer/release keyboard grab
+
+ //give back focus
+
+ if (active_window) {
+ if (QWidget *fw = active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q->sendEvent(fw, &e);
+ }
+ }
+ }
+
+ } else {
+ // A popup was closed, so the previous popup gets the focus.
+
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+
+ //### regrab the keyboard and mouse in case 'popup' lost the grab
+
+
+ }
+
+}
+
+static int openPopupCount = 0;
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ openPopupCount++;
+ if (!popupWidgets) { // create list
+ popupWidgets = new QWidgetList;
+
+ /* only grab if you are the first/parent popup */
+ //#### ->grabMouse(popup,true);
+ //#### ->grabKeyboard(popup,true);
+ //### popupGrabOk = true;
+ }
+ popupWidgets->append(popup); // add to end of list
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+}
+
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QApplication::setWheelScrollLines(int lines)
+{
+ QApplicationPrivate::wheel_scroll_lines = lines;
+}
+
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+#endif
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeMenu:
+ if (enable)
+ QApplicationPrivate::animate_menu = true;
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ if (enable)
+ QApplicationPrivate::animate_tooltip = true;
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
+ return false;
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ return QApplicationPrivate::animate_ui;
+ }
+}
+
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+
+ QList<QPlatformScreen *> screens = pi->screens();
+ QList<QPlatformScreen *>::const_iterator screen = screens.constBegin();
+ QList<QPlatformScreen *>::const_iterator end = screens.constEnd();
+
+ // The first screen in a virtual environment should know about all top levels
+ if (pi->isVirtualDesktop()) {
+ QWidgetWindow *w = qobject_cast<QWidgetWindow *>((*screen)->topLevelAt(pos));
+ return w ? w->widget() : 0;
+ }
+
+ while (screen != end) {
+ if ((*screen)->geometry().contains(pos)) {
+ QWidgetWindow *w = qobject_cast<QWidgetWindow *>((*screen)->topLevelAt(pos));
+ return w ? w->widget() : 0;
+ }
+ ++screen;
+ }
+ return 0;
+}
+
+void QApplication::beep()
+{
+}
+
+void QApplication::alert(QWidget *, int)
+{
+}
+
+QPlatformNativeInterface *QApplication::platformNativeInterface()
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ return pi->nativeInterface();
+}
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+class QDummyInputContext : public QInputContext
+{
+public:
+ explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {}
+ ~QDummyInputContext() {}
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+ bool isComposing() const { return false; }
+
+};
+#endif // QT_NO_QWS_INPUTMETHODS
+
+void qt_init(QApplicationPrivate *, int type)
+{
+ Q_UNUSED(type);
+
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ QColormap::initialize();
+#ifndef QT_NO_CURSOR
+// QCursorData::initialize();
+#endif
+
+ qApp->setObjectName(appName);
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ qApp->setInputContext(new QDummyInputContext(qApp));
+#endif
+}
+
+void qt_cleanup()
+{
+ QPixmapCache::clear();
+#ifndef QT_NO_CURSOR
+ QCursorData::cleanup();
+#endif
+ QColormap::cleanup();
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+
+ QApplicationPrivate::active_window = 0; //### this should not be necessary
+}
+
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget && windowIcon().isNull()
+ && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
+ setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qbackingstore.cpp b/src/widgets/kernel/qbackingstore.cpp
new file mode 100644
index 0000000000..1ee66f09cc
--- /dev/null
+++ b/src/widgets/kernel/qbackingstore.cpp
@@ -0,0 +1,1665 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qplatformdefs.h"
+
+#include "qbackingstore_p.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qpaintengine.h>
+#include <QtGui/qgraphicsproxywidget.h>
+
+#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
+#include <private/qpaintengine_raster_p.h>
+#include <private/qgraphicseffect_p.h>
+
+#ifdef Q_WS_QWS
+#include <QtGui/qwsmanager_qws.h>
+#include <private/qwsmanager_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern QRegion qt_dirtyRegion(QWidget *);
+
+/*
+ A version of QRect::intersects() that does not normalize the rects.
+*/
+static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
+{
+ return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right())
+ && qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
+}
+
+/**
+ * Flushes the contents of the \a windowSurface into the screen area of \a widget.
+ * \a tlwOffset is the position of the top level widget relative to the window surface.
+ * \a region is the region to be updated in \a widget coordinates.
+ */
+static inline void qt_flush(QWidget *widget, const QRegion &region, QWindowSurface *windowSurface,
+ QWidget *tlw, const QPoint &tlwOffset)
+{
+ Q_ASSERT(widget);
+ Q_ASSERT(!region.isEmpty());
+ Q_ASSERT(windowSurface);
+ Q_ASSERT(tlw);
+
+#if !defined(QT_NO_PAINT_DEBUG) && !defined(Q_WS_QWS)
+ // QWS does flush update in QWindowSurface::flush (because it needs to lock the surface etc).
+ static int flushUpdate = qgetenv("QT_FLUSH_UPDATE").toInt();
+ if (flushUpdate > 0)
+ QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false);
+#endif
+
+ //The performance hit by doing this should be negligible. However, be aware that
+ //using this FPS when you have > 1 windowsurface can give you inaccurate FPS
+ static bool fpsDebug = qgetenv("QT_DEBUG_FPS").toInt();
+ if (fpsDebug) {
+ static QTime time = QTime::currentTime();
+ static int frames = 0;
+
+ frames++;
+
+ if(time.elapsed() > 5000) {
+ double fps = double(frames * 1000) /time.restart();
+ fprintf(stderr,"FPS: %.1f\n",fps);
+ frames = 0;
+ }
+ }
+ if (widget != tlw)
+ windowSurface->flush(widget->windowHandle(), region, tlwOffset + widget->mapTo(tlw, QPoint()));
+ else
+ windowSurface->flush(widget->windowHandle(), region, tlwOffset);
+}
+
+#ifndef QT_NO_PAINT_DEBUG
+#ifdef Q_WS_WIN
+static void showYellowThing_win(QWidget *widget, const QRegion &region, int msec)
+{
+ HBRUSH brush;
+ static int i = 0;
+ switch (i) {
+ case 0:
+ brush = CreateSolidBrush(RGB(255, 255, 0));
+ break;
+ case 1:
+ brush = CreateSolidBrush(RGB(255, 200, 55));
+ break;
+ case 2:
+ brush = CreateSolidBrush(RGB(200, 255, 55));
+ break;
+ case 3:
+ brush = CreateSolidBrush(RGB(200, 200, 0));
+ break;
+ }
+ i = (i + 1) & 3;
+
+ HDC hdc = widget->getDC();
+
+ const QVector<QRect> &rects = region.rects();
+ foreach (QRect rect, rects) {
+ RECT winRect;
+ SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom());
+ FillRect(hdc, &winRect, brush);
+ }
+
+ widget->releaseDC(hdc);
+ ::Sleep(msec);
+}
+#endif
+
+void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped)
+{
+#ifdef Q_WS_QWS
+ Q_UNUSED(widget);
+ Q_UNUSED(unclipped);
+ static QWSYellowSurface surface(true);
+ surface.setDelay(msec);
+ surface.flush(widget, toBePainted, QPoint());
+#else
+ QRegion paintRegion = toBePainted;
+ QRect widgetRect = widget->rect();
+
+ if (!widget->internalWinId()) {
+ QWidget *nativeParent = widget->nativeParentWidget();
+ const QPoint offset = widget->mapTo(nativeParent, QPoint(0, 0));
+ paintRegion.translate(offset);
+ widgetRect.translate(offset);
+ widget = nativeParent;
+ }
+
+#ifdef Q_WS_WIN
+ Q_UNUSED(unclipped);
+ showYellowThing_win(widget, paintRegion, msec);
+#else
+ //flags to fool painter
+ bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped);
+ if (unclipped && !widget->d_func()->paintOnScreen())
+ widget->setAttribute(Qt::WA_PaintUnclipped);
+
+ const bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent);
+ if (setFlag)
+ widget->setAttribute(Qt::WA_WState_InPaintEvent);
+
+ //setup the engine
+ QPaintEngine *pe = widget->paintEngine();
+ if (pe) {
+ pe->setSystemClip(paintRegion);
+ {
+ QPainter p(widget);
+ p.setClipRegion(paintRegion);
+ static int i = 0;
+ switch (i) {
+ case 0:
+ p.fillRect(widgetRect, QColor(255,255,0));
+ break;
+ case 1:
+ p.fillRect(widgetRect, QColor(255,200,55));
+ break;
+ case 2:
+ p.fillRect(widgetRect, QColor(200,255,55));
+ break;
+ case 3:
+ p.fillRect(widgetRect, QColor(200,200,0));
+ break;
+ }
+ i = (i+1) & 3;
+ p.end();
+ }
+ }
+
+ if (setFlag)
+ widget->setAttribute(Qt::WA_WState_InPaintEvent, false);
+
+ //restore
+ widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped);
+
+ if (pe)
+ pe->setSystemClip(QRegion());
+
+ QApplication::syncX();
+
+#if defined(Q_OS_UNIX)
+ ::usleep(1000 * msec);
+#endif
+#endif // Q_WS_WIN
+#endif // Q_WS_QWS
+}
+
+bool QWidgetBackingStore::flushPaint(QWidget *widget, const QRegion &rgn)
+{
+ if (!widget)
+ return false;
+
+ int delay = 0;
+ if (widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
+ static int flushPaintEvent = qgetenv("QT_FLUSH_PAINT_EVENT").toInt();
+ if (!flushPaintEvent)
+ return false;
+ delay = flushPaintEvent;
+ } else {
+ static int flushPaint = qgetenv("QT_FLUSH_PAINT").toInt();
+ if (!flushPaint)
+ return false;
+ delay = flushPaint;
+ }
+
+ QWidgetBackingStore::showYellowThing(widget, rgn, delay * 10, true);
+ return true;
+}
+
+void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
+{
+ if (widget->d_func()->paintOnScreen() || rgn.isEmpty())
+ return;
+
+ QWidget *tlw = widget->window();
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (!tlwExtra)
+ return;
+
+ const QPoint offset = widget->mapTo(tlw, QPoint());
+ qt_flush(widget, rgn, tlwExtra->backingStore->windowSurface, tlw, offset);
+}
+#endif // QT_NO_PAINT_DEBUG
+
+/*
+ Moves the whole rect by (dx, dy) in widget's coordinate system.
+ Doesn't generate any updates.
+*/
+bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)
+{
+ const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
+ const QRect tlwRect(QRect(pos, rect.size()));
+ if (fullUpdatePending || dirty.intersects(tlwRect))
+ return false; // We don't want to scroll junk.
+ return windowSurface->scroll(tlwRect, dx, dy);
+}
+
+void QWidgetBackingStore::releaseBuffer()
+{
+ if (windowSurface)
+#if defined(Q_WS_QPA)
+ windowSurface->resize(QSize());
+#else
+ windowSurface->setGeometry(QRect());
+#endif
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ for (int i = 0; i < subSurfaces.size(); ++i)
+ subSurfaces.at(i)->setGeometry(QRect());
+#endif
+}
+
+/*!
+ Prepares the window surface to paint a\ toClean region of the \a widget and
+ updates the BeginPaintInfo struct accordingly.
+
+ The \a toClean region might be clipped by the window surface.
+*/
+void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowSurface *windowSurface,
+ BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates)
+{
+#ifdef Q_WS_QWS
+ QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(windowSurface);
+ QWidget *surfaceWidget = surface->window();
+
+ if (!surface->isValid()) {
+ // this looks strange but it really just releases the surface
+ surface->releaseSurface();
+ // the old window surface is deleted in setWindowSurface, which is
+ // called from QWindowSurface constructor.
+ windowSurface = tlw->d_func()->createDefaultWindowSurface();
+ surface = static_cast<QWSWindowSurface *>(windowSurface);
+ // createDefaultWindowSurface() will set topdata->windowSurface on the
+ // widget to zero. However, if this is a sub-surface, it should point
+ // to the widget's sub windowSurface, so we set that here:
+ if (!surfaceWidget->isWindow())
+ surfaceWidget->d_func()->topData()->windowSurface = windowSurface;
+ surface->setGeometry(topLevelRect());
+ returnInfo->windowSurfaceRecreated = true;
+ }
+
+ const QRegion toCleanUnclipped(toClean);
+
+ if (surfaceWidget->isWindow())
+ tlwOffset = surface->painterOffset();
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ else if (toCleanIsInTopLevelCoordinates)
+ toClean &= surface->clipRegion().translated(surfaceWidget->mapTo(tlw, QPoint()));
+ if (!toCleanIsInTopLevelCoordinates && windowSurface == this->windowSurface)
+ toClean &= surface->clipRegion().translated(-widget->mapTo(surfaceWidget, QPoint()));
+#else
+ toClean &= surface->clipRegion();
+#endif
+
+ if (toClean.isEmpty()) {
+ if (surfaceWidget->isWindow()) {
+ dirtyFromPreviousSync += toCleanUnclipped;
+ hasDirtyFromPreviousSync = true;
+ }
+
+ returnInfo->nothingToPaint = true;
+ // Nothing to repaint. However, we might have newly exposed areas on the
+ // screen, so we have to make sure those are flushed.
+ flush();
+ return;
+ }
+
+ if (surfaceWidget->isWindow()) {
+ if (toCleanUnclipped != toClean) {
+ dirtyFromPreviousSync += (toCleanUnclipped - surface->clipRegion());
+ hasDirtyFromPreviousSync = true;
+ }
+ if (hasDirtyFromPreviousSync) {
+ dirtyFromPreviousSync -= toClean;
+ hasDirtyFromPreviousSync = !dirtyFromPreviousSync.isEmpty();
+ }
+ }
+
+#endif // Q_WS_QWS
+
+ Q_UNUSED(widget);
+ Q_UNUSED(toCleanIsInTopLevelCoordinates);
+
+ // Always flush repainted areas.
+ dirtyOnScreen += toClean;
+
+#if defined(Q_WS_QWS) && !defined(Q_BACKINGSTORE_SUBSURFACES)
+ toClean.translate(tlwOffset);
+#endif
+
+#ifdef QT_NO_PAINT_DEBUG
+ windowSurface->beginPaint(toClean);
+#else
+ returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean);
+ // Avoid deadlock with QT_FLUSH_PAINT: the server will wait for
+ // the BackingStore lock, so if we hold that, the server will
+ // never release the Communication lock that we are waiting for in
+ // sendSynchronousCommand
+ if (!returnInfo->wasFlushed)
+ windowSurface->beginPaint(toClean);
+#endif
+
+ Q_UNUSED(returnInfo);
+}
+
+void QWidgetBackingStore::endPaint(const QRegion &cleaned, QWindowSurface *windowSurface,
+ BeginPaintInfo *beginPaintInfo)
+{
+#ifndef QT_NO_PAINT_DEBUG
+ if (!beginPaintInfo->wasFlushed)
+ windowSurface->endPaint(cleaned);
+ else
+ QWidgetBackingStore::unflushPaint(tlw, cleaned);
+#else
+ Q_UNUSED(beginPaintInfo);
+ windowSurface->endPaint(cleaned);
+#endif
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ flush(static_cast<QWSWindowSurface *>(windowSurface)->window(), windowSurface);
+#else
+ flush();
+#endif
+}
+
+/*!
+ Returns the region (in top-level coordinates) that needs repaint and/or flush.
+
+ If the widget is non-zero, only the dirty region for the widget is returned
+ and the region will be in widget coordinates.
+*/
+QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
+{
+ const bool widgetDirty = widget && widget != tlw;
+ const QRect tlwRect(topLevelRect());
+#if defined(Q_WS_QPA)
+ const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
+#else
+ const QRect surfaceGeometry(windowSurface->geometry());
+#endif
+ if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
+ if (widgetDirty) {
+ const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
+ const QPoint offset(widget->mapTo(tlw, QPoint()));
+ const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset));
+ return dirtyWidgetRect.translated(-offset);
+ }
+ return QRect(QPoint(), tlwRect.size());
+ }
+
+ // Calculate the region that needs repaint.
+ QRegion r(dirty);
+ for (int i = 0; i < dirtyWidgets.size(); ++i) {
+ QWidget *w = dirtyWidgets.at(i);
+ if (widgetDirty && w != widget && !widget->isAncestorOf(w))
+ continue;
+ r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint()));
+ }
+
+ // Append the region that needs flush.
+ r += dirtyOnScreen;
+
+ if (dirtyOnScreenWidgets) { // Only in use with native child widgets.
+ for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
+ QWidget *w = dirtyOnScreenWidgets->at(i);
+ if (widgetDirty && w != widget && !widget->isAncestorOf(w))
+ continue;
+ QWidgetPrivate *wd = w->d_func();
+ Q_ASSERT(wd->needsFlush);
+ r += wd->needsFlush->translated(w->mapTo(tlw, QPoint()));
+ }
+ }
+
+ if (widgetDirty) {
+ // Intersect with the widget geometry and translate to its coordinates.
+ const QPoint offset(widget->mapTo(tlw, QPoint()));
+ r &= widget->rect().translated(offset);
+ r.translate(-offset);
+ }
+ return r;
+}
+
+/*!
+ Returns the static content inside the \a parent if non-zero; otherwise the static content
+ for the entire backing store is returned. The content will be clipped to \a withinClipRect
+ if non-empty.
+*/
+QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const
+{
+ if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) {
+#if defined(Q_WS_QPA)
+ const QSize surfaceGeometry(windowSurface->size());
+#else
+ const QRect surfaceGeometry(windowSurface->geometry());
+#endif
+ QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
+ if (!withinClipRect.isEmpty())
+ surfaceRect &= withinClipRect;
+ return QRegion(surfaceRect);
+ }
+
+ QRegion region;
+ if (parent && parent->d_func()->children.isEmpty())
+ return region;
+
+ const bool clipToRect = !withinClipRect.isEmpty();
+ const int count = staticWidgets.count();
+ for (int i = 0; i < count; ++i) {
+ QWidget *w = staticWidgets.at(i);
+ QWidgetPrivate *wd = w->d_func();
+ if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty()
+ || !w->isVisible() || (parent && !parent->isAncestorOf(w))) {
+ continue;
+ }
+
+ QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height());
+ const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint());
+ if (clipToRect)
+ rect &= withinClipRect.translated(-offset);
+ if (rect.isEmpty())
+ continue;
+
+ rect &= wd->clipRect();
+ if (rect.isEmpty())
+ continue;
+
+ QRegion visible(rect);
+ wd->clipToEffectiveMask(visible);
+ if (visible.isEmpty())
+ continue;
+ wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true);
+
+ visible.translate(offset);
+ region += visible;
+ }
+
+ return region;
+}
+
+static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
+{
+ if (!widget)
+ return;
+
+ if (updateImmediately) {
+ QEvent event(QEvent::UpdateRequest);
+ QApplication::sendEvent(widget, &event);
+ } else {
+ QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
+ }
+}
+
+/*!
+ Marks the region of the widget as dirty (if not already marked as dirty) and
+ posts an UpdateRequest event to the top-level widget (if not already posted).
+
+ If updateImmediately is true, the event is sent immediately instead of posted.
+
+ If invalidateBuffer is true, all widgets intersecting with the region will be dirty.
+
+ If the widget paints directly on screen, the event is sent to the widget
+ instead of the top-level widget, and invalidateBuffer is completely ignored.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately,
+ bool invalidateBuffer)
+{
+ Q_ASSERT(tlw->d_func()->extra);
+ Q_ASSERT(tlw->d_func()->extra->topextra);
+ Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
+ Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
+ Q_ASSERT(widget->window() == tlw);
+ Q_ASSERT(!rgn.isEmpty());
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ if (widget->d_func()->paintOnScreen()) {
+ if (widget->d_func()->dirty.isEmpty()) {
+ widget->d_func()->dirty = rgn;
+ sendUpdateRequest(widget, updateImmediately);
+ return;
+ } else if (qt_region_strictContains(widget->d_func()->dirty, widget->rect())) {
+ if (updateImmediately)
+ sendUpdateRequest(widget, updateImmediately);
+ return; // Already dirty.
+ }
+
+ const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
+ widget->d_func()->dirty += rgn;
+ if (!eventAlreadyPosted || updateImmediately)
+ sendUpdateRequest(widget, updateImmediately);
+ return;
+ }
+
+ if (fullUpdatePending) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (!windowSurface->hasFeature(QWindowSurface::PartialUpdates)) {
+ fullUpdatePending = true;
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ const QPoint offset = widget->mapTo(tlw, QPoint());
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
+ if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return; // Already dirty.
+ }
+
+ if (invalidateBuffer) {
+ const bool eventAlreadyPosted = !dirty.isEmpty();
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (widget->d_func()->graphicsEffect)
+ dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
+ else
+#endif //QT_NO_GRAPHICSEFFECT
+ dirty += rgn.translated(offset);
+ if (!eventAlreadyPosted || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (dirtyWidgets.isEmpty()) {
+ addDirtyWidget(widget, rgn);
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (widget->d_func()->inDirtyList) {
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (widget->d_func()->graphicsEffect)
+ widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect());
+ else
+#endif //QT_NO_GRAPHICSEFFECT
+ widget->d_func()->dirty += rgn;
+ }
+ } else {
+ addDirtyWidget(widget, rgn);
+ }
+
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+}
+
+/*!
+ This function is equivalent to calling markDirty(QRegion(rect), ...), but
+ is more efficient as it eliminates QRegion operations/allocations and can
+ use the rect more precisely for additional cut-offs.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool updateImmediately,
+ bool invalidateBuffer)
+{
+ Q_ASSERT(tlw->d_func()->extra);
+ Q_ASSERT(tlw->d_func()->extra->topextra);
+ Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
+ Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
+ Q_ASSERT(widget->window() == tlw);
+ Q_ASSERT(!rect.isEmpty());
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ if (widget->d_func()->paintOnScreen()) {
+ if (widget->d_func()->dirty.isEmpty()) {
+ widget->d_func()->dirty = QRegion(rect);
+ sendUpdateRequest(widget, updateImmediately);
+ return;
+ } else if (qt_region_strictContains(widget->d_func()->dirty, rect)) {
+ if (updateImmediately)
+ sendUpdateRequest(widget, updateImmediately);
+ return; // Already dirty.
+ }
+
+ const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
+ widget->d_func()->dirty += rect;
+ if (!eventAlreadyPosted || updateImmediately)
+ sendUpdateRequest(widget, updateImmediately);
+ return;
+ }
+
+ if (fullUpdatePending) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (!windowSurface->hasFeature(QWindowSurface::PartialUpdates)) {
+ fullUpdatePending = true;
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
+ const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
+ if (qt_region_strictContains(dirty, translatedRect)) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return; // Already dirty
+ }
+
+ if (invalidateBuffer) {
+ const bool eventAlreadyPosted = !dirty.isEmpty();
+ dirty += translatedRect;
+ if (!eventAlreadyPosted || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (dirtyWidgets.isEmpty()) {
+ addDirtyWidget(widget, rect);
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (widget->d_func()->inDirtyList) {
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect))
+ widget->d_func()->dirty += widgetRect;
+ } else {
+ addDirtyWidget(widget, rect);
+ }
+
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+}
+
+/*!
+ Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from
+ the backing store to the \a widget's native parent next time flush() is called.
+
+ Paint on screen widgets are ignored.
+*/
+void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widget, const QPoint &topLevelOffset)
+{
+ if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty())
+ return;
+
+#if defined(Q_WS_QWS) || defined(Q_WS_MAC)
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region.translated(topLevelOffset);
+ return;
+#endif
+
+ // Top-level.
+ if (widget == tlw) {
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region;
+ return;
+ }
+
+ // Alien widgets.
+ if (!widget->internalWinId() && !widget->isWindow()) {
+ QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
+ if (nativeParent == tlw) {
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region.translated(topLevelOffset);
+ return;
+ }
+
+ // Alien widgets with native parent != tlw.
+ QWidgetPrivate *nativeParentPrivate = nativeParent->d_func();
+ if (!nativeParentPrivate->needsFlush)
+ nativeParentPrivate->needsFlush = new QRegion;
+ const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint());
+ *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset);
+ appendDirtyOnScreenWidget(nativeParent);
+ return;
+ }
+
+ // Native child widgets.
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+ if (!widgetPrivate->needsFlush)
+ widgetPrivate->needsFlush = new QRegion;
+ *widgetPrivate->needsFlush += region;
+ appendDirtyOnScreenWidget(widget);
+}
+
+void QWidgetBackingStore::removeDirtyWidget(QWidget *w)
+{
+ if (!w)
+ return;
+
+ dirtyWidgetsRemoveAll(w);
+ dirtyOnScreenWidgetsRemoveAll(w);
+ resetWidget(w);
+
+ QWidgetPrivate *wd = w->d_func();
+ const int n = wd->children.count();
+ for (int i = 0; i < n; ++i) {
+ if (QWidget *child = qobject_cast<QWidget*>(wd->children.at(i)))
+ removeDirtyWidget(child);
+ }
+}
+
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+bool QWidgetBackingStore::hasDirtyWindowDecoration() const
+{
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (tlwExtra && tlwExtra->qwsManager)
+ return !tlwExtra->qwsManager->d_func()->dirtyRegions.isEmpty();
+ return false;
+}
+
+void QWidgetBackingStore::paintWindowDecoration()
+{
+ if (!hasDirtyWindowDecoration())
+ return;
+
+ QDecoration &decoration = QApplication::qwsDecoration();
+ const QRect decorationRect = tlw->rect();
+ QRegion decorationRegion = decoration.region(tlw, decorationRect);
+
+ QWSManagerPrivate *managerPrivate = tlw->d_func()->topData()->qwsManager->d_func();
+ const bool doClipping = !managerPrivate->entireDecorationNeedsRepaint
+ && !managerPrivate->dirtyClip.isEmpty();
+
+ if (doClipping) {
+ decorationRegion &= static_cast<QWSWindowSurface *>(windowSurface)->clipRegion();
+ decorationRegion &= managerPrivate->dirtyClip;
+ }
+
+ if (decorationRegion.isEmpty())
+ return;
+
+ //### The QWS decorations do not always paint the pixels they promise to paint.
+ // This causes painting problems with QWSMemorySurface. Since none of the other
+ // window surfaces actually use the region, passing an empty region is a safe
+ // workaround.
+
+ windowSurface->beginPaint(QRegion());
+
+ QPaintEngine *engine = windowSurface->paintDevice()->paintEngine();
+ Q_ASSERT(engine);
+ const QRegion oldSystemClip(engine->systemClip());
+ engine->setSystemClip(decorationRegion.translated(tlwOffset));
+
+ QPainter painter(windowSurface->paintDevice());
+ painter.setFont(QApplication::font());
+ painter.translate(tlwOffset);
+
+ const int numDirty = managerPrivate->dirtyRegions.size();
+ for (int i = 0; i < numDirty; ++i) {
+ const int area = managerPrivate->dirtyRegions.at(i);
+
+ QRegion clipRegion = decoration.region(tlw, decorationRect, area);
+ if (!clipRegion.isEmpty()) {
+ // Decoration styles changes the clip and assumes the old clip is non-empty,
+ // so we have to set it, but in theory it shouldn't be required.
+ painter.setClipRegion(clipRegion);
+ decoration.paint(&painter, tlw, area, managerPrivate->dirtyStates.at(i));
+ }
+ }
+ markDirtyOnScreen(decorationRegion, tlw, QPoint());
+
+ painter.end();
+ windowSurface->endPaint(decorationRegion);
+ managerPrivate->clearDirtyRegions();
+ engine->setSystemClip(oldSystemClip);
+}
+#endif
+
+void QWidgetBackingStore::updateLists(QWidget *cur)
+{
+ if (!cur)
+ return;
+
+ QList<QObject*> children = cur->children();
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget*>(children.at(i));
+ if (!child)
+ continue;
+
+ updateLists(child);
+ }
+
+ if (cur->testAttribute(Qt::WA_StaticContents))
+ addStaticWidget(cur);
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QTLWExtra *extra = cur->d_func()->maybeTopData();
+ if (extra && extra->windowSurface && cur != tlw)
+ subSurfaces.append(extra->windowSurface);
+#endif
+}
+
+QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
+ : tlw(topLevel), dirtyOnScreenWidgets(0), hasDirtyFromPreviousSync(false)
+ , fullUpdatePending(0)
+{
+ windowSurface = tlw->windowSurface();
+ if (!windowSurface)
+ windowSurface = topLevel->d_func()->createDefaultWindowSurface();
+
+ // The QWindowSurface constructor will call QWidget::setWindowSurface(),
+ // but automatically created surfaces should not be added to the topdata.
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ Q_ASSERT(topLevel->d_func()->topData()->windowSurface == windowSurface);
+#endif
+ topLevel->d_func()->topData()->windowSurface = 0;
+
+ // Ensure all existing subsurfaces and static widgets are added to their respective lists.
+ updateLists(topLevel);
+}
+
+QWidgetBackingStore::~QWidgetBackingStore()
+{
+ for (int c = 0; c < dirtyWidgets.size(); ++c) {
+ resetWidget(dirtyWidgets.at(c));
+ }
+
+ delete windowSurface;
+ windowSurface = 0;
+ delete dirtyOnScreenWidgets;
+ dirtyOnScreenWidgets = 0;
+}
+
+//parent's coordinates; move whole rect; update parent and widget
+//assume the screen blt has already been done, so we don't need to refresh that part
+void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
+{
+ Q_Q(QWidget);
+ if (!q->isVisible() || (dx == 0 && dy == 0))
+ return;
+
+ QWidget *tlw = q->window();
+ QTLWExtra* x = tlw->d_func()->topData();
+ if (x->inTopLevelResize)
+ return;
+
+ static int accelEnv = -1;
+ if (accelEnv == -1) {
+ accelEnv = qgetenv("QT_NO_FAST_MOVE").toInt() == 0;
+ }
+
+ QWidget *pw = q->parentWidget();
+ QPoint toplevelOffset = pw->mapTo(tlw, QPoint());
+ QWidgetPrivate *pd = pw->d_func();
+ QRect clipR(pd->clipRect());
+#ifdef Q_WS_QWS
+ QWidgetBackingStore *wbs = x->backingStore.data();
+ QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface);
+ clipR = clipR.intersected(surface->clipRegion().translated(-toplevelOffset).boundingRect());
+#endif
+ const QRect newRect(rect.translated(dx, dy));
+ QRect destRect = rect.intersected(clipR);
+ if (destRect.isValid())
+ destRect = destRect.translated(dx, dy).intersected(clipR);
+ const QRect sourceRect(destRect.translated(-dx, -dy));
+ const QRect parentRect(rect & clipR);
+
+ bool accelerateMove = accelEnv && isOpaque
+#ifndef QT_NO_GRAPHICSVIEW
+ // No accelerate move for proxy widgets.
+ && !tlw->d_func()->extra->proxyWidget
+#endif
+ && !isOverlapped(sourceRect) && !isOverlapped(destRect);
+
+ if (!accelerateMove) {
+ QRegion parentR(effectiveRectFor(parentRect));
+ if (!extra || !extra->hasMask) {
+ parentR -= newRect;
+ } else {
+ // invalidateBuffer() excludes anything outside the mask
+ parentR += newRect & clipR;
+ }
+ pd->invalidateBuffer(parentR);
+ invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
+ } else {
+
+ QWidgetBackingStore *wbs = x->backingStore.data();
+ QRegion childExpose(newRect & clipR);
+
+ if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw))
+ childExpose -= destRect;
+
+ if (!pw->updatesEnabled())
+ return;
+
+ const bool childUpdatesEnabled = q->updatesEnabled();
+ if (childUpdatesEnabled && !childExpose.isEmpty()) {
+ childExpose.translate(-data.crect.topLeft());
+ wbs->markDirty(childExpose, q);
+ isMoved = true;
+ }
+
+ QRegion parentExpose(parentRect);
+ parentExpose -= newRect;
+ if (extra && extra->hasMask)
+ parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft());
+
+ if (!parentExpose.isEmpty()) {
+ wbs->markDirty(parentExpose, pw);
+ pd->isMoved = true;
+ }
+
+ if (childUpdatesEnabled) {
+ QRegion needsFlush(sourceRect);
+ needsFlush += destRect;
+ wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset);
+ }
+ }
+}
+
+//widget's coordinates; scroll within rect; only update widget
+void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
+{
+ Q_Q(QWidget);
+ QWidget *tlw = q->window();
+ QTLWExtra* x = tlw->d_func()->topData();
+ if (x->inTopLevelResize)
+ return;
+
+ QWidgetBackingStore *wbs = x->backingStore.data();
+ if (!wbs)
+ return;
+
+ static int accelEnv = -1;
+ if (accelEnv == -1) {
+ accelEnv = qgetenv("QT_NO_FAST_SCROLL").toInt() == 0;
+ }
+
+ QRect scrollRect = rect & clipRect();
+ bool overlapped = false;
+ bool accelerateScroll = accelEnv && isOpaque
+ && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft())));
+
+#if defined(Q_WS_QWS)
+ QWSWindowSurface *surface;
+ surface = static_cast<QWSWindowSurface*>(wbs->windowSurface);
+
+ if (accelerateScroll && !surface->isBuffered()) {
+ const QRegion surfaceClip = surface->clipRegion();
+ const QRegion outsideClip = QRegion(rect) - surfaceClip;
+ if (!outsideClip.isEmpty()) {
+ const QVector<QRect> clipped = (surfaceClip & rect).rects();
+ if (clipped.size() < 8) {
+ for (int i = 0; i < clipped.size(); ++i)
+ this->scrollRect(clipped.at(i), dx, dy);
+ return;
+ } else {
+ accelerateScroll = false;
+ }
+ }
+ }
+#endif // Q_WS_QWS
+
+ if (!accelerateScroll) {
+ if (overlapped) {
+ QRegion region(scrollRect);
+ subtractOpaqueSiblings(region);
+ invalidateBuffer(region);
+ }else {
+ invalidateBuffer(scrollRect);
+ }
+ } else {
+ const QPoint toplevelOffset = q->mapTo(tlw, QPoint());
+#ifdef Q_WS_QWS
+ QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface);
+ const QRegion clip = surface->clipRegion().translated(-toplevelOffset) & scrollRect;
+ const QRect clipBoundingRect = clip.boundingRect();
+ scrollRect &= clipBoundingRect;
+#endif
+ const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;
+ const QRect sourceRect = destRect.translated(-dx, -dy);
+
+ QRegion childExpose(scrollRect);
+ if (sourceRect.isValid()) {
+ if (wbs->bltRect(sourceRect, dx, dy, q))
+ childExpose -= destRect;
+ }
+
+ if (inDirtyList) {
+ if (rect == q->rect()) {
+ dirty.translate(dx, dy);
+ } else {
+ QRegion dirtyScrollRegion = dirty.intersected(scrollRect);
+ if (!dirtyScrollRegion.isEmpty()) {
+ dirty -= dirtyScrollRegion;
+ dirtyScrollRegion.translate(dx, dy);
+ dirty += dirtyScrollRegion;
+ }
+ }
+ }
+
+ if (!q->updatesEnabled())
+ return;
+
+ if (!childExpose.isEmpty()) {
+ wbs->markDirty(childExpose, q);
+ isScrolled = true;
+ }
+
+ // Instead of using native scroll-on-screen, we copy from
+ // backingstore, giving only one screen update for each
+ // scroll, and a solid appearance
+ wbs->markDirtyOnScreen(destRect, q, toplevelOffset);
+ }
+}
+
+static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
+{
+ if (!tlw || !tlwExtra)
+ return true;
+
+#ifdef Q_WS_X11
+ // Delay the sync until we get an Expose event from X11 (initial show).
+ // Qt::WA_Mapped is set to true, but the actual mapping has not yet occurred.
+ // However, we must repaint immediately regardless of the state if someone calls repaint().
+ if (tlwExtra->waitingForMapNotify && !tlwExtra->inRepaint)
+ return true;
+#endif
+
+ if (!tlw->testAttribute(Qt::WA_Mapped))
+ return true;
+
+ if (!tlw->isVisible()
+#ifndef Q_WS_X11
+ // If we're minimized on X11, WA_Mapped will be false and we
+ // will return in the case above. Some window managers on X11
+ // sends us the PropertyNotify to change the minimized state
+ // *AFTER* we've received the expose event, which is baaad.
+ || tlw->isMinimized()
+#endif
+ )
+ return true;
+
+ return false;
+}
+
+/*!
+ Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store.
+
+ If there's nothing to repaint, the area is flushed and painting does not occur;
+ otherwise the area is marked as dirty on screen and will be flushed right after
+ we are done with all painting.
+*/
+void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion)
+{
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (discardSyncRequest(tlw, tlwExtra) || tlwExtra->inTopLevelResize)
+ return;
+
+ if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible()
+ || !exposedWidget->updatesEnabled() || exposedRegion.isEmpty()) {
+ return;
+ }
+
+ // If there's no preserved contents support we always need
+ // to do a full repaint before flushing
+ if (!windowSurface->hasFeature(QWindowSurface::PreservedContents))
+ fullUpdatePending = true;
+
+ // Nothing to repaint.
+ if (!isDirty()) {
+ qt_flush(exposedWidget, exposedRegion, windowSurface, tlw, tlwOffset);
+ return;
+ }
+
+ if (exposedWidget != tlw)
+ markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint()));
+ else
+ markDirtyOnScreen(exposedRegion, exposedWidget, QPoint());
+ sync();
+}
+
+/*!
+ Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
+*/
+void QWidgetBackingStore::sync()
+{
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (discardSyncRequest(tlw, tlwExtra)) {
+ // If the top-level is minimized, it's not visible on the screen so we can delay the
+ // update until it's shown again. In order to do that we must keep the dirty states.
+ // These will be cleared when we receive the first expose after showNormal().
+ // However, if the widget is not visible (isVisible() returns false), everything will
+ // be invalidated once the widget is shown again, so clear all dirty states.
+ if (!tlw->isVisible()) {
+ dirty = QRegion();
+ for (int i = 0; i < dirtyWidgets.size(); ++i)
+ resetWidget(dirtyWidgets.at(i));
+ dirtyWidgets.clear();
+ fullUpdatePending = false;
+ }
+ return;
+ }
+
+ const bool updatesDisabled = !tlw->updatesEnabled();
+ bool repaintAllWidgets = false;
+
+ const bool inTopLevelResize = tlwExtra->inTopLevelResize;
+ const QRect tlwRect(topLevelRect());
+#ifdef Q_WS_QPA
+ const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
+#else
+ const QRect surfaceGeometry(windowSurface->geometry());
+#endif
+ if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
+ if (hasStaticContents()) {
+ // Repaint existing dirty area and newly visible area.
+ const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
+ const QRegion staticRegion(staticContents(0, clipRect));
+ QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
+ newVisible -= staticRegion;
+ dirty += newVisible;
+ windowSurface->setStaticContents(staticRegion);
+ } else {
+ // Repaint everything.
+ dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
+ for (int i = 0; i < dirtyWidgets.size(); ++i)
+ resetWidget(dirtyWidgets.at(i));
+ dirtyWidgets.clear();
+ repaintAllWidgets = true;
+ }
+ }
+
+#ifdef Q_WS_QPA
+ if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size())
+ windowSurface->resize(tlwRect.size());
+#else
+ if (inTopLevelResize || surfaceGeometry != tlwRect)
+ windowSurface->setGeometry(tlwRect);
+#endif
+
+ if (updatesDisabled)
+ return;
+
+ if (hasDirtyFromPreviousSync)
+ dirty += dirtyFromPreviousSync;
+
+ // Contains everything that needs repaint.
+ QRegion toClean(dirty);
+
+ // Loop through all update() widgets and remove them from the list before they are
+ // painted (in case someone calls update() in paintEvent). If the widget is opaque
+ // and does not have transparent overlapping siblings, append it to the
+ // opaqueNonOverlappedWidgets list and paint it directly without composition.
+ QVarLengthArray<QWidget *, 32> opaqueNonOverlappedWidgets;
+ for (int i = 0; i < dirtyWidgets.size(); ++i) {
+ QWidget *w = dirtyWidgets.at(i);
+ QWidgetPrivate *wd = w->d_func();
+ if (wd->data.in_destructor)
+ continue;
+
+ // Clip with mask() and clipRect().
+ wd->dirty &= wd->clipRect();
+ wd->clipToEffectiveMask(wd->dirty);
+
+ // Subtract opaque siblings and children.
+ bool hasDirtySiblingsAbove = false;
+ // We know for sure that the widget isn't overlapped if 'isMoved' is true.
+ if (!wd->isMoved)
+ wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove);
+ // Scrolled and moved widgets must draw all children.
+ if (!wd->isScrolled && !wd->isMoved)
+ wd->subtractOpaqueChildren(wd->dirty, w->rect());
+
+ if (wd->dirty.isEmpty()) {
+ resetWidget(w);
+ continue;
+ }
+
+ const QRegion widgetDirty(w != tlw ? wd->dirty.translated(w->mapTo(tlw, QPoint()))
+ : wd->dirty);
+ toClean += widgetDirty;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (tlw->d_func()->extra->proxyWidget) {
+ resetWidget(w);
+ continue;
+ }
+#endif
+
+ if (!hasDirtySiblingsAbove && wd->isOpaque && !dirty.intersects(widgetDirty.boundingRect())) {
+ opaqueNonOverlappedWidgets.append(w);
+ } else {
+ resetWidget(w);
+ dirty += widgetDirty;
+ }
+ }
+ dirtyWidgets.clear();
+
+ fullUpdatePending = false;
+
+ if (toClean.isEmpty()) {
+ // Nothing to repaint. However, we might have newly exposed areas on the
+ // screen if this function was called from sync(QWidget *, QRegion)), so
+ // we have to make sure those are flushed.
+ flush();
+ return;
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (tlw->d_func()->extra->proxyWidget) {
+ updateStaticContentsSize();
+ dirty = QRegion();
+ const QVector<QRect> rects(toClean.rects());
+ for (int i = 0; i < rects.size(); ++i)
+ tlw->d_func()->extra->proxyWidget->update(rects.at(i));
+ return;
+ }
+#endif
+
+#ifndef Q_BACKINGSTORE_SUBSURFACES
+ BeginPaintInfo beginPaintInfo;
+ beginPaint(toClean, tlw, windowSurface, &beginPaintInfo);
+ if (beginPaintInfo.nothingToPaint) {
+ for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
+ resetWidget(opaqueNonOverlappedWidgets[i]);
+ dirty = QRegion();
+ return;
+ }
+#endif
+
+ // Must do this before sending any paint events because
+ // the size may change in the paint event.
+ updateStaticContentsSize();
+ const QRegion dirtyCopy(dirty);
+ dirty = QRegion();
+
+ // Paint opaque non overlapped widgets.
+ for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
+ QWidget *w = opaqueNonOverlappedWidgets[i];
+ QWidgetPrivate *wd = w->d_func();
+
+ int flags = QWidgetPrivate::DrawRecursive;
+ // Scrolled and moved widgets must draw all children.
+ if (!wd->isScrolled && !wd->isMoved)
+ flags |= QWidgetPrivate::DontDrawOpaqueChildren;
+ if (w == tlw)
+ flags |= QWidgetPrivate::DrawAsRoot;
+
+ QRegion toBePainted(wd->dirty);
+ resetWidget(w);
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QWindowSurface *subSurface = w->windowSurface();
+ BeginPaintInfo beginPaintInfo;
+
+ QPoint off = w->mapTo(tlw, QPoint());
+ toBePainted.translate(off);
+ beginPaint(toBePainted, w, subSurface, &beginPaintInfo, true);
+ toBePainted.translate(-off);
+
+ if (beginPaintInfo.nothingToPaint)
+ continue;
+
+ if (beginPaintInfo.windowSurfaceRecreated) {
+ // Eep the window surface has changed. The old one may have been
+ // deleted, in which case we will segfault on the call to
+ // painterOffset() below. Use the new window surface instead.
+ subSurface = w->windowSurface();
+ }
+
+ QPoint offset(tlwOffset);
+ if (subSurface == windowSurface)
+ offset += w->mapTo(tlw, QPoint());
+ else
+ offset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
+ wd->drawWidget(subSurface->paintDevice(), toBePainted, offset, flags, 0, this);
+
+ endPaint(toBePainted, subSurface, &beginPaintInfo);
+#else
+ QPoint offset(tlwOffset);
+ if (w != tlw)
+ offset += w->mapTo(tlw, QPoint());
+ wd->drawWidget(windowSurface->paintDevice(), toBePainted, offset, flags, 0, this);
+#endif
+ }
+
+ // Paint the rest with composition.
+#ifndef Q_BACKINGSTORE_SUBSURFACES
+ if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
+ const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
+ tlw->d_func()->drawWidget(windowSurface->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
+ }
+
+ endPaint(toClean, windowSurface, &beginPaintInfo);
+#else
+ if (!repaintAllWidgets && dirtyCopy.isEmpty())
+ return; // Nothing more to paint.
+
+ QList<QWindowSurface *> surfaceList(subSurfaces);
+ surfaceList.prepend(windowSurface);
+ const QRect dirtyBoundingRect(dirtyCopy.boundingRect());
+
+ // Loop through all window surfaces (incl. the top-level surface) and
+ // repaint those intersecting with the bounding rect of the dirty region.
+ for (int i = 0; i < surfaceList.size(); ++i) {
+ QWindowSurface *subSurface = surfaceList.at(i);
+ QWidget *w = subSurface->window();
+ QWidgetPrivate *wd = w->d_func();
+
+ const QRect clipRect = wd->clipRect().translated(w->mapTo(tlw, QPoint()));
+ if (!qRectIntersects(dirtyBoundingRect, clipRect))
+ continue;
+
+ toClean = dirtyCopy;
+ BeginPaintInfo beginPaintInfo;
+ beginPaint(toClean, w, subSurface, &beginPaintInfo);
+ if (beginPaintInfo.nothingToPaint)
+ continue;
+
+ if (beginPaintInfo.windowSurfaceRecreated) {
+ // Eep the window surface has changed. The old one may have been
+ // deleted, in which case we will segfault on the call to
+ // painterOffset() below. Use the new window surface instead.
+ subSurface = w->windowSurface();
+ }
+
+ int flags = QWidgetPrivate::DrawRecursive;
+ if (w == tlw)
+ flags |= QWidgetPrivate::DrawAsRoot;
+ const QPoint painterOffset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
+ wd->drawWidget(subSurface->paintDevice(), toClean, painterOffset, flags, 0, this);
+
+ endPaint(toClean, subSurface, &beginPaintInfo);
+ }
+#endif
+}
+
+/*!
+ Flushes the contents of the backing store into the top-level widget.
+ If the \a widget is non-zero, the content is flushed to the \a widget.
+ If the \a surface is non-zero, the content of the \a surface is flushed.
+*/
+void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface)
+{
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ paintWindowDecoration();
+#endif
+
+ if (!dirtyOnScreen.isEmpty()) {
+ QWidget *target = widget ? widget : tlw;
+ QWindowSurface *source = surface ? surface : windowSurface;
+ qt_flush(target, dirtyOnScreen, source, tlw, tlwOffset);
+ dirtyOnScreen = QRegion();
+ }
+
+ if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty())
+ return;
+
+ for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
+ QWidget *w = dirtyOnScreenWidgets->at(i);
+ QWidgetPrivate *wd = w->d_func();
+ Q_ASSERT(wd->needsFlush);
+ qt_flush(w, *wd->needsFlush, windowSurface, tlw, tlwOffset);
+ *wd->needsFlush = QRegion();
+ }
+ dirtyOnScreenWidgets->clear();
+}
+
+static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
+{
+ Q_ASSERT(widget);
+ if (QApplication::closingDown())
+ return true;
+
+ if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
+ return true;
+
+ if (!widget->isVisible() || !widget->updatesEnabled())
+ return true;
+
+ return false;
+}
+
+/*!
+ Invalidates the buffer when the widget is resized.
+ Static areas are never invalidated unless absolutely needed.
+*/
+void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(!q->isWindow());
+ Q_ASSERT(q->parentWidget());
+
+ const bool staticContents = q->testAttribute(Qt::WA_StaticContents);
+ const bool sizeDecreased = (data.crect.width() < oldSize.width())
+ || (data.crect.height() < oldSize.height());
+
+ const QPoint offset(data.crect.x() - oldPos.x(), data.crect.y() - oldPos.y());
+ const bool parentAreaExposed = !offset.isNull() || sizeDecreased;
+ const QRect newWidgetRect(q->rect());
+ const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height());
+
+ if (!staticContents || graphicsEffect) {
+ QRegion staticChildren;
+ QWidgetBackingStore *bs = 0;
+ if (offset.isNull() && (bs = maybeBackingStore()))
+ staticChildren = bs->staticContents(q, oldWidgetRect);
+ const bool hasStaticChildren = !staticChildren.isEmpty();
+
+ if (hasStaticChildren) {
+ QRegion dirty(newWidgetRect);
+ dirty -= staticChildren;
+ invalidateBuffer(dirty);
+ } else {
+ // Entire widget needs repaint.
+ invalidateBuffer(newWidgetRect);
+ }
+
+ if (!parentAreaExposed)
+ return;
+
+ // Invalidate newly exposed area of the parent.
+ if (!graphicsEffect && extra && extra->hasMask) {
+ QRegion parentExpose(extra->mask.translated(oldPos));
+ parentExpose &= QRect(oldPos, oldSize);
+ if (hasStaticChildren)
+ parentExpose -= data.crect; // Offset is unchanged, safe to do this.
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ if (hasStaticChildren && !graphicsEffect) {
+ QRegion parentExpose(QRect(oldPos, oldSize));
+ parentExpose -= data.crect; // Offset is unchanged, safe to do this.
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
+ }
+ }
+ return;
+ }
+
+ // Move static content to its new position.
+ if (!offset.isNull()) {
+ if (sizeDecreased) {
+ const QSize minSize(qMin(oldSize.width(), data.crect.width()),
+ qMin(oldSize.height(), data.crect.height()));
+ moveRect(QRect(oldPos, minSize), offset.x(), offset.y());
+ } else {
+ moveRect(QRect(oldPos, oldSize), offset.x(), offset.y());
+ }
+ }
+
+ // Invalidate newly visible area of the widget.
+ if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {
+ QRegion newVisible(newWidgetRect);
+ newVisible -= oldWidgetRect;
+ invalidateBuffer(newVisible);
+ }
+
+ if (!parentAreaExposed)
+ return;
+
+ // Invalidate newly exposed area of the parent.
+ const QRect oldRect(oldPos, oldSize);
+ if (extra && extra->hasMask) {
+ QRegion parentExpose(oldRect);
+ parentExpose &= extra->mask.translated(oldPos);
+ parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ QRegion parentExpose(oldRect);
+ parentExpose -= data.crect;
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ }
+}
+
+/*!
+ Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e.
+ all widgets intersecting with the region will be repainted when the backing store
+ is synced.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
+{
+ Q_Q(QWidget);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty())
+ return;
+
+ QRegion wrgn(rgn);
+ wrgn &= clipRect();
+ if (!graphicsEffect && extra && extra->hasMask)
+ wrgn &= extra->mask;
+ if (wrgn.isEmpty())
+ return;
+
+ tlwExtra->backingStore->markDirty(wrgn, q, false, true);
+}
+
+/*!
+ This function is equivalent to calling invalidateBuffer(QRegion(rect), ...), but
+ is more efficient as it eliminates QRegion operations/allocations and can
+ use the rect more precisely for additional cut-offs.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetPrivate::invalidateBuffer(const QRect &rect)
+{
+ Q_Q(QWidget);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ if (discardInvalidateBufferRequest(q, tlwExtra) || rect.isEmpty())
+ return;
+
+ QRect wRect(rect);
+ wRect &= clipRect();
+ if (wRect.isEmpty())
+ return;
+
+ if (graphicsEffect || !extra || !extra->hasMask) {
+ tlwExtra->backingStore->markDirty(wRect, q, false, true);
+ return;
+ }
+
+ QRegion wRgn(extra->mask);
+ wRgn &= wRect;
+ if (wRgn.isEmpty())
+ return;
+
+ tlwExtra->backingStore->markDirty(wRgn, q, false, true);
+}
+
+void QWidgetPrivate::repaint_sys(const QRegion &rgn)
+{
+ if (data.in_destructor)
+ return;
+
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_StaticContents)) {
+ if (!extra)
+ createExtra();
+ extra->staticContentsSize = data.crect.size();
+ }
+
+#ifdef Q_WS_QPA //Dont even call q->p
+ QPaintEngine *engine = 0;
+#else
+ QPaintEngine *engine = q->paintEngine();
+#endif
+ // QGLWidget does not support partial updates if:
+ // 1) The context is double buffered
+ // 2) The context is single buffered and auto-fill background is enabled.
+ const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
+ || engine->type() == QPaintEngine::OpenGL2))
+ && (usesDoubleBufferedGLContext || q->autoFillBackground());
+ QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
+
+#ifdef Q_WS_MAC
+ // No difference between update() and repaint() on the Mac.
+ update_sys(toBePainted);
+ return;
+#endif
+
+ toBePainted &= clipRect();
+ clipToEffectiveMask(toBePainted);
+ if (toBePainted.isEmpty())
+ return; // Nothing to repaint.
+
+#ifndef QT_NO_PAINT_DEBUG
+ bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted);
+#endif
+
+ drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0);
+
+#ifndef QT_NO_PAINT_DEBUG
+ if (flushed)
+ QWidgetBackingStore::unflushPaint(q, toBePainted);
+#endif
+
+ if (!q->testAttribute(Qt::WA_PaintOutsidePaintEvent) && q->paintingActive())
+ qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qbackingstore_p.h b/src/widgets/kernel/qbackingstore_p.h
new file mode 100644
index 0000000000..05f4bfcb6c
--- /dev/null
+++ b/src/widgets/kernel/qbackingstore_p.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBACKINGSTORE_P_H
+#define QBACKINGSTORE_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 <QDebug>
+#include <QtGui/qwidget.h>
+#include <private/qwidget_p.h>
+#include <private/qwindowsurface_p.h>
+#ifdef Q_WS_QWS
+#include <private/qwindowsurface_qws_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QWindowSurface;
+
+struct BeginPaintInfo {
+ inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), windowSurfaceRecreated(0) {}
+ uint wasFlushed : 1;
+ uint nothingToPaint : 1;
+ uint windowSurfaceRecreated : 1;
+};
+
+class Q_AUTOTEST_EXPORT QWidgetBackingStore
+{
+public:
+ QWidgetBackingStore(QWidget *t);
+ ~QWidgetBackingStore();
+
+ static void showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool);
+
+ void sync(QWidget *exposedWidget, const QRegion &exposedRegion);
+ void sync();
+ void flush(QWidget *widget = 0, QWindowSurface *surface = 0);
+
+ inline QPoint topLevelOffset() const { return tlwOffset; }
+
+ QWindowSurface *surface() const { return windowSurface; }
+
+ inline bool isDirty() const
+ {
+ return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !hasDirtyFromPreviousSync
+ && !fullUpdatePending
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ && !hasDirtyWindowDecoration()
+#endif
+ );
+ }
+
+ // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+ void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false,
+ bool invalidateBuffer = false);
+ void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false,
+ bool invalidateBuffer = false);
+
+private:
+ QWidget *tlw;
+ QRegion dirtyOnScreen; // needsFlush
+ QRegion dirty; // needsRepaint
+ QRegion dirtyFromPreviousSync;
+ QVector<QWidget *> dirtyWidgets;
+ QVector<QWidget *> *dirtyOnScreenWidgets;
+ QList<QWidget *> staticWidgets;
+ QWindowSurface *windowSurface;
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QList<QWindowSurface*> subSurfaces;
+#endif
+ uint hasDirtyFromPreviousSync : 1;
+ uint fullUpdatePending : 1;
+
+ QPoint tlwOffset;
+
+ static bool flushPaint(QWidget *widget, const QRegion &rgn);
+ static void unflushPaint(QWidget *widget, const QRegion &rgn);
+
+ bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
+ void releaseBuffer();
+
+ void beginPaint(QRegion &toClean, QWidget *widget, QWindowSurface *windowSurface,
+ BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true);
+ void endPaint(const QRegion &cleaned, QWindowSurface *windowSurface, BeginPaintInfo *beginPaintInfo);
+
+ QRegion dirtyRegion(QWidget *widget = 0) const;
+ QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const;
+
+ void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset);
+
+ void removeDirtyWidget(QWidget *w);
+
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ bool hasDirtyWindowDecoration() const;
+ void paintWindowDecoration();
+#endif
+ void updateLists(QWidget *widget);
+
+ inline void addDirtyWidget(QWidget *widget, const QRegion &rgn)
+ {
+ if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) {
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (widgetPrivate->graphicsEffect)
+ widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect());
+ else
+#endif //QT_NO_GRAPHICSEFFECT
+ widgetPrivate->dirty = rgn;
+ dirtyWidgets.append(widget);
+ widgetPrivate->inDirtyList = true;
+ }
+ }
+
+ inline void dirtyWidgetsRemoveAll(QWidget *widget)
+ {
+ int i = 0;
+ while (i < dirtyWidgets.size()) {
+ if (dirtyWidgets.at(i) == widget)
+ dirtyWidgets.remove(i);
+ else
+ ++i;
+ }
+ }
+
+ inline void addStaticWidget(QWidget *widget)
+ {
+ if (!widget)
+ return;
+
+ Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents));
+ if (!staticWidgets.contains(widget))
+ staticWidgets.append(widget);
+ }
+
+ inline void removeStaticWidget(QWidget *widget)
+ { staticWidgets.removeAll(widget); }
+
+ // Move the reparented widget and all its static children from this backing store
+ // to the new backing store if reparented into another top-level / backing store.
+ inline void moveStaticWidgets(QWidget *reparented)
+ {
+ Q_ASSERT(reparented);
+ QWidgetBackingStore *newBs = reparented->d_func()->maybeBackingStore();
+ if (newBs == this)
+ return;
+
+ int i = 0;
+ while (i < staticWidgets.size()) {
+ QWidget *w = staticWidgets.at(i);
+ if (reparented == w || reparented->isAncestorOf(w)) {
+ staticWidgets.removeAt(i);
+ if (newBs)
+ newBs->addStaticWidget(w);
+ } else {
+ ++i;
+ }
+ }
+ }
+
+ inline QRect topLevelRect() const
+ {
+#ifdef Q_WS_QWS
+ return tlw->frameGeometry();
+#else
+ return tlw->data->crect;
+#endif
+ }
+
+ inline void appendDirtyOnScreenWidget(QWidget *widget)
+ {
+ if (!widget)
+ return;
+
+ if (!dirtyOnScreenWidgets) {
+ dirtyOnScreenWidgets = new QVector<QWidget *>;
+ dirtyOnScreenWidgets->append(widget);
+ } else if (!dirtyOnScreenWidgets->contains(widget)) {
+ dirtyOnScreenWidgets->append(widget);
+ }
+ }
+
+ inline void dirtyOnScreenWidgetsRemoveAll(QWidget *widget)
+ {
+ if (!widget || !dirtyOnScreenWidgets)
+ return;
+
+ int i = 0;
+ while (i < dirtyOnScreenWidgets->size()) {
+ if (dirtyOnScreenWidgets->at(i) == widget)
+ dirtyOnScreenWidgets->remove(i);
+ else
+ ++i;
+ }
+ }
+
+ inline void resetWidget(QWidget *widget)
+ {
+ if (widget) {
+ widget->d_func()->inDirtyList = false;
+ widget->d_func()->isScrolled = false;
+ widget->d_func()->isMoved = false;
+ widget->d_func()->dirty = QRegion();
+ }
+ }
+
+ inline void updateStaticContentsSize()
+ {
+ for (int i = 0; i < staticWidgets.size(); ++i) {
+ QWidgetPrivate *wd = staticWidgets.at(i)->d_func();
+ if (!wd->extra)
+ wd->createExtra();
+ wd->extra->staticContentsSize = wd->data.crect.size();
+ }
+ }
+
+ inline bool hasStaticContents() const
+ { return !staticWidgets.isEmpty() && windowSurface->hasFeature(QWindowSurface::StaticContents); }
+
+ friend QRegion qt_dirtyRegion(QWidget *);
+ friend class QWidgetPrivate;
+ friend class QWidget;
+ friend class QWSManagerPrivate;
+ friend class QETWidget;
+ friend class QWindowSurface;
+ friend class QWSWindowSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBACKINGSTORE_P_H
diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp
new file mode 100644
index 0000000000..6946f9bd27
--- /dev/null
+++ b/src/widgets/kernel/qboxlayout.cpp
@@ -0,0 +1,1550 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxlayout.h"
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qlist.h"
+#include "qsizepolicy.h"
+#include "qvector.h"
+
+#include "qlayoutengine_p.h"
+#include "qlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Returns true if the \a widget can be added to the \a layout;
+ otherwise returns false.
+*/
+static bool checkWidget(QLayout *layout, QWidget *widget)
+{
+ if (!widget) {
+ qWarning("QLayout: Cannot add null widget to %s/%s", layout->metaObject()->className(),
+ layout->objectName().toLocal8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+struct QBoxLayoutItem
+{
+ QBoxLayoutItem(QLayoutItem *it, int stretch_ = 0)
+ : item(it), stretch(stretch_), magic(false) { }
+ ~QBoxLayoutItem() { delete item; }
+
+ int hfw(int w) {
+ if (item->hasHeightForWidth()) {
+ return item->heightForWidth(w);
+ } else {
+ return item->sizeHint().height();
+ }
+ }
+ int mhfw(int w) {
+ if (item->hasHeightForWidth()) {
+ return item->heightForWidth(w);
+ } else {
+ return item->minimumSize().height();
+ }
+ }
+ int hStretch() {
+ if (stretch == 0 && item->widget()) {
+ return item->widget()->sizePolicy().horizontalStretch();
+ } else {
+ return stretch;
+ }
+ }
+ int vStretch() {
+ if (stretch == 0 && item->widget()) {
+ return item->widget()->sizePolicy().verticalStretch();
+ } else {
+ return stretch;
+ }
+ }
+
+ QLayoutItem *item;
+ int stretch;
+ bool magic;
+};
+
+class QBoxLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QBoxLayout)
+public:
+ QBoxLayoutPrivate() : hfwWidth(-1), dirty(true), spacing(-1) { }
+ ~QBoxLayoutPrivate();
+
+ void setDirty() {
+ geomArray.clear();
+ hfwWidth = -1;
+ hfwHeight = -1;
+ dirty = true;
+ }
+
+ QList<QBoxLayoutItem *> list;
+ QVector<QLayoutStruct> geomArray;
+ int hfwWidth;
+ int hfwHeight;
+ int hfwMinHeight;
+ QSize sizeHint;
+ QSize minSize;
+ QSize maxSize;
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ Qt::Orientations expanding;
+ uint hasHfw : 1;
+ uint dirty : 1;
+ QBoxLayout::Direction dir;
+ int spacing;
+
+ inline void deleteAll() { while (!list.isEmpty()) delete list.takeFirst(); }
+
+ void setupGeom();
+ void calcHfw(int);
+
+ void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
+};
+
+QBoxLayoutPrivate::~QBoxLayoutPrivate()
+{
+}
+
+static inline bool horz(QBoxLayout::Direction dir)
+{
+ return dir == QBoxLayout::RightToLeft || dir == QBoxLayout::LeftToRight;
+}
+
+/**
+ * The purpose of this function is to make sure that widgets are not laid out outside its layout.
+ * E.g. the layoutItemRect margins are only meant to take of the surrounding margins/spacings.
+ * However, if the margin is 0, it can easily cover the area of a widget above it.
+ */
+void QBoxLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const
+{
+ int l = leftMargin;
+ int t = topMargin;
+ int r = rightMargin;
+ int b = bottomMargin;
+#ifdef Q_WS_MAC
+ Q_Q(const QBoxLayout);
+ if (horz(dir)) {
+ QBoxLayoutItem *leftBox = 0;
+ QBoxLayoutItem *rightBox = 0;
+
+ if (left || right) {
+ leftBox = list.value(0);
+ rightBox = list.value(list.count() - 1);
+ if (dir == QBoxLayout::RightToLeft)
+ qSwap(leftBox, rightBox);
+
+ int leftDelta = 0;
+ int rightDelta = 0;
+ if (leftBox) {
+ QLayoutItem *itm = leftBox->item;
+ if (QWidget *w = itm->widget())
+ leftDelta = itm->geometry().left() - w->geometry().left();
+ }
+ if (rightBox) {
+ QLayoutItem *itm = rightBox->item;
+ if (QWidget *w = itm->widget())
+ rightDelta = w->geometry().right() - itm->geometry().right();
+ }
+ QWidget *w = q->parentWidget();
+ Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection();
+ if (layoutDirection == Qt::RightToLeft)
+ qSwap(leftDelta, rightDelta);
+
+ l = qMax(l, leftDelta);
+ r = qMax(r, rightDelta);
+ }
+
+ int count = top || bottom ? list.count() : 0;
+ for (int i = 0; i < count; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ QLayoutItem *itm = box->item;
+ QWidget *w = itm->widget();
+ if (w) {
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (top)
+ t = qMax(t, lir.top() - wr.top());
+ if (bottom)
+ b = qMax(b, wr.bottom() - lir.bottom());
+ }
+ }
+ } else { // vertical layout
+ QBoxLayoutItem *topBox = 0;
+ QBoxLayoutItem *bottomBox = 0;
+
+ if (top || bottom) {
+ topBox = list.value(0);
+ bottomBox = list.value(list.count() - 1);
+ if (dir == QBoxLayout::BottomToTop) {
+ qSwap(topBox, bottomBox);
+ }
+
+ if (top && topBox) {
+ QLayoutItem *itm = topBox->item;
+ QWidget *w = itm->widget();
+ if (w)
+ t = qMax(t, itm->geometry().top() - w->geometry().top());
+ }
+
+ if (bottom && bottomBox) {
+ QLayoutItem *itm = bottomBox->item;
+ QWidget *w = itm->widget();
+ if (w)
+ b = qMax(b, w->geometry().bottom() - itm->geometry().bottom());
+ }
+ }
+
+ int count = left || right ? list.count() : 0;
+ for (int i = 0; i < count; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ QLayoutItem *itm = box->item;
+ QWidget *w = itm->widget();
+ if (w) {
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (left)
+ l = qMax(l, lir.left() - wr.left());
+ if (right)
+ r = qMax(r, wr.right() - lir.right());
+ }
+ }
+ }
+#endif
+ if (left)
+ *left = l;
+ if (top)
+ *top = t;
+ if (right)
+ *right = r;
+ if (bottom)
+ *bottom = b;
+}
+
+
+/*
+ Initializes the data structure needed by qGeomCalc and
+ recalculates max/min and size hint.
+*/
+void QBoxLayoutPrivate::setupGeom()
+{
+ if (!dirty)
+ return;
+
+ Q_Q(QBoxLayout);
+ int maxw = horz(dir) ? 0 : QLAYOUTSIZE_MAX;
+ int maxh = horz(dir) ? QLAYOUTSIZE_MAX : 0;
+ int minw = 0;
+ int minh = 0;
+ int hintw = 0;
+ int hinth = 0;
+
+ bool horexp = false;
+ bool verexp = false;
+
+ hasHfw = false;
+
+ int n = list.count();
+ geomArray.clear();
+ QVector<QLayoutStruct> a(n);
+
+ QSizePolicy::ControlTypes controlTypes1;
+ QSizePolicy::ControlTypes controlTypes2;
+ int fixedSpacing = q->spacing();
+ int previousNonEmptyIndex = -1;
+
+ QStyle *style = 0;
+ if (fixedSpacing < 0) {
+ if (QWidget *parentWidget = q->parentWidget())
+ style = parentWidget->style();
+ }
+
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = list.at(i);
+ QSize max = box->item->maximumSize();
+ QSize min = box->item->minimumSize();
+ QSize hint = box->item->sizeHint();
+ Qt::Orientations exp = box->item->expandingDirections();
+ bool empty = box->item->isEmpty();
+ int spacing = 0;
+
+ if (!empty) {
+ if (fixedSpacing >= 0) {
+ spacing = (previousNonEmptyIndex >= 0) ? fixedSpacing : 0;
+#ifdef Q_WS_MAC
+ if (!horz(dir) && previousNonEmptyIndex >= 0) {
+ QBoxLayoutItem *sibling = (dir == QBoxLayout::TopToBottom ? box : list.at(previousNonEmptyIndex));
+ if (sibling) {
+ QWidget *wid = sibling->item->widget();
+ if (wid)
+ spacing = qMax(spacing, sibling->item->geometry().top() - wid->geometry().top());
+ }
+ }
+#endif
+ } else {
+ controlTypes1 = controlTypes2;
+ controlTypes2 = box->item->controlTypes();
+ if (previousNonEmptyIndex >= 0) {
+ QSizePolicy::ControlTypes actual1 = controlTypes1;
+ QSizePolicy::ControlTypes actual2 = controlTypes2;
+ if (dir == QBoxLayout::RightToLeft || dir == QBoxLayout::BottomToTop)
+ qSwap(actual1, actual2);
+
+ if (style) {
+ spacing = style->combinedLayoutSpacing(actual1, actual2,
+ horz(dir) ? Qt::Horizontal : Qt::Vertical,
+ 0, q->parentWidget());
+ if (spacing < 0)
+ spacing = 0;
+ }
+ }
+ }
+
+ if (previousNonEmptyIndex >= 0)
+ a[previousNonEmptyIndex].spacing = spacing;
+ previousNonEmptyIndex = i;
+ }
+
+ bool ignore = empty && box->item->widget(); // ignore hidden widgets
+ bool dummy = true;
+ if (horz(dir)) {
+ bool expand = (exp & Qt::Horizontal || box->stretch > 0);
+ horexp = horexp || expand;
+ maxw += spacing + max.width();
+ minw += spacing + min.width();
+ hintw += spacing + hint.width();
+ if (!ignore)
+ qMaxExpCalc(maxh, verexp, dummy,
+ max.height(), exp & Qt::Vertical, box->item->isEmpty());
+ minh = qMax(minh, min.height());
+ hinth = qMax(hinth, hint.height());
+
+ a[i].sizeHint = hint.width();
+ a[i].maximumSize = max.width();
+ a[i].minimumSize = min.width();
+ a[i].expansive = expand;
+ a[i].stretch = box->stretch ? box->stretch : box->hStretch();
+ } else {
+ bool expand = (exp & Qt::Vertical || box->stretch > 0);
+ verexp = verexp || expand;
+ maxh += spacing + max.height();
+ minh += spacing + min.height();
+ hinth += spacing + hint.height();
+ if (!ignore)
+ qMaxExpCalc(maxw, horexp, dummy,
+ max.width(), exp & Qt::Horizontal, box->item->isEmpty());
+ minw = qMax(minw, min.width());
+ hintw = qMax(hintw, hint.width());
+
+ a[i].sizeHint = hint.height();
+ a[i].maximumSize = max.height();
+ a[i].minimumSize = min.height();
+ a[i].expansive = expand;
+ a[i].stretch = box->stretch ? box->stretch : box->vStretch();
+ }
+
+ a[i].empty = empty;
+ a[i].spacing = 0; // might be be initialized with a non-zero value in a later iteration
+ hasHfw = hasHfw || box->item->hasHeightForWidth();
+ }
+
+ geomArray = a;
+
+ expanding = (Qt::Orientations)
+ ((horexp ? Qt::Horizontal : 0)
+ | (verexp ? Qt::Vertical : 0));
+
+ minSize = QSize(minw, minh);
+ maxSize = QSize(maxw, maxh).expandedTo(minSize);
+ sizeHint = QSize(hintw, hinth).expandedTo(minSize).boundedTo(maxSize);
+
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+ QSize extra(left + right, top + bottom);
+
+ minSize += extra;
+ maxSize += extra;
+ sizeHint += extra;
+
+ dirty = false;
+}
+
+/*
+ Calculates and stores the preferred height given the width \a w.
+*/
+void QBoxLayoutPrivate::calcHfw(int w)
+{
+ QVector<QLayoutStruct> &a = geomArray;
+ int n = a.count();
+ int h = 0;
+ int mh = 0;
+
+ Q_ASSERT(n == list.size());
+
+ if (horz(dir)) {
+ qGeomCalc(a, 0, n, 0, w);
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = list.at(i);
+ h = qMax(h, box->hfw(a.at(i).size));
+ mh = qMax(mh, box->mhfw(a.at(i).size));
+ }
+ } else {
+ for (int i = 0; i < n; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ int spacing = a.at(i).spacing;
+ h += box->hfw(w);
+ mh += box->mhfw(w);
+ h += spacing;
+ mh += spacing;
+ }
+ }
+ hfwWidth = w;
+ hfwHeight = h;
+ hfwMinHeight = mh;
+}
+
+
+/*!
+ \class QBoxLayout
+
+ \brief The QBoxLayout class lines up child widgets horizontally or
+ vertically.
+
+ \ingroup geomanagement
+
+ QBoxLayout takes the space it gets (from its parent layout or from
+ the parentWidget()), divides it up into a row of boxes, and makes
+ each managed widget fill one box.
+
+ \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ If the QBoxLayout's orientation is Qt::Horizontal the boxes are
+ placed in a row, with suitable sizes. Each widget (or other box)
+ will get at least its minimum size and at most its maximum size.
+ Any excess space is shared according to the stretch factors (more
+ about that below).
+
+ \image qvboxlayout-with-5-children.png Vertical box layout with five child widgets
+
+ If the QBoxLayout's orientation is Qt::Vertical, the boxes are
+ placed in a column, again with suitable sizes.
+
+ The easiest way to create a QBoxLayout is to use one of the
+ convenience classes, e.g. QHBoxLayout (for Qt::Horizontal boxes)
+ or QVBoxLayout (for Qt::Vertical boxes). You can also use the
+ QBoxLayout constructor directly, specifying its direction as
+ LeftToRight, RightToLeft, TopToBottom, or BottomToTop.
+
+ If the QBoxLayout is not the top-level layout (i.e. it is not
+ managing all of the widget's area and children), you must add it
+ to its parent layout before you can do anything with it. The
+ normal way to add a layout is by calling
+ parentLayout-\>addLayout().
+
+ Once you have done this, you can add boxes to the QBoxLayout using
+ one of four functions:
+
+ \list
+ \o addWidget() to add a widget to the QBoxLayout and set the
+ widget's stretch factor. (The stretch factor is along the row of
+ boxes.)
+
+ \o addSpacing() to create an empty box; this is one of the
+ functions you use to create nice and spacious dialogs. See below
+ for ways to set margins.
+
+ \o addStretch() to create an empty, stretchable box.
+
+ \o addLayout() to add a box containing another QLayout to the row
+ and set that layout's stretch factor.
+ \endlist
+
+ Use insertWidget(), insertSpacing(), insertStretch() or
+ insertLayout() to insert a box at a specified position in the
+ layout.
+
+ QBoxLayout also includes two margin widths:
+
+ \list
+ \o setContentsMargins() sets the width of the outer border on
+ each side of the widget. This is the width of the reserved space
+ along each of the QBoxLayout's four sides.
+ \o setSpacing() sets the width between neighboring boxes. (You
+ can use addSpacing() to get more space at a particular spot.)
+ \endlist
+
+ The margin default is provided by the style. The default margin
+ most Qt styles specify is 9 for child widgets and 11 for windows.
+ The spacing defaults to the same as the margin width for a
+ top-level layout, or to the same as the parent layout.
+
+ To remove a widget from a layout, call removeWidget(). Calling
+ QWidget::hide() on a widget also effectively removes the widget
+ from the layout until QWidget::show() is called.
+
+ You will almost always want to use QVBoxLayout and QHBoxLayout
+ rather than QBoxLayout because of their convenient constructors.
+
+ \sa QGridLayout, QStackedLayout, {Layout Management}
+*/
+
+/*!
+ \enum QBoxLayout::Direction
+
+ This type is used to determine the direction of a box layout.
+
+ \value LeftToRight Horizontal from left to right.
+ \value RightToLeft Horizontal from right to left.
+ \value TopToBottom Vertical from top to bottom.
+ \value BottomToTop Vertical from bottom to top.
+
+ \omitvalue Down
+ \omitvalue Up
+*/
+
+/*!
+ Constructs a new QBoxLayout with direction \a dir and parent widget \a
+ parent.
+
+ \sa direction()
+*/
+QBoxLayout::QBoxLayout(Direction dir, QWidget *parent)
+ : QLayout(*new QBoxLayoutPrivate, 0, parent)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new QBoxLayout with direction \a dir and main widget \a
+ parent. \a parent may not be 0.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+
+ \a name is the internal object name.
+
+ \sa direction()
+*/
+QBoxLayout::QBoxLayout(QWidget *parent, Direction dir,
+ int margin, int spacing, const char *name)
+ : QLayout(*new QBoxLayoutPrivate, 0, parent)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setMargin(margin);
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing<0 ? margin : spacing);
+}
+
+/*!
+ Constructs a new QBoxLayout called \a name, with direction \a dir,
+ and inserts it into \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, the layout will inherit its
+ parent's spacing().
+*/
+QBoxLayout::QBoxLayout(QLayout *parentLayout, Direction dir, int spacing,
+ const char *name)
+ : QLayout(*new QBoxLayoutPrivate, parentLayout, 0)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing);
+}
+
+/*!
+ Constructs a new QBoxLayout called \a name, with direction \a dir.
+
+ If \a spacing is -1, the layout will inherit its parent's
+ spacing(); otherwise \a spacing is used.
+
+ You must insert this box into another layout.
+*/
+QBoxLayout::QBoxLayout(Direction dir, int spacing, const char *name)
+ : QLayout(*new QBoxLayoutPrivate,0, 0)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing);
+}
+#endif // QT3_SUPPORT
+
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QBoxLayout::~QBoxLayout()
+{
+ Q_D(QBoxLayout);
+ d->deleteAll(); // must do it before QObject deletes children, so can't be in ~QBoxLayoutPrivate
+}
+
+/*!
+ Reimplements QLayout::spacing(). If the spacing property is
+ valid, that value is returned. Otherwise, a value for the spacing
+ property is computed and returned. Since layout spacing in a widget
+ is style dependent, if the parent is a widget, it queries the style
+ for the (horizontal or vertical) spacing of the layout. Otherwise,
+ the parent is a layout, and it queries the parent layout for the
+ spacing().
+
+ \sa QLayout::spacing(), setSpacing()
+ */
+int QBoxLayout::spacing() const
+{
+ Q_D(const QBoxLayout);
+ if (d->spacing >=0) {
+ return d->spacing;
+ } else {
+ return qSmartSpacing(this, d->dir == LeftToRight || d->dir == RightToLeft
+ ? QStyle::PM_LayoutHorizontalSpacing
+ : QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ Reimplements QLayout::setSpacing(). Sets the spacing
+ property to \a spacing.
+
+ \sa QLayout::setSpacing(), spacing()
+ */
+void QBoxLayout::setSpacing(int spacing)
+{
+ Q_D(QBoxLayout);
+ d->spacing = spacing;
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::sizeHint() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->sizeHint;
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::minimumSize() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->minSize;
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::maximumSize() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+
+ QSize s = d->maxSize.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
+
+ if (alignment() & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (alignment() & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+/*!
+ \reimp
+*/
+bool QBoxLayout::hasHeightForWidth() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->hasHfw;
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::heightForWidth(int w) const
+{
+ Q_D(const QBoxLayout);
+ if (!hasHeightForWidth())
+ return -1;
+
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+
+ w -= left + right;
+ if (w != d->hfwWidth)
+ const_cast<QBoxLayout*>(this)->d_func()->calcHfw(w);
+
+ return d->hfwHeight + top + bottom;
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::minimumHeightForWidth(int w) const
+{
+ Q_D(const QBoxLayout);
+ (void) heightForWidth(w);
+ int top, bottom;
+ d->effectiveMargins(0, &top, 0, &bottom);
+ return d->hasHfw ? (d->hfwMinHeight + top + bottom) : -1;
+}
+
+/*!
+ Resets cached information.
+*/
+void QBoxLayout::invalidate()
+{
+ Q_D(QBoxLayout);
+ d->setDirty();
+ QLayout::invalidate();
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::count() const
+{
+ Q_D(const QBoxLayout);
+ return d->list.count();
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QBoxLayout::itemAt(int index) const
+{
+ Q_D(const QBoxLayout);
+ return index >= 0 && index < d->list.count() ? d->list.at(index)->item : 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QBoxLayout::takeAt(int index)
+{
+ Q_D(QBoxLayout);
+ if (index < 0 || index >= d->list.count())
+ return 0;
+ QBoxLayoutItem *b = d->list.takeAt(index);
+ QLayoutItem *item = b->item;
+ b->item = 0;
+ delete b;
+
+ invalidate();
+ return item;
+}
+
+
+/*!
+ \reimp
+*/
+Qt::Orientations QBoxLayout::expandingDirections() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->expanding;
+}
+
+/*!
+ \reimp
+*/
+void QBoxLayout::setGeometry(const QRect &r)
+{
+ Q_D(QBoxLayout);
+ if (d->dirty || r != geometry()) {
+ QRect oldRect = geometry();
+ QLayout::setGeometry(r);
+ if (d->dirty)
+ d->setupGeom();
+ QRect cr = alignment() ? alignmentRect(r) : r;
+
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ QRect s(cr.x() + left, cr.y() + top,
+ cr.width() - (left + right),
+ cr.height() - (top + bottom));
+
+ QVector<QLayoutStruct> a = d->geomArray;
+ int pos = horz(d->dir) ? s.x() : s.y();
+ int space = horz(d->dir) ? s.width() : s.height();
+ int n = a.count();
+ if (d->hasHfw && !horz(d->dir)) {
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->hasHeightForWidth()) {
+ int width = qBound(box->item->minimumSize().width(), s.width(), box->item->maximumSize().width());
+ a[i].sizeHint = a[i].minimumSize =
+ box->item->heightForWidth(width);
+ }
+ }
+ }
+
+ Direction visualDir = d->dir;
+ QWidget *parent = parentWidget();
+ if (parent && parent->isRightToLeft()) {
+ if (d->dir == LeftToRight)
+ visualDir = RightToLeft;
+ else if (d->dir == RightToLeft)
+ visualDir = LeftToRight;
+ }
+
+ qGeomCalc(a, 0, n, pos, space);
+
+ bool reverse = (horz(visualDir)
+ ? ((r.right() > oldRect.right()) != (visualDir == RightToLeft))
+ : r.bottom() > oldRect.bottom());
+ for (int j = 0; j < n; j++) {
+ int i = reverse ? n-j-1 : j;
+ QBoxLayoutItem *box = d->list.at(i);
+
+ switch (visualDir) {
+ case LeftToRight:
+ box->item->setGeometry(QRect(a.at(i).pos, s.y(), a.at(i).size, s.height()));
+ break;
+ case RightToLeft:
+ box->item->setGeometry(QRect(s.left() + s.right() - a.at(i).pos - a.at(i).size + 1,
+ s.y(), a.at(i).size, s.height()));
+ break;
+ case TopToBottom:
+ box->item->setGeometry(QRect(s.x(), a.at(i).pos, s.width(), a.at(i).size));
+ break;
+ case BottomToTop:
+ box->item->setGeometry(QRect(s.x(),
+ s.top() + s.bottom() - a.at(i).pos - a.at(i).size + 1,
+ s.width(), a.at(i).size));
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QBoxLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QBoxLayout);
+ QBoxLayoutItem *it = new QBoxLayoutItem(item);
+ d->list.append(it);
+ invalidate();
+}
+
+/*!
+ Inserts \a item into this box layout at position \a index. If \a
+ index is negative, the item is added at the end.
+
+ \sa addItem(), insertWidget(), insertLayout(), insertStretch(),
+ insertSpacing()
+*/
+void QBoxLayout::insertItem(int index, QLayoutItem *item)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(item);
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts a non-stretchable space (a QSpacerItem) at position \a index, with
+ size \a size. If \a index is negative the space is added at the end.
+
+ The box layout has default margin and spacing. This function adds
+ additional space.
+
+ \sa addSpacing(), insertItem(), QSpacerItem
+*/
+void QBoxLayout::insertSpacing(int index, int size)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ QT_TRY {
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.insert(index, it);
+
+ } QT_CATCH(...) {
+ delete b;
+ QT_RETHROW;
+ }
+ invalidate();
+}
+
+/*!
+ Inserts a stretchable space (a QSpacerItem) at position \a
+ index, with zero minimum size and stretch factor \a stretch. If \a
+ index is negative the space is added at the end.
+
+ \sa addStretch(), insertItem(), QSpacerItem
+*/
+void QBoxLayout::insertStretch(int index, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
+ it->magic = true;
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ \since 4.4
+
+ Inserts \a spacerItem at position \a index, with zero minimum
+ size and stretch factor. If \a index is negative the
+ space is added at the end.
+
+ \sa addSpacerItem(), insertStretch(), insertSpacing()
+*/
+void QBoxLayout::insertSpacerItem(int index, QSpacerItem *spacerItem)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(spacerItem);
+ it->magic = true;
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts \a layout at position \a index, with stretch factor \a
+ stretch. If \a index is negative, the layout is added at the end.
+
+ \a layout becomes a child of the box layout.
+
+ \sa addLayout(), insertItem()
+*/
+void QBoxLayout::insertLayout(int index, QLayout *layout, int stretch)
+{
+ Q_D(QBoxLayout);
+ addChildLayout(layout);
+ if (index < 0) // append
+ index = d->list.count();
+ QBoxLayoutItem *it = new QBoxLayoutItem(layout, stretch);
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts \a widget at position \a index, with stretch factor \a
+ stretch and alignment \a alignment. If \a index is negative, the
+ widget is added at the end.
+
+ The stretch factor applies only in the \l{direction()}{direction}
+ of the QBoxLayout, and is relative to the other boxes and widgets
+ in this QBoxLayout. Widgets and boxes with higher stretch factors
+ grow more.
+
+ If the stretch factor is 0 and nothing else in the QBoxLayout has
+ a stretch factor greater than zero, the space is distributed
+ according to the QWidget:sizePolicy() of each widget that's
+ involved.
+
+ The alignment is specified by \a alignment. The default alignment
+ is 0, which means that the widget fills the entire cell.
+
+ \sa addWidget(), insertItem()
+*/
+void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
+ Qt::Alignment alignment)
+{
+ Q_D(QBoxLayout);
+ if (!checkWidget(this, widget))
+ return;
+ addChildWidget(widget);
+ if (index < 0) // append
+ index = d->list.count();
+ QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
+ b->setAlignment(alignment);
+
+ QBoxLayoutItem *it;
+ QT_TRY{
+ it = new QBoxLayoutItem(b, stretch);
+ } QT_CATCH(...) {
+ delete b;
+ QT_RETHROW;
+ }
+
+ QT_TRY{
+ d->list.insert(index, it);
+ } QT_CATCH(...) {
+ delete it;
+ QT_RETHROW;
+ }
+ invalidate();
+}
+
+/*!
+ Adds a non-stretchable space (a QSpacerItem) with size \a size
+ to the end of this box layout. QBoxLayout provides default margin
+ and spacing. This function adds additional space.
+
+ \sa insertSpacing(), addItem(), QSpacerItem
+*/
+void QBoxLayout::addSpacing(int size)
+{
+ insertSpacing(-1, size);
+}
+
+/*!
+ Adds a stretchable space (a QSpacerItem) with zero minimum
+ size and stretch factor \a stretch to the end of this box layout.
+
+ \sa insertStretch(), addItem(), QSpacerItem
+*/
+void QBoxLayout::addStretch(int stretch)
+{
+ insertStretch(-1, stretch);
+}
+
+/*!
+ \since 4.4
+
+ Adds \a spacerItem to the end of this box layout.
+
+ \sa addSpacing(), addStretch()
+*/
+void QBoxLayout::addSpacerItem(QSpacerItem *spacerItem)
+{
+ insertSpacerItem(-1, spacerItem);
+}
+
+/*!
+ Adds \a widget to the end of this box layout, with a stretch
+ factor of \a stretch and alignment \a alignment.
+
+ The stretch factor applies only in the \l{direction()}{direction}
+ of the QBoxLayout, and is relative to the other boxes and widgets
+ in this QBoxLayout. Widgets and boxes with higher stretch factors
+ grow more.
+
+ If the stretch factor is 0 and nothing else in the QBoxLayout has
+ a stretch factor greater than zero, the space is distributed
+ according to the QWidget:sizePolicy() of each widget that's
+ involved.
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+ \sa insertWidget(), addItem(), addLayout(), addStretch(),
+ addSpacing(), addStrut()
+*/
+void QBoxLayout::addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
+{
+ insertWidget(-1, widget, stretch, alignment);
+}
+
+/*!
+ Adds \a layout to the end of the box, with serial stretch factor
+ \a stretch.
+
+ \sa insertLayout(), addItem(), addWidget()
+*/
+void QBoxLayout::addLayout(QLayout *layout, int stretch)
+{
+ insertLayout(-1, layout, stretch);
+}
+
+/*!
+ Limits the perpendicular dimension of the box (e.g. height if the
+ box is \l LeftToRight) to a minimum of \a size. Other constraints
+ may increase the limit.
+
+ \sa addItem()
+*/
+void QBoxLayout::addStrut(int size)
+{
+ Q_D(QBoxLayout);
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.append(it);
+ invalidate();
+}
+
+/*!
+ \fn int QBoxLayout::findWidget(QWidget *widget)
+
+ Use indexOf(\a widget) instead.
+*/
+
+/*!
+ Sets the stretch factor for \a widget to \a stretch and returns
+ true if \a widget is found in this layout (not including child
+ layouts); otherwise returns false.
+
+ \sa setAlignment()
+*/
+bool QBoxLayout::setStretchFactor(QWidget *widget, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (!widget)
+ return false;
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->widget() == widget) {
+ box->stretch = stretch;
+ invalidate();
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets the stretch factor for the layout \a layout to \a stretch and
+ returns true if \a layout is found in this layout (not including
+ child layouts); otherwise returns false.
+*/
+bool QBoxLayout::setStretchFactor(QLayout *layout, int stretch)
+{
+ Q_D(QBoxLayout);
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->layout() == layout) {
+ if (box->stretch != stretch) {
+ box->stretch = stretch;
+ invalidate();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ Sets the stretch factor at position \a index. to \a stretch.
+
+ \since 4.5
+*/
+
+void QBoxLayout::setStretch(int index, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (index >= 0 && index < d->list.size()) {
+ QBoxLayoutItem *box = d->list.at(index);
+ if (box->stretch != stretch) {
+ box->stretch = stretch;
+ invalidate();
+ }
+ }
+}
+
+/*!
+ Returns the stretch factor at position \a index.
+
+ \since 4.5
+*/
+
+int QBoxLayout::stretch(int index) const
+{
+ Q_D(const QBoxLayout);
+ if (index >= 0 && index < d->list.size())
+ return d->list.at(index)->stretch;
+ return -1;
+}
+
+/*!
+ Sets the direction of this layout to \a direction.
+*/
+void QBoxLayout::setDirection(Direction direction)
+{
+ Q_D(QBoxLayout);
+ if (d->dir == direction)
+ return;
+ if (horz(d->dir) != horz(direction)) {
+ //swap around the spacers (the "magic" bits)
+ //#### a bit yucky, knows too much.
+ //#### probably best to add access functions to spacerItem
+ //#### or even a QSpacerItem::flip()
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->magic) {
+ QSpacerItem *sp = box->item->spacerItem();
+ if (sp) {
+ if (sp->expandingDirections() == Qt::Orientations(0) /*No Direction*/) {
+ //spacing or strut
+ QSize s = sp->sizeHint();
+ sp->changeSize(s.height(), s.width(),
+ horz(direction) ? QSizePolicy::Fixed:QSizePolicy::Minimum,
+ horz(direction) ? QSizePolicy::Minimum:QSizePolicy::Fixed);
+
+ } else {
+ //stretch
+ if (horz(direction))
+ sp->changeSize(0, 0, QSizePolicy::Expanding,
+ QSizePolicy::Minimum);
+ else
+ sp->changeSize(0, 0, QSizePolicy::Minimum,
+ QSizePolicy::Expanding);
+ }
+ }
+ }
+ }
+ }
+ d->dir = direction;
+ invalidate();
+}
+
+/*!
+ \fn QBoxLayout::Direction QBoxLayout::direction() const
+
+ Returns the direction of the box. addWidget() and addSpacing()
+ work in this direction; the stretch stretches in this direction.
+
+ \sa QBoxLayout::Direction addWidget() addSpacing()
+*/
+
+QBoxLayout::Direction QBoxLayout::direction() const
+{
+ Q_D(const QBoxLayout);
+ return d->dir;
+}
+
+/*!
+ \class QHBoxLayout
+ \brief The QHBoxLayout class lines up widgets horizontally.
+
+ \ingroup geomanagement
+
+ This class is used to construct horizontal box layout objects. See
+ QBoxLayout for details.
+
+ The simplest use of the class is like this:
+
+ \snippet doc/src/snippets/layouts/layouts.cpp 0
+ \snippet doc/src/snippets/layouts/layouts.cpp 1
+ \snippet doc/src/snippets/layouts/layouts.cpp 2
+ \codeline
+ \snippet doc/src/snippets/layouts/layouts.cpp 3
+ \snippet doc/src/snippets/layouts/layouts.cpp 4
+ \snippet doc/src/snippets/layouts/layouts.cpp 5
+
+ First, we create the widgets we want in the layout. Then, we
+ create the QHBoxLayout object and add the widgets into the
+ layout. Finally, we call QWidget::setLayout() to install the
+ QHBoxLayout object onto the widget. At that point, the widgets in
+ the layout are reparented to have \c window as their parent.
+
+ \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
+*/
+
+
+/*!
+ Constructs a new top-level horizontal box with
+ parent \a parent.
+*/
+QHBoxLayout::QHBoxLayout(QWidget *parent)
+ : QBoxLayout(LeftToRight, parent)
+{
+}
+
+/*!
+ Constructs a new horizontal box. You must add
+ it to another layout.
+*/
+QHBoxLayout::QHBoxLayout()
+ : QBoxLayout(LeftToRight)
+{
+}
+
+
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level horizontal box called \a name, with
+ parent \a parent.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+*/
+QHBoxLayout::QHBoxLayout(QWidget *parent, int margin,
+ int spacing, const char *name)
+ : QBoxLayout(LeftToRight, parent)
+{
+ setMargin(margin);
+ setSpacing(spacing<0 ? margin : spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ Constructs a new horizontal box called name \a name and adds it to
+ \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QHBoxLayout will inherit its
+ parent's spacing().
+*/
+QHBoxLayout::QHBoxLayout(QLayout *parentLayout, int spacing,
+ const char *name)
+ : QBoxLayout(LeftToRight)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+ if (parentLayout) {
+ setParent(parentLayout);
+ parentLayout->addItem(this);
+ }
+}
+
+/*!
+ Constructs a new horizontal box called name \a name. You must add
+ it to another layout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QHBoxLayout will inherit its
+ parent's spacing().
+*/
+QHBoxLayout::QHBoxLayout(int spacing, const char *name)
+ : QBoxLayout(LeftToRight)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QHBoxLayout::~QHBoxLayout()
+{
+}
+
+/*!
+ \class QVBoxLayout
+ \brief The QVBoxLayout class lines up widgets vertically.
+
+ \ingroup geomanagement
+
+ This class is used to construct vertical box layout objects. See
+ QBoxLayout for details.
+
+ The simplest use of the class is like this:
+
+ \snippet doc/src/snippets/layouts/layouts.cpp 6
+ \snippet doc/src/snippets/layouts/layouts.cpp 7
+ \snippet doc/src/snippets/layouts/layouts.cpp 8
+ \codeline
+ \snippet doc/src/snippets/layouts/layouts.cpp 9
+ \snippet doc/src/snippets/layouts/layouts.cpp 10
+ \snippet doc/src/snippets/layouts/layouts.cpp 11
+
+ First, we create the widgets we want in the layout. Then, we
+ create the QVBoxLayout object and add the widgets into the
+ layout. Finally, we call QWidget::setLayout() to install the
+ QVBoxLayout object onto the widget. At that point, the widgets in
+ the layout are reparented to have \c window as their parent.
+
+ \image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
+*/
+
+/*!
+ Constructs a new top-level vertical box with
+ parent \a parent.
+*/
+QVBoxLayout::QVBoxLayout(QWidget *parent)
+ : QBoxLayout(TopToBottom, parent)
+{
+}
+
+/*!
+ Constructs a new vertical box. You must add
+ it to another layout.
+
+*/
+QVBoxLayout::QVBoxLayout()
+ : QBoxLayout(TopToBottom)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level vertical box called \a name, with
+ parent \a parent.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+*/
+QVBoxLayout::QVBoxLayout(QWidget *parent, int margin, int spacing,
+ const char *name)
+ : QBoxLayout(TopToBottom, parent)
+{
+ setMargin(margin);
+ setSpacing(spacing<0 ? margin : spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ Constructs a new vertical box called name \a name and adds it to
+ \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QVBoxLayout will inherit its
+ parent's spacing().
+*/
+QVBoxLayout::QVBoxLayout(QLayout *parentLayout, int spacing,
+ const char *name)
+ : QBoxLayout(TopToBottom)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+ if (parentLayout) {
+ setParent(parentLayout);
+ parentLayout->addItem(this);
+ }
+}
+
+/*!
+ Constructs a new vertical box called name \a name. You must add
+ it to another layout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QVBoxLayout will inherit its
+ parent's spacing().
+*/
+QVBoxLayout::QVBoxLayout(int spacing, const char *name)
+ : QBoxLayout(TopToBottom)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+
+#endif
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QVBoxLayout::~QVBoxLayout()
+{
+}
+
+/*!
+ \fn QWidget *QLayout::mainWidget() const
+
+ Use parentWidget() instead.
+*/
+
+/*!
+ \fn void QLayout::remove(QWidget *widget)
+
+ Use removeWidget(\a widget) instead.
+*/
+
+/*!
+ \fn void QLayout::add(QWidget *widget)
+
+ Use addWidget(\a widget) instead.
+*/
+
+/*!
+ \fn QLayoutIterator QLayout::iterator()
+
+ Use a QLayoutIterator() constructor instead.
+*/
+
+/*!
+ \fn int QLayout::defaultBorder() const
+
+ Use spacing() instead.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qboxlayout.h b/src/widgets/kernel/qboxlayout.h
new file mode 100644
index 0000000000..66ce23a9f5
--- /dev/null
+++ b/src/widgets/kernel/qboxlayout.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXLAYOUT_H
+#define QBOXLAYOUT_H
+
+#include <QtGui/qlayout.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qwidget.h>
+#endif
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QBoxLayoutPrivate;
+
+class Q_GUI_EXPORT QBoxLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QBoxLayout)
+public:
+ enum Direction { LeftToRight, RightToLeft, TopToBottom, BottomToTop,
+ Down = TopToBottom, Up = BottomToTop };
+
+ explicit QBoxLayout(Direction, QWidget *parent = 0);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(QWidget *parent, Direction, int border = 0, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(QLayout *parentLayout, Direction, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(Direction, int spacing, const char *name = 0);
+#endif
+ ~QBoxLayout();
+
+ Direction direction() const;
+ void setDirection(Direction);
+
+ void addSpacing(int size);
+ void addStretch(int stretch = 0);
+ void addSpacerItem(QSpacerItem *spacerItem);
+ void addWidget(QWidget *, int stretch = 0, Qt::Alignment alignment = 0);
+ void addLayout(QLayout *layout, int stretch = 0);
+ void addStrut(int);
+ void addItem(QLayoutItem *);
+
+ void insertSpacing(int index, int size);
+ void insertStretch(int index, int stretch = 0);
+ void insertSpacerItem(int index, QSpacerItem *spacerItem);
+ void insertWidget(int index, QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0);
+ void insertLayout(int index, QLayout *layout, int stretch = 0);
+
+ int spacing() const;
+ void setSpacing(int spacing);
+
+ bool setStretchFactor(QWidget *w, int stretch);
+ bool setStretchFactor(QLayout *l, int stretch);
+ void setStretch(int index, int stretch);
+ int stretch(int index) const;
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int minimumHeightForWidth(int) const;
+
+ Qt::Orientations expandingDirections() const;
+ void invalidate();
+ QLayoutItem *itemAt(int) const;
+ QLayoutItem *takeAt(int);
+ int count() const;
+ void setGeometry(const QRect&);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT int findWidget(QWidget* w) {return indexOf(w);}
+#endif
+protected:
+ // ### Qt 5: make public
+ void insertItem(int index, QLayoutItem *);
+
+private:
+ Q_DISABLE_COPY(QBoxLayout)
+};
+
+class Q_GUI_EXPORT QHBoxLayout : public QBoxLayout
+{
+ Q_OBJECT
+public:
+ QHBoxLayout();
+ explicit QHBoxLayout(QWidget *parent);
+ ~QHBoxLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(QWidget *parent, int border,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(QLayout *parentLayout,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(int spacing, const char *name = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QHBoxLayout)
+};
+
+class Q_GUI_EXPORT QVBoxLayout : public QBoxLayout
+{
+ Q_OBJECT
+public:
+ QVBoxLayout();
+ explicit QVBoxLayout(QWidget *parent);
+ ~QVBoxLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(QWidget *parent, int border,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(QLayout *parentLayout,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(int spacing, const char *name = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QVBoxLayout)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBOXLAYOUT_H
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
new file mode 100644
index 0000000000..6e1414dc5d
--- /dev/null
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+#include "qdesktopwidget.h"
+#include "qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
+{
+ if (!widget) {
+ qWarning("QDesktopWidget::screenGeometry(): Attempt "
+ "to get the screen geometry of a null widget");
+ return QRect();
+ }
+ QRect rect = QWidgetPrivate::screenGeometry(widget);
+ if (rect.isNull())
+ return screenGeometry(screenNumber(widget));
+ else return rect;
+}
+
+const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
+{
+ if (!widget) {
+ qWarning("QDesktopWidget::availableGeometry(): Attempt "
+ "to get the available geometry of a null widget");
+ return QRect();
+ }
+ QRect rect = QWidgetPrivate::screenGeometry(widget);
+ if (rect.isNull())
+ return availableGeometry(screenNumber(widget));
+ else
+ return rect;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h
new file mode 100644
index 0000000000..deb896029a
--- /dev/null
+++ b/src/widgets/kernel/qdesktopwidget.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESKTOPWIDGET_H
+#define QDESKTOPWIDGET_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QApplication;
+class QDesktopWidgetPrivate;
+
+class Q_GUI_EXPORT QDesktopWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(bool virtualDesktop READ isVirtualDesktop)
+ Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged)
+ Q_PROPERTY(int primaryScreen READ primaryScreen)
+public:
+ QDesktopWidget();
+ ~QDesktopWidget();
+
+ bool isVirtualDesktop() const;
+
+ int numScreens() const;
+ int screenCount() const;
+ int primaryScreen() const;
+
+ int screenNumber(const QWidget *widget = 0) const;
+ int screenNumber(const QPoint &) const;
+
+ QWidget *screen(int screen = -1);
+
+ const QRect screenGeometry(int screen = -1) const;
+ const QRect screenGeometry(const QWidget *widget) const;
+ const QRect screenGeometry(const QPoint &point) const
+ { return screenGeometry(screenNumber(point)); }
+
+ const QRect availableGeometry(int screen = -1) const;
+ const QRect availableGeometry(const QWidget *widget) const;
+ const QRect availableGeometry(const QPoint &point) const
+ { return availableGeometry(screenNumber(point)); }
+
+Q_SIGNALS:
+ void resized(int);
+ void workAreaResized(int);
+ void screenCountChanged(int);
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+
+private:
+ Q_DISABLE_COPY(QDesktopWidget)
+ Q_DECLARE_PRIVATE(QDesktopWidget)
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+};
+
+inline int QDesktopWidget::screenCount() const
+{ return numScreens(); }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDESKTOPWIDGET_H
diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc
new file mode 100644
index 0000000000..a79a098d74
--- /dev/null
+++ b/src/widgets/kernel/qdesktopwidget.qdoc
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesktopWidget
+ \brief The QDesktopWidget class provides access to screen information on multi-head systems.
+
+ \ingroup advanced
+ \ingroup desktop
+
+ Systems with more than one graphics card and monitor can manage the
+ physical screen space available either as multiple desktops, or as a
+ large virtual desktop.
+
+ This class provides information about the user's desktop, such as its
+ total size, number of screens, the geometry of each screen, and whether
+ they are configured as separate desktops or a single virtual desktop.
+
+ Widgets provided by Qt use this class to place tooltips, menus and
+ dialog boxes on the correct screen for their parent or application
+ widgets. Applications can use this class to obtain information that
+ can be used to save window positions, or to place child widgets and
+ dialogs on one particular screen.
+
+ \section1 Obtaining a Desktop Widget
+
+ The QApplication::desktop() function is used to get an instance of
+ QDesktopWidget.
+
+ The widget's screenGeometry() function provides information about the
+ geometry of the available screens with. The number of screens
+ available is returned by screenCount, and the screenCountChanged()
+ signal is emitted when screens are added or removed.
+ The screen number that a particular point or widget is located in
+ is returned by screenNumber().
+
+ \section1 Screen Geometry
+
+ To obtain the dimensions of a particular screen, call the screenGeometry()
+ function. On some desktop environments, not all of the screen is
+ available for applications to use; for example, an application dock or
+ menu bar may take up some space. Use the availableGeometry() function
+ to obtain the available area for applications.
+
+ QDesktopWidget also inherits the QWidget properties, width() and
+ height(), which specify the size of the desktop. However, for
+ desktops with multiple screens, the size of the desktop is the union
+ of all the screen sizes, so width() and height() should \e not be
+ used for computing the size of a widget to be placed on one of the
+ screens.
+
+ On systems that are configured to use the available screens as a
+ single, large virtual desktop, the virtualDesktop property will be
+ set to true. In this case, the widget's size is usually the size of
+ the bounding rectangle of all the screens.
+
+ \section1 Use of the Primary Screen
+
+ For an application, the screen where the main widget resides is the
+ primary screen. This is stored in the primaryScreen property.
+ All windows opened in the context of the application should be
+ constrained to the boundaries of the primary screen; for example,
+ it would be inconvenient if a dialog box popped up on a different
+ screen, or split over two screens.
+
+ \image qdesktopwidget.png Managing Multiple Screens
+
+ In the illustration above, Application One's primary screen is
+ screen 0, and App Two's primary screen is screen 1.
+
+ \sa QApplication, QApplication::desktop(), QX11Info::appRootWindow()
+*/
+
+/*!
+ \fn QDesktopWidget::QDesktopWidget()
+
+ \internal
+
+ Creates the desktop widget.
+
+ If the system supports a virtual desktop, this widget will have
+ the size of the virtual desktop; otherwise this widget will have
+ the size of the primary screen.
+
+ Instead of using QDesktopWidget directly, use QApplication::desktop().
+*/
+
+/*!
+ \fn QDesktopWidget::~QDesktopWidget()
+
+ \internal
+
+ Destroys the desktop widget and frees any allocated resources.
+*/
+
+/*!
+ \fn int QDesktopWidget::numScreens() const
+
+ Returns the number of available screens.
+
+ \obsolete
+
+ This function is deprecated. Use screenCount instead.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn QWidget *QDesktopWidget::screen(int screen)
+
+ Returns a widget that represents the screen with index \a screen
+ (a value of -1 means the default screen).
+
+ If the system uses a virtual desktop, the returned widget will
+ have the geometry of the entire virtual desktop; i.e., bounding
+ every \a screen.
+
+ \sa primaryScreen, screenCount, virtualDesktop
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(int screen) const
+
+ Returns the available geometry of the screen with index \a screen. What
+ is available will be subrect of screenGeometry() based on what the
+ platform decides is available (for example excludes the dock and menu bar
+ on Mac OS X, or the task bar on Windows). The default screen is used if
+ \a screen is -1.
+
+ \sa screenNumber(), screenGeometry()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
+ \overload
+
+ Returns the available geometry of the screen which contains \a widget.
+
+ \sa screenGeometry()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(const QPoint &p) const
+ \overload
+
+ Returns the available geometry of the screen which contains \a p.
+
+ \sa screenGeometry()
+*/
+
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(int screen) const
+
+ Returns the geometry of the screen with index \a screen. The default
+ screen is used if \a screen is -1.
+
+ \sa screenNumber()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
+ \overload
+
+ Returns the geometry of the screen which contains \a widget.
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(const QPoint &p) const
+ \overload
+
+ Returns the geometry of the screen which contains \a p.
+*/
+
+
+/*!
+ \fn int QDesktopWidget::screenNumber(const QWidget *widget) const
+
+ Returns the index of the screen that contains the largest
+ part of \a widget, or -1 if the widget not on a screen.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn int QDesktopWidget::screenNumber(const QPoint &point) const
+
+ \overload
+ Returns the index of the screen that contains the \a point, or the
+ screen which is the shortest distance from the \a point.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn void QDesktopWidget::resizeEvent(QResizeEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn void QDesktopWidget::resized(int screen)
+
+ This signal is emitted when the size of \a screen changes.
+*/
+
+/*!
+ \fn void QDesktopWidget::workAreaResized(int screen)
+
+ This signal is emitted when the work area available on \a screen changes.
+*/
+
+/*!
+ \property QDesktopWidget::screenCount
+ \brief the number of screens currently available on the system.
+
+ \since 4.6
+
+ \sa screenCountChanged()
+*/
+
+/*!
+ \property QDesktopWidget::primaryScreen
+ \brief the index of the screen that is configured to be the primary screen
+ on the system.
+*/
+
+/*!
+ \property QDesktopWidget::virtualDesktop
+
+ \brief if the system manages the available screens in a virtual desktop.
+
+ For virtual desktops, screen() will always return the same widget.
+ The size of the virtual desktop is the size of this desktop
+ widget.
+*/
+
+/*!
+ \fn void QDesktopWidget::screenCountChanged(int newCount)
+
+ \since 4.6
+
+ This signal is emitted when the number of screens changes to \a newCount.
+
+ \sa screenCount
+*/
diff --git a/src/widgets/kernel/qdesktopwidget_qpa.cpp b/src/widgets/kernel/qdesktopwidget_qpa.cpp
new file mode 100644
index 0000000000..7b175dbe95
--- /dev/null
+++ b/src/widgets/kernel/qdesktopwidget_qpa.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "private/qapplication_p.h"
+#include <QWidget>
+#include "private/qwidget_p.h"
+#include "private/qdesktopwidget_qpa_p.h"
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+void QDesktopWidgetPrivate::updateScreenList()
+{
+ Q_Q(QDesktopWidget);
+ QList<QPlatformScreen *> screenList = QGuiApplicationPrivate::platformIntegration()->screens();
+ int targetLength = screenList.length();
+ int currentLength = screens.length();
+
+ // Add or remove screen widgets as necessary
+ if(currentLength > targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength-- > targetLength) {
+ screen = screens.takeLast();
+ delete screen;
+ }
+ }
+ else if (currentLength < targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength < targetLength) {
+ screen = new QDesktopScreenWidget(currentLength++);
+ screens.append(screen);
+ }
+ }
+
+ QRegion virtualGeometry;
+
+ // update the geometry of each screen widget
+ for (int i = 0; i < screens.length(); i++) {
+ QRect screenGeometry = screenList.at(i)->geometry();
+ screens.at(i)->setGeometry(screenGeometry);
+ virtualGeometry += screenGeometry;
+ }
+
+ q->setGeometry(virtualGeometry.boundingRect());
+}
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ Q_D(QDesktopWidget);
+ setObjectName(QLatin1String("desktop"));
+ d->updateScreenList();
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return QGuiApplicationPrivate::platformIntegration()->isVirtualDesktop();
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return 0;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ return qMax(pi->screens().size(), 1);
+}
+
+QWidget *QDesktopWidget::screen(int screen)
+{
+ Q_D(QDesktopWidget);
+ if (screen < 0 || screen >= d->screens.length())
+ return d->screens.at(0);
+ return d->screens.at(screen);
+}
+
+const QRect QDesktopWidget::availableGeometry(int screenNo) const
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens[screenNo]->availableGeometry();
+}
+
+const QRect QDesktopWidget::screenGeometry(int screenNo) const
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens[screenNo]->geometry();
+}
+
+int QDesktopWidget::screenNumber(const QWidget *w) const
+{
+ if (!w)
+ return 0;
+
+ QRect frame = w->frameGeometry();
+ if (!w->isWindow())
+ frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
+ const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2;
+ return screenNumber(midpoint);
+}
+
+int QDesktopWidget::screenNumber(const QPoint &p) const
+{
+ QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+
+ for (int i = 0; i < screens.size(); ++i)
+ if (screens[i]->geometry().contains(p))
+ return i;
+
+ return primaryScreen(); //even better would be closest screen
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qdesktopwidget_qpa_p.h b/src/widgets/kernel/qdesktopwidget_qpa_p.h
new file mode 100644
index 0000000000..d6ed686a3f
--- /dev/null
+++ b/src/widgets/kernel/qdesktopwidget_qpa_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESKTOPWIDGET_QPA_P_H
+#define QDESKTOPWIDGET_QPA_P_H
+
+#include "QDesktopWidget"
+#include "private/qwidget_p.h"
+
+class QDesktopScreenWidget : public QWidget {
+ Q_OBJECT
+public:
+ QDesktopScreenWidget(int screenNumber = -1)
+ {
+ setWindowFlags(Qt::Desktop);
+ setVisible(false);
+ QTLWExtra *topData = d_func()->topData();
+ topData->screenIndex = screenNumber;
+ }
+};
+
+class QDesktopWidgetPrivate : public QWidgetPrivate {
+ Q_DECLARE_PUBLIC(QDesktopWidget)
+
+public:
+ ~QDesktopWidgetPrivate() {foreach(QDesktopScreenWidget *s, screens) delete s; }
+ void updateScreenList();
+
+ QList<QDesktopScreenWidget *> screens;
+};
+
+#endif // QDESKTOPWIDGET_QPA_P_H
diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp
new file mode 100644
index 0000000000..d098c01f0f
--- /dev/null
+++ b/src/widgets/kernel/qformlayout.cpp
@@ -0,0 +1,2079 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qdebug.h"
+#include "qformlayout.h"
+#include "qlabel.h"
+#include "qlayout_p.h"
+#include "qlayoutengine_p.h"
+#include "qrect.h"
+#include "qvector.h"
+#include "qwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+// Fixed column matrix, stores items as [i11, i12, i21, i22...],
+// with FORTRAN-style index operator(r, c).
+template <class T, int NumColumns>
+class FixedColumnMatrix {
+public:
+ typedef QVector<T> Storage;
+
+ FixedColumnMatrix() { }
+
+ void clear() { m_storage.clear(); }
+
+ const T &operator()(int r, int c) const { return m_storage[r * NumColumns + c]; }
+ T &operator()(int r, int c) { return m_storage[r * NumColumns + c]; }
+
+ int rowCount() const { return m_storage.size() / NumColumns; }
+ void addRow(const T &value);
+ void insertRow(int r, const T &value);
+ void removeRow(int r);
+
+ bool find(const T &value, int *rowPtr, int *colPtr) const ;
+ int count(const T &value) const { return m_storage.count(value); }
+
+ // Hmmpf.. Some things are faster that way.
+ const Storage &storage() const { return m_storage; }
+
+ static void storageIndexToPosition(int idx, int *rowPtr, int *colPtr);
+
+private:
+ Storage m_storage;
+};
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::addRow(const T &value)
+{
+ for (int i = 0; i < NumColumns; ++i)
+ m_storage.append(value);
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::insertRow(int r, const T &value)
+{
+ Q_TYPENAME Storage::iterator it = m_storage.begin();
+ it += r * NumColumns;
+ m_storage.insert(it, NumColumns, value);
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::removeRow(int r)
+{
+ m_storage.remove(r * NumColumns, NumColumns);
+}
+
+template <class T, int NumColumns>
+bool FixedColumnMatrix<T, NumColumns>::find(const T &value, int *rowPtr, int *colPtr) const
+{
+ const int idx = m_storage.indexOf(value);
+ if (idx == -1)
+ return false;
+ storageIndexToPosition(idx, rowPtr, colPtr);
+ return true;
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::storageIndexToPosition(int idx, int *rowPtr, int *colPtr)
+{
+ *rowPtr = idx / NumColumns;
+ *colPtr = idx % NumColumns;
+}
+} // namespace
+
+// special values for unset fields; must not clash with values of FieldGrowthPolicy or
+// RowWrapPolicy
+const uint DefaultFieldGrowthPolicy = 255;
+const uint DefaultRowWrapPolicy = 255;
+
+enum { ColumnCount = 2 };
+
+// -- our data structure for our items
+// This owns the QLayoutItem
+struct QFormLayoutItem
+{
+ QFormLayoutItem(QLayoutItem* i) : item(i), fullRow(false), isHfw(false) { }
+ ~QFormLayoutItem() { delete item; }
+
+ // Wrappers
+ QWidget *widget() const { return item->widget(); }
+ QLayout *layout() const { return item->layout(); }
+
+ bool hasHeightForWidth() const { return item->hasHeightForWidth(); }
+ int heightForWidth(int width) const { return item->heightForWidth(width); }
+ int minimumHeightForWidth(int width) const { return item->minimumHeightForWidth(width); }
+ Qt::Orientations expandingDirections() const { return item->expandingDirections(); }
+ QSizePolicy::ControlTypes controlTypes() const { return item->controlTypes(); }
+ int vStretch() const { return widget() ? widget()->sizePolicy().verticalStretch() : 0; }
+
+ void setGeometry(const QRect& r) { item->setGeometry(r); }
+ QRect geometry() const { return item->geometry(); }
+
+ // For use with FixedColumnMatrix
+ bool operator==(const QFormLayoutItem& other) { return item == other.item; }
+
+ QLayoutItem *item;
+ bool fullRow;
+
+ // set by updateSizes
+ bool isHfw;
+ QSize minSize;
+ QSize sizeHint;
+ QSize maxSize;
+
+ // also set by updateSizes
+ int sbsHSpace; // only used for side by side, for the field item only (not label)
+ int vSpace; // This is the spacing to the item in the row above
+
+ // set by setupVerticalLayoutData
+ bool sideBySide;
+ int vLayoutIndex;
+
+ // set by setupHorizontalLayoutData
+ int layoutPos;
+ int layoutWidth;
+};
+
+class QFormLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QFormLayout)
+
+public:
+ typedef FixedColumnMatrix<QFormLayoutItem *, ColumnCount> ItemMatrix;
+
+ QFormLayoutPrivate();
+ ~QFormLayoutPrivate() { }
+
+ int insertRow(int row);
+ void insertRows(int row, int count);
+ void setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item);
+ void setLayout(int row, QFormLayout::ItemRole role, QLayout *layout);
+ void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget);
+
+ void arrangeWidgets(const QVector<QLayoutStruct>& layouts, QRect &rect);
+
+ void updateSizes();
+
+ void setupVerticalLayoutData(int width);
+ void setupHorizontalLayoutData(int width);
+
+ QStyle* getStyle() const;
+
+ inline bool haveHfwCached(int width) const
+ {
+ return (hfw_width == width) || (width == sh_width && hfw_sh_height >= 0);
+ }
+
+ void recalcHFW(int w);
+ void setupHfwLayoutData();
+
+ uint fieldGrowthPolicy : 8;
+ uint rowWrapPolicy : 8;
+ uint has_hfw : 2;
+ uint dirty : 2; // have we laid out yet?
+ uint sizesDirty : 2; // have we (not) gathered layout item sizes?
+ uint expandVertical : 1; // Do we expand vertically?
+ uint expandHorizontal : 1; // Do we expand horizonally?
+ Qt::Alignment labelAlignment;
+ Qt::Alignment formAlignment;
+
+ ItemMatrix m_matrix;
+ QList<QFormLayoutItem *> m_things;
+
+ int layoutWidth; // the last width that we called setupVerticalLayoutData on (for vLayouts)
+
+ int hfw_width; // the last width we calculated HFW for
+ int hfw_height; // what that height was
+ int hfw_minheight; // what that minheight was
+
+ int hfw_sh_height; // the hfw for sh_width
+ int hfw_sh_minheight; // the minhfw for sh_width
+
+ int min_width; // the width that gets turned into minSize (from updateSizes)
+ int sh_width; // the width that gets turned into prefSize (from updateSizes)
+ int thresh_width; // the width that we start splitting label/field pairs at (from updateSizes)
+ QSize minSize;
+ QSize prefSize;
+ int formMaxWidth;
+ void calcSizeHints();
+
+ QVector<QLayoutStruct> vLayouts; // set by setupVerticalLayoutData;
+ int vLayoutCount; // Number of rows we calculated in setupVerticalLayoutData
+ int maxLabelWidth; // the label width we calculated in setupVerticalLayoutData
+
+ QVector<QLayoutStruct> hfwLayouts;
+
+ int hSpacing;
+ int vSpacing;
+};
+
+QFormLayoutPrivate::QFormLayoutPrivate()
+ : fieldGrowthPolicy(DefaultFieldGrowthPolicy),
+ rowWrapPolicy(DefaultRowWrapPolicy), has_hfw(false), dirty(true), sizesDirty(true),
+ expandVertical(0), expandHorizontal(0), labelAlignment(0), formAlignment(0),
+ layoutWidth(-1), hfw_width(-1), hfw_sh_height(-1), min_width(-1),
+ sh_width(-1), thresh_width(QLAYOUTSIZE_MAX), hSpacing(-1), vSpacing(-1)
+{
+}
+
+static Qt::Alignment fixedAlignment(Qt::Alignment alignment, Qt::LayoutDirection layoutDirection)
+{
+ if (layoutDirection == Qt::RightToLeft && alignment & Qt::AlignAbsolute) {
+ // swap left and right, and eliminate absolute flag
+ return Qt::Alignment((alignment & ~(Qt::AlignLeft | Qt::AlignRight | Qt::AlignAbsolute))
+ | ((alignment & Qt::AlignRight) ? Qt::AlignLeft : 0)
+ | ((alignment & Qt::AlignLeft) ? Qt::AlignRight : 0));
+ } else {
+ return alignment & ~Qt::AlignAbsolute;
+ }
+}
+
+static int storageIndexFromLayoutItem(const QFormLayoutPrivate::ItemMatrix &m,
+ QFormLayoutItem *item)
+{
+ if (item) {
+ return m.storage().indexOf(item);
+ } else {
+ return -1;
+ }
+}
+
+static void updateFormLayoutItem(QFormLayoutItem *item, int userVSpacing,
+ QFormLayout::FieldGrowthPolicy fieldGrowthPolicy,
+ bool fullRow)
+{
+ item->minSize = item->item->minimumSize();
+ item->sizeHint = item->item->sizeHint();
+ item->maxSize = item->item->maximumSize();
+
+ if (!fullRow && (fieldGrowthPolicy == QFormLayout::FieldsStayAtSizeHint
+ || (fieldGrowthPolicy == QFormLayout::ExpandingFieldsGrow
+ && !(item->item->expandingDirections() & Qt::Horizontal))))
+ item->maxSize.setWidth(item->sizeHint.width());
+
+ item->isHfw = item->item->hasHeightForWidth();
+ item->vSpace = userVSpacing;
+}
+
+/*
+ Iterate over all the controls and gather their size information
+ (min, sizeHint and max). Also work out what the spacing between
+ pairs of controls should be, and figure out the min and sizeHint
+ widths.
+*/
+void QFormLayoutPrivate::updateSizes()
+{
+ Q_Q(QFormLayout);
+
+ if (sizesDirty) {
+ QFormLayout::RowWrapPolicy wrapPolicy = q->rowWrapPolicy();
+ bool wrapAllRows = (wrapPolicy == QFormLayout::WrapAllRows);
+ bool dontWrapRows = (wrapPolicy == QFormLayout::DontWrapRows);
+ int rr = m_matrix.rowCount();
+
+ has_hfw = false;
+
+ // If any control can expand, so can this layout
+ // Wrapping doesn't affect expansion, though, just the minsize
+ bool expandH = false;
+ bool expandV = false;
+
+ QFormLayoutItem *prevLbl = 0;
+ QFormLayoutItem *prevFld = 0;
+
+ QWidget *parent = q->parentWidget();
+ QStyle *style = parent ? parent->style() : 0;
+
+ int userVSpacing = q->verticalSpacing();
+ int userHSpacing = wrapAllRows ? 0 : q->horizontalSpacing();
+
+ int maxMinLblWidth = 0;
+ int maxMinFldWidth = 0; // field with label
+ int maxMinIfldWidth = 0; // independent field
+
+ int maxShLblWidth = 0;
+ int maxShFldWidth = 0;
+ int maxShIfldWidth = 0;
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Skip empty rows
+ if (!label && !field)
+ continue;
+
+ if (label) {
+ updateFormLayoutItem(label, userVSpacing, q->fieldGrowthPolicy(), false);
+ if (label->isHfw)
+ has_hfw = true;
+ Qt::Orientations o = label->expandingDirections();
+
+ if (o & Qt::Vertical)
+ expandV = true;
+ if (o & Qt::Horizontal)
+ expandH = true;
+ }
+ if (field) {
+ updateFormLayoutItem(field, userVSpacing, q->fieldGrowthPolicy(), !label && field->fullRow);
+ field->sbsHSpace = (!label && field->fullRow) ? 0 : userHSpacing;
+ if (field->isHfw)
+ has_hfw = true;
+
+ Qt::Orientations o = field->expandingDirections();
+
+ if (o & Qt::Vertical)
+ expandV = true;
+ if (o & Qt::Horizontal)
+ expandH = true;
+ }
+
+ // See if we need to calculate default spacings
+ if ((userHSpacing < 0 || userVSpacing < 0) && style) {
+ QSizePolicy::ControlTypes lbltypes =
+ QSizePolicy::ControlTypes(label ? label->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtypes =
+ QSizePolicy::ControlTypes(field ? field->controlTypes() : QSizePolicy::DefaultType);
+
+ // VSpacing
+ if (userVSpacing < 0) {
+ if (wrapAllRows) {
+ // label spacing is to a previous item
+ QFormLayoutItem *lbltop = prevFld ? prevFld : prevLbl;
+ // field spacing is to the label (or a previous item)
+ QFormLayoutItem *fldtop = label ? label : lbltop;
+ QSizePolicy::ControlTypes lbltoptypes =
+ QSizePolicy::ControlTypes(lbltop ? lbltop->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtoptypes =
+ QSizePolicy::ControlTypes(fldtop ? fldtop->controlTypes() : QSizePolicy::DefaultType);
+ if (label && lbltop)
+ label->vSpace = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ if (field && fldtop)
+ field->vSpace = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ } else {
+ // Side by side.. we have to also consider the spacings to empty cells, which can strangely be more than
+ // non empty cells..
+ QFormLayoutItem *lbltop = prevLbl ? prevLbl : prevFld;
+ QFormLayoutItem *fldtop = prevFld;
+ QSizePolicy::ControlTypes lbltoptypes =
+ QSizePolicy::ControlTypes(lbltop ? lbltop->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtoptypes =
+ QSizePolicy::ControlTypes(fldtop ? fldtop->controlTypes() : QSizePolicy::DefaultType);
+
+ // To be compatible to QGridLayout, we have to compare solitary labels & fields with both predecessors
+ if (label) {
+ if (!field) {
+ int lblspacing = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ int fldspacing = style->combinedLayoutSpacing(fldtoptypes, lbltypes, Qt::Vertical, 0, parent);
+ label->vSpace = qMax(lblspacing, fldspacing);
+ } else
+ label->vSpace = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ }
+
+ if (field) {
+ // check spacing against both the previous label and field
+ if (!label) {
+ int lblspacing = style->combinedLayoutSpacing(lbltoptypes, fldtypes, Qt::Vertical, 0, parent);
+ int fldspacing = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ field->vSpace = qMax(lblspacing, fldspacing);
+ } else
+ field->vSpace = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ }
+ }
+ }
+
+ // HSpacing
+ // hard-coded the left and right control types so that all the rows have the same
+ // inter-column spacing (otherwise the right column isn't always left aligned)
+ if (userHSpacing < 0 && !wrapAllRows && (label || !field->fullRow) && field)
+ field->sbsHSpace = style->combinedLayoutSpacing(QSizePolicy::Label, QSizePolicy::LineEdit, Qt::Horizontal, 0, parent);
+ }
+
+ // Now update our min/sizehint widths
+ // We choose to put the spacing in the field side in sbs, so
+ // the right edge of the labels will align, but fields may
+ // be a little ragged.. since different controls may have
+ // different appearances, a slight raggedness in the left
+ // edges of fields can be tolerated.
+ // (Note - field->sbsHSpace is 0 for WrapAllRows mode)
+ if (label) {
+ maxMinLblWidth = qMax(maxMinLblWidth, label->minSize.width());
+ maxShLblWidth = qMax(maxShLblWidth, label->sizeHint.width());
+ if (field) {
+ maxMinFldWidth = qMax(maxMinFldWidth, field->minSize.width() + field->sbsHSpace);
+ maxShFldWidth = qMax(maxShFldWidth, field->sizeHint.width() + field->sbsHSpace);
+ }
+ } else if (field) {
+ maxMinIfldWidth = qMax(maxMinIfldWidth, field->minSize.width());
+ maxShIfldWidth = qMax(maxShIfldWidth, field->sizeHint.width());
+ }
+
+ prevLbl = label;
+ prevFld = field;
+ }
+
+ // Now, finally update the min/sizeHint widths
+ if (wrapAllRows) {
+ sh_width = qMax(maxShLblWidth, qMax(maxShIfldWidth, maxShFldWidth));
+ min_width = qMax(maxMinLblWidth, qMax(maxMinIfldWidth, maxMinFldWidth));
+ // in two line, we don't care as much about the threshold width
+ thresh_width = 0;
+ } else if (dontWrapRows) {
+ // This is just the max widths glommed together
+ sh_width = qMax(maxShLblWidth + maxShFldWidth, maxShIfldWidth);
+ min_width = qMax(maxMinLblWidth + maxMinFldWidth, maxMinIfldWidth);
+ thresh_width = QWIDGETSIZE_MAX;
+ } else {
+ // This is just the max widths glommed together
+ sh_width = qMax(maxShLblWidth + maxShFldWidth, maxShIfldWidth);
+ // min width needs to be the min when everything is wrapped,
+ // otherwise we'll never get set with a width that causes wrapping
+ min_width = qMax(maxMinLblWidth, qMax(maxMinIfldWidth, maxMinFldWidth));
+ // We split a pair at label sh + field min (### for now..)
+ thresh_width = maxShLblWidth + maxMinFldWidth;
+ }
+
+ // Update the expansions
+ expandVertical = expandV;
+ expandHorizontal = expandH;
+ }
+ sizesDirty = false;
+}
+
+void QFormLayoutPrivate::recalcHFW(int w)
+{
+ setupHfwLayoutData();
+
+ int h = 0;
+ int mh = 0;
+
+ for (int r = 0; r < vLayoutCount; ++r) {
+ int spacing = hfwLayouts.at(r).spacing;
+ h += hfwLayouts.at(r).sizeHint + spacing;
+ mh += hfwLayouts.at(r).minimumSize + spacing;
+ }
+
+ if (sh_width > 0 && sh_width == w) {
+ hfw_sh_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_sh_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+ } else {
+ hfw_width = w;
+ hfw_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+ }
+}
+
+void QFormLayoutPrivate::setupHfwLayoutData()
+{
+ // setupVerticalLayoutData must be called before this
+ // setupHorizontalLayoutData must also be called before this
+ // copies non hfw data into hfw
+ // then updates size and min
+
+
+ // Note: QGridLayout doesn't call minimumHeightForWidth,
+ // but instead uses heightForWidth for both min and sizeHint.
+ // For the common case where minimumHeightForWidth just calls
+ // heightForWidth, we do the calculation twice, which can be
+ // very expensive for word wrapped QLabels/QTextEdits, for example.
+ // So we just use heightForWidth as well.
+ int i;
+ int rr = m_matrix.rowCount();
+
+ hfwLayouts.clear();
+ hfwLayouts.resize(vLayoutCount);
+ for (i = 0; i < vLayoutCount; ++i)
+ hfwLayouts[i] = vLayouts.at(i);
+
+ for (i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ if (label) {
+ if (label->isHfw) {
+ // We don't check sideBySide here, since a label is only
+ // ever side by side with its field
+ int hfw = label->heightForWidth(label->layoutWidth);
+ hfwLayouts[label->vLayoutIndex].minimumSize = hfw;
+ hfwLayouts[label->vLayoutIndex].sizeHint = hfw;
+ } else {
+ // Reset these here, so the field can do a qMax below (the previous value may have
+ // been the fields non-hfw values, which are often larger than hfw)
+ hfwLayouts[label->vLayoutIndex].sizeHint = label->sizeHint.height();
+ hfwLayouts[label->vLayoutIndex].minimumSize = label->minSize.height();
+ }
+ }
+
+ if (field) {
+ int hfw = field->isHfw ? field->heightForWidth(field->layoutWidth) : 0;
+ int h = field->isHfw ? hfw : field->sizeHint.height();
+ int mh = field->isHfw ? hfw : field->minSize.height();
+
+ if (field->sideBySide) {
+ int oh = hfwLayouts.at(field->vLayoutIndex).sizeHint;
+ int omh = hfwLayouts.at(field->vLayoutIndex).minimumSize;
+
+ hfwLayouts[field->vLayoutIndex].sizeHint = qMax(h, oh);
+ hfwLayouts[field->vLayoutIndex].minimumSize = qMax(mh, omh);
+ } else {
+ hfwLayouts[field->vLayoutIndex].sizeHint = h;
+ hfwLayouts[field->vLayoutIndex].minimumSize = mh;
+ }
+ }
+ }
+}
+
+/*
+ Given up to four items involved in a vertical spacing calculation
+ (two rows * two columns), return the max vertical spacing for the
+ row containing item1 (which may also include item2)
+ We assume parent and item1 are not null.
+
+ If a particular row is split, then the spacings for that row and
+ the following row are affected, and this function should be
+ called with recalculate = true for both rows (note: only rows with both
+ a label and a field can be split).
+
+ In particular:
+
+ 1) the split label's row vspace needs to be changed to qMax(label/prevLabel, label/prevField)
+ [call with item1 = label, item2 = null, prevItem1 & prevItem2 as before]
+ 2) the split field's row vspace needs to be changed to the label/field spacing
+ [call with item1 = field, item2 = null, prevItem1 = label, prevItem2 = null]
+
+ [if the next row has one item, 'item']
+ 3a) the following row's vspace needs to be changed to item/field spacing (would
+ previously been the qMax(item/label, item/field) spacings)
+ [call with item1 = item, item2 = null, prevItem1 = field, prevItem2 = null]
+
+ [if the next row has two items, 'label2' and 'field2']
+ 3b) the following row's vspace needs to be changed to be qMax(field/label2, field/field2) spacing
+ [call with item1 = label2, item2 = field2, prevItem1 = field, prevItem2 = null]
+
+ In the (common) non split case, we can just use the precalculated vspace (possibly qMaxed between
+ label and field).
+
+ If recalculate is true, we expect:
+ - parent != null
+ - item1 != null
+ - item2 can be null
+ - prevItem1 can be null
+ - if item2 is not null, prevItem2 will be null (e.g. steps 1 or 3 above)
+ - if prevItem1 is null, prevItem2 will be null
+*/
+static inline int spacingHelper(QWidget* parent, QStyle *style, int userVSpacing, bool recalculate, QFormLayoutItem* item1, QFormLayoutItem* item2, QFormLayoutItem* prevItem1, QFormLayoutItem *prevItem2)
+{
+ int spacing = userVSpacing;
+ if (spacing < 0) {
+ if (!recalculate) {
+ if (item1)
+ spacing = item1->vSpace;
+ if (item2)
+ spacing = qMax(spacing, item2->vSpace);
+ } else {
+ if (style && prevItem1) {
+ QSizePolicy::ControlTypes itemtypes =
+ QSizePolicy::ControlTypes(item1 ? item1->controlTypes() : QSizePolicy::DefaultType);
+ int spacing2 = 0;
+
+ spacing = style->combinedLayoutSpacing(itemtypes, prevItem1->controlTypes(), Qt::Vertical, 0, parent);
+
+ // At most of one of item2 and prevItem2 will be nonnull
+ if (item2)
+ spacing2 = style->combinedLayoutSpacing(item2->controlTypes(), prevItem1->controlTypes(), Qt::Vertical, 0, parent);
+ else if (prevItem2)
+ spacing2 = style->combinedLayoutSpacing(itemtypes, prevItem2->controlTypes(), Qt::Vertical, 0, parent);
+
+ spacing = qMax(spacing, spacing2);
+ }
+ }
+ } else {
+ if (prevItem1) {
+ QWidget *wid = prevItem1->item->widget();
+ if (wid)
+ spacing = qMax(spacing, prevItem1->geometry().top() - wid->geometry().top() );
+ }
+ if (prevItem2) {
+ QWidget *wid = prevItem2->item->widget();
+ if (wid)
+ spacing = qMax(spacing, prevItem2->geometry().top() - wid->geometry().top() );
+ }
+ }
+ return spacing;
+}
+
+static inline void initLayoutStruct(QLayoutStruct& sl, QFormLayoutItem* item)
+{
+ sl.init(item->vStretch(), item->minSize.height());
+ sl.sizeHint = item->sizeHint.height();
+ sl.maximumSize = item->maxSize.height();
+ sl.expansive = (item->expandingDirections() & Qt::Vertical);
+ sl.empty = false;
+}
+
+void QFormLayoutPrivate::setupVerticalLayoutData(int width)
+{
+ Q_Q(QFormLayout);
+
+ // Early out if we have no changes that would cause a change in vertical layout
+ if ((width == layoutWidth || (width >= thresh_width && layoutWidth >= thresh_width)) && !dirty && !sizesDirty)
+ return;
+
+ layoutWidth = width;
+
+ int rr = m_matrix.rowCount();
+ int vidx = 1;
+ QFormLayout::RowWrapPolicy rowWrapPolicy = q->rowWrapPolicy();
+ bool wrapAllRows = (rowWrapPolicy == QFormLayout::WrapAllRows);
+ bool addTopBottomStretch = true;
+
+ vLayouts.clear();
+ vLayouts.resize((2 * rr) + 2); // a max, some may be unused
+
+ QStyle *style = 0;
+
+ int userVSpacing = q->verticalSpacing();
+
+ if (userVSpacing < 0) {
+ if (QWidget *widget = q->parentWidget())
+ style = widget->style();
+ }
+
+ // make sure our sizes are up to date
+ updateSizes();
+
+ // Grab the widest label width here
+ // This might be different from the value computed during
+ // sizeHint/minSize, since we don't count label/field pairs that
+ // are split.
+ maxLabelWidth = 0;
+ if (!wrapAllRows) {
+ for (int i = 0; i < rr; ++i) {
+ const QFormLayoutItem *label = m_matrix(i, 0);
+ const QFormLayoutItem *field = m_matrix(i, 1);
+ if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width))
+ maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width());
+ }
+ } else {
+ maxLabelWidth = width;
+ }
+
+ QFormLayoutItem *prevItem1 = 0;
+ QFormLayoutItem *prevItem2 = 0;
+ bool prevRowSplit = false;
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Totally ignore empty rows...
+ if (!label && !field)
+ continue;
+
+ QSize min1;
+ QSize min2;
+ QSize sh1;
+ QSize sh2;
+ if (label) {
+ min1 = label->minSize;
+ sh1 = label->sizeHint;
+ }
+ if (field) {
+ min2 = field->minSize;
+ sh2 = field->sizeHint;
+ }
+
+ // In separate lines, we make a vLayout for everything that isn't null
+ // in side by side, we only separate label/field if we're going to wrap it
+ bool splitSideBySide = (rowWrapPolicy == QFormLayout::WrapLongRows)
+ && ((maxLabelWidth < sh1.width()) || (width < (maxLabelWidth + min2.width())));
+
+ if (wrapAllRows || splitSideBySide) {
+ if (label) {
+ initLayoutStruct(vLayouts[vidx], label);
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, splitSideBySide || prevRowSplit, label, 0, prevItem1, prevItem2);
+
+ label->vLayoutIndex = vidx;
+ label->sideBySide = false;
+
+ prevItem1 = label;
+ prevItem2 = 0;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ ++vidx;
+ }
+
+ if (field) {
+ initLayoutStruct(vLayouts[vidx], field);
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, splitSideBySide || prevRowSplit, field, 0, prevItem1, prevItem2);
+
+ field->vLayoutIndex = vidx;
+ field->sideBySide = false;
+
+ prevItem1 = field;
+ prevItem2 = 0;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ ++vidx;
+ }
+
+ prevRowSplit = splitSideBySide;
+ } else {
+ // we're in side by side mode, and we have enough space to do that
+ QSize max1(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ QSize max2(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+
+ int stretch1 = 0;
+ int stretch2 = 0;
+ bool expanding = false;
+
+ if (label) {
+ max1 = label->maxSize;
+ if (label->expandingDirections() & Qt::Vertical)
+ expanding = true;
+
+ label->sideBySide = (field != 0);
+ label->vLayoutIndex = vidx;
+ stretch1 = label->vStretch();
+ }
+
+ if (field) {
+ max2 = field->maxSize;
+ if (field->expandingDirections() & Qt::Vertical)
+ expanding = true;
+
+ field->sideBySide = (label || !field->fullRow);
+ field->vLayoutIndex = vidx;
+ stretch2 = field->vStretch();
+ }
+
+ vLayouts[vidx].init(qMax(stretch1, stretch2), qMax(min1.height(), min2.height()));
+ vLayouts[vidx].sizeHint = qMax(sh1.height(), sh2.height());
+ vLayouts[vidx].maximumSize = qMin(max1.height(), max2.height());
+ vLayouts[vidx].expansive = expanding || (vLayouts[vidx].stretch > 0);
+ vLayouts[vidx].empty = false;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, prevRowSplit, label, field, prevItem1, prevItem2);
+
+ if (label) {
+ prevItem1 = label;
+ prevItem2 = field;
+ } else {
+ prevItem1 = field;
+ prevItem2 = 0;
+ }
+
+ prevRowSplit = false;
+ ++vidx;
+ }
+ }
+
+ if (addTopBottomStretch) {
+ Qt::Alignment formAlignment = q->formAlignment();
+
+ if (!(formAlignment & Qt::AlignBottom)) {
+ // AlignTop (default if unspecified) or AlignVCenter: We add a stretch at the bottom
+ vLayouts[vidx].init(1, 0);
+ vLayouts[vidx].expansive = true;
+ ++vidx;
+ }
+
+ if (formAlignment & (Qt::AlignVCenter | Qt::AlignBottom)) {
+ // AlignVCenter or AlignBottom: We add a stretch at the top
+ vLayouts[0].init(1, 0);
+ vLayouts[0].expansive = true;
+ } else {
+ vLayouts[0].init(0, 0);
+ }
+ } else {
+ vLayouts[0].init(0, 0);
+ }
+
+ vLayoutCount = vidx;
+ dirty = false;
+}
+
+void QFormLayoutPrivate::setupHorizontalLayoutData(int width)
+{
+ Q_Q(QFormLayout);
+
+ // requires setupVerticalLayoutData to be called first
+
+ int fieldMaxWidth = 0;
+
+ int rr = m_matrix.rowCount();
+ bool wrapAllRows = (q->rowWrapPolicy() == QFormLayout::WrapAllRows);
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Totally ignore empty rows...
+ if (!label && !field)
+ continue;
+
+ if (label) {
+ // if there is a field, and we're side by side, we use maxLabelWidth
+ // otherwise we just use the sizehint
+ label->layoutWidth = (field && label->sideBySide) ? maxLabelWidth : label->sizeHint.width();
+ label->layoutPos = 0;
+ }
+
+ if (field) {
+ // This is the default amount allotted to fields in sbs
+ int fldwidth = width - maxLabelWidth - field->sbsHSpace;
+
+ // If we've split a row, we still decide to align
+ // the field with all the other field if it will fit
+ // Fields in sbs mode get the remnants of the maxLabelWidth
+ if (!field->sideBySide) {
+ if (wrapAllRows || (!label && field->fullRow) || field->sizeHint.width() > fldwidth) {
+ field->layoutWidth = width;
+ field->layoutPos = 0;
+ } else {
+ field->layoutWidth = fldwidth;
+ field->layoutPos = width - fldwidth;
+ }
+ } else {
+ // We're sbs, so we should have a label
+ field->layoutWidth = fldwidth;
+ field->layoutPos = width - fldwidth;
+ }
+
+ fieldMaxWidth = qMax(fieldMaxWidth, field->maxSize.width());
+ }
+ }
+
+ formMaxWidth = maxLabelWidth + fieldMaxWidth;
+}
+
+void QFormLayoutPrivate::calcSizeHints()
+{
+ Q_Q(QFormLayout);
+
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ updateSizes();
+ setupVerticalLayoutData(QLAYOUTSIZE_MAX);
+ // Don't need to call setupHorizontal here
+
+ int h = topMargin + bottomMargin;
+ int mh = topMargin + bottomMargin;
+
+ // The following are set in updateSizes
+ int w = sh_width + leftMargin + rightMargin;
+ int mw = min_width + leftMargin + rightMargin;
+
+ for (int i = 0; i < vLayoutCount; ++i) {
+ int spacing = vLayouts.at(i).spacing;
+ h += vLayouts.at(i).sizeHint + spacing;
+ mh += vLayouts.at(i).minimumSize + spacing;
+ }
+
+ minSize.rwidth() = qMin(mw, QLAYOUTSIZE_MAX);
+ minSize.rheight() = qMin(mh, QLAYOUTSIZE_MAX);
+ prefSize.rwidth() = qMin(w, QLAYOUTSIZE_MAX);
+ prefSize.rheight() = qMin(h, QLAYOUTSIZE_MAX);
+}
+
+int QFormLayoutPrivate::insertRow(int row)
+{
+ int rowCnt = m_matrix.rowCount();
+ if (uint(row) > uint(rowCnt))
+ row = rowCnt;
+
+ insertRows(row, 1);
+ return row;
+}
+
+void QFormLayoutPrivate::insertRows(int row, int count)
+{
+ while (count > 0) {
+ m_matrix.insertRow(row, 0);
+ --count;
+ }
+}
+
+void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item)
+{
+ const bool fullRow = role == QFormLayout::SpanningRole;
+ const int column = role == QFormLayout::SpanningRole ? 1 : static_cast<int>(role);
+ if (uint(row) >= uint(m_matrix.rowCount()) || uint(column) > 1U) {
+ qWarning("QFormLayoutPrivate::setItem: Invalid cell (%d, %d)", row, column);
+ return;
+ }
+
+ if (!item)
+ return;
+
+ if (m_matrix(row, column)) {
+ qWarning("QFormLayoutPrivate::setItem: Cell (%d, %d) already occupied", row, column);
+ return;
+ }
+
+ QFormLayoutItem *i = new QFormLayoutItem(item);
+ i->fullRow = fullRow;
+ m_matrix(row, column) = i;
+
+ m_things.append(i);
+}
+
+void QFormLayoutPrivate::setLayout(int row, QFormLayout::ItemRole role, QLayout *layout)
+{
+ if (layout) {
+ Q_Q(QFormLayout);
+ q->addChildLayout(layout);
+ setItem(row, role, layout);
+ }
+}
+
+void QFormLayoutPrivate::setWidget(int row, QFormLayout::ItemRole role, QWidget *widget)
+{
+ if (widget) {
+ Q_Q(QFormLayout);
+ q->addChildWidget(widget);
+ setItem(row, role, QLayoutPrivate::createWidgetItem(q, widget));
+ }
+}
+
+QStyle* QFormLayoutPrivate::getStyle() const
+{
+ Q_Q(const QFormLayout);
+
+ // ### cache
+ if (QWidget *parentWidget = q->parentWidget())
+ return parentWidget->style();
+ else
+ return QApplication::style();
+}
+
+/*!
+ \class QFormLayout
+ \since 4.4
+ \brief The QFormLayout class manages forms of input widgets and their associated labels.
+
+ \ingroup geomanagement
+
+
+ QFormLayout is a convenience layout class that lays out its
+ children in a two-column form. The left column consists of labels
+ and the right column consists of "field" widgets (line editors,
+ spin boxes, etc.).
+
+ Traditionally, such two-column form layouts were achieved using
+ QGridLayout. QFormLayout is a higher-level alternative that
+ provides the following advantages:
+
+ \list
+ \o \bold{Adherence to the different platform's look and feel guidelines.}
+
+ For example, the
+ \l{Mac OS X Aqua} and KDE guidelines specify that the
+ labels should be right-aligned, whereas Windows and GNOME
+ applications normally use left-alignment.
+
+ \o \bold{Support for wrapping long rows.}
+
+ For devices with small displays, QFormLayout can be set to
+ \l{WrapLongRows}{wrap long rows}, or even to
+ \l{WrapAllRows}{wrap all rows}.
+
+ \o \bold{Convenient API for creating label--field pairs.}
+
+ The addRow() overload that takes a QString and a QWidget *
+ creates a QLabel behind the scenes and automatically set up
+ its buddy. We can then write code like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 0
+
+ Compare this with the following code, written using QGridLayout:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 1
+ \endlist
+
+ The table below shows the default appearance in different styles.
+
+ \table
+ \header
+ \o QCommonStyle derived styles (except QPlastiqueStyle)
+ \o QMacStyle
+ \o QPlastiqueStyle
+ \o Qt Extended styles
+ \row
+ \o \inlineimage qformlayout-win.png
+ \o \inlineimage qformlayout-mac.png
+ \o \inlineimage qformlayout-kde.png
+ \o \inlineimage qformlayout-qpe.png
+ \row
+ \o Traditional style used for Windows, GNOME, and earlier
+ versions of KDE. Labels are left aligned, and expanding
+ fields grow to fill the available space. (This normally
+ corresponds to what we would get using a two-column
+ QGridLayout.)
+ \o Style based on the
+ \l{Mac OS X Aqua} guidelines. Labels are right-aligned,
+ the fields don't grow beyond their size hint, and the
+ form is horizontally centered.
+ \o Recommended style for
+ \l{KDE applications}. Similar to MacStyle, except that the form
+ is left-aligned and all fields grow to fill the available
+ space.
+ \o Default style for Qt Extended styles. Labels are right-aligned,
+ expanding fields grow to fill the available space, and row
+ wrapping is enabled for long lines.
+ \endtable
+
+ The form styles can be also be overridden individually by calling
+ setLabelAlignment(), setFormAlignment(), setFieldGrowthPolicy(),
+ and setRowWrapPolicy(). For example, to simulate the form layout
+ appearance of QMacStyle on all platforms, but with left-aligned
+ labels, you could write:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 2
+
+ \sa QGridLayout, QBoxLayout, QStackedLayout
+*/
+
+
+/*!
+ \enum QFormLayout::FieldGrowthPolicy
+
+ This enum specifies the different policies that can be used to
+ control the way in which the form's fields grow.
+
+ \value FieldsStayAtSizeHint
+ The fields never grow beyond their
+ \l{QWidgetItem::sizeHint()}{effective size hint}. This is
+ the default for QMacStyle.
+
+ \value ExpandingFieldsGrow
+ Fields with an horizontal \l{QSizePolicy}{size policy} of
+ \l{QSizePolicy::}{Expanding} or
+ \l{QSizePolicy::}{MinimumExpanding} will grow to fill the
+ available space. The other fields will not grow beyond
+ their effective size hint. This is the default policy for
+ Plastique.
+
+ \value AllNonFixedFieldsGrow
+ All fields with a size policy that allows them to grow
+ will grow to fill the available space. This is the default
+ policy for most styles.
+
+ \sa fieldGrowthPolicy
+*/
+
+/*!
+ \enum QFormLayout::RowWrapPolicy
+
+ This enum specifies the different policies that can be used to
+ control the way in which the form's rows wrap.
+
+ \value DontWrapRows
+ Fields are always laid out next to their label. This is
+ the default policy for all styles except Qt Extended styles
+ and QS60Style.
+
+ \value WrapLongRows
+ Labels are given enough horizontal space to fit the widest label,
+ and the rest of the space is given to the fields. If the minimum
+ size of a field pair is wider than the available space, the field
+ is wrapped to the next line. This is the default policy for
+ Qt Extended styles and and QS60Style.
+
+ \value WrapAllRows
+ Fields are always laid out below their label.
+
+ \sa rowWrapPolicy
+*/
+
+/*!
+ \enum QFormLayout::ItemRole
+
+ This enum specifies the types of widgets (or other layout items)
+ that may appear in a row.
+
+ \value LabelRole A label widget.
+ \value FieldRole A field widget.
+ \value SpanningRole A widget that spans label and field columns.
+
+ \sa itemAt(), getItemPosition()
+*/
+
+/*!
+ Constructs a new form layout with the given \a parent widget.
+
+ \sa QWidget::setLayout()
+*/
+QFormLayout::QFormLayout(QWidget *parent)
+ : QLayout(*new QFormLayoutPrivate, 0, parent)
+{
+}
+
+/*!
+ Destroys the form layout.
+*/
+QFormLayout::~QFormLayout()
+{
+ Q_D(QFormLayout);
+
+ /*
+ The clearing and destruction order here is important. We start by clearing
+ m_things so that QLayout and the rest of the world know that we don't babysit
+ the layout items anymore and don't care if they are destroyed.
+ */
+ d->m_things.clear();
+ qDeleteAll(d->m_matrix.storage());
+ d->m_matrix.clear();
+}
+
+/*!
+ Adds a new row to the bottom of this form layout, with the given
+ \a label and \a field.
+
+ \sa insertRow()
+*/
+void QFormLayout::addRow(QWidget *label, QWidget *field)
+{
+ insertRow(-1, label, field);
+}
+
+/*!
+ \overload
+*/
+void QFormLayout::addRow(QWidget *label, QLayout *field)
+{
+ insertRow(-1, label, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text. The \a field is set as the new
+ QLabel's \l{QLabel::setBuddy()}{buddy}.
+*/
+void QFormLayout::addRow(const QString &labelText, QWidget *field)
+{
+ insertRow(-1, labelText, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text.
+*/
+void QFormLayout::addRow(const QString &labelText, QLayout *field)
+{
+ insertRow(-1, labelText, field);
+}
+
+/*!
+ \overload
+
+ Adds the specified \a widget at the end of this form layout. The
+ \a widget spans both columns.
+*/
+void QFormLayout::addRow(QWidget *widget)
+{
+ insertRow(-1, widget);
+}
+
+/*!
+ \overload
+
+ Adds the specified \a layout at the end of this form layout. The
+ \a layout spans both columns.
+*/
+void QFormLayout::addRow(QLayout *layout)
+{
+ insertRow(-1, layout);
+}
+
+/*!
+ Inserts a new row at position \a row in this form layout, with
+ the given \a label and \a field. If \a row is out of bounds, the
+ new row is added at the end.
+
+ \sa addRow()
+*/
+void QFormLayout::insertRow(int row, QWidget *label, QWidget *field)
+{
+ Q_D(QFormLayout);
+
+ row = d->insertRow(row);
+ if (label)
+ d->setWidget(row, LabelRole, label);
+ if (field)
+ d->setWidget(row, FieldRole, field);
+ invalidate();
+}
+
+/*!
+ \overload
+*/
+void QFormLayout::insertRow(int row, QWidget *label, QLayout *field)
+{
+ Q_D(QFormLayout);
+
+ row = d->insertRow(row);
+ if (label)
+ d->setWidget(row, LabelRole, label);
+ if (field)
+ d->setLayout(row, FieldRole, field);
+ invalidate();
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text. The \a field is set as the new
+ QLabel's \l{QLabel::setBuddy()}{buddy}.
+*/
+void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field)
+{
+ QLabel *label = 0;
+ if (!labelText.isEmpty()) {
+ label = new QLabel(labelText);
+#ifndef QT_NO_SHORTCUT
+ label->setBuddy(field);
+#endif
+ }
+ insertRow(row, label, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text.
+*/
+void QFormLayout::insertRow(int row, const QString &labelText, QLayout *field)
+{
+ insertRow(row, labelText.isEmpty() ? 0 : new QLabel(labelText), field);
+}
+
+/*!
+ \overload
+
+ Inserts the specified \a widget at position \a row in this form
+ layout. The \a widget spans both columns. If \a row is out of
+ bounds, the widget is added at the end.
+*/
+void QFormLayout::insertRow(int row, QWidget *widget)
+{
+ Q_D(QFormLayout);
+
+ if (!widget) {
+ qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName()));
+ return;
+ }
+
+ row = d->insertRow(row);
+ d->setWidget(row, SpanningRole, widget);
+ invalidate();
+}
+
+/*!
+ \overload
+
+ Inserts the specified \a layout at position \a row in this form
+ layout. The \a layout spans both columns. If \a row is out of
+ bounds, the widget is added at the end.
+*/
+void QFormLayout::insertRow(int row, QLayout *layout)
+{
+ Q_D(QFormLayout);
+
+ if (!layout) {
+ qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName()));
+ return;
+ }
+
+ row = d->insertRow(row);
+ d->setLayout(row, SpanningRole, layout);
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QFormLayout);
+
+ int row = d->insertRow(d->m_matrix.rowCount());
+ d->setItem(row, FieldRole, item);
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+int QFormLayout::count() const
+{
+ Q_D(const QFormLayout);
+ return d->m_things.count();
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QFormLayout::itemAt(int index) const
+{
+ Q_D(const QFormLayout);
+ if (QFormLayoutItem *formItem = d->m_things.value(index))
+ return formItem->item;
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QFormLayout::takeAt(int index)
+{
+ Q_D(QFormLayout);
+
+ const int storageIndex = storageIndexFromLayoutItem(d->m_matrix, d->m_things.value(index));
+ if (storageIndex == -1) {
+ qWarning("QFormLayout::takeAt: Invalid index %d", index);
+ return 0;
+ }
+
+ int row, col;
+ QFormLayoutPrivate::ItemMatrix::storageIndexToPosition(storageIndex, &row, &col);
+ Q_ASSERT(d->m_matrix(row, col));
+
+ QFormLayoutItem *item = d->m_matrix(row, col);
+ Q_ASSERT(item);
+ d->m_things.removeAt(index);
+ d->m_matrix(row, col) = 0;
+
+ invalidate();
+
+ // grab ownership back from the QFormLayoutItem
+ QLayoutItem *i = item->item;
+ item->item = 0;
+ delete item;
+ return i;
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QFormLayout::expandingDirections() const
+{
+ Q_D(const QFormLayout);
+ QFormLayoutPrivate *e = const_cast<QFormLayoutPrivate *>(d);
+ e->updateSizes();
+
+ Qt::Orientations o = 0;
+ if (e->expandHorizontal)
+ o = Qt::Horizontal;
+ if (e->expandVertical)
+ o |= Qt::Vertical;
+ return o;
+}
+
+/*!
+ \reimp
+*/
+bool QFormLayout::hasHeightForWidth() const
+{
+ Q_D(const QFormLayout);
+ QFormLayoutPrivate *e = const_cast<QFormLayoutPrivate *>(d);
+ e->updateSizes();
+ return (d->has_hfw || rowWrapPolicy() == WrapLongRows);
+}
+
+/*!
+ \reimp
+*/
+int QFormLayout::heightForWidth(int width) const
+{
+ Q_D(const QFormLayout);
+ if (!hasHeightForWidth())
+ return -1;
+
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ int targetWidth = width - leftMargin - rightMargin;
+
+ if (!d->haveHfwCached(targetWidth)) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->setupVerticalLayoutData(targetWidth);
+ dat->setupHorizontalLayoutData(targetWidth);
+ dat->recalcHFW(targetWidth);
+ }
+ if (targetWidth == d->sh_width)
+ return d->hfw_sh_height + topMargin + bottomMargin;
+ else
+ return d->hfw_height + topMargin + bottomMargin;
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QFormLayout);
+ if (d->dirty || rect != geometry()) {
+ QRect cr = rect;
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ cr.adjust(+leftMargin, +topMargin, -rightMargin, -bottomMargin);
+
+ bool hfw = hasHeightForWidth();
+ d->setupVerticalLayoutData(cr.width());
+ d->setupHorizontalLayoutData(cr.width());
+ if (hfw && (!d->haveHfwCached(cr.width()) || d->hfwLayouts.size() != d->vLayoutCount))
+ d->recalcHFW(cr.width());
+ if (hfw) {
+ qGeomCalc(d->hfwLayouts, 0, d->vLayoutCount, cr.y(), cr.height());
+ d->arrangeWidgets(d->hfwLayouts, cr);
+ } else {
+ qGeomCalc(d->vLayouts, 0, d->vLayoutCount, cr.y(), cr.height());
+ d->arrangeWidgets(d->vLayouts, cr);
+ }
+ QLayout::setGeometry(rect);
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QFormLayout::sizeHint() const
+{
+ Q_D(const QFormLayout);
+ if (!d->prefSize.isValid()) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->calcSizeHints();
+ }
+ return d->prefSize;
+}
+
+/*!
+ \reimp
+*/
+QSize QFormLayout::minimumSize() const
+{
+ // ### fix minimumSize if hfw
+ Q_D(const QFormLayout);
+ if (!d->minSize.isValid()) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->calcSizeHints();
+ }
+ return d->minSize;
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::invalidate()
+{
+ Q_D(QFormLayout);
+ d->dirty = true;
+ d->sizesDirty = true;
+ d->minSize = QSize();
+ d->prefSize = QSize();
+ d->formMaxWidth = -1;
+ d->hfw_width = -1;
+ d->sh_width = -1;
+ d->layoutWidth = -1;
+ d->hfw_sh_height = -1;
+ QLayout::invalidate();
+}
+
+/*!
+ Returns the number of rows in the form.
+
+ \sa QLayout::count()
+*/
+int QFormLayout::rowCount() const
+{
+ Q_D(const QFormLayout);
+ return d->m_matrix.rowCount();
+}
+
+/*!
+ Returns the layout item in the given \a row with the specified \a
+ role (column). Returns 0 if there is no such item.
+
+ \sa QLayout::itemAt(), setItem()
+*/
+QLayoutItem *QFormLayout::itemAt(int row, ItemRole role) const
+{
+ Q_D(const QFormLayout);
+ if (uint(row) >= uint(d->m_matrix.rowCount()))
+ return 0;
+ switch (role) {
+ case SpanningRole:
+ if (QFormLayoutItem *item = d->m_matrix(row, 1))
+ if (item->fullRow)
+ return item->item;
+ break;
+ case LabelRole:
+ case FieldRole:
+ if (QFormLayoutItem *item = d->m_matrix(row, (role == LabelRole) ? 0 : 1))
+ return item->item;
+ break;
+ }
+ return 0;
+}
+
+/*!
+ Retrieves the row and role (column) of the item at the specified
+ \a index. If \a index is out of bounds, *\a rowPtr is set to -1;
+ otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+
+ \sa itemAt(), count(), getLayoutPosition(), getWidgetPosition()
+*/
+void QFormLayout::getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const
+{
+ Q_D(const QFormLayout);
+ int col = -1;
+ int row = -1;
+
+ const int storageIndex = storageIndexFromLayoutItem(d->m_matrix, d->m_things.value(index));
+ if (storageIndex != -1)
+ QFormLayoutPrivate::ItemMatrix::storageIndexToPosition(storageIndex, &row, &col);
+
+ if (rowPtr)
+ *rowPtr = row;
+ if (rolePtr && col != -1) {
+ const bool spanning = col == 1 && d->m_matrix(row, col)->fullRow;
+ if (spanning) {
+ *rolePtr = SpanningRole;
+ } else {
+ *rolePtr = ItemRole(col);
+ }
+ }
+}
+
+/*!
+ Retrieves the row and role (column) of the specified child \a
+ layout. If \a layout is not in the form layout, *\a rowPtr is set
+ to -1; otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+*/
+void QFormLayout::getLayoutPosition(QLayout *layout, int *rowPtr, ItemRole *rolePtr) const
+{
+ int n = count();
+ int index = 0;
+ while (index < n) {
+ if (itemAt(index) == layout)
+ break;
+ ++index;
+ }
+ getItemPosition(index, rowPtr, rolePtr);
+}
+
+/*!
+ Retrieves the row and role (column) of the specified \a widget in
+ the layout. If \a widget is not in the layout, *\a rowPtr is set
+ to -1; otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+
+ \sa getItemPosition(), itemAt()
+*/
+void QFormLayout::getWidgetPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const
+{
+ getItemPosition(indexOf(widget), rowPtr, rolePtr);
+}
+
+// ### eliminate labelForField()
+
+/*!
+ Returns the label associated with the given \a field.
+
+ \sa itemAt()
+*/
+QWidget *QFormLayout::labelForField(QWidget *field) const
+{
+ Q_D(const QFormLayout);
+
+ int row;
+ ItemRole role;
+
+ getWidgetPosition(field, &row, &role);
+
+ if (row != -1 && role == FieldRole) {
+ if (QFormLayoutItem *label = d->m_matrix(row, LabelRole))
+ return label->widget();
+ }
+ return 0;
+}
+
+/*!
+ \overload
+*/
+QWidget *QFormLayout::labelForField(QLayout *field) const
+{
+ Q_D(const QFormLayout);
+
+ int row;
+ ItemRole role;
+
+ getLayoutPosition(field, &row, &role);
+
+ if (row != -1 && role == FieldRole) {
+ if (QFormLayoutItem *label = d->m_matrix(row, LabelRole))
+ return label->widget();
+ }
+ return 0;
+}
+
+/*!
+ \property QFormLayout::fieldGrowthPolicy
+ \brief the way in which the form's fields grow
+
+ The default value depends on the widget or application style. For
+ QMacStyle, the default is FieldsStayAtSizeHint; for QCommonStyle
+ derived styles (like Plastique and Windows), the default
+ is ExpandingFieldsGrow; for Qt Extended styles, the default is
+ AllNonFixedFieldsGrow.
+
+ If none of the fields can grow and the form is resized, extra
+ space is distributed according to the current
+ \l{formAlignment}{form alignment}.
+
+ \sa formAlignment, rowWrapPolicy
+*/
+
+void QFormLayout::setFieldGrowthPolicy(FieldGrowthPolicy policy)
+{
+ Q_D(QFormLayout);
+ if (FieldGrowthPolicy(d->fieldGrowthPolicy) != policy) {
+ d->fieldGrowthPolicy = policy;
+ invalidate();
+ }
+}
+
+QFormLayout::FieldGrowthPolicy QFormLayout::fieldGrowthPolicy() const
+{
+ Q_D(const QFormLayout);
+ if (d->fieldGrowthPolicy == DefaultFieldGrowthPolicy) {
+ return QFormLayout::FieldGrowthPolicy(d->getStyle()->styleHint(QStyle::SH_FormLayoutFieldGrowthPolicy));
+ } else {
+ return QFormLayout::FieldGrowthPolicy(d->fieldGrowthPolicy);
+ }
+}
+
+/*!
+ \property QFormLayout::rowWrapPolicy
+ \brief the way in which the form's rows wrap
+
+ The default value depends on the widget or application style. For
+ Qt Extended styles and QS60Style, the default is WrapLongRows;
+ for the other styles, the default is DontWrapRows.
+
+ If you want to display each label above its associated field
+ (instead of next to it), set this property to WrapAllRows.
+
+ \sa fieldGrowthPolicy
+*/
+
+void QFormLayout::setRowWrapPolicy(RowWrapPolicy policy)
+{
+ Q_D(QFormLayout);
+ if (RowWrapPolicy(d->rowWrapPolicy) != policy) {
+ d->rowWrapPolicy = policy;
+ invalidate();
+ }
+}
+
+QFormLayout::RowWrapPolicy QFormLayout::rowWrapPolicy() const
+{
+ Q_D(const QFormLayout);
+ if (d->rowWrapPolicy == DefaultRowWrapPolicy) {
+ return QFormLayout::RowWrapPolicy(d->getStyle()->styleHint(QStyle::SH_FormLayoutWrapPolicy));
+ } else {
+ return QFormLayout::RowWrapPolicy(d->rowWrapPolicy);
+ }
+}
+
+/*!
+ \property QFormLayout::labelAlignment
+ \brief the horizontal alignment of the labels
+
+ The default value depends on the widget or application style. For
+ QCommonStyle derived styles, except for QPlastiqueStyle, the
+ default is Qt::AlignLeft; for the other styles, the default is
+ Qt::AlignRight.
+
+ \sa formAlignment
+*/
+
+void QFormLayout::setLabelAlignment(Qt::Alignment alignment)
+{
+ Q_D(QFormLayout);
+ if (d->labelAlignment != alignment) {
+ d->labelAlignment = alignment;
+ invalidate();
+ }
+}
+
+Qt::Alignment QFormLayout::labelAlignment() const
+{
+ Q_D(const QFormLayout);
+ if (!d->labelAlignment) {
+ return Qt::Alignment(d->getStyle()->styleHint(QStyle::SH_FormLayoutLabelAlignment));
+ } else {
+ return d->labelAlignment;
+ }
+}
+
+/*!
+ \property QFormLayout::formAlignment
+ \brief the alignment of the form layout's contents within the layout's geometry
+
+ The default value depends on the widget or application style. For
+ QMacStyle, the default is Qt::AlignHCenter | Qt::AlignTop; for the
+ other styles, the default is Qt::AlignLeft | Qt::AlignTop.
+
+ \sa labelAlignment, rowWrapPolicy
+*/
+
+void QFormLayout::setFormAlignment(Qt::Alignment alignment)
+{
+ Q_D(QFormLayout);
+ if (d->formAlignment != alignment) {
+ d->formAlignment = alignment;
+ invalidate();
+ }
+}
+
+Qt::Alignment QFormLayout::formAlignment() const
+{
+ Q_D(const QFormLayout);
+ if (!d->formAlignment) {
+ return Qt::Alignment(d->getStyle()->styleHint(QStyle::SH_FormLayoutFormAlignment));
+ } else {
+ return d->formAlignment;
+ }
+}
+
+/*!
+ \property QFormLayout::horizontalSpacing
+ \brief the spacing between widgets that are laid out side by side
+
+ By default, if no value is explicitly set, the layout's horizontal
+ spacing is inherited from the parent layout, or from the style settings
+ for the parent widget.
+
+ \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QFormLayout::setHorizontalSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ if (spacing != d->hSpacing) {
+ d->hSpacing = spacing;
+ invalidate();
+ }
+}
+
+int QFormLayout::horizontalSpacing() const
+{
+ Q_D(const QFormLayout);
+ if (d->hSpacing >= 0) {
+ return d->hSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+}
+
+/*!
+ \property QFormLayout::verticalSpacing
+ \brief the spacing between widgets that are laid out vertically
+
+ By default, if no value is explicitly set, the layout's vertical spacing is
+ inherited from the parent layout, or from the style settings for the parent
+ widget.
+
+ \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QFormLayout::setVerticalSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ if (spacing != d->vSpacing) {
+ d->vSpacing = spacing;
+ invalidate();
+ }
+}
+
+int QFormLayout::verticalSpacing() const
+{
+ Q_D(const QFormLayout);
+ if (d->vSpacing >= 0) {
+ return d->vSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ This function sets both the vertical and horizontal spacing to
+ \a spacing.
+
+ \sa setVerticalSpacing(), setHorizontalSpacing()
+*/
+void QFormLayout::setSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ d->vSpacing = d->hSpacing = spacing;
+ invalidate();
+}
+
+/*!
+ If the vertical spacing is equal to the horizontal spacing,
+ this function returns that value; otherwise it returns -1.
+
+ \sa setSpacing(), verticalSpacing(), horizontalSpacing()
+*/
+int QFormLayout::spacing() const
+{
+ int hSpacing = horizontalSpacing();
+ if (hSpacing == verticalSpacing()) {
+ return hSpacing;
+ } else {
+ return -1;
+ }
+}
+
+void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, QRect &rect)
+{
+ Q_Q(QFormLayout);
+
+ int i;
+ const int rr = m_matrix.rowCount();
+ QWidget *w = q->parentWidget();
+ Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection();
+
+ Qt::Alignment formAlignment = fixedAlignment(q->formAlignment(), layoutDirection);
+ int leftOffset = 0;
+ int delta = rect.width() - formMaxWidth;
+ if (formAlignment & (Qt::AlignHCenter | Qt::AlignRight) && delta > 0) {
+ leftOffset = delta;
+ if (formAlignment & Qt::AlignHCenter)
+ leftOffset >>= 1;
+ }
+
+ for (i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ if (label) {
+ int height = layouts.at(label->vLayoutIndex).size;
+ if ((label->expandingDirections() & Qt::Vertical) == 0) {
+ /*
+ If the field on the right-hand side is tall,
+ we want the label to be top-aligned, but not too
+ much. So we introduce a 7 / 4 factor so that it
+ gets some extra pixels at the top.
+ */
+ height = qMin(height,
+ qMin(label->sizeHint.height() * 7 / 4,
+ label->maxSize.height()));
+ }
+
+ QSize sz(qMin(label->layoutWidth, label->sizeHint.width()), height);
+ int x = leftOffset + rect.x() + label->layoutPos;
+ if (fixedAlignment(q->labelAlignment(), layoutDirection) & Qt::AlignRight)
+ x += label->layoutWidth - sz.width();
+ QPoint p(x, layouts.at(label->vLayoutIndex).pos);
+ // ### expansion & sizepolicy stuff
+
+ label->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
+ }
+
+ if (field) {
+ QSize sz(field->layoutWidth, layouts.at(field->vLayoutIndex).size);
+ QPoint p(field->layoutPos + leftOffset + rect.x(), layouts.at(field->vLayoutIndex).pos);
+/*
+ if ((field->widget() && field->widget()->sizePolicy().horizontalPolicy() & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag | QSizePolicy::IgnoreFlag))
+ || (field->layout() && sz.width() < field->maxSize.width())) {
+ sz.rwidth() = field->layoutWidth;
+ }
+*/
+ if (field->maxSize.isValid())
+ sz = sz.boundedTo(field->maxSize);
+
+ field->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
+ }
+ }
+}
+
+/*!
+ Sets the widget in the given \a row for the given \a role to \a widget, extending the
+ layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a widget is not inserted and an error message is
+ sent to the console.
+
+ \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setWidget().
+
+ \sa setLayout()
+*/
+void QFormLayout::setWidget(int row, ItemRole role, QWidget *widget)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setWidget(row, role, widget);
+}
+
+/*!
+ Sets the sub-layout in the given \a row for the given \a role to \a layout, extending the
+ form layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a layout is not inserted and an error message is
+ sent to the console.
+
+ \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setLayout().
+
+ \sa setWidget()
+*/
+void QFormLayout::setLayout(int row, ItemRole role, QLayout *layout)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setLayout(row, role, layout);
+}
+
+/*!
+ Sets the item in the given \a row for the given \a role to \a item, extending the
+ layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a item is not inserted and an error message is
+ sent to the console.
+ The \a item spans both columns.
+
+ \warning Do not use this function to add child layouts or child
+ widget items. Use setLayout() or setWidget() instead.
+
+ \sa setLayout()
+*/
+void QFormLayout::setItem(int row, ItemRole role, QLayoutItem *item)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setItem(row, role, item);
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetFieldGrowthPolicy()
+{
+ Q_D(QFormLayout);
+ d->fieldGrowthPolicy = DefaultFieldGrowthPolicy;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetRowWrapPolicy()
+{
+ Q_D(QFormLayout);
+ d->rowWrapPolicy = DefaultRowWrapPolicy;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetFormAlignment()
+{
+ Q_D(QFormLayout);
+ d->formAlignment = 0;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetLabelAlignment()
+{
+ Q_D(QFormLayout);
+ d->labelAlignment = 0;
+}
+
+#if 0
+void QFormLayout::dump() const
+{
+ Q_D(const QFormLayout);
+ for (int i = 0; i < rowCount(); ++i) {
+ for (int j = 0; j < 2; ++j) {
+ qDebug("m_matrix(%d, %d) = %p", i, j, d->m_matrix(i, j));
+ }
+ }
+ for (int i = 0; i < d->m_things.count(); ++i)
+ qDebug("m_things[%d] = %p", i, d->m_things.at(i));
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qformlayout.h b/src/widgets/kernel/qformlayout.h
new file mode 100644
index 0000000000..f229ac2d83
--- /dev/null
+++ b/src/widgets/kernel/qformlayout.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFORMLAYOUT_H
+#define QFORMLAYOUT_H
+
+#include <QtGui/QLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QFormLayoutPrivate;
+
+class Q_GUI_EXPORT QFormLayout : public QLayout
+{
+ Q_OBJECT
+ Q_ENUMS(FormStyle FieldGrowthPolicy RowWrapPolicy ItemRole)
+ Q_DECLARE_PRIVATE(QFormLayout)
+ Q_PROPERTY(FieldGrowthPolicy fieldGrowthPolicy READ fieldGrowthPolicy WRITE setFieldGrowthPolicy RESET resetFieldGrowthPolicy)
+ Q_PROPERTY(RowWrapPolicy rowWrapPolicy READ rowWrapPolicy WRITE setRowWrapPolicy RESET resetRowWrapPolicy)
+ Q_PROPERTY(Qt::Alignment labelAlignment READ labelAlignment WRITE setLabelAlignment RESET resetLabelAlignment)
+ Q_PROPERTY(Qt::Alignment formAlignment READ formAlignment WRITE setFormAlignment RESET resetFormAlignment)
+ Q_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ Q_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+
+public:
+ enum FieldGrowthPolicy {
+ FieldsStayAtSizeHint,
+ ExpandingFieldsGrow,
+ AllNonFixedFieldsGrow
+ };
+
+ enum RowWrapPolicy {
+ DontWrapRows,
+ WrapLongRows,
+ WrapAllRows
+ };
+
+ enum ItemRole {
+ LabelRole = 0,
+ FieldRole = 1,
+ SpanningRole = 2
+ };
+
+ explicit QFormLayout(QWidget *parent = 0);
+ ~QFormLayout();
+
+ void setFieldGrowthPolicy(FieldGrowthPolicy policy);
+ FieldGrowthPolicy fieldGrowthPolicy() const;
+ void setRowWrapPolicy(RowWrapPolicy policy);
+ RowWrapPolicy rowWrapPolicy() const;
+ void setLabelAlignment(Qt::Alignment alignment);
+ Qt::Alignment labelAlignment() const;
+ void setFormAlignment(Qt::Alignment alignment);
+ Qt::Alignment formAlignment() const;
+
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+
+ int spacing() const;
+ void setSpacing(int);
+
+ void addRow(QWidget *label, QWidget *field);
+ void addRow(QWidget *label, QLayout *field);
+ void addRow(const QString &labelText, QWidget *field);
+ void addRow(const QString &labelText, QLayout *field);
+ void addRow(QWidget *widget);
+ void addRow(QLayout *layout);
+
+ void insertRow(int row, QWidget *label, QWidget *field);
+ void insertRow(int row, QWidget *label, QLayout *field);
+ void insertRow(int row, const QString &labelText, QWidget *field);
+ void insertRow(int row, const QString &labelText, QLayout *field);
+ void insertRow(int row, QWidget *widget);
+ void insertRow(int row, QLayout *layout);
+
+ void setItem(int row, ItemRole role, QLayoutItem *item);
+ void setWidget(int row, ItemRole role, QWidget *widget);
+ void setLayout(int row, ItemRole role, QLayout *layout);
+
+ QLayoutItem *itemAt(int row, ItemRole role) const;
+ void getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const;
+ void getWidgetPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const;
+ void getLayoutPosition(QLayout *layout, int *rowPtr, ItemRole *rolePtr) const;
+ QWidget *labelForField(QWidget *field) const;
+ QWidget *labelForField(QLayout *field) const;
+
+ // reimplemented from QLayout
+ void addItem(QLayoutItem *item);
+ QLayoutItem *itemAt(int index) const;
+ QLayoutItem *takeAt(int index);
+
+ void setGeometry(const QRect &rect);
+ QSize minimumSize() const;
+ QSize sizeHint() const;
+ void invalidate();
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
+ Qt::Orientations expandingDirections() const;
+ int count() const;
+
+ int rowCount() const;
+
+#if 0
+ void dump() const;
+#endif
+
+private:
+ void resetFieldGrowthPolicy();
+ void resetRowWrapPolicy();
+ void resetLabelAlignment();
+ void resetFormAlignment();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp
new file mode 100644
index 0000000000..daabe4f436
--- /dev/null
+++ b/src/widgets/kernel/qgesture.cpp
@@ -0,0 +1,1118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesture.h"
+#include "private/qgesture_p.h"
+#include "private/qstandardgestures_p.h"
+#include "qgraphicsview.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+ /*!
+ \class QGesture
+ \since 4.6
+ \ingroup gestures
+
+ \brief The QGesture class represents a gesture, containing properties that
+ describe the corresponding user input.
+
+ Gesture objects are not constructed directly by developers. They are created by
+ the QGestureRecognizer object that is registered with the application; see
+ QGestureRecognizer::registerRecognizer().
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \section1 Gesture Properties
+
+ The class has a list of properties that can be queried by the user to get
+ some gesture-specific arguments. For example, the pinch gesture has a scale
+ factor that is exposed as a property.
+
+ Developers of custom gesture recognizers can add additional properties in
+ order to provide additional information about a gesture. This can be done
+ by adding new dynamic properties to a QGesture object, or by subclassing
+ the QGesture class (or one of its subclasses).
+
+ \section1 Lifecycle of a Gesture Object
+
+ A QGesture instance is implicitly created when needed and is owned by Qt.
+ Developers should never destroy them or store them for later use as Qt may
+ destroy particular instances of them and create new ones to replace them.
+
+ The registered gesture recognizer monitors the input events for the target
+ object via its \l{QGestureRecognizer::}{recognize()} function, updating the
+ properties of the gesture object as required.
+
+ The gesture object may be delivered to the target object in a QGestureEvent if
+ the corresponding gesture is active or has just been canceled. Each event that
+ is delivered contains a list of gesture objects, since support for more than
+ one gesture may be enabled for the target object. Due to the way events are
+ handled in Qt, gesture events may be filtered by other objects.
+
+ \sa QGestureEvent, QGestureRecognizer
+*/
+
+/*!
+ Constructs a new gesture object with the given \a parent.
+
+ QGesture objects are created by gesture recognizers in the
+ QGestureRecognizer::create() function.
+*/
+QGesture::QGesture(QObject *parent)
+ : QObject(*new QGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::CustomGesture;
+}
+
+/*!
+ \internal
+*/
+QGesture::QGesture(QGesturePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Destroys the gesture object.
+*/
+QGesture::~QGesture()
+{
+}
+
+/*!
+ \property QGesture::state
+ \brief the current state of the gesture
+*/
+
+/*!
+ \property QGesture::gestureType
+ \brief the type of the gesture
+*/
+
+/*!
+ \property QGesture::hotSpot
+
+ \brief The point that is used to find the receiver for the gesture event.
+
+ The hot-spot is a point in the global coordinate system, use
+ QWidget::mapFromGlobal() or QGestureEvent::mapToGraphicsScene() to get a
+ local hot-spot.
+
+ The hot-spot should be set by the gesture recognizer to allow gesture event
+ delivery to a QGraphicsObject.
+*/
+
+/*!
+ \property QGesture::hasHotSpot
+ \brief whether the gesture has a hot-spot
+*/
+
+Qt::GestureType QGesture::gestureType() const
+{
+ return d_func()->gestureType;
+}
+
+Qt::GestureState QGesture::state() const
+{
+ return d_func()->state;
+}
+
+QPointF QGesture::hotSpot() const
+{
+ return d_func()->hotSpot;
+}
+
+void QGesture::setHotSpot(const QPointF &value)
+{
+ Q_D(QGesture);
+ d->hotSpot = value;
+ d->isHotSpotSet = true;
+}
+
+bool QGesture::hasHotSpot() const
+{
+ return d_func()->isHotSpotSet;
+}
+
+void QGesture::unsetHotSpot()
+{
+ d_func()->isHotSpotSet = false;
+}
+
+/*!
+ \property QGesture::gestureCancelPolicy
+ \brief the policy for deciding what happens on accepting a gesture
+
+ On accepting one gesture Qt can automatically cancel other gestures
+ that belong to other targets. The policy is normally set to not cancel
+ any other gestures and can be set to cancel all active gestures in the
+ context. For example for all child widgets.
+*/
+
+/*!
+ \enum QGesture::GestureCancelPolicy
+
+ This enum describes how accepting a gesture can cancel other gestures
+ automatically.
+
+ \value CancelNone On accepting this gesture no other gestures will be affected.
+
+ \value CancelAllInContext On accepting this gesture all gestures that are
+ active in the context (respecting the Qt::GestureFlag that were specified
+ when subscribed to the gesture) will be cancelled.
+*/
+
+void QGesture::setGestureCancelPolicy(GestureCancelPolicy policy)
+{
+ Q_D(QGesture);
+ d->gestureCancelPolicy = static_cast<uint>(policy);
+}
+
+QGesture::GestureCancelPolicy QGesture::gestureCancelPolicy() const
+{
+ Q_D(const QGesture);
+ return static_cast<GestureCancelPolicy>(d->gestureCancelPolicy);
+}
+
+/*!
+ \class QPanGesture
+ \since 4.6
+ \brief The QPanGesture class describes a panning gesture made by the user.
+ \ingroup gestures
+
+ \image pangesture.png
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \sa QPinchGesture, QSwipeGesture
+*/
+
+/*!
+ \property QPanGesture::lastOffset
+ \brief the last offset recorded for this gesture
+
+ The last offset contains the change in position of the user's input as
+ reported in the \l offset property when a previous gesture event was
+ delivered for this gesture.
+
+ If no previous event was delivered with information about this gesture
+ (i.e., this gesture object contains information about the first movement
+ in the gesture) then this property contains a zero size.
+*/
+
+/*!
+ \property QPanGesture::offset
+ \brief the total offset from the first input position to the current input
+ position
+
+ The offset measures the total change in position of the user's input
+ covered by the gesture on the input device.
+*/
+
+/*!
+ \property QPanGesture::delta
+ \brief the offset from the previous input position to the current input
+
+ This is essentially the same as the difference between offset() and
+ lastOffset().
+*/
+
+/*!
+ \property QPanGesture::acceleration
+ \brief the acceleration in the motion of the touch point for this gesture
+*/
+
+/*!
+ \property QPanGesture::horizontalVelocity
+ \brief the horizontal component of the motion of the touch point for this
+ gesture
+ \since 4.7.1
+ \internal
+
+ \sa verticalVelocity, acceleration
+*/
+
+/*!
+ \property QPanGesture::verticalVelocity
+ \brief the vertical component of the motion of the touch point for this
+ gesture
+ \since 4.7.1
+ \internal
+
+ \sa horizontalVelocity, acceleration
+*/
+
+/*!
+ \internal
+*/
+QPanGesture::QPanGesture(QObject *parent)
+ : QGesture(*new QPanGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::PanGesture;
+}
+
+
+QPointF QPanGesture::lastOffset() const
+{
+ return d_func()->lastOffset;
+}
+
+QPointF QPanGesture::offset() const
+{
+ return d_func()->offset;
+}
+
+QPointF QPanGesture::delta() const
+{
+ Q_D(const QPanGesture);
+ return d->offset - d->lastOffset;
+}
+
+qreal QPanGesture::acceleration() const
+{
+ return d_func()->acceleration;
+}
+
+void QPanGesture::setLastOffset(const QPointF &value)
+{
+ d_func()->lastOffset = value;
+}
+
+void QPanGesture::setOffset(const QPointF &value)
+{
+ d_func()->offset = value;
+}
+
+void QPanGesture::setAcceleration(qreal value)
+{
+ d_func()->acceleration = value;
+}
+
+/*!
+ \class QPinchGesture
+ \since 4.6
+ \brief The QPinchGesture class describes a pinch gesture made by the user.
+ \ingroup touch
+ \ingroup gestures
+
+ A pinch gesture is a form of touch user input in which the user typically
+ touches two points on the input device with a thumb and finger, before moving
+ them closer together or further apart to change the scale factor, zoom, or level
+ of detail of the user interface.
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \image pinchgesture.png
+
+ Instead of repeatedly applying the same pinching gesture, the user may
+ continue to touch the input device in one place, and apply a second touch
+ to a new point, continuing the gesture. When this occurs, gesture events
+ will continue to be delivered to the target object, containing an instance
+ of QPinchGesture in the Qt::GestureUpdated state.
+
+ \sa QPanGesture, QSwipeGesture
+*/
+
+/*!
+ \enum QPinchGesture::ChangeFlag
+
+ This enum describes the changes that can occur to the properties of
+ the gesture object.
+
+ \value ScaleFactorChanged The scale factor held by scaleFactor changed.
+ \value RotationAngleChanged The rotation angle held by rotationAngle changed.
+ \value CenterPointChanged The center point held by centerPoint changed.
+
+ \sa changeFlags, totalChangeFlags
+*/
+
+/*!
+ \property QPinchGesture::totalChangeFlags
+ \brief the property of the gesture that has change
+
+ This property indicates which of the other properties has changed since the
+ gesture has started. You can use this information to determine which aspect
+ of your user interface needs to be updated.
+
+ \sa changeFlags, scaleFactor, rotationAngle, centerPoint
+*/
+
+/*!
+ \property QPinchGesture::changeFlags
+ \brief the property of the gesture that has changed in the current step
+
+ This property indicates which of the other properties has changed since
+ the previous gesture event included information about this gesture. You
+ can use this information to determine which aspect of your user interface
+ needs to be updated.
+
+ \sa totalChangeFlags, scaleFactor, rotationAngle, centerPoint
+*/
+
+/*!
+ \property QPinchGesture::totalScaleFactor
+ \brief the total scale factor
+
+ The total scale factor measures the total change in scale factor from the
+ original value to the current scale factor.
+
+ \sa scaleFactor, lastScaleFactor
+*/
+/*!
+ \property QPinchGesture::lastScaleFactor
+ \brief the last scale factor recorded for this gesture
+
+ The last scale factor contains the scale factor reported in the
+ \l scaleFactor property when a previous gesture event included
+ information about this gesture.
+
+ If no previous event was delivered with information about this gesture
+ (i.e., this gesture object contains information about the first movement
+ in the gesture) then this property contains zero.
+
+ \sa scaleFactor, totalScaleFactor
+*/
+/*!
+ \property QPinchGesture::scaleFactor
+ \brief the current scale factor
+
+ The scale factor measures the scale factor associated with the distance
+ between two of the user's inputs on a touch device.
+
+ \sa totalScaleFactor, lastScaleFactor
+*/
+
+/*!
+ \property QPinchGesture::totalRotationAngle
+ \brief the total angle covered by the gesture
+
+ This total angle measures the complete angle covered by the gesture. Usually, this
+ is equal to the value held by the \l rotationAngle property, except in the case where
+ the user performs multiple rotations by removing and repositioning one of the touch
+ points, as described above. In this case, the total angle will be the sum of the
+ rotation angles for the multiple stages of the gesture.
+
+ \sa rotationAngle, lastRotationAngle
+*/
+/*!
+ \property QPinchGesture::lastRotationAngle
+ \brief the last reported angle covered by the gesture motion
+
+ The last rotation angle is the angle as reported in the \l rotationAngle property
+ when a previous gesture event was delivered for this gesture.
+
+ \sa rotationAngle, totalRotationAngle
+*/
+/*!
+ \property QPinchGesture::rotationAngle
+ \brief the angle covered by the gesture motion
+
+ \sa totalRotationAngle, lastRotationAngle
+*/
+
+/*!
+ \property QPinchGesture::startCenterPoint
+ \brief the starting position of the center point
+
+ \sa centerPoint, lastCenterPoint
+*/
+/*!
+ \property QPinchGesture::lastCenterPoint
+ \brief the last position of the center point recorded for this gesture
+
+ \sa centerPoint, startCenterPoint
+*/
+/*!
+ \property QPinchGesture::centerPoint
+ \brief the current center point
+
+ The center point is the midpoint between the two input points in the gesture.
+
+ \sa startCenterPoint, lastCenterPoint
+*/
+
+/*!
+ \internal
+*/
+QPinchGesture::QPinchGesture(QObject *parent)
+ : QGesture(*new QPinchGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::PinchGesture;
+}
+
+QPinchGesture::ChangeFlags QPinchGesture::totalChangeFlags() const
+{
+ return d_func()->totalChangeFlags;
+}
+
+void QPinchGesture::setTotalChangeFlags(QPinchGesture::ChangeFlags value)
+{
+ d_func()->totalChangeFlags = value;
+}
+
+QPinchGesture::ChangeFlags QPinchGesture::changeFlags() const
+{
+ return d_func()->changeFlags;
+}
+
+void QPinchGesture::setChangeFlags(QPinchGesture::ChangeFlags value)
+{
+ d_func()->changeFlags = value;
+}
+
+QPointF QPinchGesture::startCenterPoint() const
+{
+ return d_func()->startCenterPoint;
+}
+
+QPointF QPinchGesture::lastCenterPoint() const
+{
+ return d_func()->lastCenterPoint;
+}
+
+QPointF QPinchGesture::centerPoint() const
+{
+ return d_func()->centerPoint;
+}
+
+void QPinchGesture::setStartCenterPoint(const QPointF &value)
+{
+ d_func()->startCenterPoint = value;
+}
+
+void QPinchGesture::setLastCenterPoint(const QPointF &value)
+{
+ d_func()->lastCenterPoint = value;
+}
+
+void QPinchGesture::setCenterPoint(const QPointF &value)
+{
+ d_func()->centerPoint = value;
+}
+
+
+qreal QPinchGesture::totalScaleFactor() const
+{
+ return d_func()->totalScaleFactor;
+}
+
+qreal QPinchGesture::lastScaleFactor() const
+{
+ return d_func()->lastScaleFactor;
+}
+
+qreal QPinchGesture::scaleFactor() const
+{
+ return d_func()->scaleFactor;
+}
+
+void QPinchGesture::setTotalScaleFactor(qreal value)
+{
+ d_func()->totalScaleFactor = value;
+}
+
+void QPinchGesture::setLastScaleFactor(qreal value)
+{
+ d_func()->lastScaleFactor = value;
+}
+
+void QPinchGesture::setScaleFactor(qreal value)
+{
+ d_func()->scaleFactor = value;
+}
+
+
+qreal QPinchGesture::totalRotationAngle() const
+{
+ return d_func()->totalRotationAngle;
+}
+
+qreal QPinchGesture::lastRotationAngle() const
+{
+ return d_func()->lastRotationAngle;
+}
+
+qreal QPinchGesture::rotationAngle() const
+{
+ return d_func()->rotationAngle;
+}
+
+void QPinchGesture::setTotalRotationAngle(qreal value)
+{
+ d_func()->totalRotationAngle = value;
+}
+
+void QPinchGesture::setLastRotationAngle(qreal value)
+{
+ d_func()->lastRotationAngle = value;
+}
+
+void QPinchGesture::setRotationAngle(qreal value)
+{
+ d_func()->rotationAngle = value;
+}
+
+/*!
+ \class QSwipeGesture
+ \since 4.6
+ \brief The QSwipeGesture class describes a swipe gesture made by the user.
+ \ingroup gestures
+
+ \image swipegesture.png
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \sa QPanGesture, QPinchGesture
+*/
+
+/*!
+ \enum QSwipeGesture::SwipeDirection
+
+ This enum describes the possible directions for the gesture's motion
+ along the horizontal and vertical axes.
+
+ \value NoDirection The gesture had no motion associated with it on a particular axis.
+ \value Left The gesture involved a horizontal motion to the left.
+ \value Right The gesture involved a horizontal motion to the right.
+ \value Up The gesture involved an upward vertical motion.
+ \value Down The gesture involved a downward vertical motion.
+*/
+
+/*!
+ \property QSwipeGesture::horizontalDirection
+ \brief the horizontal direction of the gesture
+
+ If the gesture has a horizontal component, the horizontal direction
+ is either Left or Right; otherwise, it is NoDirection.
+
+ \sa verticalDirection, swipeAngle
+*/
+
+/*!
+ \property QSwipeGesture::verticalDirection
+ \brief the vertical direction of the gesture
+
+ If the gesture has a vertical component, the vertical direction
+ is either Up or Down; otherwise, it is NoDirection.
+
+ \sa horizontalDirection, swipeAngle
+*/
+
+/*!
+ \property QSwipeGesture::swipeAngle
+ \brief the angle of the motion associated with the gesture
+
+ If the gesture has either a horizontal or vertical component, the
+ swipe angle describes the angle between the direction of motion and the
+ x-axis as defined using the standard widget
+ \l{Coordinate System}{coordinate system}.
+
+ \sa horizontalDirection, verticalDirection
+*/
+
+/*!
+ \property QSwipeGesture::velocity
+ \since 4.7.1
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QSwipeGesture::QSwipeGesture(QObject *parent)
+ : QGesture(*new QSwipeGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::SwipeGesture;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 90 || d->swipeAngle > 270)
+ return QSwipeGesture::Right;
+ else
+ return QSwipeGesture::Left;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle <= 0 || d->swipeAngle == 180)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 180)
+ return QSwipeGesture::Up;
+ else
+ return QSwipeGesture::Down;
+}
+
+qreal QSwipeGesture::swipeAngle() const
+{
+ return d_func()->swipeAngle;
+}
+
+void QSwipeGesture::setSwipeAngle(qreal value)
+{
+ d_func()->swipeAngle = value;
+}
+
+/*!
+ \class QTapGesture
+ \since 4.6
+ \brief The QTapGesture class describes a tap gesture made by the user.
+ \ingroup gestures
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \sa QPanGesture, QPinchGesture
+*/
+
+/*!
+ \property QTapGesture::position
+ \brief the position of the tap
+*/
+
+/*!
+ \internal
+*/
+QTapGesture::QTapGesture(QObject *parent)
+ : QGesture(*new QTapGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::TapGesture;
+}
+
+QPointF QTapGesture::position() const
+{
+ return d_func()->position;
+}
+
+void QTapGesture::setPosition(const QPointF &value)
+{
+ d_func()->position = value;
+}
+/*!
+ \class QTapAndHoldGesture
+ \since 4.6
+ \brief The QTapAndHoldGesture class describes a tap-and-hold (aka LongTap)
+ gesture made by the user.
+ \ingroup gestures
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \sa QPanGesture, QPinchGesture
+*/
+
+/*!
+ \property QTapAndHoldGesture::position
+ \brief the position of the tap
+*/
+
+/*!
+ \internal
+*/
+QTapAndHoldGesture::QTapAndHoldGesture(QObject *parent)
+ : QGesture(*new QTapAndHoldGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::TapAndHoldGesture;
+}
+
+QPointF QTapAndHoldGesture::position() const
+{
+ return d_func()->position;
+}
+
+void QTapAndHoldGesture::setPosition(const QPointF &value)
+{
+ d_func()->position = value;
+}
+
+/*!
+ Set the timeout, in milliseconds, before the gesture triggers.
+
+ The recognizer will detect a touch down and and if \a msecs
+ later the touch is still down, it will trigger the QTapAndHoldGesture.
+ The default value is 700 milliseconds.
+*/
+// static
+void QTapAndHoldGesture::setTimeout(int msecs)
+{
+ QTapAndHoldGesturePrivate::Timeout = msecs;
+}
+
+/*!
+ Gets the timeout, in milliseconds, before the gesture triggers.
+
+ The recognizer will detect a touch down and and if timeout()
+ later the touch is still down, it will trigger the QTapAndHoldGesture.
+ The default value is 700 milliseconds.
+*/
+// static
+int QTapAndHoldGesture::timeout()
+{
+ return QTapAndHoldGesturePrivate::Timeout;
+}
+
+int QTapAndHoldGesturePrivate::Timeout = 700; // in ms
+
+
+/*!
+ \class QGestureEvent
+ \since 4.6
+ \ingroup events
+ \ingroup gestures
+
+ \brief The QGestureEvent class provides the description of triggered gestures.
+
+ The QGestureEvent class contains a list of gestures, which can be obtained using the
+ gestures() function.
+
+ The gestures are either active or canceled. A list of those that are currently being
+ executed can be obtained using the activeGestures() function. A list of those which
+ were previously active and have been canceled can be accessed using the
+ canceledGestures() function. A gesture might be canceled if the current window loses
+ focus, for example, or because of a timeout, or for other reasons.
+
+ If the event handler does not accept the event by calling the generic
+ QEvent::accept() function, all individual QGesture object that were not
+ accepted and in the Qt::GestureStarted state will be propagated up the
+ parent widget chain until a widget accepts them individually, by calling
+ QGestureEvent::accept() for each of them, or an event filter consumes the
+ event.
+
+ \section1 Further Reading
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \sa QGesture, QGestureRecognizer,
+ QWidget::grabGesture(), QGraphicsObject::grabGesture()
+*/
+
+/*!
+ Creates new QGestureEvent containing a list of \a gestures.
+*/
+QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures)
+ : QEvent(QEvent::Gesture)
+{
+ d = reinterpret_cast<QEventPrivate *>(new QGestureEventPrivate(gestures));
+}
+
+/*!
+ Destroys QGestureEvent.
+*/
+QGestureEvent::~QGestureEvent()
+{
+ delete reinterpret_cast<QGestureEventPrivate *>(d);
+}
+
+/*!
+ Returns all gestures that are delivered in the event.
+*/
+QList<QGesture *> QGestureEvent::gestures() const
+{
+ return d_func()->gestures;
+}
+
+/*!
+ Returns a gesture object by \a type.
+*/
+QGesture *QGestureEvent::gesture(Qt::GestureType type) const
+{
+ const QGestureEventPrivate *d = d_func();
+ for(int i = 0; i < d->gestures.size(); ++i)
+ if (d->gestures.at(i)->gestureType() == type)
+ return d->gestures.at(i);
+ return 0;
+}
+
+/*!
+ Returns a list of active (not canceled) gestures.
+*/
+QList<QGesture *> QGestureEvent::activeGestures() const
+{
+ QList<QGesture *> gestures;
+ foreach (QGesture *gesture, d_func()->gestures) {
+ if (gesture->state() != Qt::GestureCanceled)
+ gestures.append(gesture);
+ }
+ return gestures;
+}
+
+/*!
+ Returns a list of canceled gestures.
+*/
+QList<QGesture *> QGestureEvent::canceledGestures() const
+{
+ QList<QGesture *> gestures;
+ foreach (QGesture *gesture, d_func()->gestures) {
+ if (gesture->state() == Qt::GestureCanceled)
+ gestures.append(gesture);
+ }
+ return gestures;
+}
+
+/*!
+ Sets the accept flag of the given \a gesture object to the specified \a value.
+
+ Setting the accept flag indicates that the event receiver wants the \a gesture.
+ Unwanted gestures may be propagated to the parent widget.
+
+ By default, gestures in events of type QEvent::Gesture are accepted, and
+ gestures in QEvent::GestureOverride events are ignored.
+
+ For convenience, the accept flag can also be set with
+ \l{QGestureEvent::accept()}{accept(gesture)}, and cleared with
+ \l{QGestureEvent::ignore()}{ignore(gesture)}.
+*/
+void QGestureEvent::setAccepted(QGesture *gesture, bool value)
+{
+ if (gesture)
+ setAccepted(gesture->gestureType(), value);
+}
+
+/*!
+ Sets the accept flag of the given \a gesture object, the equivalent of calling
+ \l{QGestureEvent::setAccepted()}{setAccepted(gesture, true)}.
+
+ Setting the accept flag indicates that the event receiver wants the
+ gesture. Unwanted gestures may be propagated to the parent widget.
+
+ \sa QGestureEvent::ignore()
+*/
+void QGestureEvent::accept(QGesture *gesture)
+{
+ if (gesture)
+ setAccepted(gesture->gestureType(), true);
+}
+
+/*!
+ Clears the accept flag parameter of the given \a gesture object, the equivalent
+ of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}.
+
+ Clearing the accept flag indicates that the event receiver does not
+ want the gesture. Unwanted gestures may be propagated to the parent widget.
+
+ \sa QGestureEvent::accept()
+*/
+void QGestureEvent::ignore(QGesture *gesture)
+{
+ if (gesture)
+ setAccepted(gesture->gestureType(), false);
+}
+
+/*!
+ Returns true if the \a gesture is accepted; otherwise returns false.
+*/
+bool QGestureEvent::isAccepted(QGesture *gesture) const
+{
+ return gesture ? isAccepted(gesture->gestureType()) : false;
+}
+
+/*!
+ Sets the accept flag of the given \a gestureType object to the specified
+ \a value.
+
+ Setting the accept flag indicates that the event receiver wants to receive
+ gestures of the specified type, \a gestureType. Unwanted gestures may be
+ propagated to the parent widget.
+
+ By default, gestures in events of type QEvent::Gesture are accepted, and
+ gestures in QEvent::GestureOverride events are ignored.
+
+ For convenience, the accept flag can also be set with
+ \l{QGestureEvent::accept()}{accept(gestureType)}, and cleared with
+ \l{QGestureEvent::ignore()}{ignore(gestureType)}.
+*/
+void QGestureEvent::setAccepted(Qt::GestureType gestureType, bool value)
+{
+ setAccepted(false);
+ d_func()->accepted[gestureType] = value;
+}
+
+/*!
+ Sets the accept flag of the given \a gestureType, the equivalent of calling
+ \l{QGestureEvent::setAccepted()}{setAccepted(gestureType, true)}.
+
+ Setting the accept flag indicates that the event receiver wants the
+ gesture. Unwanted gestures may be propagated to the parent widget.
+
+ \sa QGestureEvent::ignore()
+*/
+void QGestureEvent::accept(Qt::GestureType gestureType)
+{
+ setAccepted(gestureType, true);
+}
+
+/*!
+ Clears the accept flag parameter of the given \a gestureType, the equivalent
+ of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}.
+
+ Clearing the accept flag indicates that the event receiver does not
+ want the gesture. Unwanted gestures may be propgated to the parent widget.
+
+ \sa QGestureEvent::accept()
+*/
+void QGestureEvent::ignore(Qt::GestureType gestureType)
+{
+ setAccepted(gestureType, false);
+}
+
+/*!
+ Returns true if the gesture of type \a gestureType is accepted; otherwise
+ returns false.
+*/
+bool QGestureEvent::isAccepted(Qt::GestureType gestureType) const
+{
+ return d_func()->accepted.value(gestureType, true);
+}
+
+/*!
+ \internal
+
+ Sets the widget for this event to the \a widget specified.
+*/
+void QGestureEvent::setWidget(QWidget *widget)
+{
+ d_func()->widget = widget;
+}
+
+/*!
+ Returns the widget on which the event occurred.
+*/
+QWidget *QGestureEvent::widget() const
+{
+ return d_func()->widget;
+}
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ Returns the scene-local coordinates if the \a gesturePoint is inside a
+ graphics view.
+
+ This functional might be useful when the gesture event is delivered to a
+ QGraphicsObject to translate a point in screen coordinates to scene-local
+ coordinates.
+
+ \sa QPointF::isNull().
+*/
+QPointF QGestureEvent::mapToGraphicsScene(const QPointF &gesturePoint) const
+{
+ QWidget *w = widget();
+ if (w) // we get the viewport as widget, not the graphics view
+ w = w->parentWidget();
+ QGraphicsView *view = qobject_cast<QGraphicsView*>(w);
+ if (view) {
+ return view->mapToScene(view->mapFromGlobal(gesturePoint.toPoint()));
+ }
+ return QPointF();
+}
+#endif //QT_NO_GRAPHICSVIEW
+
+/*!
+ \internal
+*/
+QGestureEventPrivate *QGestureEvent::d_func()
+{
+ return reinterpret_cast<QGestureEventPrivate *>(d);
+}
+
+/*!
+ \internal
+*/
+const QGestureEventPrivate *QGestureEvent::d_func() const
+{
+ return reinterpret_cast<const QGestureEventPrivate *>(d);
+}
+
+#ifdef Q_NO_USING_KEYWORD
+/*!
+ \fn void QGestureEvent::setAccepted(bool accepted)
+
+ Sets or clears the event's internal flag that determines whether it should
+ be delivered to other objects.
+
+ Calling this function with a value of true for \a accepted indicates that the
+ caller has accepted the event and that it should not be propagated further.
+ Calling this function with a value of false indicates that the caller has
+ ignored the event and that it should be delivered to other objects.
+
+ For convenience, the accept flag can also be set with accept(), and cleared
+ with ignore().
+
+ \sa QEvent::accepted
+*/
+/*!
+ \fn bool QGestureEvent::isAccepted() const
+
+ Returns true is the event has been accepted; otherwise returns false.
+
+ \sa QEvent::accepted
+*/
+/*!
+ \fn void QGestureEvent::accept()
+
+ Accepts the event, the equivalent of calling setAccepted(true).
+
+ \sa QEvent::accept()
+*/
+/*!
+ \fn void QGestureEvent::ignore()
+
+ Ignores the event, the equivalent of calling setAccepted(false).
+
+ \sa QEvent::ignore()
+*/
+#endif
+
+QT_END_NAMESPACE
+
+#include <moc_qgesture.cpp>
+
+#endif // QT_NO_GESTURES
diff --git a/src/widgets/kernel/qgesture.h b/src/widgets/kernel/qgesture.h
new file mode 100644
index 0000000000..78fd2e47f1
--- /dev/null
+++ b/src/widgets/kernel/qgesture.h
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_H
+#define QGESTURE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qmetatype.h>
+#include <QtGui/qevent.h>
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_HEADER
+
+Q_DECLARE_METATYPE(Qt::GestureState)
+Q_DECLARE_METATYPE(Qt::GestureType)
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGesturePrivate;
+class Q_GUI_EXPORT QGesture : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGesture)
+
+ Q_PROPERTY(Qt::GestureState state READ state)
+ Q_PROPERTY(Qt::GestureType gestureType READ gestureType)
+ Q_PROPERTY(QGesture::GestureCancelPolicy gestureCancelPolicy READ gestureCancelPolicy WRITE setGestureCancelPolicy)
+ Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot RESET unsetHotSpot)
+ Q_PROPERTY(bool hasHotSpot READ hasHotSpot)
+
+public:
+ explicit QGesture(QObject *parent = 0);
+ ~QGesture();
+
+ Qt::GestureType gestureType() const;
+
+ Qt::GestureState state() const;
+
+ QPointF hotSpot() const;
+ void setHotSpot(const QPointF &value);
+ bool hasHotSpot() const;
+ void unsetHotSpot();
+
+ enum GestureCancelPolicy {
+ CancelNone = 0,
+ CancelAllInContext
+ };
+
+ void setGestureCancelPolicy(GestureCancelPolicy policy);
+ GestureCancelPolicy gestureCancelPolicy() const;
+
+protected:
+ QGesture(QGesturePrivate &dd, QObject *parent);
+
+private:
+ friend class QGestureEvent;
+ friend class QGestureRecognizer;
+ friend class QGestureManager;
+ friend class QGraphicsScenePrivate;
+};
+
+class QPanGesturePrivate;
+class Q_GUI_EXPORT QPanGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPanGesture)
+
+ Q_PROPERTY(QPointF lastOffset READ lastOffset WRITE setLastOffset)
+ Q_PROPERTY(QPointF offset READ offset WRITE setOffset)
+ Q_PROPERTY(QPointF delta READ delta STORED false)
+ Q_PROPERTY(qreal acceleration READ acceleration WRITE setAcceleration)
+ Q_PRIVATE_PROPERTY(QPanGesture::d_func(), qreal horizontalVelocity READ horizontalVelocity WRITE setHorizontalVelocity)
+ Q_PRIVATE_PROPERTY(QPanGesture::d_func(), qreal verticalVelocity READ verticalVelocity WRITE setVerticalVelocity)
+
+public:
+ QPanGesture(QObject *parent = 0);
+
+ QPointF lastOffset() const;
+ QPointF offset() const;
+ QPointF delta() const;
+ qreal acceleration() const;
+
+ void setLastOffset(const QPointF &value);
+ void setOffset(const QPointF &value);
+ void setAcceleration(qreal value);
+
+ friend class QPanGestureRecognizer;
+ friend class QWinNativePanGestureRecognizer;
+};
+
+class QPinchGesturePrivate;
+class Q_GUI_EXPORT QPinchGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPinchGesture)
+ Q_FLAGS(ChangeFlags ChangeFlag)
+
+public:
+ enum ChangeFlag {
+ ScaleFactorChanged = 0x1,
+ RotationAngleChanged = 0x2,
+ CenterPointChanged = 0x4
+ };
+ Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
+
+ Q_PROPERTY(ChangeFlags totalChangeFlags READ totalChangeFlags WRITE setTotalChangeFlags)
+ Q_PROPERTY(ChangeFlags changeFlags READ changeFlags WRITE setChangeFlags)
+
+ Q_PROPERTY(qreal totalScaleFactor READ totalScaleFactor WRITE setTotalScaleFactor)
+ Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor WRITE setLastScaleFactor)
+ Q_PROPERTY(qreal scaleFactor READ scaleFactor WRITE setScaleFactor)
+
+ Q_PROPERTY(qreal totalRotationAngle READ totalRotationAngle WRITE setTotalRotationAngle)
+ Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle WRITE setLastRotationAngle)
+ Q_PROPERTY(qreal rotationAngle READ rotationAngle WRITE setRotationAngle)
+
+ Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint WRITE setStartCenterPoint)
+ Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint WRITE setLastCenterPoint)
+ Q_PROPERTY(QPointF centerPoint READ centerPoint WRITE setCenterPoint)
+
+public:
+ QPinchGesture(QObject *parent = 0);
+
+ ChangeFlags totalChangeFlags() const;
+ void setTotalChangeFlags(ChangeFlags value);
+
+ ChangeFlags changeFlags() const;
+ void setChangeFlags(ChangeFlags value);
+
+ QPointF startCenterPoint() const;
+ QPointF lastCenterPoint() const;
+ QPointF centerPoint() const;
+ void setStartCenterPoint(const QPointF &value);
+ void setLastCenterPoint(const QPointF &value);
+ void setCenterPoint(const QPointF &value);
+
+ qreal totalScaleFactor() const;
+ qreal lastScaleFactor() const;
+ qreal scaleFactor() const;
+ void setTotalScaleFactor(qreal value);
+ void setLastScaleFactor(qreal value);
+ void setScaleFactor(qreal value);
+
+ qreal totalRotationAngle() const;
+ qreal lastRotationAngle() const;
+ qreal rotationAngle() const;
+ void setTotalRotationAngle(qreal value);
+ void setLastRotationAngle(qreal value);
+ void setRotationAngle(qreal value);
+
+ friend class QPinchGestureRecognizer;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPinchGesture::ChangeFlags)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QPinchGesture::ChangeFlags)
+
+QT_BEGIN_NAMESPACE
+
+class QSwipeGesturePrivate;
+class Q_GUI_EXPORT QSwipeGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSwipeGesture)
+ Q_ENUMS(SwipeDirection)
+
+ Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection STORED false)
+ Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection STORED false)
+ Q_PROPERTY(qreal swipeAngle READ swipeAngle WRITE setSwipeAngle)
+ Q_PRIVATE_PROPERTY(QSwipeGesture::d_func(), qreal velocity READ velocity WRITE setVelocity)
+
+public:
+ enum SwipeDirection { NoDirection, Left, Right, Up, Down };
+ QSwipeGesture(QObject *parent = 0);
+
+ SwipeDirection horizontalDirection() const;
+ SwipeDirection verticalDirection() const;
+
+ qreal swipeAngle() const;
+ void setSwipeAngle(qreal value);
+
+ friend class QSwipeGestureRecognizer;
+};
+
+class QTapGesturePrivate;
+class Q_GUI_EXPORT QTapGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QTapGesture)
+
+ Q_PROPERTY(QPointF position READ position WRITE setPosition)
+
+public:
+ QTapGesture(QObject *parent = 0);
+
+ QPointF position() const;
+ void setPosition(const QPointF &pos);
+
+ friend class QTapGestureRecognizer;
+};
+
+class QTapAndHoldGesturePrivate;
+class Q_GUI_EXPORT QTapAndHoldGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QTapAndHoldGesture)
+
+ Q_PROPERTY(QPointF position READ position WRITE setPosition)
+
+public:
+ QTapAndHoldGesture(QObject *parent = 0);
+
+ QPointF position() const;
+ void setPosition(const QPointF &pos);
+
+ static void setTimeout(int msecs);
+ static int timeout();
+
+ friend class QTapAndHoldGestureRecognizer;
+};
+
+class QGesture;
+class QGestureEventPrivate;
+class Q_GUI_EXPORT QGestureEvent : public QEvent
+{
+public:
+ QGestureEvent(const QList<QGesture *> &gestures);
+ ~QGestureEvent();
+
+ QList<QGesture *> gestures() const;
+ QGesture *gesture(Qt::GestureType type) const;
+
+ QList<QGesture *> activeGestures() const;
+ QList<QGesture *> canceledGestures() const;
+
+#ifdef Q_NO_USING_KEYWORD
+ inline void setAccepted(bool accepted) { QEvent::setAccepted(accepted); }
+ inline bool isAccepted() const { return QEvent::isAccepted(); }
+
+ inline void accept() { QEvent::accept(); }
+ inline void ignore() { QEvent::ignore(); }
+#else
+ using QEvent::setAccepted;
+ using QEvent::isAccepted;
+ using QEvent::accept;
+ using QEvent::ignore;
+#endif
+
+ void setAccepted(QGesture *, bool);
+ void accept(QGesture *);
+ void ignore(QGesture *);
+ bool isAccepted(QGesture *) const;
+
+ void setAccepted(Qt::GestureType, bool);
+ void accept(Qt::GestureType);
+ void ignore(Qt::GestureType);
+ bool isAccepted(Qt::GestureType) const;
+
+ void setWidget(QWidget *widget);
+ QWidget *widget() const;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ QPointF mapToGraphicsScene(const QPointF &gesturePoint) const;
+#endif
+
+private:
+ QGestureEventPrivate *d_func();
+ const QGestureEventPrivate *d_func() const;
+
+ friend class QApplication;
+ friend class QGestureManager;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy)
+QT_END_HEADER
+
+#endif // QT_NO_GESTURES
+
+#endif // QGESTURE_H
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
new file mode 100644
index 0000000000..9dd089cc9e
--- /dev/null
+++ b/src/widgets/kernel/qgesture_p.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_P_H
+#define QGESTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrect.h"
+#include "qpoint.h"
+#include "qgesture.h"
+#include "qelapsedtimer.h"
+#include "private/qobject_p.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+class QGesturePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGesture)
+
+public:
+ QGesturePrivate()
+ : gestureType(Qt::CustomGesture), state(Qt::NoGesture),
+ isHotSpotSet(false), gestureCancelPolicy(0)
+ {
+ }
+
+ Qt::GestureType gestureType;
+ Qt::GestureState state;
+ QPointF hotSpot;
+ QPointF sceneHotSpot;
+ uint isHotSpotSet : 1;
+ uint gestureCancelPolicy : 2;
+};
+
+class QPanGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPanGesture)
+
+public:
+ QPanGesturePrivate()
+ : acceleration(0), xVelocity(0), yVelocity(0)
+ {
+ }
+
+ qreal horizontalVelocity() const { return xVelocity; }
+ void setHorizontalVelocity(qreal value) { xVelocity = value; }
+ qreal verticalVelocity() const { return yVelocity; }
+ void setVerticalVelocity(qreal value) { yVelocity = value; }
+
+ QPointF lastOffset;
+ QPointF offset;
+ QPoint startPosition;
+ qreal acceleration;
+ qreal xVelocity;
+ qreal yVelocity;
+};
+
+class QPinchGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPinchGesture)
+
+public:
+ QPinchGesturePrivate()
+ : totalChangeFlags(0), changeFlags(0),
+ totalScaleFactor(1), lastScaleFactor(1), scaleFactor(1),
+ totalRotationAngle(0), lastRotationAngle(0), rotationAngle(0),
+ isNewSequence(true)
+ {
+ }
+
+ QPinchGesture::ChangeFlags totalChangeFlags;
+ QPinchGesture::ChangeFlags changeFlags;
+
+ QPointF startCenterPoint;
+ QPointF lastCenterPoint;
+ QPointF centerPoint;
+
+ qreal totalScaleFactor;
+ qreal lastScaleFactor;
+ qreal scaleFactor;
+
+ qreal totalRotationAngle;
+ qreal lastRotationAngle;
+ qreal rotationAngle;
+
+ bool isNewSequence;
+ QPointF startPosition[2];
+};
+
+class QSwipeGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QSwipeGesture)
+
+public:
+ QSwipeGesturePrivate()
+ : horizontalDirection(QSwipeGesture::NoDirection),
+ verticalDirection(QSwipeGesture::NoDirection),
+ swipeAngle(0),
+ started(false), velocityValue(0)
+ {
+ }
+
+ qreal velocity() const { return velocityValue; }
+ void setVelocity(qreal value) { velocityValue = value; }
+
+ QSwipeGesture::SwipeDirection horizontalDirection;
+ QSwipeGesture::SwipeDirection verticalDirection;
+ qreal swipeAngle;
+
+ QPoint lastPositions[3];
+ bool started;
+ qreal velocityValue;
+ QElapsedTimer time;
+};
+
+class QTapGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QTapGesture)
+
+public:
+ QTapGesturePrivate()
+ {
+ }
+
+ QPointF position;
+};
+
+class QTapAndHoldGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QTapAndHoldGesture)
+
+public:
+ QTapAndHoldGesturePrivate()
+ : timerId(0)
+ {
+ }
+
+ QPointF position;
+ int timerId;
+ static int Timeout;
+};
+
+#ifndef QT_NO_GESTURES
+class QNativeGestureEvent : public QEvent
+{
+public:
+ enum Type {
+ None,
+ GestureBegin,
+ GestureEnd,
+ Pan,
+ Zoom,
+ Rotate,
+ Swipe
+ };
+
+ QNativeGestureEvent()
+ : QEvent(QEvent::NativeGesture), gestureType(None), percentage(0)
+#ifdef Q_WS_WIN
+ , sequenceId(0), argument(0)
+#endif
+ {
+ }
+
+ Type gestureType;
+ float percentage;
+ QPoint position;
+ float angle;
+#ifdef Q_WS_WIN
+ ulong sequenceId;
+ quint64 argument;
+#endif
+};
+
+class QGestureEventPrivate
+{
+public:
+ inline QGestureEventPrivate(const QList<QGesture *> &list)
+ : gestures(list), widget(0)
+ {
+ }
+
+ QList<QGesture *> gestures;
+ QWidget *widget;
+ QMap<Qt::GestureType, bool> accepted;
+ QMap<Qt::GestureType, QWidget *> targetWidgets;
+};
+#endif // QT_NO_GESTURES
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#endif // QGESTURE_P_H
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
new file mode 100644
index 0000000000..5359fb37e8
--- /dev/null
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -0,0 +1,721 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qgesturemanager_p.h"
+#include "private/qstandardgestures_p.h"
+#include "private/qwidget_p.h"
+#include "private/qgesture_p.h"
+#include "private/qgraphicsitem_p.h"
+#include "private/qevent_p.h"
+#include "private/qapplication_p.h"
+#include "qgesture.h"
+#include "qevent.h"
+#include "qgraphicsitem.h"
+
+#ifdef Q_WS_MAC
+#include "qmacgesturerecognizer_mac_p.h"
+#endif
+#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
+#include "qwinnativepangesturerecognizer_win_p.h"
+#endif
+
+#include "qdebug.h"
+
+// #define GESTURE_DEBUG
+#ifndef GESTURE_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+QGestureManager::QGestureManager(QObject *parent)
+ : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
+{
+ qRegisterMetaType<Qt::GestureState>();
+
+#if defined(Q_WS_MAC)
+ registerGestureRecognizer(new QMacSwipeGestureRecognizer);
+ registerGestureRecognizer(new QMacPinchGestureRecognizer);
+ #if defined(QT_MAC_USE_COCOA)
+ registerGestureRecognizer(new QMacPanGestureRecognizer);
+ #endif
+#else
+ registerGestureRecognizer(new QPanGestureRecognizer);
+ registerGestureRecognizer(new QPinchGestureRecognizer);
+ registerGestureRecognizer(new QSwipeGestureRecognizer);
+ registerGestureRecognizer(new QTapGestureRecognizer);
+#endif
+#if defined(Q_OS_WIN)
+ #if !defined(QT_NO_NATIVE_GESTURES)
+ if (QApplicationPrivate::HasTouchSupport)
+ registerGestureRecognizer(new QWinNativePanGestureRecognizer);
+ #endif
+#else
+ registerGestureRecognizer(new QTapAndHoldGestureRecognizer);
+#endif
+}
+
+QGestureManager::~QGestureManager()
+{
+ qDeleteAll(m_recognizers.values());
+ foreach (QGestureRecognizer *recognizer, m_obsoleteGestures.keys()) {
+ qDeleteAll(m_obsoleteGestures.value(recognizer));
+ delete recognizer;
+ }
+ m_obsoleteGestures.clear();
+}
+
+Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
+{
+ QGesture *dummy = recognizer->create(0);
+ if (!dummy) {
+ qWarning("QGestureManager::registerGestureRecognizer: "
+ "the recognizer fails to create a gesture object, skipping registration.");
+ return Qt::GestureType(0);
+ }
+ Qt::GestureType type = dummy->gestureType();
+ if (type == Qt::CustomGesture) {
+ // generate a new custom gesture id
+ ++m_lastCustomGestureId;
+ type = Qt::GestureType(m_lastCustomGestureId);
+ }
+ m_recognizers.insertMulti(type, recognizer);
+ delete dummy;
+ return type;
+}
+
+void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
+{
+ QList<QGestureRecognizer *> list = m_recognizers.values(type);
+ while (QGestureRecognizer *recognizer = m_recognizers.take(type)) {
+ if (!m_obsoleteGestures.contains(recognizer)) {
+ // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager
+ m_obsoleteGestures.insert(recognizer, QSet<QGesture *>());
+ }
+ }
+ foreach (QGesture *g, m_gestureToRecognizer.keys()) {
+ QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
+ if (list.contains(recognizer)) {
+ m_deletedRecognizers.insert(g, recognizer);
+ }
+ }
+
+ QMap<ObjectGesture, QList<QGesture *> >::const_iterator iter = m_objectGestures.begin();
+ while (iter != m_objectGestures.end()) {
+ ObjectGesture objectGesture = iter.key();
+ if (objectGesture.gesture == type) {
+ foreach (QGesture *g, iter.value()) {
+ if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) {
+ m_gestureToRecognizer.remove(g);
+ m_obsoleteGestures[recognizer].insert(g);
+ }
+ }
+ }
+ ++iter;
+ }
+}
+
+void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
+{
+ QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
+ while (iter != m_objectGestures.end()) {
+ ObjectGesture objectGesture = iter.key();
+ if (objectGesture.gesture == type && target == objectGesture.object) {
+ QSet<QGesture *> gestures = iter.value().toSet();
+ for (QHash<QGestureRecognizer *, QSet<QGesture *> >::iterator
+ it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) {
+ it.value() -= gestures;
+ }
+ foreach (QGesture *g, gestures) {
+ m_deletedRecognizers.remove(g);
+ m_gestureToRecognizer.remove(g);
+ m_maybeGestures.remove(g);
+ m_activeGestures.remove(g);
+ m_gestureOwners.remove(g);
+ m_gestureTargets.remove(g);
+ m_gesturesToDelete.insert(g);
+ }
+
+ iter = m_objectGestures.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+// get or create a QGesture object that will represent the state for a given object, used by the recognizer
+QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recognizer, Qt::GestureType type)
+{
+ // if the widget is being deleted we should be careful not to
+ // create a new state, as it will create QWeakPointer which doesn't work
+ // from the destructor.
+ if (object->isWidgetType()) {
+ if (static_cast<QWidget *>(object)->d_func()->data.in_destructor)
+ return 0;
+ } else if (QGesture *g = qobject_cast<QGesture *>(object)) {
+ return g;
+#ifndef QT_NO_GRAPHICSVIEW
+ } else {
+ Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
+ QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(object);
+ if (graphicsObject->QGraphicsItem::d_func()->inDestructor)
+ return 0;
+#endif
+ }
+
+ // check if the QGesture for this recognizer has already been created
+ foreach (QGesture *state, m_objectGestures.value(QGestureManager::ObjectGesture(object, type))) {
+ if (m_gestureToRecognizer.value(state) == recognizer)
+ return state;
+ }
+
+ Q_ASSERT(recognizer);
+ QGesture *state = recognizer->create(object);
+ if (!state)
+ return 0;
+ state->setParent(this);
+ if (state->gestureType() == Qt::CustomGesture) {
+ // if the recognizer didn't fill in the gesture type, then this
+ // is a custom gesture with autogenerated id and we fill it.
+ state->d_func()->gestureType = type;
+#if defined(GESTURE_DEBUG)
+ state->setObjectName(QString::number((int)type));
+#endif
+ }
+ m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state);
+ m_gestureToRecognizer[state] = recognizer;
+ m_gestureOwners[state] = object;
+
+ return state;
+}
+
+bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
+ Qt::GestureType> &contexts,
+ QEvent *event)
+{
+ QSet<QGesture *> triggeredGestures;
+ QSet<QGesture *> finishedGestures;
+ QSet<QGesture *> newMaybeGestures;
+ QSet<QGesture *> notGestures;
+
+ // TODO: sort contexts by the gesture type and check if one of the contexts
+ // is already active.
+
+ bool consumeEventHint = false;
+
+ // filter the event through recognizers
+ typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
+ ContextIterator contextEnd = contexts.end();
+ for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) {
+ Qt::GestureType gestureType = context.value();
+ QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
+ typeToRecognizerIterator = m_recognizers.lowerBound(gestureType),
+ typeToRecognizerEnd = m_recognizers.upperBound(gestureType);
+ for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) {
+ QGestureRecognizer *recognizer = typeToRecognizerIterator.value();
+ QObject *target = context.key();
+ QGesture *state = getState(target, recognizer, gestureType);
+ if (!state)
+ continue;
+ QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event);
+ QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask;
+ QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask;
+ if (recognizerState == QGestureRecognizer::TriggerGesture) {
+ DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
+ triggeredGestures << state;
+ } else if (recognizerState == QGestureRecognizer::FinishGesture) {
+ DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
+ finishedGestures << state;
+ } else if (recognizerState == QGestureRecognizer::MayBeGesture) {
+ DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
+ newMaybeGestures << state;
+ } else if (recognizerState == QGestureRecognizer::CancelGesture) {
+ DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
+ notGestures << state;
+ } else if (recognizerState == QGestureRecognizer::Ignore) {
+ DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
+ } else {
+ DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
+ << "ignored the event: " << state;
+ }
+ if (resultHint & QGestureRecognizer::ConsumeEventHint) {
+ DEBUG() << "QGestureManager: we were asked to consume the event: "
+ << state;
+ consumeEventHint = true;
+ }
+ }
+ }
+ if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
+ && newMaybeGestures.isEmpty() && notGestures.isEmpty())
+ return consumeEventHint;
+
+ QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
+ triggeredGestures &= m_activeGestures;
+
+ // check if a running gesture switched back to maybe state
+ QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
+
+ // check if a maybe gesture switched to canceled - reset it but don't send an event
+ QSet<QGesture *> maybeToCanceledGestures = m_maybeGestures & notGestures;
+
+ // check if a running gesture switched back to not gesture state,
+ // i.e. were canceled
+ QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
+
+ // new gestures in maybe state
+ m_maybeGestures += newMaybeGestures;
+
+ // gestures that were in maybe state
+ QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures
+ | finishedGestures | canceledGestures
+ | notGestures);
+ m_maybeGestures -= notMaybeGestures;
+
+ Q_ASSERT((startedGestures & finishedGestures).isEmpty());
+ Q_ASSERT((startedGestures & newMaybeGestures).isEmpty());
+ Q_ASSERT((startedGestures & canceledGestures).isEmpty());
+ Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty());
+ Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
+ Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
+
+ QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
+ if (!notStarted.isEmpty()) {
+ // there are some gestures that claim to be finished, but never started.
+ // probably those are "singleshot" gestures so we'll fake the started state.
+ foreach (QGesture *gesture, notStarted)
+ gesture->d_func()->state = Qt::GestureStarted;
+ QSet<QGesture *> undeliveredGestures;
+ deliverEvents(notStarted, &undeliveredGestures);
+ finishedGestures -= undeliveredGestures;
+ }
+
+ m_activeGestures += startedGestures;
+ // sanity check: all triggered gestures should already be in active gestures list
+ Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size());
+ m_activeGestures -= finishedGestures;
+ m_activeGestures -= activeToMaybeGestures;
+ m_activeGestures -= canceledGestures;
+
+ // set the proper gesture state on each gesture
+ foreach (QGesture *gesture, startedGestures)
+ gesture->d_func()->state = Qt::GestureStarted;
+ foreach (QGesture *gesture, triggeredGestures)
+ gesture->d_func()->state = Qt::GestureUpdated;
+ foreach (QGesture *gesture, finishedGestures)
+ gesture->d_func()->state = Qt::GestureFinished;
+ foreach (QGesture *gesture, canceledGestures)
+ gesture->d_func()->state = Qt::GestureCanceled;
+ foreach (QGesture *gesture, activeToMaybeGestures)
+ gesture->d_func()->state = Qt::GestureFinished;
+
+ if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
+ !startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
+ !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
+ DEBUG() << "QGestureManager::filterEventThroughContexts:"
+ << "\n\tactiveGestures:" << m_activeGestures
+ << "\n\tmaybeGestures:" << m_maybeGestures
+ << "\n\tstarted:" << startedGestures
+ << "\n\ttriggered:" << triggeredGestures
+ << "\n\tfinished:" << finishedGestures
+ << "\n\tcanceled:" << canceledGestures
+ << "\n\tmaybe-canceled:" << maybeToCanceledGestures;
+ }
+
+ QSet<QGesture *> undeliveredGestures;
+ deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
+ &undeliveredGestures);
+
+ foreach (QGesture *g, startedGestures) {
+ if (undeliveredGestures.contains(g))
+ continue;
+ if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
+ DEBUG() << "lets try to cancel some";
+ // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
+ cancelGesturesForChildren(g);
+ }
+ }
+
+ m_activeGestures -= undeliveredGestures;
+
+ // reset gestures that ended
+ QSet<QGesture *> endedGestures =
+ finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
+ foreach (QGesture *gesture, endedGestures) {
+ recycle(gesture);
+ m_gestureTargets.remove(gesture);
+ }
+
+ //Clean up the Gestures
+ qDeleteAll(m_gesturesToDelete);
+ m_gesturesToDelete.clear();
+
+ return consumeEventHint;
+}
+
+// Cancel all gestures of children of the widget that original is associated with
+void QGestureManager::cancelGesturesForChildren(QGesture *original)
+{
+ Q_ASSERT(original);
+ QWidget *originatingWidget = m_gestureTargets.value(original);
+ Q_ASSERT(originatingWidget);
+
+ // iterate over all active gestures and all maybe gestures
+ // for each find the owner
+ // if the owner is part of our sub-hierarchy, cancel it.
+
+ QSet<QGesture*> cancelledGestures;
+ QSet<QGesture*>::Iterator iter = m_activeGestures.begin();
+ while (iter != m_activeGestures.end()) {
+ QWidget *widget = m_gestureTargets.value(*iter);
+ // note that we don't touch the gestures for our originatingWidget
+ if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) {
+ DEBUG() << " found a gesture to cancel" << (*iter);
+ (*iter)->d_func()->state = Qt::GestureCanceled;
+ cancelledGestures << *iter;
+ iter = m_activeGestures.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+
+ // TODO handle 'maybe' gestures too
+
+ // sort them per target widget by cherry picking from almostCanceledGestures and delivering
+ QSet<QGesture *> almostCanceledGestures = cancelledGestures;
+ while (!almostCanceledGestures.isEmpty()) {
+ QWidget *target = 0;
+ QSet<QGesture*> gestures;
+ iter = almostCanceledGestures.begin();
+ // sort per target widget
+ while (iter != almostCanceledGestures.end()) {
+ QWidget *widget = m_gestureTargets.value(*iter);
+ if (target == 0)
+ target = widget;
+ if (target == widget) {
+ gestures << *iter;
+ iter = almostCanceledGestures.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+ Q_ASSERT(target);
+
+ QSet<QGesture*> undeliveredGestures;
+ deliverEvents(gestures, &undeliveredGestures);
+ }
+
+ for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter)
+ recycle(*iter);
+}
+
+void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
+{
+ QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture);
+ if(!recognizer) //The Gesture is removed while in the even loop, so the recognizers for this gestures was removed
+ return;
+ m_deletedRecognizers.remove(gesture);
+ if (m_deletedRecognizers.keys(recognizer).isEmpty()) {
+ // no more active gestures, cleanup!
+ qDeleteAll(m_obsoleteGestures.value(recognizer));
+ m_obsoleteGestures.remove(recognizer);
+ delete recognizer;
+ }
+}
+
+// return true if accepted (consumed)
+bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
+{
+ QMap<Qt::GestureType, int> types;
+ QMultiMap<QObject *, Qt::GestureType> contexts;
+ QWidget *w = receiver;
+ typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
+ if (!w->d_func()->gestureContext.isEmpty()) {
+ for(ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ types.insert(it.key(), 0);
+ contexts.insertMulti(w, it.key());
+ }
+ }
+ // find all gesture contexts for the widget tree
+ w = w->isWindow() ? 0 : w->parentWidget();
+ while (w)
+ {
+ for (ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ if (!(it.value() & Qt::DontStartGestureOnChildren)) {
+ if (!types.contains(it.key())) {
+ types.insert(it.key(), 0);
+ contexts.insertMulti(w, it.key());
+ }
+ }
+ }
+ if (w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
+}
+
+#ifndef QT_NO_GRAPHICSVIEW
+bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
+{
+ QMap<Qt::GestureType, int> types;
+ QMultiMap<QObject *, Qt::GestureType> contexts;
+ QGraphicsObject *item = receiver;
+ if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
+ typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
+ for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ types.insert(it.key(), 0);
+ contexts.insertMulti(item, it.key());
+ }
+ }
+ // find all gesture contexts for the graphics object tree
+ item = item->parentObject();
+ while (item)
+ {
+ typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
+ for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ if (!(it.value() & Qt::DontStartGestureOnChildren)) {
+ if (!types.contains(it.key())) {
+ types.insert(it.key(), 0);
+ contexts.insertMulti(item, it.key());
+ }
+ }
+ }
+ item = item->parentObject();
+ }
+ return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event);
+}
+#endif
+
+bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
+{
+ if (!m_gestureToRecognizer.contains(static_cast<QGesture *>(receiver)))
+ return false;
+ QGesture *state = static_cast<QGesture *>(receiver);
+ QMultiMap<QObject *, Qt::GestureType> contexts;
+ contexts.insert(state, state->gestureType());
+ return filterEventThroughContexts(contexts, event);
+}
+
+void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
+ QMap<QWidget *, QList<QGesture *> > *conflicts,
+ QMap<QWidget *, QList<QGesture *> > *normal)
+{
+ typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes;
+ GestureByTypes gestureByTypes;
+
+ // sort gestures by types
+ foreach (QGesture *gesture, gestures) {
+ QWidget *receiver = m_gestureTargets.value(gesture, 0);
+ Q_ASSERT(receiver);
+ gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
+ }
+
+ // for each gesture type
+ foreach (Qt::GestureType type, gestureByTypes.keys()) {
+ QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type);
+ foreach (QWidget *widget, gestures.keys()) {
+ QWidget *w = widget->parentWidget();
+ while (w) {
+ QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it
+ = w->d_func()->gestureContext.find(type);
+ if (it != w->d_func()->gestureContext.end()) {
+ // i.e. 'w' listens to gesture 'type'
+ Qt::GestureFlags flags = it.value();
+ if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) {
+ // conflicting gesture!
+ (*conflicts)[widget].append(gestures[widget]);
+ break;
+ }
+ }
+ if (w->isWindow()) {
+ w = 0;
+ break;
+ }
+ w = w->parentWidget();
+ }
+ if (!w)
+ (*normal)[widget].append(gestures[widget]);
+ }
+ }
+}
+
+void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
+ QSet<QGesture *> *undeliveredGestures)
+{
+ if (gestures.isEmpty())
+ return;
+
+ typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget;
+ GesturesPerWidget conflictedGestures;
+ GesturesPerWidget normalStartedGestures;
+
+ QSet<QGesture *> startedGestures;
+ // first figure out the initial receivers of gestures
+ for (QSet<QGesture *>::const_iterator it = gestures.begin(),
+ e = gestures.end(); it != e; ++it) {
+ QGesture *gesture = *it;
+ QWidget *target = m_gestureTargets.value(gesture, 0);
+ if (!target) {
+ // the gesture has just started and doesn't have a target yet.
+ Q_ASSERT(gesture->state() == Qt::GestureStarted);
+ if (gesture->hasHotSpot()) {
+ // guess the target widget using the hotspot of the gesture
+ QPoint pt = gesture->hotSpot().toPoint();
+ if (QWidget *topLevel = qApp->topLevelAt(pt)) {
+ QWidget *child = topLevel->childAt(topLevel->mapFromGlobal(pt));
+ target = child ? child : topLevel;
+ }
+ } else {
+ // or use the context of the gesture
+ QObject *context = m_gestureOwners.value(gesture, 0);
+ if (context->isWidgetType())
+ target = static_cast<QWidget *>(context);
+ }
+ if (target)
+ m_gestureTargets.insert(gesture, target);
+ }
+
+ Qt::GestureType gestureType = gesture->gestureType();
+ Q_ASSERT(gestureType != Qt::CustomGesture);
+ Q_UNUSED(gestureType);
+
+ if (target) {
+ if (gesture->state() == Qt::GestureStarted) {
+ startedGestures.insert(gesture);
+ } else {
+ normalStartedGestures[target].append(gesture);
+ }
+ } else {
+ DEBUG() << "QGestureManager::deliverEvent: could not find the target for gesture"
+ << gesture->gestureType();
+ qWarning("QGestureManager::deliverEvent: could not find the target for gesture");
+ undeliveredGestures->insert(gesture);
+ }
+ }
+
+ getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures);
+ DEBUG() << "QGestureManager::deliverEvents:"
+ << "\nstarted: " << startedGestures
+ << "\nconflicted: " << conflictedGestures
+ << "\nnormal: " << normalStartedGestures
+ << "\n";
+
+ // if there are conflicting gestures, send the GestureOverride event
+ for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(),
+ e = conflictedGestures.end(); it != e; ++it) {
+ QWidget *receiver = it.key();
+ QList<QGesture *> gestures = it.value();
+ DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to"
+ << receiver
+ << "gestures:" << gestures;
+ QGestureEvent event(gestures);
+ event.t = QEvent::GestureOverride;
+ // mark event and individual gestures as ignored
+ event.ignore();
+ foreach(QGesture *g, gestures)
+ event.setAccepted(g, false);
+
+ QApplication::sendEvent(receiver, &event);
+ bool eventAccepted = event.isAccepted();
+ foreach(QGesture *gesture, event.gestures()) {
+ if (eventAccepted || event.isAccepted(gesture)) {
+ QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
+ Q_ASSERT(w);
+ DEBUG() << "override event: gesture was accepted:" << gesture << w;
+ QList<QGesture *> &gestures = normalStartedGestures[w];
+ gestures.append(gesture);
+ // override the target
+ m_gestureTargets[gesture] = w;
+ } else {
+ DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture;
+ QList<QGesture *> &gestures = normalStartedGestures[receiver];
+ gestures.append(gesture);
+ }
+ }
+ }
+
+ // delivering gestures that are not in conflicted state
+ for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(),
+ e = normalStartedGestures.end(); it != e; ++it) {
+ if (!it.value().isEmpty()) {
+ DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key()
+ << "gestures:" << it.value();
+ QGestureEvent event(it.value());
+ QApplication::sendEvent(it.key(), &event);
+ bool eventAccepted = event.isAccepted();
+ foreach (QGesture *gesture, event.gestures()) {
+ if (gesture->state() == Qt::GestureStarted &&
+ (eventAccepted || event.isAccepted(gesture))) {
+ QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
+ Q_ASSERT(w);
+ DEBUG() << "started gesture was delivered and accepted by" << w;
+ m_gestureTargets[gesture] = w;
+ }
+ }
+ }
+ }
+}
+
+void QGestureManager::recycle(QGesture *gesture)
+{
+ QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0);
+ if (recognizer) {
+ gesture->setGestureCancelPolicy(QGesture::CancelNone);
+ recognizer->reset(gesture);
+ m_activeGestures.remove(gesture);
+ } else {
+ cleanupGesturesForRemovedRecognizer(gesture);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#include "moc_qgesturemanager_p.cpp"
diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h
new file mode 100644
index 0000000000..b4d9f61ec0
--- /dev/null
+++ b/src/widgets/kernel/qgesturemanager_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTUREMANAGER_P_H
+#define QGESTUREMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qobject.h"
+#include "qbasictimer.h"
+#include "private/qwidget_p.h"
+#include "qgesturerecognizer.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+class QBasicTimer;
+class QGraphicsObject;
+class QGestureManager : public QObject
+{
+ Q_OBJECT
+public:
+ QGestureManager(QObject *parent);
+ ~QGestureManager();
+
+ Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer);
+ void unregisterGestureRecognizer(Qt::GestureType type);
+
+ bool filterEvent(QWidget *receiver, QEvent *event);
+ bool filterEvent(QObject *receiver, QEvent *event);
+#ifndef QT_NO_GRAPHICSVIEW
+ bool filterEvent(QGraphicsObject *receiver, QEvent *event);
+#endif //QT_NO_GRAPHICSVIEW
+
+ static QGestureManager* instance(); // declared in qapplication.cpp
+
+ void cleanupCachedGestures(QObject *target, Qt::GestureType type);
+
+ void recycle(QGesture *gesture);
+
+protected:
+ bool filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts,
+ QEvent *event);
+
+private:
+ QMultiMap<Qt::GestureType, QGestureRecognizer *> m_recognizers;
+
+ QSet<QGesture *> m_activeGestures;
+ QSet<QGesture *> m_maybeGestures;
+
+ enum State {
+ Gesture,
+ NotGesture,
+ MaybeGesture // this means timers are up and waiting for some
+ // more events, and input events are handled by
+ // gesture recognizer explicitly
+ } state;
+
+ struct ObjectGesture
+ {
+ QObject* object;
+ Qt::GestureType gesture;
+
+ ObjectGesture(QObject *o, const Qt::GestureType &g) : object(o), gesture(g) { }
+ inline bool operator<(const ObjectGesture &rhs) const
+ {
+ if (object < rhs.object)
+ return true;
+ if (object == rhs.object)
+ return gesture < rhs.gesture;
+ return false;
+ }
+ };
+
+ QMap<ObjectGesture, QList<QGesture *> > m_objectGestures;
+ QHash<QGesture *, QGestureRecognizer *> m_gestureToRecognizer;
+ QHash<QGesture *, QObject *> m_gestureOwners;
+
+ QHash<QGesture *, QWidget *> m_gestureTargets;
+
+ int m_lastCustomGestureId;
+
+ QHash<QGestureRecognizer *, QSet<QGesture *> > m_obsoleteGestures;
+ QHash<QGesture *, QGestureRecognizer *> m_deletedRecognizers;
+ QSet<QGesture *> m_gesturesToDelete;
+ void cleanupGesturesForRemovedRecognizer(QGesture *gesture);
+
+ QGesture *getState(QObject *widget, QGestureRecognizer *recognizer,
+ Qt::GestureType gesture);
+ void deliverEvents(const QSet<QGesture *> &gestures,
+ QSet<QGesture *> *undeliveredGestures);
+ void getGestureTargets(const QSet<QGesture*> &gestures,
+ QMap<QWidget *, QList<QGesture *> > *conflicts,
+ QMap<QWidget *, QList<QGesture *> > *normal);
+
+ void cancelGesturesForChildren(QGesture *originatingGesture);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#endif // QGESTUREMANAGER_P_H
diff --git a/src/widgets/kernel/qgesturerecognizer.cpp b/src/widgets/kernel/qgesturerecognizer.cpp
new file mode 100644
index 0000000000..f7a4a189b9
--- /dev/null
+++ b/src/widgets/kernel/qgesturerecognizer.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesturerecognizer.h"
+
+#include "private/qgesture_p.h"
+#include "private/qgesturemanager_p.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGestureRecognizer
+ \since 4.6
+ \brief The QGestureRecognizer class provides the infrastructure for gesture recognition.
+ \ingroup gestures
+
+ Gesture recognizers are responsible for creating and managing QGesture objects and
+ monitoring input events sent to QWidget and QGraphicsObject subclasses.
+ QGestureRecognizer is the base class for implementing custom gestures.
+
+ Developers that only need to provide gesture recognition for standard gestures do not
+ need to use this class directly. Instances will be created behind the scenes by the
+ framework.
+
+ For an overview of gesture handling in Qt and information on using gestures
+ in your applications, see the \l{Gestures Programming} document.
+
+ \section1 Recognizing Gestures
+
+ The process of recognizing gestures involves filtering input events sent to specific
+ objects, and modifying the associated QGesture objects to include relevant information
+ about the user's input.
+
+ Gestures are created when the framework calls create() to handle user input
+ for a particular instance of a QWidget or QGraphicsObject subclass. A QGesture object
+ is created for each widget or item that is configured to use gestures.
+
+ Once a QGesture has been created for a target object, the gesture recognizer will
+ receive events for it in its recognize() handler function.
+
+ When a gesture is canceled, the reset() function is called, giving the recognizer the
+ chance to update the appropriate properties in the corresponding QGesture object.
+
+ \section1 Supporting New Gestures
+
+ To add support for new gestures, you need to derive from QGestureRecognizer to create
+ a custom recognizer class, construct an instance of this class, and register it with
+ the application by calling QGestureRecognizer::registerRecognizer(). You can also
+ subclass QGesture to create a custom gesture class, or rely on dynamic properties
+ to express specific details of the gesture you want to handle.
+
+ Your custom QGestureRecognizer subclass needs to reimplement the recognize()
+ function to handle and filter the incoming input events for QWidget and
+ QGraphicsObject subclasses. Although the logic for gesture recognition is
+ implemented in this function, you can store persistent information about the
+ state of the recognition process in the QGesture object supplied. The
+ recognize() function must return a value of QGestureRecognizer::Result that
+ indicates the state of recognition for a given gesture and target object.
+ This determines whether or not a gesture event will be delivered to a target
+ object.
+
+ If you choose to represent a gesture by a custom QGesture subclass, you will need to
+ reimplement the create() function to construct instances of your gesture class.
+ Similarly, you may need to reimplement the reset() function if your custom gesture
+ objects need to be specially handled when a gesture is canceled.
+
+ \sa QGesture
+*/
+
+/*!
+ \enum QGestureRecognizer::ResultFlag
+
+ This enum describes the result of the current event filtering step in
+ a gesture recognizer state machine.
+
+ The result consists of a state value (one of Ignore, MayBeGesture,
+ TriggerGesture, FinishGesture, CancelGesture) and an optional hint
+ (ConsumeEventHint).
+
+ \value Ignore The event does not change the state of the recognizer.
+
+ \value MayBeGesture The event changed the internal state of the recognizer,
+ but it isn't clear yet if it is a gesture or not. The recognizer needs to
+ filter more events to decide. Gesture recognizers in the MayBeGesture state
+ may be reset automatically if they take too long to recognize gestures.
+
+ \value TriggerGesture The gesture has been triggered and the appropriate
+ QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value FinishGesture The gesture has been finished successfully and the
+ appropriate QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value CancelGesture The event made it clear that it is not a gesture. If
+ the gesture recognizer was in GestureTriggered state before, then the
+ gesture is canceled and the appropriate QGesture object will be delivered
+ to the target as a part of a QGestureEvent.
+
+ \value ConsumeEventHint This hint specifies that the gesture framework
+ should consume the filtered event and not deliver it to the receiver.
+
+ \omitvalue ResultState_Mask
+ \omitvalue ResultHint_Mask
+
+ \sa QGestureRecognizer::recognize()
+*/
+
+/*!
+ Constructs a new gesture recognizer object.
+*/
+QGestureRecognizer::QGestureRecognizer()
+{
+}
+
+/*!
+ Destroys the gesture recognizer.
+*/
+QGestureRecognizer::~QGestureRecognizer()
+{
+}
+
+/*!
+ This function is called by Qt to create a new QGesture object for the
+ given \a target (QWidget or QGraphicsObject).
+
+ Reimplement this function to create a custom QGesture-derived gesture
+ object if necessary.
+
+ The application takes ownership of the created gesture object.
+*/
+QGesture *QGestureRecognizer::create(QObject *target)
+{
+ Q_UNUSED(target);
+ return new QGesture;
+}
+
+/*!
+ This function is called by the framework to reset a given \a gesture.
+
+ Reimplement this function to implement additional requirements for custom QGesture
+ objects. This may be necessary if you implement a custom QGesture whose properties
+ need special handling when the gesture is reset.
+*/
+void QGestureRecognizer::reset(QGesture *gesture)
+{
+ if (gesture) {
+ QGesturePrivate *d = gesture->d_func();
+ d->state = Qt::NoGesture;
+ d->hotSpot = QPointF();
+ d->sceneHotSpot = QPointF();
+ d->isHotSpotSet = false;
+ }
+}
+
+/*!
+ \fn QGestureRecognizer::recognize(QGesture *gesture, QObject *watched, QEvent *event)
+
+ Handles the given \a event for the \a watched object, updating the state of the \a gesture
+ object as required, and returns a suitable result for the current recognition step.
+
+ This function is called by the framework to allow the recognizer to filter input events
+ dispatched to QWidget or QGraphicsObject instances that it is monitoring.
+
+ The result reflects how much of the gesture has been recognized. The state of the
+ \a gesture object is set depending on the result.
+
+ \sa QGestureRecognizer::Result
+*/
+
+/*!
+ Registers the given \a recognizer in the gesture framework and returns a gesture ID
+ for it.
+
+ The application takes ownership of the \a recognizer and returns the gesture type
+ ID associated with it. For gesture recognizers which handle custom QGesture
+ objects (i.e., those which return Qt::CustomGesture in a QGesture::gestureType()
+ function) the return value is a generated gesture ID with the Qt::CustomGesture
+ flag set.
+
+ \sa unregisterRecognizer(), QGestureRecognizer::create(), QGesture
+*/
+Qt::GestureType QGestureRecognizer::registerRecognizer(QGestureRecognizer *recognizer)
+{
+ return QGestureManager::instance()->registerGestureRecognizer(recognizer);
+}
+
+/*!
+ Unregisters all gesture recognizers of the specified \a type.
+
+ \sa registerRecognizer()
+*/
+void QGestureRecognizer::unregisterRecognizer(Qt::GestureType type)
+{
+ QGestureManager::instance()->unregisterGestureRecognizer(type);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
diff --git a/src/widgets/kernel/qgesturerecognizer.h b/src/widgets/kernel/qgesturerecognizer.h
new file mode 100644
index 0000000000..80d978d6bb
--- /dev/null
+++ b/src/widgets/kernel/qgesturerecognizer.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURERECOGNIZER_H
+#define QGESTURERECOGNIZER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QObject;
+class QEvent;
+class QGesture;
+class Q_GUI_EXPORT QGestureRecognizer
+{
+public:
+ enum ResultFlag
+ {
+ Ignore = 0x0001,
+
+ MayBeGesture = 0x0002,
+ TriggerGesture = 0x0004,
+ FinishGesture = 0x0008,
+ CancelGesture = 0x0010,
+
+ ResultState_Mask = 0x00ff,
+
+ ConsumeEventHint = 0x0100,
+ // StoreEventHint = 0x0200,
+ // ReplayStoredEventsHint = 0x0400,
+ // DiscardStoredEventsHint = 0x0800,
+
+ ResultHint_Mask = 0xff00
+ };
+ Q_DECLARE_FLAGS(Result, ResultFlag)
+
+ QGestureRecognizer();
+ virtual ~QGestureRecognizer();
+
+ virtual QGesture *create(QObject *target);
+ virtual Result recognize(QGesture *state, QObject *watched,
+ QEvent *event) = 0;
+ virtual void reset(QGesture *state);
+
+ static Qt::GestureType registerRecognizer(QGestureRecognizer *recognizer);
+ static void unregisterRecognizer(Qt::GestureType type);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QGestureRecognizer::Result)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_GESTURES
+
+#endif // QGESTURERECOGNIZER_H
diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp
new file mode 100644
index 0000000000..19d101a0b0
--- /dev/null
+++ b/src/widgets/kernel/qgridlayout.cpp
@@ -0,0 +1,1889 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgridlayout.h"
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qlist.h"
+#include "qsizepolicy.h"
+#include "qvector.h"
+#include "qvarlengtharray.h"
+#include "qlayoutengine_p.h"
+#include "qlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QGridLayoutSizeTriple
+{
+ QSize minS;
+ QSize hint;
+ QSize maxS;
+};
+
+/*
+ Three internal classes related to QGridLayout: (1) QGridBox is a
+ QLayoutItem with (row, column) information and (torow, tocolumn) information; (3) QGridLayoutData is
+ the internal representation of a QGridLayout.
+*/
+
+class QGridBox
+{
+public:
+ QGridBox(QLayoutItem *lit) { item_ = lit; }
+
+ QGridBox(const QLayout *l, QWidget *wid) { item_ = QLayoutPrivate::createWidgetItem(l, wid); }
+ ~QGridBox() { delete item_; }
+
+ QSize sizeHint() const { return item_->sizeHint(); }
+ QSize minimumSize() const { return item_->minimumSize(); }
+ QSize maximumSize() const { return item_->maximumSize(); }
+ Qt::Orientations expandingDirections() const { return item_->expandingDirections(); }
+ bool isEmpty() const { return item_->isEmpty(); }
+
+ bool hasHeightForWidth() const { return item_->hasHeightForWidth(); }
+ int heightForWidth(int w) const { return item_->heightForWidth(w); }
+
+ void setAlignment(Qt::Alignment a) { item_->setAlignment(a); }
+ void setGeometry(const QRect &r) { item_->setGeometry(r); }
+ Qt::Alignment alignment() const { return item_->alignment(); }
+ QLayoutItem *item() { return item_; }
+ QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; }
+
+ int hStretch() { return item_->widget() ?
+ item_->widget()->sizePolicy().horizontalStretch() : 0; }
+ int vStretch() { return item_->widget() ?
+ item_->widget()->sizePolicy().verticalStretch() : 0; }
+
+private:
+ friend class QGridLayoutPrivate;
+ friend class QGridLayout;
+
+ inline int toRow(int rr) const { return torow >= 0 ? torow : rr - 1; }
+ inline int toCol(int cc) const { return tocol >= 0 ? tocol : cc - 1; }
+
+ QLayoutItem *item_;
+ int row, col;
+ int torow, tocol;
+};
+
+class QGridLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QGridLayout)
+public:
+ QGridLayoutPrivate();
+
+ void add(QGridBox*, int row, int col);
+ void add(QGridBox*, int row1, int row2, int col1, int col2);
+ QSize sizeHint(int hSpacing, int vSpacing) const;
+ QSize minimumSize(int hSpacing, int vSpacing) const;
+ QSize maximumSize(int hSpacing, int vSpacing) const;
+
+ Qt::Orientations expandingDirections(int hSpacing, int vSpacing) const;
+
+ void distribute(QRect rect, int hSpacing, int vSpacing);
+ inline int numRows() const { return rr; }
+ inline int numCols() const { return cc; }
+ inline void expand(int rows, int cols)
+ { setSize(qMax(rows, rr), qMax(cols, cc)); }
+ inline void setRowStretch(int r, int s)
+ { expand(r + 1, 0); rStretch[r] = s; setDirty(); }
+ inline void setColStretch(int c, int s)
+ { expand(0, c + 1); cStretch[c] = s; setDirty(); }
+ inline int rowStretch(int r) const { return rStretch.at(r); }
+ inline int colStretch(int c) const { return cStretch.at(c); }
+ inline void setRowMinimumHeight(int r, int s)
+ { expand(r + 1, 0); rMinHeights[r] = s; setDirty(); }
+ inline void setColumnMinimumWidth(int c, int s)
+ { expand(0, c + 1); cMinWidths[c] = s; setDirty(); }
+ inline int rowSpacing(int r) const { return rMinHeights.at(r); }
+ inline int colSpacing(int c) const { return cMinWidths.at(c); }
+
+ inline void setReversed(bool r, bool c) { hReversed = c; vReversed = r; }
+ inline bool horReversed() const { return hReversed; }
+ inline bool verReversed() const { return vReversed; }
+ inline void setDirty() { needRecalc = true; hfw_width = -1; }
+ inline bool isDirty() const { return needRecalc; }
+ bool hasHeightForWidth(int hSpacing, int vSpacing);
+ int heightForWidth(int width, int hSpacing, int vSpacing);
+ int minimumHeightForWidth(int width, int hSpacing, int vSpacing);
+
+ inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; }
+ inline int count() const { return things.count(); }
+ QRect cellRect(int row, int col) const;
+
+ inline QLayoutItem *itemAt(int index) const {
+ if (index < things.count())
+ return things.at(index)->item();
+ else
+ return 0;
+ }
+ inline QLayoutItem *takeAt(int index) {
+ QLayoutItem *item = 0;
+ if (index < things.count()) {
+ QGridBox *b = things.takeAt(index);
+ if (b) {
+ item = b->takeItem();
+ delete b;
+ }
+ }
+ return item;
+ }
+
+ void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) {
+ if (index < things.count()) {
+ QGridBox *b = things.at(index);
+ int toRow = b->toRow(rr);
+ int toCol = b->toCol(cc);
+ *row = b->row;
+ *column = b->col;
+ *rowSpan = toRow - *row + 1;
+ *columnSpan = toCol - *column +1;
+ }
+ }
+ void deleteAll();
+
+private:
+ void setNextPosAfter(int r, int c);
+ void recalcHFW(int w);
+ void addHfwData(QGridBox *box, int width);
+ void init();
+ QSize findSize(int QLayoutStruct::*, int hSpacing, int vSpacing) const;
+ void addData(QGridBox *b, const QGridLayoutSizeTriple &sizes, bool r, bool c);
+ void setSize(int rows, int cols);
+ void setupSpacings(QVector<QLayoutStruct> &chain, QGridBox *grid[], int fixedSpacing,
+ Qt::Orientation orientation);
+ void setupLayoutData(int hSpacing, int vSpacing);
+ void setupHfwLayoutData();
+ void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
+
+ int rr;
+ int cc;
+ QVector<QLayoutStruct> rowData;
+ QVector<QLayoutStruct> colData;
+ QVector<QLayoutStruct> *hfwData;
+ QVector<int> rStretch;
+ QVector<int> cStretch;
+ QVector<int> rMinHeights;
+ QVector<int> cMinWidths;
+ QList<QGridBox *> things;
+
+ int hfw_width;
+ int hfw_height;
+ int hfw_minheight;
+ int nextR;
+ int nextC;
+
+ int horizontalSpacing;
+ int verticalSpacing;
+ int leftMargin;
+ int topMargin;
+ int rightMargin;
+ int bottomMargin;
+
+ uint hReversed : 1;
+ uint vReversed : 1;
+ uint needRecalc : 1;
+ uint has_hfw : 1;
+ uint addVertical : 1;
+};
+
+void QGridLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const
+{
+ int l = leftMargin;
+ int t = topMargin;
+ int r = rightMargin;
+ int b = bottomMargin;
+#ifdef Q_WS_MAC
+ int leftMost = INT_MAX;
+ int topMost = INT_MAX;
+ int rightMost = 0;
+ int bottomMost = 0;
+
+ QWidget *w = 0;
+ const int n = things.count();
+ for (int i = 0; i < n; ++i) {
+ QGridBox *box = things.at(i);
+ QLayoutItem *itm = box->item();
+ w = itm->widget();
+ if (w) {
+ bool visualHReversed = hReversed != (w->layoutDirection() == Qt::RightToLeft);
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (box->col <= leftMost) {
+ if (box->col < leftMost) {
+ // we found an item even closer to the margin, discard.
+ leftMost = box->col;
+ if (visualHReversed)
+ r = rightMargin;
+ else
+ l = leftMargin;
+ }
+ if (visualHReversed) {
+ r = qMax(r, wr.right() - lir.right());
+ } else {
+ l = qMax(l, lir.left() - wr.left());
+ }
+ }
+ if (box->row <= topMost) {
+ if (box->row < topMost) {
+ // we found an item even closer to the margin, discard.
+ topMost = box->row;
+ if (vReversed)
+ b = bottomMargin;
+ else
+ t = topMargin;
+ }
+ if (vReversed)
+ b = qMax(b, wr.bottom() - lir.bottom());
+ else
+ t = qMax(t, lir.top() - wr.top());
+ }
+ if (box->toCol(cc) >= rightMost) {
+ if (box->toCol(cc) > rightMost) {
+ // we found an item even closer to the margin, discard.
+ rightMost = box->toCol(cc);
+ if (visualHReversed)
+ l = leftMargin;
+ else
+ r = rightMargin;
+ }
+ if (visualHReversed) {
+ l = qMax(l, lir.left() - wr.left());
+ } else {
+ r = qMax(r, wr.right() - lir.right());
+ }
+
+ }
+ if (box->toRow(rr) >= bottomMost) {
+ if (box->toRow(rr) > bottomMost) {
+ // we found an item even closer to the margin, discard.
+ bottomMost = box->toRow(rr);
+ if (vReversed)
+ t = topMargin;
+ else
+ b = bottomMargin;
+ }
+ if (vReversed)
+ t = qMax(t, lir.top() - wr.top());
+ else
+ b = qMax(b, wr.bottom() - lir.bottom());
+ }
+ }
+ }
+
+#endif
+ if (left)
+ *left = l;
+ if (top)
+ *top = t;
+ if (right)
+ *right = r;
+ if (bottom)
+ *bottom = b;
+}
+
+QGridLayoutPrivate::QGridLayoutPrivate()
+{
+ addVertical = false;
+ setDirty();
+ rr = cc = 0;
+ nextR = nextC = 0;
+ hfwData = 0;
+ hReversed = false;
+ vReversed = false;
+ horizontalSpacing = -1;
+ verticalSpacing = -1;
+}
+
+#if 0
+QGridLayoutPrivate::QGridLayoutPrivate(int nRows, int nCols)
+ : rowData(0), colData(0)
+{
+ init();
+ if (nRows < 0) {
+ nRows = 1;
+ addVertical = false;
+ }
+ if (nCols < 0) {
+ nCols = 1;
+ addVertical = true;
+ }
+ setSize(nRows, nCols);
+}
+#endif
+
+void QGridLayoutPrivate::deleteAll()
+{
+ while (!things.isEmpty())
+ delete things.takeFirst();
+ delete hfwData;
+}
+
+bool QGridLayoutPrivate::hasHeightForWidth(int hSpacing, int vSpacing)
+{
+ setupLayoutData(hSpacing, vSpacing);
+ return has_hfw;
+}
+
+/*
+ Assumes that setupLayoutData() has been called, and that
+ qGeomCalc() has filled in colData with appropriate values.
+*/
+void QGridLayoutPrivate::recalcHFW(int w)
+{
+ /*
+ Go through all children, using colData and heightForWidth()
+ and put the results in hfwData.
+ */
+ if (!hfwData)
+ hfwData = new QVector<QLayoutStruct>(rr);
+ setupHfwLayoutData();
+ QVector<QLayoutStruct> &rData = *hfwData;
+
+ int h = 0;
+ int mh = 0;
+ for (int r = 0; r < rr; r++) {
+ int spacing = rData.at(r).spacing;
+ h += rData.at(r).sizeHint + spacing;
+ mh += rData.at(r).minimumSize + spacing;
+ }
+
+ hfw_width = w;
+ hfw_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+}
+
+int QGridLayoutPrivate::heightForWidth(int w, int hSpacing, int vSpacing)
+{
+ setupLayoutData(hSpacing, vSpacing);
+ if (!has_hfw)
+ return -1;
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+
+ int hMargins = left + right;
+ if (w - hMargins != hfw_width) {
+ qGeomCalc(colData, 0, cc, 0, w - hMargins);
+ recalcHFW(w - hMargins);
+ }
+ return hfw_height + top + bottom;
+}
+
+int QGridLayoutPrivate::minimumHeightForWidth(int w, int hSpacing, int vSpacing)
+{
+ (void)heightForWidth(w, hSpacing, vSpacing);
+ if (!has_hfw)
+ return -1;
+ int top, bottom;
+ effectiveMargins(0, &top, 0, &bottom);
+ return hfw_minheight + top + bottom;
+}
+
+QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int hSpacing, int vSpacing) const
+{
+ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
+ that->setupLayoutData(hSpacing, vSpacing);
+
+ int w = 0;
+ int h = 0;
+
+ for (int r = 0; r < rr; r++)
+ h += rowData.at(r).*size + rowData.at(r).spacing;
+ for (int c = 0; c < cc; c++)
+ w += colData.at(c).*size + colData.at(c).spacing;
+
+ w = qMin(QLAYOUTSIZE_MAX, w);
+ h = qMin(QLAYOUTSIZE_MAX, h);
+
+ return QSize(w, h);
+}
+
+Qt::Orientations QGridLayoutPrivate::expandingDirections(int hSpacing, int vSpacing) const
+{
+ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
+ that->setupLayoutData(hSpacing, vSpacing);
+ Qt::Orientations ret;
+
+ for (int r = 0; r < rr; r++) {
+ if (rowData.at(r).expansive) {
+ ret |= Qt::Vertical;
+ break;
+ }
+ }
+ for (int c = 0; c < cc; c++) {
+ if (colData.at(c).expansive) {
+ ret |= Qt::Horizontal;
+ break;
+ }
+ }
+ return ret;
+}
+
+QSize QGridLayoutPrivate::sizeHint(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::sizeHint, hSpacing, vSpacing);
+}
+
+QSize QGridLayoutPrivate::maximumSize(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::maximumSize, hSpacing, vSpacing);
+}
+
+QSize QGridLayoutPrivate::minimumSize(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::minimumSize, hSpacing, vSpacing);
+}
+
+void QGridLayoutPrivate::setSize(int r, int c)
+{
+ if ((int)rowData.size() < r) {
+ int newR = qMax(r, rr * 2);
+ rowData.resize(newR);
+ rStretch.resize(newR);
+ rMinHeights.resize(newR);
+ for (int i = rr; i < newR; i++) {
+ rowData[i].init();
+ rowData[i].maximumSize = 0;
+ rowData[i].pos = 0;
+ rowData[i].size = 0;
+ rStretch[i] = 0;
+ rMinHeights[i] = 0;
+ }
+ }
+ if ((int)colData.size() < c) {
+ int newC = qMax(c, cc * 2);
+ colData.resize(newC);
+ cStretch.resize(newC);
+ cMinWidths.resize(newC);
+ for (int i = cc; i < newC; i++) {
+ colData[i].init();
+ colData[i].maximumSize = 0;
+ colData[i].pos = 0;
+ colData[i].size = 0;
+ cStretch[i] = 0;
+ cMinWidths[i] = 0;
+ }
+ }
+
+ if (hfwData && (int)hfwData->size() < r) {
+ delete hfwData;
+ hfwData = 0;
+ hfw_width = -1;
+ }
+ rr = r;
+ cc = c;
+}
+
+void QGridLayoutPrivate::setNextPosAfter(int row, int col)
+{
+ if (addVertical) {
+ if (col > nextC || (col == nextC && row >= nextR)) {
+ nextR = row + 1;
+ nextC = col;
+ if (nextR >= rr) {
+ nextR = 0;
+ nextC++;
+ }
+ }
+ } else {
+ if (row > nextR || (row == nextR && col >= nextC)) {
+ nextR = row;
+ nextC = col + 1;
+ if (nextC >= cc) {
+ nextC = 0;
+ nextR++;
+ }
+ }
+ }
+}
+
+void QGridLayoutPrivate::add(QGridBox *box, int row, int col)
+{
+ expand(row + 1, col + 1);
+ box->row = box->torow = row;
+ box->col = box->tocol = col;
+ things.append(box);
+ setDirty();
+ setNextPosAfter(row, col);
+}
+
+void QGridLayoutPrivate::add(QGridBox *box, int row1, int row2, int col1, int col2)
+{
+ if (row2 >= 0 && row2 < row1)
+ qWarning("QGridLayout: Multi-cell fromRow greater than toRow");
+ if (col2 >= 0 && col2 < col1)
+ qWarning("QGridLayout: Multi-cell fromCol greater than toCol");
+ if (row1 == row2 && col1 == col2) {
+ add(box, row1, col1);
+ return;
+ }
+ expand(row2 + 1, col2 + 1);
+ box->row = row1;
+ box->col = col1;
+
+ box->torow = row2;
+ box->tocol = col2;
+
+ things.append(box);
+ setDirty();
+ if (col2 < 0)
+ col2 = cc - 1;
+
+ setNextPosAfter(row2, col2);
+}
+
+void QGridLayoutPrivate::addData(QGridBox *box, const QGridLayoutSizeTriple &sizes, bool r, bool c)
+{
+ const QWidget *widget = box->item()->widget();
+
+ if (box->isEmpty() && widget)
+ return;
+
+ if (c) {
+ QLayoutStruct *data = &colData[box->col];
+ if (!cStretch.at(box->col))
+ data->stretch = qMax(data->stretch, box->hStretch());
+ data->sizeHint = qMax(sizes.hint.width(), data->sizeHint);
+ data->minimumSize = qMax(sizes.minS.width(), data->minimumSize);
+
+ qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.width(),
+ box->expandingDirections() & Qt::Horizontal, box->isEmpty());
+ }
+ if (r) {
+ QLayoutStruct *data = &rowData[box->row];
+ if (!rStretch.at(box->row))
+ data->stretch = qMax(data->stretch, box->vStretch());
+ data->sizeHint = qMax(sizes.hint.height(), data->sizeHint);
+ data->minimumSize = qMax(sizes.minS.height(), data->minimumSize);
+
+ qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.height(),
+ box->expandingDirections() & Qt::Vertical, box->isEmpty());
+ }
+}
+
+static void initEmptyMultiBox(QVector<QLayoutStruct> &chain, int start, int end)
+{
+ for (int i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->empty && data->maximumSize == 0) // truly empty box
+ data->maximumSize = QWIDGETSIZE_MAX;
+ data->empty = false;
+ }
+}
+
+static void distributeMultiBox(QVector<QLayoutStruct> &chain, int start, int end, int minSize,
+ int sizeHint, QVector<int> &stretchArray, int stretch)
+{
+ int i;
+ int w = 0;
+ int wh = 0;
+ int max = 0;
+
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ w += data->minimumSize;
+ wh += data->sizeHint;
+ max += data->maximumSize;
+ if (stretchArray.at(i) == 0)
+ data->stretch = qMax(data->stretch, stretch);
+
+ if (i != end) {
+ int spacing = data->spacing;
+ w += spacing;
+ wh += spacing;
+ max += spacing;
+ }
+ }
+
+ if (max < minSize) { // implies w < minSize
+ /*
+ We must increase the maximum size of at least one of the
+ items. qGeomCalc() will put the extra space in between the
+ items. We must recover that extra space and put it
+ somewhere. It does not really matter where, since the user
+ can always specify stretch factors and avoid this code.
+ */
+ qGeomCalc(chain, start, end - start + 1, 0, minSize);
+ int pos = 0;
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ int nextPos = (i == end) ? minSize : chain.at(i + 1).pos;
+ int realSize = nextPos - pos;
+ if (i != end)
+ realSize -= data->spacing;
+ if (data->minimumSize < realSize)
+ data->minimumSize = realSize;
+ if (data->maximumSize < data->minimumSize)
+ data->maximumSize = data->minimumSize;
+ pos = nextPos;
+ }
+ } else if (w < minSize) {
+ qGeomCalc(chain, start, end - start + 1, 0, minSize);
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->minimumSize < data->size)
+ data->minimumSize = data->size;
+ }
+ }
+
+ if (wh < sizeHint) {
+ qGeomCalc(chain, start, end - start + 1, 0, sizeHint);
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->sizeHint < data->size)
+ data->sizeHint = data->size;
+ }
+ }
+}
+
+static QGridBox *&gridAt(QGridBox *grid[], int r, int c, int cc,
+ Qt::Orientation orientation = Qt::Vertical)
+{
+ if (orientation == Qt::Horizontal)
+ qSwap(r, c);
+ return grid[(r * cc) + c];
+}
+
+void QGridLayoutPrivate::setupSpacings(QVector<QLayoutStruct> &chain,
+ QGridBox *grid[], int fixedSpacing,
+ Qt::Orientation orientation)
+{
+ Q_Q(QGridLayout);
+ int numRows = rr; // or columns if orientation is horizontal
+ int numColumns = cc; // or rows if orientation is horizontal
+
+ if (orientation == Qt::Horizontal) {
+ qSwap(numRows, numColumns);
+ }
+
+ QStyle *style = 0;
+ if (fixedSpacing < 0) {
+ if (QWidget *parentWidget = q->parentWidget())
+ style = parentWidget->style();
+ }
+
+ for (int c = 0; c < numColumns; ++c) {
+ QGridBox *previousBox = 0;
+ int previousRow = -1; // previous *non-empty* row
+
+ for (int r = 0; r < numRows; ++r) {
+ if (chain.at(r).empty)
+ continue;
+
+ QGridBox *box = gridAt(grid, r, c, cc, orientation);
+ if (previousRow != -1 && (!box || previousBox != box)) {
+ int spacing = fixedSpacing;
+ if (spacing < 0) {
+ QSizePolicy::ControlTypes controlTypes1 = QSizePolicy::DefaultType;
+ QSizePolicy::ControlTypes controlTypes2 = QSizePolicy::DefaultType;
+ if (previousBox)
+ controlTypes1 = previousBox->item()->controlTypes();
+ if (box)
+ controlTypes2 = box->item()->controlTypes();
+
+ if ((orientation == Qt::Horizontal && hReversed)
+ || (orientation == Qt::Vertical && vReversed))
+ qSwap(controlTypes1, controlTypes2);
+
+ if (style)
+ spacing = style->combinedLayoutSpacing(controlTypes1, controlTypes2,
+ orientation, 0, q->parentWidget());
+ } else {
+ if (orientation == Qt::Vertical) {
+ QGridBox *sibling = vReversed ? previousBox : box;
+ if (sibling) {
+ QWidget *wid = sibling->item()->widget();
+ if (wid)
+ spacing = qMax(spacing, sibling->item()->geometry().top() - wid->geometry().top() );
+ }
+ }
+ }
+
+ if (spacing > chain.at(previousRow).spacing)
+ chain[previousRow].spacing = spacing;
+ }
+
+ previousBox = box;
+ previousRow = r;
+ }
+ }
+}
+
+//#define QT_LAYOUT_DISABLE_CACHING
+
+void QGridLayoutPrivate::setupLayoutData(int hSpacing, int vSpacing)
+{
+ Q_Q(QGridLayout);
+
+#ifndef QT_LAYOUT_DISABLE_CACHING
+ if (!needRecalc)
+ return;
+#endif
+ has_hfw = false;
+ int i;
+
+ for (i = 0; i < rr; i++) {
+ rowData[i].init(rStretch.at(i), rMinHeights.at(i));
+ rowData[i].maximumSize = rStretch.at(i) ? QLAYOUTSIZE_MAX : rMinHeights.at(i);
+ }
+ for (i = 0; i < cc; i++) {
+ colData[i].init(cStretch.at(i), cMinWidths.at(i));
+ colData[i].maximumSize = cStretch.at(i) ? QLAYOUTSIZE_MAX : cMinWidths.at(i);
+ }
+
+ int n = things.size();
+ QVarLengthArray<QGridLayoutSizeTriple> sizes(n);
+
+ bool has_multi = false;
+
+ /*
+ Grid of items. We use it to determine which items are
+ adjacent to which and compute the spacings correctly.
+ */
+ QVarLengthArray<QGridBox *> grid(rr * cc);
+ qMemSet(grid.data(), 0, rr * cc * sizeof(QGridBox *));
+
+ /*
+ Initialize 'sizes' and 'grid' data structures, and insert
+ non-spanning items to our row and column data structures.
+ */
+ for (i = 0; i < n; ++i) {
+ QGridBox * const box = things.at(i);
+ sizes[i].minS = box->minimumSize();
+ sizes[i].hint = box->sizeHint();
+ sizes[i].maxS = box->maximumSize();
+
+ if (box->hasHeightForWidth())
+ has_hfw = true;
+
+ if (box->row == box->toRow(rr)) {
+ addData(box, sizes[i], true, false);
+ } else {
+ initEmptyMultiBox(rowData, box->row, box->toRow(rr));
+ has_multi = true;
+ }
+
+ if (box->col == box->toCol(cc)) {
+ addData(box, sizes[i], false, true);
+ } else {
+ initEmptyMultiBox(colData, box->col, box->toCol(cc));
+ has_multi = true;
+ }
+
+ for (int r = box->row; r <= box->toRow(rr); ++r) {
+ for (int c = box->col; c <= box->toCol(cc); ++c) {
+ gridAt(grid.data(), r, c, cc) = box;
+ }
+ }
+ }
+
+ setupSpacings(colData, grid.data(), hSpacing, Qt::Horizontal);
+ setupSpacings(rowData, grid.data(), vSpacing, Qt::Vertical);
+
+ /*
+ Insert multicell items to our row and column data structures.
+ This must be done after the non-spanning items to obtain a
+ better distribution in distributeMultiBox().
+ */
+ if (has_multi) {
+ for (i = 0; i < n; ++i) {
+ QGridBox * const box = things.at(i);
+
+ if (box->row != box->toRow(rr))
+ distributeMultiBox(rowData, box->row, box->toRow(rr), sizes[i].minS.height(),
+ sizes[i].hint.height(), rStretch, box->vStretch());
+ if (box->col != box->toCol(cc))
+ distributeMultiBox(colData, box->col, box->toCol(cc), sizes[i].minS.width(),
+ sizes[i].hint.width(), cStretch, box->hStretch());
+ }
+ }
+
+ for (i = 0; i < rr; i++)
+ rowData[i].expansive = rowData.at(i).expansive || rowData.at(i).stretch > 0;
+ for (i = 0; i < cc; i++)
+ colData[i].expansive = colData.at(i).expansive || colData.at(i).stretch > 0;
+
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ needRecalc = false;
+}
+
+void QGridLayoutPrivate::addHfwData(QGridBox *box, int width)
+{
+ QVector<QLayoutStruct> &rData = *hfwData;
+ if (box->hasHeightForWidth()) {
+ int hint = box->heightForWidth(width);
+ rData[box->row].sizeHint = qMax(hint, rData.at(box->row).sizeHint);
+ rData[box->row].minimumSize = qMax(hint, rData.at(box->row).minimumSize);
+ } else {
+ QSize hint = box->sizeHint();
+ QSize minS = box->minimumSize();
+ rData[box->row].sizeHint = qMax(hint.height(), rData.at(box->row).sizeHint);
+ rData[box->row].minimumSize = qMax(minS.height(), rData.at(box->row).minimumSize);
+ }
+}
+
+/*
+ Similar to setupLayoutData(), but uses heightForWidth(colData)
+ instead of sizeHint(). Assumes that setupLayoutData() and
+ qGeomCalc(colData) has been called.
+*/
+void QGridLayoutPrivate::setupHfwLayoutData()
+{
+ QVector<QLayoutStruct> &rData = *hfwData;
+ for (int i = 0; i < rr; i++) {
+ rData[i] = rowData.at(i);
+ rData[i].minimumSize = rData[i].sizeHint = rMinHeights.at(i);
+ }
+
+ for (int pass = 0; pass < 2; ++pass) {
+ for (int i = 0; i < things.size(); ++i) {
+ QGridBox *box = things.at(i);
+ int r1 = box->row;
+ int c1 = box->col;
+ int r2 = box->toRow(rr);
+ int c2 = box->toCol(cc);
+ int w = colData.at(c2).pos + colData.at(c2).size - colData.at(c1).pos;
+
+ if (r1 == r2) {
+ if (pass == 0)
+ addHfwData(box, w);
+ } else {
+ if (pass == 0) {
+ initEmptyMultiBox(rData, r1, r2);
+ } else {
+ QSize hint = box->sizeHint();
+ QSize min = box->minimumSize();
+ if (box->hasHeightForWidth()) {
+ int hfwh = box->heightForWidth(w);
+ if (hfwh > hint.height())
+ hint.setHeight(hfwh);
+ if (hfwh > min.height())
+ min.setHeight(hfwh);
+ }
+ distributeMultiBox(rData, r1, r2, min.height(), hint.height(),
+ rStretch, box->vStretch());
+ }
+ }
+ }
+ }
+ for (int i = 0; i < rr; i++)
+ rData[i].expansive = rData.at(i).expansive || rData.at(i).stretch > 0;
+}
+
+void QGridLayoutPrivate::distribute(QRect r, int hSpacing, int vSpacing)
+{
+ Q_Q(QGridLayout);
+ bool visualHReversed = hReversed;
+ QWidget *parent = q->parentWidget();
+ if (parent && parent->isRightToLeft())
+ visualHReversed = !visualHReversed;
+
+ setupLayoutData(hSpacing, vSpacing);
+
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+ r.adjust(+left, +top, -right, -bottom);
+
+ qGeomCalc(colData, 0, cc, r.x(), r.width());
+ QVector<QLayoutStruct> *rDataPtr;
+ if (has_hfw) {
+ recalcHFW(r.width());
+ qGeomCalc(*hfwData, 0, rr, r.y(), r.height());
+ rDataPtr = hfwData;
+ } else {
+ qGeomCalc(rowData, 0, rr, r.y(), r.height());
+ rDataPtr = &rowData;
+ }
+ QVector<QLayoutStruct> &rData = *rDataPtr;
+ int i;
+
+ bool reverse = ((r.bottom() > rect.bottom()) || (r.bottom() == rect.bottom()
+ && ((r.right() > rect.right()) != visualHReversed)));
+ int n = things.size();
+ for (i = 0; i < n; ++i) {
+ QGridBox *box = things.at(reverse ? n-i-1 : i);
+ int r2 = box->toRow(rr);
+ int c2 = box->toCol(cc);
+
+ int x = colData.at(box->col).pos;
+ int y = rData.at(box->row).pos;
+ int x2p = colData.at(c2).pos + colData.at(c2).size; // x2+1
+ int y2p = rData.at(r2).pos + rData.at(r2).size; // y2+1
+ int w = x2p - x;
+ int h = y2p - y;
+
+ if (visualHReversed)
+ x = r.left() + r.right() - x - w + 1;
+ if (vReversed)
+ y = r.top() + r.bottom() - y - h + 1;
+
+ box->setGeometry(QRect(x, y, w, h));
+ }
+}
+
+QRect QGridLayoutPrivate::cellRect(int row, int col) const
+{
+ if (row < 0 || row >= rr || col < 0 || col >= cc)
+ return QRect();
+
+ const QVector<QLayoutStruct> *rDataPtr;
+ if (has_hfw && hfwData)
+ rDataPtr = hfwData;
+ else
+ rDataPtr = &rowData;
+ return QRect(colData.at(col).pos, rDataPtr->at(row).pos,
+ colData.at(col).size, rDataPtr->at(row).size);
+}
+
+/*!
+ \class QGridLayout
+
+ \brief The QGridLayout class lays out widgets in a grid.
+
+ \ingroup geomanagement
+
+
+ QGridLayout takes the space made available to it (by its parent
+ layout or by the parentWidget()), divides it up into rows and
+ columns, and puts each widget it manages into the correct cell.
+
+ Columns and rows behave identically; we will discuss columns, but
+ there are equivalent functions for rows.
+
+ Each column has a minimum width and a stretch factor. The minimum
+ width is the greatest of that set using setColumnMinimumWidth() and the
+ minimum width of each widget in that column. The stretch factor is
+ set using setColumnStretch() and determines how much of the available
+ space the column will get over and above its necessary minimum.
+
+ Normally, each managed widget or layout is put into a cell of its
+ own using addWidget(). It is also possible for a widget to occupy
+ multiple cells using the row and column spanning overloads of
+ addItem() and addWidget(). If you do this, QGridLayout will guess
+ how to distribute the size over the columns/rows (based on the
+ stretch factors).
+
+ To remove a widget from a layout, call removeWidget(). Calling
+ QWidget::hide() on a widget also effectively removes the widget
+ from the layout until QWidget::show() is called.
+
+ This illustration shows a fragment of a dialog with a five-column,
+ three-row grid (the grid is shown overlaid in magenta):
+
+ \image gridlayout.png A grid layout
+
+ Columns 0, 2 and 4 in this dialog fragment are made up of a
+ QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
+ placeholders made with setColumnMinimumWidth(). Row 0 consists of three
+ QLabel objects, row 1 of three QLineEdit objects and row 2 of
+ three QListBox objects. We used placeholder columns (1 and 3) to
+ get the right amount of space between the columns.
+
+ Note that the columns and rows are not equally wide or tall. If
+ you want two columns to have the same width, you must set their
+ minimum widths and stretch factors to be the same yourself. You do
+ this using setColumnMinimumWidth() and setColumnStretch().
+
+ If the QGridLayout is not the top-level layout (i.e. does not
+ manage all of the widget's area and children), you must add it to
+ its parent layout when you create it, but before you do anything
+ with it. The normal way to add a layout is by calling
+ addLayout() on the parent layout.
+
+ Once you have added your layout you can start putting widgets and
+ other layouts into the cells of your grid layout using
+ addWidget(), addItem(), and addLayout().
+
+ QGridLayout also includes two margin widths:
+ the \l{getContentsMargins()}{contents margin} and the spacing().
+ The contents margin is the width of the reserved space along each
+ of the QGridLayout's four sides. The spacing() is the width of the
+ automatically allocated spacing between neighboring boxes.
+
+ The default contents margin values are provided by the
+ \l{QStyle::pixelMetric()}{style}. The default value Qt styles specify
+ is 9 for child widgets and 11 for windows. The spacing defaults to the same as
+ the margin width for a top-level layout, or to the same as the
+ parent layout.
+
+ \sa QBoxLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
+*/
+
+
+/*!
+ Constructs a new QGridLayout with parent widget, \a parent. The
+ layout has one row and one column initially, and will expand when
+ new items are inserted.
+*/
+QGridLayout::QGridLayout(QWidget *parent)
+ : QLayout(*new QGridLayoutPrivate, 0, parent)
+{
+ Q_D(QGridLayout);
+ d->expand(1, 1);
+}
+
+/*!
+ Constructs a new grid layout.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout()
+ : QLayout(*new QGridLayoutPrivate, 0, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(1, 1);
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+ Constructs a new QGridLayout with \a nRows rows, \a nCols columns
+ and parent widget, \a parent. \a parent may not be 0. The grid
+ layout is called \a name.
+
+ \a margin is the number of pixels between the edge of the widget
+ and its managed children. \a space is the default number of pixels
+ between cells. If \a space is -1, the value of \a margin is used.
+*/
+QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin,
+ int space, const char *name)
+ : QLayout(*new QGridLayoutPrivate, 0, parent)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setMargin(margin);
+ setSpacing(space < 0 ? margin : space);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ \obsolete
+
+ Constructs a new grid with \a nRows rows and \a nCols columns. If
+ \a spacing is -1, this QGridLayout inherits its parent's
+ spacing(); otherwise \a spacing is used. The grid layout is called
+ \a name.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols,
+ int spacing, const char *name)
+ : QLayout(*new QGridLayoutPrivate, parentLayout, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ \obsolete
+
+ Constructs a new grid with \a nRows rows and \a nCols columns. If
+ \a spacing is -1, this QGridLayout inherits its parent's
+ spacing(); otherwise \a spacing is used. The grid layout is called
+ \a name.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout(int nRows, int nCols, int spacing, const char *name)
+ : QLayout(*new QGridLayoutPrivate, 0, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+
+/*!
+\internal (mostly)
+
+Sets the positioning mode used by addItem(). If \a orient is
+Qt::Horizontal, this layout is expanded to \a n columns, and items
+will be added columns-first. Otherwise it is expanded to \a n rows and
+items will be added rows-first.
+*/
+
+void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
+{
+ Q_D(QGridLayout);
+ if (orient == Qt::Horizontal) {
+ d->expand(1, n);
+ d->addVertical = false;
+ } else {
+ d->expand(n,1);
+ d->addVertical = true;
+ }
+}
+
+
+/*!
+ Destroys the grid layout. Geometry management is terminated if
+ this is a top-level grid.
+
+ The layout's widgets aren't destroyed.
+*/
+QGridLayout::~QGridLayout()
+{
+ Q_D(QGridLayout);
+ d->deleteAll();
+}
+
+/*!
+ \property QGridLayout::horizontalSpacing
+ \brief the spacing between widgets that are laid out side by side
+ \since 4.3
+
+ If no value is explicitly set, the layout's horizontal spacing is
+ inherited from the parent layout, or from the style settings for
+ the parent widget.
+
+ \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QGridLayout::setHorizontalSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->horizontalSpacing = spacing;
+ invalidate();
+}
+
+int QGridLayout::horizontalSpacing() const
+{
+ Q_D(const QGridLayout);
+ if (d->horizontalSpacing >= 0) {
+ return d->horizontalSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+}
+
+/*!
+ \property QGridLayout::verticalSpacing
+ \brief the spacing between widgets that are laid out on top of each other
+ \since 4.3
+
+ If no value is explicitly set, the layout's vertical spacing is
+ inherited from the parent layout, or from the style settings for
+ the parent widget.
+
+ \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QGridLayout::setVerticalSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->verticalSpacing = spacing;
+ invalidate();
+}
+
+int QGridLayout::verticalSpacing() const
+{
+ Q_D(const QGridLayout);
+ if (d->verticalSpacing >= 0) {
+ return d->verticalSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ This function sets both the vertical and horizontal spacing to
+ \a spacing.
+
+ \sa setVerticalSpacing(), setHorizontalSpacing()
+*/
+void QGridLayout::setSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->horizontalSpacing = d->verticalSpacing = spacing;
+ invalidate();
+}
+
+/*!
+ If the vertical spacing is equal to the horizontal spacing,
+ this function returns that value; otherwise it return -1.
+
+ \sa setSpacing(), verticalSpacing(), horizontalSpacing()
+*/
+int QGridLayout::spacing() const
+{
+ int hSpacing = horizontalSpacing();
+ if (hSpacing == verticalSpacing()) {
+ return hSpacing;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Returns the number of rows in this grid.
+*/
+int QGridLayout::rowCount() const
+{
+ Q_D(const QGridLayout);
+ return d->numRows();
+}
+
+/*!
+ Returns the number of columns in this grid.
+*/
+int QGridLayout::columnCount() const
+{
+ Q_D(const QGridLayout);
+ return d->numCols();
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::sizeHint() const
+{
+ Q_D(const QGridLayout);
+ QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing()));
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ result += QSize(left + right, top + bottom);
+ return result;
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::minimumSize() const
+{
+ Q_D(const QGridLayout);
+ QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing()));
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ result += QSize(left + right, top + bottom);
+ return result;
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::maximumSize() const
+{
+ Q_D(const QGridLayout);
+
+ QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing());
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ s += QSize(left + right, top + bottom);
+ s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
+ if (alignment() & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (alignment() & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+/*!
+ \reimp
+*/
+bool QGridLayout::hasHeightForWidth() const
+{
+ return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ \reimp
+*/
+int QGridLayout::heightForWidth(int w) const
+{
+ Q_D(const QGridLayout);
+ QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
+ return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ \reimp
+*/
+int QGridLayout::minimumHeightForWidth(int w) const
+{
+ Q_D(const QGridLayout);
+ QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
+ return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing());
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \compat
+
+ Searches for widget \a w in this layout (not including child
+ layouts). If \a w is found, it sets \c{*}\a{row} and
+ \c{*}\a{column} to the row and column that the widget
+ occupies and returns true; otherwise returns false.
+
+ If the widget spans multiple rows/columns, the top-left cell
+ is returned.
+
+ Use indexOf() and getItemPosition() instead.
+*/
+bool QGridLayout::findWidget(QWidget* w, int *row, int *column)
+{
+ Q_D(QGridLayout);
+ int index = indexOf(w);
+ if (index < 0)
+ return false;
+ int dummy1, dummy2;
+ d->getItemPosition(index, row, column, &dummy1, &dummy2);
+ return true;
+}
+#endif
+/*!
+ \reimp
+*/
+int QGridLayout::count() const
+{
+ Q_D(const QGridLayout);
+ return d->count();
+}
+
+
+/*!
+ \reimp
+*/
+QLayoutItem *QGridLayout::itemAt(int index) const
+{
+ Q_D(const QGridLayout);
+ return d->itemAt(index);
+}
+
+/*!
+ \since 4.4
+
+ Returns the layout item that occupies cell (\a row, \a column), or 0 if
+ the cell is empty.
+
+ \sa getItemPosition(), indexOf()
+*/
+QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
+{
+ Q_D(const QGridLayout);
+ int n = d->things.count();
+ for (int i = 0; i < n; ++i) {
+ QGridBox *box = d->things.at(i);
+ if (row >= box->row && row <= box->toRow(d->rr)
+ && column >= box->col && column <= box->toCol(d->cc)) {
+ return box->item();
+ }
+ }
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QGridLayout::takeAt(int index)
+{
+ Q_D(QGridLayout);
+ return d->takeAt(index);
+}
+
+/*!
+ Returns the position information of the item with the given \a index.
+
+ The variables passed as \a row and \a column are updated with the position of the
+ item in the layout, and the \a rowSpan and \a columnSpan variables are updated
+ with the vertical and horizontal spans of the item.
+
+ \sa itemAtPosition(), itemAt()
+*/
+void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
+{
+ Q_D(QGridLayout);
+ d->getItemPosition(index, row, column, rowSpan, columnSpan);
+}
+
+
+/*!
+ \reimp
+*/
+void QGridLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QGridLayout);
+ if (d->isDirty() || rect != geometry()) {
+ QRect cr = alignment() ? alignmentRect(rect) : rect;
+ d->distribute(cr, horizontalSpacing(), verticalSpacing());
+ QLayout::setGeometry(rect);
+ }
+}
+
+/*!
+ Returns the geometry of the cell with row \a row and column \a column
+ in the grid. Returns an invalid rectangle if \a row or \a column is
+ outside the grid.
+
+ \warning in the current version of Qt this function does not
+ return valid results until setGeometry() has been called, i.e.
+ after the parentWidget() is visible.
+*/
+QRect QGridLayout::cellRect(int row, int column) const
+{
+ Q_D(const QGridLayout);
+ return d->cellRect(row, column);
+}
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+ Expands this grid so that it will have \a nRows rows and \a nCols
+ columns. Will not shrink the grid. You should not need to call
+ this function because QGridLayout expands automatically as new
+ items are inserted.
+*/
+void QGridLayout::expand(int nRows, int nCols)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+}
+#endif
+
+/*!
+ \reimp
+*/
+void QGridLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QGridLayout);
+ int r, c;
+ d->getNextPos(r, c);
+ addItem(item, r, c);
+}
+
+/*!
+ Adds \a item at position \a row, \a column, spanning \a rowSpan
+ rows and \a columnSpan columns, and aligns it according to \a
+ alignment. If \a rowSpan and/or \a columnSpan is -1, then the item
+ will extend to the bottom and/or right edge, respectively. The
+ layout takes ownership of the \a item.
+
+ \warning Do not use this function to add child layouts or child
+ widget items. Use addLayout() or addWidget() instead.
+*/
+void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ QGridBox *b = new QGridBox(item);
+ b->setAlignment(alignment);
+ d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
+ invalidate();
+}
+
+/*
+ Returns true if the widget \a w can be added to the layout \a l;
+ otherwise returns false.
+*/
+static bool checkWidget(QLayout *l, QWidget *w)
+{
+ if (!w) {
+ qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
+ l->objectName().toLocal8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Adds the given \a widget to the cell grid at \a row, \a column. The
+ top-left position is (0, 0) by default.
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+*/
+void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
+{
+ if (!checkWidget(this, widget))
+ return;
+ if (row < 0 || column < 0) {
+ qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
+ widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
+ metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
+ return;
+ }
+ addChildWidget(widget);
+ QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
+ addItem(b, row, column, 1, 1, alignment);
+}
+
+/*!
+ \overload
+
+ This version adds the given \a widget to the cell grid, spanning
+ multiple rows/columns. The cell will start at \a fromRow, \a
+ fromColumn spanning \a rowSpan rows and \a columnSpan columns. The
+ \a widget will have the given \a alignment.
+
+ If \a rowSpan and/or \a columnSpan is -1, then the widget will
+ extend to the bottom and/or right edge, respectively.
+
+*/
+void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
+ int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ if (!checkWidget(this, widget))
+ return;
+ int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
+ int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
+ addChildWidget(widget);
+ QGridBox *b = new QGridBox(this, widget);
+ b->setAlignment(alignment);
+ d->add(b, fromRow, toRow, fromColumn, toColumn);
+ invalidate();
+}
+
+/*!
+ \fn void QGridLayout::addWidget(QWidget *widget)
+
+ \overload
+ \internal
+*/
+
+/*!
+ Places the \a layout at position (\a row, \a column) in the grid. The
+ top-left position is (0, 0).
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+ A non-zero alignment indicates that the layout should not grow to
+ fill the available space but should be sized according to
+ sizeHint().
+
+
+ \a layout becomes a child of the grid layout.
+*/
+void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ addChildLayout(layout);
+ QGridBox *b = new QGridBox(layout);
+ b->setAlignment(alignment);
+ d->add(b, row, column);
+}
+
+/*!
+ \overload
+ This version adds the layout \a layout to the cell grid, spanning multiple
+ rows/columns. The cell will start at \a row, \a column spanning \a
+ rowSpan rows and \a columnSpan columns.
+
+ If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom
+ and/or right edge, respectively.
+*/
+void QGridLayout::addLayout(QLayout *layout, int row, int column,
+ int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ addChildLayout(layout);
+ QGridBox *b = new QGridBox(layout);
+ b->setAlignment(alignment);
+ d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
+}
+
+/*!
+ Sets the stretch factor of row \a row to \a stretch. The first row
+ is number 0.
+
+ The stretch factor is relative to the other rows in this grid.
+ Rows with a higher stretch factor take more of the available
+ space.
+
+ The default stretch factor is 0. If the stretch factor is 0 and no
+ other row in this table can grow at all, the row may still grow.
+
+ \sa rowStretch(), setRowMinimumHeight(), setColumnStretch()
+*/
+void QGridLayout::setRowStretch(int row, int stretch)
+{
+ Q_D(QGridLayout);
+ d->setRowStretch(row, stretch);
+ invalidate();
+}
+
+/*!
+ Returns the stretch factor for row \a row.
+
+ \sa setRowStretch()
+*/
+int QGridLayout::rowStretch(int row) const
+{
+ Q_D(const QGridLayout);
+ return d->rowStretch(row);
+}
+
+/*!
+ Returns the stretch factor for column \a column.
+
+ \sa setColumnStretch()
+*/
+int QGridLayout::columnStretch(int column) const
+{
+ Q_D(const QGridLayout);
+ return d->colStretch(column);
+}
+
+/*!
+ Sets the stretch factor of column \a column to \a stretch. The first
+ column is number 0.
+
+ The stretch factor is relative to the other columns in this grid.
+ Columns with a higher stretch factor take more of the available
+ space.
+
+ The default stretch factor is 0. If the stretch factor is 0 and no
+ other column in this table can grow at all, the column may still
+ grow.
+
+ An alternative approach is to add spacing using addItem() with a
+ QSpacerItem.
+
+ \sa columnStretch(), setRowStretch()
+*/
+void QGridLayout::setColumnStretch(int column, int stretch)
+{
+ Q_D(QGridLayout);
+ d->setColStretch(column, stretch);
+ invalidate();
+}
+
+
+
+/*!
+ Sets the minimum height of row \a row to \a minSize pixels.
+
+ \sa rowMinimumHeight(), setColumnMinimumWidth()
+*/
+void QGridLayout::setRowMinimumHeight(int row, int minSize)
+{
+ Q_D(QGridLayout);
+ d->setRowMinimumHeight(row, minSize);
+ invalidate();
+}
+
+/*!
+ Returns the minimum width set for row \a row.
+
+ \sa setRowMinimumHeight()
+*/
+int QGridLayout::rowMinimumHeight(int row) const
+{
+ Q_D(const QGridLayout);
+ return d->rowSpacing(row);
+}
+
+/*!
+ Sets the minimum width of column \a column to \a minSize pixels.
+
+ \sa columnMinimumWidth(), setRowMinimumHeight()
+*/
+void QGridLayout::setColumnMinimumWidth(int column, int minSize)
+{
+ Q_D(QGridLayout);
+ d->setColumnMinimumWidth(column, minSize);
+ invalidate();
+}
+
+/*!
+ Returns the column spacing for column \a column.
+
+ \sa setColumnMinimumWidth()
+*/
+int QGridLayout::columnMinimumWidth(int column) const
+{
+ Q_D(const QGridLayout);
+ return d->colSpacing(column);
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QGridLayout::expandingDirections() const
+{
+ Q_D(const QGridLayout);
+ return d->expandingDirections(horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ Sets the grid's origin corner, i.e. position (0, 0), to \a corner.
+*/
+void QGridLayout::setOriginCorner(Qt::Corner corner)
+{
+ Q_D(QGridLayout);
+ d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
+ corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
+}
+
+/*!
+ Returns the corner that's used for the grid's origin, i.e. for
+ position (0, 0).
+*/
+Qt::Corner QGridLayout::originCorner() const
+{
+ Q_D(const QGridLayout);
+ if (d->horReversed()) {
+ return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
+ } else {
+ return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGridLayout::invalidate()
+{
+ Q_D(QGridLayout);
+ d->setDirty();
+ QLayout::invalidate();
+}
+
+/*!
+ \fn void QGridLayout::addRowSpacing(int row, int minsize)
+
+ Use addItem(new QSpacerItem(0, minsize), row, 0) instead.
+*/
+
+/*!
+ \fn void QGridLayout::addColSpacing(int col, int minsize)
+
+ Use addItem(new QSpacerItem(minsize, 0), 0, col) instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCellWidget(QWidget *widget, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addWidget() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addItem() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addLayout() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn int QGridLayout::numRows() const
+
+ Use rowCount() instead.
+*/
+
+/*!
+ \fn int QGridLayout::numCols() const
+
+ Use columnCount() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setColStretch(int col, int stretch)
+
+ Use setColumnStretch() instead.
+*/
+
+/*!
+ \fn int QGridLayout::colStretch(int col) const
+
+ Use columnStretch() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setColSpacing(int col, int minSize)
+
+ Use setColumnMinimumWidth() instead.
+*/
+
+/*!
+ \fn int QGridLayout::colSpacing(int col) const
+
+ Use columnMinimumWidth() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setRowSpacing(int row, int minSize)
+
+ Use setRowMinimumHeight(\a row, \a minSize) instead.
+*/
+
+/*!
+ \fn int QGridLayout::rowSpacing(int row) const
+
+ Use rowMinimumHeight(\a row) instead.
+*/
+
+/*!
+ \fn QRect QGridLayout::cellGeometry(int row, int column) const
+
+ Use cellRect(\a row, \a column) instead.
+*/
+
+/*!
+ \fn void QGridLayout::setOrigin(Qt::Corner corner)
+
+ Use setOriginCorner(\a corner) instead.
+*/
+
+/*!
+ \fn Qt::Corner QGridLayout::origin() const
+
+ Use originCorner() instead.
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qgridlayout.h b/src/widgets/kernel/qgridlayout.h
new file mode 100644
index 0000000000..0ac66e8f87
--- /dev/null
+++ b/src/widgets/kernel/qgridlayout.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRIDLAYOUT_H
+#define QGRIDLAYOUT_H
+
+#include <QtGui/qlayout.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qwidget.h>
+#endif
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGridLayoutPrivate;
+
+class Q_GUI_EXPORT QGridLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGridLayout)
+ QDOC_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ QDOC_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+
+public:
+ explicit QGridLayout(QWidget *parent);
+ QGridLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(QWidget *parent, int nRows , int nCols = 1, int border = 0,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(int nRows , int nCols = 1, int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(QLayout *parentLayout, int nRows = 1, int nCols = 1, int spacing = -1,
+ const char *name = 0);
+#endif
+ ~QGridLayout();
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+ void setSpacing(int spacing);
+ int spacing() const;
+
+ void setRowStretch(int row, int stretch);
+ void setColumnStretch(int column, int stretch);
+ int rowStretch(int row) const;
+ int columnStretch(int column) const;
+
+ void setRowMinimumHeight(int row, int minSize);
+ void setColumnMinimumWidth(int column, int minSize);
+ int rowMinimumHeight(int row) const;
+ int columnMinimumWidth(int column) const;
+
+ int columnCount() const;
+ int rowCount() const;
+
+ QRect cellRect(int row, int column) const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QRect cellGeometry(int row, int column) const {return cellRect(row, column);}
+#endif
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int minimumHeightForWidth(int) const;
+
+ Qt::Orientations expandingDirections() const;
+ void invalidate();
+
+ inline void addWidget(QWidget *w) { QLayout::addWidget(w); }
+ void addWidget(QWidget *, int row, int column, Qt::Alignment = 0);
+ void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
+ void addLayout(QLayout *, int row, int column, Qt::Alignment = 0);
+ void addLayout(QLayout *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
+
+ void setOriginCorner(Qt::Corner);
+ Qt::Corner originCorner() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setOrigin(Qt::Corner corner) { setOriginCorner(corner); }
+ inline QT3_SUPPORT Qt::Corner origin() const { return originCorner(); }
+#endif
+ QLayoutItem *itemAt(int index) const;
+ QLayoutItem *itemAtPosition(int row, int column) const;
+ QLayoutItem *takeAt(int index);
+ int count() const;
+ void setGeometry(const QRect&);
+
+ void addItem(QLayoutItem *item, int row, int column, int rowSpan = 1, int columnSpan = 1, Qt::Alignment = 0);
+
+ void setDefaultPositioning(int n, Qt::Orientation orient);
+ void getItemPosition(int idx, int *row, int *column, int *rowSpan, int *columnSpan);
+
+protected:
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT bool findWidget(QWidget* w, int *r, int *c);
+#endif
+ void addItem(QLayoutItem *);
+
+private:
+ Q_DISABLE_COPY(QGridLayout)
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT void expand(int rows, int cols);
+ inline QT3_SUPPORT void addRowSpacing(int row, int minsize) { addItem(new QSpacerItem(0,minsize), row, 0); }
+ inline QT3_SUPPORT void addColSpacing(int col, int minsize) { addItem(new QSpacerItem(minsize,0), 0, col); }
+ inline QT3_SUPPORT void addMultiCellWidget(QWidget *w, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addWidget(w, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+ inline QT3_SUPPORT void addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addItem(l, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+ inline QT3_SUPPORT void addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addLayout(layout, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+
+ inline QT3_SUPPORT int numRows() const { return rowCount(); }
+ inline QT3_SUPPORT int numCols() const { return columnCount(); }
+ inline QT3_SUPPORT void setColStretch(int col, int stretch) {setColumnStretch(col, stretch); }
+ inline QT3_SUPPORT int colStretch(int col) const {return columnStretch(col); }
+ inline QT3_SUPPORT void setColSpacing(int col, int minSize) { setColumnMinimumWidth(col, minSize); }
+ inline QT3_SUPPORT int colSpacing(int col) const { return columnMinimumWidth(col); }
+ inline QT3_SUPPORT void setRowSpacing(int row, int minSize) {setRowMinimumHeight(row, minSize); }
+ inline QT3_SUPPORT int rowSpacing(int row) const {return rowMinimumHeight(row); }
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRIDLAYOUT_H
diff --git a/src/widgets/kernel/qguieventdispatcher_glib.cpp b/src/widgets/kernel/qguieventdispatcher_glib.cpp
new file mode 100644
index 0000000000..3fa10eb7e9
--- /dev/null
+++ b/src/widgets/kernel/qguieventdispatcher_glib.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguieventdispatcher_glib_p.h"
+
+#include "qapplication.h"
+#include "qx11info_x11.h"
+
+#include "qt_x11_p.h"
+
+#include <glib.h>
+
+QT_BEGIN_NAMESPACE
+
+struct GX11EventSource
+{
+ GSource source;
+ GPollFD pollfd;
+ QEventLoop::ProcessEventsFlags flags;
+ QGuiEventDispatcherGlib *q;
+ QGuiEventDispatcherGlibPrivate *d;
+};
+
+class QGuiEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
+{
+ Q_DECLARE_PUBLIC(QGuiEventDispatcherGlib)
+
+public:
+ QGuiEventDispatcherGlibPrivate();
+ GX11EventSource *x11EventSource;
+ QList<XEvent> queuedUserInputEvents;
+};
+
+static gboolean x11EventSourcePrepare(GSource *s, gint *timeout)
+{
+ if (timeout)
+ *timeout = -1;
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+ return (XEventsQueued(X11->display, QueuedAfterFlush)
+ || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()));
+}
+
+static gboolean x11EventSourceCheck(GSource *s)
+{
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+ return (XEventsQueued(X11->display, QueuedAfterFlush)
+ || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()));
+}
+
+static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data)
+{
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+
+ ulong marker = XNextRequest(X11->display);
+ do {
+ XEvent event;
+ if (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = source->d->queuedUserInputEvents.takeFirst();
+ } else if (XEventsQueued(X11->display, QueuedAlready)) {
+ // process events from the X server
+ XNextEvent(X11->display, &event);
+
+ if (source->flags & QEventLoop::ExcludeUserInputEvents) {
+ // queue user input events
+ switch (event.type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case XKeyPress:
+ case XKeyRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ source->d->queuedUserInputEvents.append(event);
+ continue;
+
+ case ClientMessage:
+ // only keep the wm_take_focus and
+ // _qt_scrolldone protocols, queue all other
+ // client messages
+ if (event.xclient.format == 32) {
+ if (event.xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) {
+ break;
+ } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
+ break;
+ }
+ }
+ source->d->queuedUserInputEvents.append(event);
+ continue;
+
+ default:
+ break;
+ }
+ }
+ } else {
+ // no event to process
+ break;
+ }
+
+ // send through event filter
+ if (source->q->filterEvent(&event))
+ continue;
+
+ if (qApp->x11ProcessEvent(&event) == 1)
+ return true;
+
+ if (event.xany.serial >= marker)
+ goto out;
+ } while (XEventsQueued(X11->display, QueuedAfterFlush));
+
+ out:
+
+ source->d->runTimersOnceWithNormalPriority();
+
+ if (callback)
+ callback(user_data);
+ return true;
+}
+
+static GSourceFuncs x11EventSourceFuncs = {
+ x11EventSourcePrepare,
+ x11EventSourceCheck,
+ x11EventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate()
+{
+ x11EventSource = reinterpret_cast<GX11EventSource *>(g_source_new(&x11EventSourceFuncs,
+ sizeof(GX11EventSource)));
+ g_source_set_can_recurse(&x11EventSource->source, true);
+
+ memset(&x11EventSource->pollfd, 0, sizeof(GPollFD));
+ x11EventSource->flags = QEventLoop::AllEvents;
+ x11EventSource->q = 0;
+ x11EventSource->d = 0;
+
+ g_source_attach(&x11EventSource->source, mainContext);
+}
+
+QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject *parent)
+ : QEventDispatcherGlib(*new QGuiEventDispatcherGlibPrivate, parent)
+{
+}
+
+QGuiEventDispatcherGlib::~QGuiEventDispatcherGlib()
+{
+ Q_D(QGuiEventDispatcherGlib);
+
+ g_source_remove_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
+ g_source_destroy(&d->x11EventSource->source);
+ d->x11EventSource = 0;
+}
+
+bool QGuiEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QGuiEventDispatcherGlib);
+ QEventLoop::ProcessEventsFlags saved_flags = d->x11EventSource->flags;
+ d->x11EventSource->flags = flags;
+ bool returnValue = QEventDispatcherGlib::processEvents(flags);
+ d->x11EventSource->flags = saved_flags;
+ return returnValue;
+}
+
+void QGuiEventDispatcherGlib::startingUp()
+{
+ Q_D(QGuiEventDispatcherGlib);
+ d->x11EventSource->pollfd.fd = XConnectionNumber(X11->display);
+ d->x11EventSource->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ d->x11EventSource->q = this;
+ d->x11EventSource->d = d;
+ g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
+}
+
+void QGuiEventDispatcherGlib::flush()
+{
+ XFlush(X11->display);
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qguieventdispatcher_glib_p.h b/src/widgets/kernel/qguieventdispatcher_glib_p.h
new file mode 100644
index 0000000000..d37db93679
--- /dev/null
+++ b/src/widgets/kernel/qguieventdispatcher_glib_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIEVENTDISPATCHER_GLIB_P_H
+#define QGUIEVENTDISPATCHER_GLIB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qeventdispatcher_glib_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGuiEventDispatcherGlibPrivate;
+
+class QGuiEventDispatcherGlib : public QEventDispatcherGlib
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGuiEventDispatcherGlib)
+
+public:
+ explicit QGuiEventDispatcherGlib(QObject *parent = 0);
+ ~QGuiEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+ void startingUp();
+ void flush();
+};
+
+QT_END_NAMESPACE
+
+#endif // QGUIEVENTDISPATCHER_GLIB_P_H
diff --git a/src/widgets/kernel/qguiplatformplugin.cpp b/src/widgets/kernel/qguiplatformplugin.cpp
new file mode 100644
index 0000000000..011b816e77
--- /dev/null
+++ b/src/widgets/kernel/qguiplatformplugin.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguiplatformplugin_p.h"
+#include <qdebug.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qsettings.h>
+#include "private/qfactoryloader_p.h"
+#include "qstylefactory.h"
+#include "qapplication.h"
+#include "qplatformdefs.h"
+#include "qicon.h"
+
+#ifdef Q_WS_WINCE
+#include "qguifunctions_wince.h"
+extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
+#endif
+
+
+#if defined(Q_WS_X11)
+#include <private/qkde_p.h>
+#include <private/qgtkstyle_p.h>
+#include <private/qt_x11_p.h>
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+
+/*! \internal
+ Return (an construct if necesseray) the Gui Platform plugin.
+
+ The plugin key to be loaded is inside the QT_PLATFORM_PLUGIN environment variable.
+ If it is not set, it will be the DESKTOP_SESSION on X11.
+
+ If no plugin can be loaded, the default one is returned.
+ */
+QGuiPlatformPlugin *qt_guiPlatformPlugin()
+{
+ static QGuiPlatformPlugin *plugin;
+ if (!plugin)
+ {
+#ifndef QT_NO_LIBRARY
+
+ QString key = QString::fromLocal8Bit(qgetenv("QT_PLATFORM_PLUGIN"));
+#ifdef Q_WS_X11
+ if (key.isEmpty()) {
+ switch(X11->desktopEnvironment) {
+ case DE_KDE:
+ key = QString::fromLatin1("kde");
+ break;
+ default:
+ key = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION"));
+ break;
+ }
+ }
+#endif
+
+ if (!key.isEmpty() && QApplication::desktopSettingsAware()) {
+ QFactoryLoader loader(QGuiPlatformPluginInterface_iid, QLatin1String("/gui_platform"));
+ plugin = qobject_cast<QGuiPlatformPlugin *>(loader.instance(key));
+ }
+#endif // QT_NO_LIBRARY
+
+ if(!plugin) {
+ static QGuiPlatformPlugin def;
+ plugin = &def;
+ }
+ }
+ return plugin;
+}
+
+
+/* \class QPlatformPlugin
+ QGuiPlatformPlugin can be used to integrate Qt applications in a platform built on top of Qt.
+ The application developer should not know or use the plugin, it is only used by Qt internaly.
+
+ But full platform that are built on top of Qt may provide a plugin so 3rd party Qt application
+ running in the platform are integrated.
+ */
+
+/*
+ The constructor can be used to install hooks in Qt
+ */
+QGuiPlatformPlugin::QGuiPlatformPlugin(QObject *parent) : QObject(parent) {}
+QGuiPlatformPlugin::~QGuiPlatformPlugin() {}
+
+
+/* return the string key to be used by default the application */
+QString QGuiPlatformPlugin::styleName()
+{
+#if defined(Q_WS_WIN) && defined(Q_WS_WINCE)
+ if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
+ return QLatin1String("WindowsMobile");
+ else
+ return QLatin1String("WindowsCE");
+#elif defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ return QLatin1String("WindowsVista");
+ else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ return QLatin1String("WindowsXP");
+ else
+ return QLatin1String("Windows"); // default styles for Windows
+#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
+ return QLatin1String("CDE"); // default style for X11 on Solaris
+#elif defined(Q_WS_S60)
+ return QLatin1String("S60"); // default style for Symbian with S60
+#elif defined(Q_OS_SYMBIAN)
+ return QLatin1String("Windows"); // default style for Symbian without S60
+#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
+ return QLatin1String("SGI"); // default style for X11 on IRIX
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ return QLatin1String("Plastique"); // default style for X11 and small devices
+#elif defined(Q_WS_MAC)
+ return QLatin1String("Macintosh"); // default style for all Mac's
+#elif defined(Q_WS_X11)
+ QString stylename;
+ switch(X11->desktopEnvironment) {
+ case DE_KDE:
+ stylename = QKde::kdeStyle();
+ break;
+ case DE_GNOME: {
+ QStringList availableStyles = QStyleFactory::keys();
+ // Set QGtkStyle for GNOME if available
+ QString gtkStyleKey = QString::fromLatin1("GTK+");
+ if (availableStyles.contains(gtkStyleKey)) {
+ stylename = gtkStyleKey;
+ break;
+ }
+ if (X11->use_xrender)
+ stylename = QLatin1String("cleanlooks");
+ else
+ stylename = QLatin1String("windows");
+ break;
+ }
+ case DE_CDE:
+ stylename = QLatin1String("cde");
+ break;
+ default:
+ // Don't do anything
+ break;
+ }
+ return stylename;
+#endif
+}
+
+/* return an additional default palette (only work on X11) */
+QPalette QGuiPlatformPlugin::palette()
+{
+#ifdef Q_WS_X11
+ if (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE)
+ return QKde::kdePalette();
+#endif
+
+ return QPalette();
+}
+
+/* the default icon theme name for QIcon::fromTheme. */
+QString QGuiPlatformPlugin::systemIconThemeName()
+{
+ QString result;
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_GNOME) {
+ result = QString::fromLatin1("gnome");
+#ifndef QT_NO_STYLE_GTK
+ result = QGtkStylePrivate::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"), result);
+#endif
+ } else if (X11->desktopEnvironment == DE_KDE) {
+ result = X11->desktopVersion >= 4 ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg");
+ QSettings settings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ settings.beginGroup(QLatin1String("Icons"));
+ result = settings.value(QLatin1String("Theme"), result).toString();
+ }
+#endif
+ return result;
+}
+
+
+QStringList QGuiPlatformPlugin::iconThemeSearchPaths()
+{
+ QStringList paths;
+#if defined(Q_WS_X11)
+ QString xdgDirString = QFile::decodeName(getenv("XDG_DATA_DIRS"));
+ if (xdgDirString.isEmpty())
+ xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
+
+ QStringList xdgDirs = xdgDirString.split(QLatin1Char(':'));
+
+ for (int i = 0 ; i < xdgDirs.size() ; ++i) {
+ QDir dir(xdgDirs[i]);
+ if (dir.exists())
+ paths.append(dir.path() + QLatin1String("/icons"));
+ }
+ if (X11->desktopEnvironment == DE_KDE) {
+ paths << QLatin1Char(':') + QKde::kdeHome() + QLatin1String("/share/icons");
+ QStringList kdeDirs = QFile::decodeName(getenv("KDEDIRS")).split(QLatin1Char(':'));
+ for (int i = 0 ; i< kdeDirs.count() ; ++i) {
+ QDir dir(QLatin1Char(':') + kdeDirs.at(i) + QLatin1String("/share/icons"));
+ if (dir.exists())
+ paths.append(dir.path());
+ }
+ }
+
+ // Add home directory first in search path
+ QDir homeDir(QDir::homePath() + QLatin1String("/.icons"));
+ if (homeDir.exists())
+ paths.prepend(homeDir.path());
+#endif
+
+#if defined(Q_WS_WIN)
+ paths.append(qApp->applicationDirPath() + QLatin1String("/icons"));
+#elif defined(Q_WS_MAC)
+ paths.append(qApp->applicationDirPath() + QLatin1String("/../Resources/icons"));
+#endif
+ return paths;
+}
+
+/* backend for QFileIconProvider, null icon means default */
+QIcon QGuiPlatformPlugin::fileSystemIcon(const QFileInfo &)
+{
+ return QIcon();
+}
+
+/* Like QStyle::styleHint */
+int QGuiPlatformPlugin::platformHint(PlatformHint hint)
+{
+ int ret = 0;
+ switch(hint)
+ {
+ case PH_ToolButtonStyle:
+ ret = Qt::ToolButtonIconOnly;
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_KDE && X11->desktopVersion >= 4
+ && QApplication::desktopSettingsAware()) {
+ ret = QKde::kdeToolButtonStyle();
+ }
+#endif
+ break;
+ case PH_ToolBarIconSize:
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_KDE && X11->desktopVersion >= 4
+ && QApplication::desktopSettingsAware()) {
+ ret = QKde::kdeToolBarIconSize();
+ }
+#endif
+ //by default keep ret = 0 so QCommonStyle will use the style default
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qguiplatformplugin_p.h b/src/widgets/kernel/qguiplatformplugin_p.h
new file mode 100644
index 0000000000..49e2d9294a
--- /dev/null
+++ b/src/widgets/kernel/qguiplatformplugin_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIPLATFORM_P_H
+#define QGUIPLATFORM_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 <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QStyle;
+class QPalette;
+class QIcon;
+class QFileDialog;
+class QColorDialog;
+class QFileInfo;
+
+struct Q_GUI_EXPORT QGuiPlatformPluginInterface : public QFactoryInterface
+{
+};
+
+#define QGuiPlatformPluginInterface_iid "com.nokia.qt.QGuiPlatformPluginInterface"
+
+Q_DECLARE_INTERFACE(QGuiPlatformPluginInterface, QGuiPlatformPluginInterface_iid)
+
+class Q_GUI_EXPORT QGuiPlatformPlugin : public QObject, public QGuiPlatformPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGuiPlatformPluginInterface:QFactoryInterface)
+ public:
+ explicit QGuiPlatformPlugin(QObject *parent = 0);
+ ~QGuiPlatformPlugin();
+
+ virtual QStringList keys() const { return QStringList() << QLatin1String("default"); };
+
+ virtual QString styleName();
+ virtual QPalette palette();
+ virtual QString systemIconThemeName();
+ virtual QStringList iconThemeSearchPaths();
+ virtual QIcon fileSystemIcon(const QFileInfo &);
+
+ enum PlatformHint { PH_ToolButtonStyle, PH_ToolBarIconSize, PH_ItemView_ActivateItemOnSingleClick };
+ virtual int platformHint(PlatformHint hint);
+
+
+ virtual void fileDialogDelete(QFileDialog *) {}
+ virtual bool fileDialogSetVisible(QFileDialog *, bool) { return false; }
+ virtual QDialog::DialogCode fileDialogResultCode(QFileDialog *) { return QDialog::Rejected; }
+ virtual void fileDialogSetDirectory(QFileDialog *, const QString &) {}
+ virtual QString fileDialogDirectory(const QFileDialog *) const { return QString(); }
+ virtual void fileDialogSelectFile(QFileDialog *, const QString &) {}
+ virtual QStringList fileDialogSelectedFiles(const QFileDialog *) const { return QStringList(); }
+ virtual void fileDialogSetFilter(QFileDialog *) {}
+ virtual void fileDialogSetNameFilters(QFileDialog *, const QStringList &) {}
+ virtual void fileDialogSelectNameFilter(QFileDialog *, const QString &) {}
+ virtual QString fileDialogSelectedNameFilter(const QFileDialog *) const { return QString(); }
+
+ virtual void colorDialogDelete(QColorDialog *) {}
+ virtual bool colorDialogSetVisible(QColorDialog *, bool) { return false; }
+ virtual void colorDialogSetCurrentColor(QColorDialog *, const QColor &) {}
+};
+
+//internal
+QGuiPlatformPlugin *qt_guiPlatformPlugin();
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QGUIPLATFORMPLUGIN_H
diff --git a/src/widgets/kernel/qicon.cpp b/src/widgets/kernel/qicon.cpp
new file mode 100644
index 0000000000..59687c709d
--- /dev/null
+++ b/src/widgets/kernel/qicon.cpp
@@ -0,0 +1,1165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qicon.h"
+#include "qicon_p.h"
+#include "qiconengine.h"
+#include "qiconengineplugin.h"
+#include "private/qfactoryloader_p.h"
+#include "private/qiconloader_p.h"
+#include "qstyleoption.h"
+#include "qpainter.h"
+#include "qfileinfo.h"
+#include "qstyle.h"
+#include "qpixmapcache.h"
+#include "qvariant.h"
+#include "qcache.h"
+#include "qdebug.h"
+#include "private/qguiplatformplugin_p.h"
+#include "qguiapplication.h"
+
+#ifdef Q_WS_MAC
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+#ifdef Q_WS_X11
+#include "private/qt_x11_p.h"
+#include "private/qkde_p.h"
+#endif
+
+#include "private/qhexstring_p.h"
+
+#ifndef QT_NO_ICON
+QT_BEGIN_NAMESPACE
+
+/*!
+ \enum QIcon::Mode
+
+ This enum type describes the mode for which a pixmap is intended
+ to be used. The currently defined modes are:
+
+ \value Normal
+ Display the pixmap when the user is
+ not interacting with the icon, but the
+ functionality represented by the icon is available.
+ \value Disabled
+ Display the pixmap when the
+ functionality represented by the icon is not available.
+ \value Active
+ Display the pixmap when the
+ functionality represented by the icon is available and
+ the user is interacting with the icon, for example, moving the
+ mouse over it or clicking it.
+ \value Selected
+ Display the pixmap when the item represented by the icon is
+ selected.
+*/
+
+/*!
+ \enum QIcon::State
+
+ This enum describes the state for which a pixmap is intended to be
+ used. The \e state can be:
+
+ \value Off Display the pixmap when the widget is in an "off" state
+ \value On Display the pixmap when the widget is in an "on" state
+*/
+
+static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
+
+static void qt_cleanup_icon_cache();
+typedef QCache<QString, QIcon> IconCache;
+Q_GLOBAL_STATIC_WITH_INITIALIZER(IconCache, qtIconCache, qAddPostRoutine(qt_cleanup_icon_cache))
+
+static void qt_cleanup_icon_cache()
+{
+ qtIconCache()->clear();
+}
+
+QIconPrivate::QIconPrivate()
+ : engine(0), ref(1),
+ serialNum(serialNumCounter.fetchAndAddRelaxed(1)),
+ detach_no(0),
+ engine_version(2),
+ v1RefCount(0)
+{
+}
+
+QPixmapIconEngine::QPixmapIconEngine()
+{
+}
+
+QPixmapIconEngine::QPixmapIconEngine(const QPixmapIconEngine &other)
+ : QIconEngineV2(other), pixmaps(other.pixmaps)
+{
+}
+
+QPixmapIconEngine::~QPixmapIconEngine()
+{
+}
+
+void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ QSize pixmapSize = rect.size();
+#if defined(Q_WS_MAC)
+ pixmapSize *= qt_mac_get_scalefactor();
+#endif
+ painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
+}
+
+static inline int area(const QSize &s) { return s.width() * s.height(); }
+
+// returns the smallest of the two that is still larger than or equal to size.
+static QPixmapIconEngineEntry *bestSizeMatch( const QSize &size, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
+{
+ int s = area(size);
+ if (pa->size == QSize() && pa->pixmap.isNull()) {
+ pa->pixmap = QPixmap(pa->fileName);
+ pa->size = pa->pixmap.size();
+ }
+ int a = area(pa->size);
+ if (pb->size == QSize() && pb->pixmap.isNull()) {
+ pb->pixmap = QPixmap(pb->fileName);
+ pb->size = pb->pixmap.size();
+ }
+ int b = area(pb->size);
+ int res = a;
+ if (qMin(a,b) >= s)
+ res = qMin(a,b);
+ else
+ res = qMax(a,b);
+ if (res == a)
+ return pa;
+ return pb;
+}
+
+QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ QPixmapIconEngineEntry *pe = 0;
+ for (int i = 0; i < pixmaps.count(); ++i)
+ if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
+ if (pe)
+ pe = bestSizeMatch(size, &pixmaps[i], pe);
+ else
+ pe = &pixmaps[i];
+ }
+ return pe;
+}
+
+
+QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
+{
+ QPixmapIconEngineEntry *pe = tryMatch(size, mode, state);
+ while (!pe){
+ QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On;
+ if (mode == QIcon::Disabled || mode == QIcon::Selected) {
+ QIcon::Mode oppositeMode = (mode == QIcon::Disabled) ? QIcon::Selected : QIcon::Disabled;
+ if ((pe = tryMatch(size, QIcon::Normal, state)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Active, state)))
+ break;
+ if ((pe = tryMatch(size, mode, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Normal, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Active, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, oppositeMode, state)))
+ break;
+ if ((pe = tryMatch(size, oppositeMode, oppositeState)))
+ break;
+ } else {
+ QIcon::Mode oppositeMode = (mode == QIcon::Normal) ? QIcon::Active : QIcon::Normal;
+ if ((pe = tryMatch(size, oppositeMode, state)))
+ break;
+ if ((pe = tryMatch(size, mode, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, oppositeMode, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Disabled, state)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Selected, state)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Disabled, oppositeState)))
+ break;
+ if ((pe = tryMatch(size, QIcon::Selected, oppositeState)))
+ break;
+ }
+
+ if (!pe)
+ return pe;
+ }
+
+ if (sizeOnly ? (pe->size.isNull() || !pe->size.isValid()) : pe->pixmap.isNull()) {
+ pe->pixmap = QPixmap(pe->fileName);
+ if (!pe->pixmap.isNull())
+ pe->size = pe->pixmap.size();
+ }
+
+ return pe;
+}
+
+QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ QPixmap pm;
+ QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, false);
+ if (pe)
+ pm = pe->pixmap;
+
+ if (pm.isNull()) {
+ int idx = pixmaps.count();
+ while (--idx >= 0) {
+ if (pe == &pixmaps[idx]) {
+ pixmaps.remove(idx);
+ break;
+ }
+ }
+ if (pixmaps.isEmpty())
+ return pm;
+ else
+ return pixmap(size, mode, state);
+ }
+
+ QSize actualSize = pm.size();
+ if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
+ actualSize.scale(size, Qt::KeepAspectRatio);
+
+ // #### Qt5 no idea what this really does, but we need to remove the QApp and style references
+// QString key = QLatin1Literal("qt_")
+// % HexString<quint64>(pm.cacheKey())
+// % HexString<uint>(pe->mode)
+// % HexString<quint64>(QApplication::palette().cacheKey())
+// % HexString<uint>(actualSize.width())
+// % HexString<uint>(actualSize.height());
+
+// if (mode == QIcon::Active) {
+// if (QPixmapCache::find(key % HexString<uint>(mode), pm))
+// return pm; // horray
+// if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), pm)) {
+// QStyleOption opt(0);
+// opt.palette = QApplication::palette();
+// QPixmap active = QApplication::style()->generatedIconPixmap(QIcon::Active, pm, &opt);
+// if (pm.cacheKey() == active.cacheKey())
+// return pm;
+// }
+// }
+
+// if (!QPixmapCache::find(key % HexString<uint>(mode), pm)) {
+ if (pm.size() != actualSize)
+ pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+// if (pe->mode != mode && mode != QIcon::Normal) {
+// QStyleOption opt(0);
+// opt.palette = QApplication::palette();
+// QPixmap generated = QApplication::style()->generatedIconPixmap(mode, pm, &opt);
+// if (!generated.isNull())
+// pm = generated;
+// }
+// QPixmapCache::insert(key % HexString<uint>(mode), pm);
+// }
+ return pm;
+}
+
+QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ QSize actualSize;
+ if (QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, true))
+ actualSize = pe->size;
+
+ if (actualSize.isNull())
+ return actualSize;
+
+ if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
+ actualSize.scale(size, Qt::KeepAspectRatio);
+ return actualSize;
+}
+
+void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
+{
+ if (!pixmap.isNull()) {
+ QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), mode, state);
+ if(pe && pe->size == pixmap.size()) {
+ pe->pixmap = pixmap;
+ pe->fileName.clear();
+ } else {
+ pixmaps += QPixmapIconEngineEntry(pixmap, mode, state);
+ }
+ }
+}
+
+void QPixmapIconEngine::addFile(const QString &fileName, const QSize &_size, QIcon::Mode mode, QIcon::State state)
+{
+ if (!fileName.isEmpty()) {
+ QSize size = _size;
+ QPixmap pixmap;
+
+ QString abs = fileName;
+ if (fileName.at(0) != QLatin1Char(':'))
+ abs = QFileInfo(fileName).absoluteFilePath();
+
+ for (int i = 0; i < pixmaps.count(); ++i) {
+ if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
+ QPixmapIconEngineEntry *pe = &pixmaps[i];
+ if(size == QSize()) {
+ pixmap = QPixmap(abs);
+ size = pixmap.size();
+ }
+ if (pe->size == QSize() && pe->pixmap.isNull()) {
+ pe->pixmap = QPixmap(pe->fileName);
+ pe->size = pe->pixmap.size();
+ }
+ if(pe->size == size) {
+ pe->pixmap = pixmap;
+ pe->fileName = abs;
+ return;
+ }
+ }
+ }
+ QPixmapIconEngineEntry e(abs, size, mode, state);
+ e.pixmap = pixmap;
+ pixmaps += e;
+ }
+}
+
+QString QPixmapIconEngine::key() const
+{
+ return QLatin1String("QPixmapIconEngine");
+}
+
+QIconEngineV2 *QPixmapIconEngine::clone() const
+{
+ return new QPixmapIconEngine(*this);
+}
+
+bool QPixmapIconEngine::read(QDataStream &in)
+{
+ int num_entries;
+ QPixmap pm;
+ QString fileName;
+ QSize sz;
+ uint mode;
+ uint state;
+
+ in >> num_entries;
+ for (int i=0; i < num_entries; ++i) {
+ if (in.atEnd()) {
+ pixmaps.clear();
+ return false;
+ }
+ in >> pm;
+ in >> fileName;
+ in >> sz;
+ in >> mode;
+ in >> state;
+ if (pm.isNull()) {
+ addFile(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
+ } else {
+ QPixmapIconEngineEntry pe(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
+ pe.pixmap = pm;
+ pixmaps += pe;
+ }
+ }
+ return true;
+}
+
+bool QPixmapIconEngine::write(QDataStream &out) const
+{
+ int num_entries = pixmaps.size();
+ out << num_entries;
+ for (int i=0; i < num_entries; ++i) {
+ if (pixmaps.at(i).pixmap.isNull())
+ out << QPixmap(pixmaps.at(i).fileName);
+ else
+ out << pixmaps.at(i).pixmap;
+ out << pixmaps.at(i).fileName;
+ out << pixmaps.at(i).size;
+ out << (uint) pixmaps.at(i).mode;
+ out << (uint) pixmaps.at(i).state;
+ }
+ return true;
+}
+
+void QPixmapIconEngine::virtual_hook(int id, void *data)
+{
+ switch (id) {
+ case QIconEngineV2::AvailableSizesHook: {
+ QIconEngineV2::AvailableSizesArgument &arg =
+ *reinterpret_cast<QIconEngineV2::AvailableSizesArgument*>(data);
+ arg.sizes.clear();
+ for (int i = 0; i < pixmaps.size(); ++i) {
+ QPixmapIconEngineEntry &pe = pixmaps[i];
+ if (pe.size == QSize() && pe.pixmap.isNull()) {
+ pe.pixmap = QPixmap(pe.fileName);
+ pe.size = pe.pixmap.size();
+ }
+ if (pe.mode == arg.mode && pe.state == arg.state && !pe.size.isEmpty())
+ arg.sizes.push_back(pe.size);
+ }
+ break;
+ }
+ default:
+ QIconEngineV2::virtual_hook(id, data);
+ }
+}
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QIconEngineFactoryInterface_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loaderV2,
+ (QIconEngineFactoryInterfaceV2_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive))
+#endif
+
+
+
+/*!
+ \class QIcon
+
+ \brief The QIcon class provides scalable icons in different modes
+ and states.
+
+ \ingroup painting
+ \ingroup shared
+
+
+ A QIcon can generate smaller, larger, active, and disabled pixmaps
+ from the set of pixmaps it is given. Such pixmaps are used by Qt
+ widgets to show an icon representing a particular action.
+
+ The simplest use of QIcon is to create one from a QPixmap file or
+ resource, and then use it, allowing Qt to work out all the required
+ icon styles and sizes. For example:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 0
+
+ To undo a QIcon, simply set a null icon in its place:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 1
+
+ Use the QImageReader::supportedImageFormats() and
+ QImageWriter::supportedImageFormats() functions to retrieve a
+ complete list of the supported file formats.
+
+ When you retrieve a pixmap using pixmap(QSize, Mode, State), and no
+ pixmap for this given size, mode and state has been added with
+ addFile() or addPixmap(), then QIcon will generate one on the
+ fly. This pixmap generation happens in a QIconEngineV2. The default
+ engine scales pixmaps down if required, but never up, and it uses
+ the current style to calculate a disabled appearance. By using
+ custom icon engines, you can customize every aspect of generated
+ icons. With QIconEnginePluginV2 it is possible to register different
+ icon engines for different file suffixes, making it possible for
+ third parties to provide additional icon engines to those included
+ with Qt.
+
+ \note Since Qt 4.2, an icon engine that supports SVG is included.
+
+ \section1 Making Classes that Use QIcon
+
+ If you write your own widgets that have an option to set a small
+ pixmap, consider allowing a QIcon to be set for that pixmap. The
+ Qt class QToolButton is an example of such a widget.
+
+ Provide a method to set a QIcon, and when you draw the icon, choose
+ whichever pixmap is appropriate for the current state of your widget.
+ For example:
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 2
+
+ You might also make use of the \c Active mode, perhaps making your
+ widget \c Active when the mouse is over the widget (see \l
+ QWidget::enterEvent()), while the mouse is pressed pending the
+ release that will activate the function, or when it is the currently
+ selected item. If the widget can be toggled, the "On" mode might be
+ used to draw a different icon.
+
+ \img icon.png QIcon
+
+ \sa {fowler}{GUI Design Handbook: Iconic Label}, {Icons Example}
+*/
+
+
+/*!
+ Constructs a null icon.
+*/
+QIcon::QIcon()
+ : d(0)
+{
+}
+
+/*!
+ Constructs an icon from a \a pixmap.
+ */
+QIcon::QIcon(const QPixmap &pixmap)
+ :d(0)
+{
+ addPixmap(pixmap);
+}
+
+/*!
+ Constructs a copy of \a other. This is very fast.
+*/
+QIcon::QIcon(const QIcon &other)
+ :d(other.d)
+{
+ if (d)
+ d->ref.ref();
+}
+
+/*!
+ Constructs an icon from the file with the given \a fileName. The
+ file will be loaded on demand.
+
+ If \a fileName contains a relative path (e.g. the filename only)
+ the relevant file must be found relative to the runtime working
+ directory.
+
+ The file name can be either refer to an actual file on disk or to
+ one of the application's embedded resources. See the
+ \l{resources.html}{Resource System} overview for details on how to
+ embed images and other resource files in the application's
+ executable.
+
+ Use the QImageReader::supportedImageFormats() and
+ QImageWriter::supportedImageFormats() functions to retrieve a
+ complete list of the supported file formats.
+*/
+QIcon::QIcon(const QString &fileName)
+ : d(0)
+{
+ addFile(fileName);
+}
+
+
+/*!
+ Creates an icon with a specific icon \a engine. The icon takes
+ ownership of the engine.
+*/
+QIcon::QIcon(QIconEngine *engine)
+ :d(new QIconPrivate)
+{
+ d->engine_version = 1;
+ d->engine = engine;
+ d->v1RefCount = new QAtomicInt(1);
+}
+
+/*!
+ Creates an icon with a specific icon \a engine. The icon takes
+ ownership of the engine.
+*/
+QIcon::QIcon(QIconEngineV2 *engine)
+ :d(new QIconPrivate)
+{
+ d->engine_version = 2;
+ d->engine = engine;
+}
+
+/*!
+ Destroys the icon.
+*/
+QIcon::~QIcon()
+{
+ if (d && !d->ref.deref())
+ delete d;
+}
+
+/*!
+ Assigns the \a other icon to this icon and returns a reference to
+ this icon.
+*/
+QIcon &QIcon::operator=(const QIcon &other)
+{
+ if (other.d)
+ other.d->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn void QIcon::swap(QIcon &other)
+ \since 4.8
+
+ Swaps icon \a other with this icon. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ Returns the icon as a QVariant.
+*/
+QIcon::operator QVariant() const
+{
+ return QVariant(QVariant::Icon, this);
+}
+
+/*! \obsolete
+
+ Returns a number that identifies the contents of this
+ QIcon object. Distinct QIcon objects can have
+ the same serial number if they refer to the same contents
+ (but they don't have to). Also, the serial number of
+ a QIcon object may change during its lifetime.
+
+ Use cacheKey() instead.
+
+ A null icon always has a serial number of 0.
+
+ Serial numbers are mostly useful in conjunction with caching.
+
+ \sa QPixmap::serialNumber()
+*/
+
+int QIcon::serialNumber() const
+{
+ return d ? d->serialNum : 0;
+}
+
+/*!
+ Returns a number that identifies the contents of this QIcon
+ object. Distinct QIcon objects can have the same key if
+ they refer to the same contents.
+ \since 4.3
+
+ The cacheKey() will change when the icon is altered via
+ addPixmap() or addFile().
+
+ Cache keys are mostly useful in conjunction with caching.
+
+ \sa QPixmap::cacheKey()
+*/
+qint64 QIcon::cacheKey() const
+{
+ if (!d)
+ return 0;
+ return (((qint64) d->serialNum) << 32) | ((qint64) (d->detach_no));
+}
+
+/*!
+ Returns a pixmap with the requested \a size, \a mode, and \a
+ state, generating one if necessary. The pixmap might be smaller than
+ requested, but never larger.
+
+ \sa actualSize(), paint()
+*/
+QPixmap QIcon::pixmap(const QSize &size, Mode mode, State state) const
+{
+ if (!d)
+ return QPixmap();
+ return d->engine->pixmap(size, mode, state);
+}
+
+/*!
+ \fn QPixmap QIcon::pixmap(int w, int h, Mode mode = Normal, State state = Off) const
+
+ \overload
+
+ Returns a pixmap of size QSize(\a w, \a h). The pixmap might be smaller than
+ requested, but never larger.
+*/
+
+/*!
+ \fn QPixmap QIcon::pixmap(int extent, Mode mode = Normal, State state = Off) const
+
+ \overload
+
+ Returns a pixmap of size QSize(\a extent, \a extent). The pixmap might be smaller
+ than requested, but never larger.
+*/
+
+/*! Returns the actual size of the icon for the requested \a size, \a
+ mode, and \a state. The result might be smaller than requested, but
+ never larger.
+
+ \sa pixmap(), paint()
+*/
+QSize QIcon::actualSize(const QSize &size, Mode mode, State state) const
+{
+ if (!d)
+ return QSize();
+ return d->engine->actualSize(size, mode, state);
+}
+
+
+/*!
+ Uses the \a painter to paint the icon with specified \a alignment,
+ required \a mode, and \a state into the rectangle \a rect.
+
+ \sa actualSize(), pixmap()
+*/
+void QIcon::paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, Mode mode, State state) const
+{
+ if (!d || !painter)
+ return;
+ QRect alignedRect = QStyle::alignedRect(painter->layoutDirection(), alignment, d->engine->actualSize(rect.size(), mode, state), rect);
+ d->engine->paint(painter, alignedRect, mode, state);
+}
+
+/*!
+ \fn void QIcon::paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment,
+ Mode mode, State state) const
+
+ \overload
+
+ Paints the icon into the rectangle QRect(\a x, \a y, \a w, \a h).
+*/
+
+/*!
+ Returns true if the icon is empty; otherwise returns false.
+
+ An icon is empty if it has neither a pixmap nor a filename.
+
+ Note: Even a non-null icon might not be able to create valid
+ pixmaps, eg. if the file does not exist or cannot be read.
+*/
+bool QIcon::isNull() const
+{
+ return !d;
+}
+
+/*!\internal
+ */
+bool QIcon::isDetached() const
+{
+ return !d || d->ref == 1;
+}
+
+/*! \internal
+ */
+void QIcon::detach()
+{
+ if (d) {
+ if (d->ref != 1) {
+ QIconPrivate *x = new QIconPrivate;
+ if (d->engine_version > 1) {
+ QIconEngineV2 *engine = static_cast<QIconEngineV2 *>(d->engine);
+ x->engine = engine->clone();
+ } else {
+ x->engine = d->engine;
+ x->v1RefCount = d->v1RefCount;
+ x->v1RefCount->ref();
+ }
+ x->engine_version = d->engine_version;
+ if (!d->ref.deref())
+ delete d;
+ d = x;
+ }
+ ++d->detach_no;
+ }
+}
+
+/*!
+ Adds \a pixmap to the icon, as a specialization for \a mode and
+ \a state.
+
+ Custom icon engines are free to ignore additionally added
+ pixmaps.
+
+ \sa addFile()
+*/
+void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
+{
+ if (pixmap.isNull())
+ return;
+ if (!d) {
+ d = new QIconPrivate;
+ d->engine = new QPixmapIconEngine;
+ } else {
+ detach();
+ }
+ d->engine->addPixmap(pixmap, mode, state);
+}
+
+
+/*! Adds an image from the file with the given \a fileName to the
+ icon, as a specialization for \a size, \a mode and \a state. The
+ file will be loaded on demand. Note: custom icon engines are free
+ to ignore additionally added pixmaps.
+
+ If \a fileName contains a relative path (e.g. the filename only)
+ the relevant file must be found relative to the runtime working
+ directory.
+
+ The file name can be either refer to an actual file on disk or to
+ one of the application's embedded resources. See the
+ \l{resources.html}{Resource System} overview for details on how to
+ embed images and other resource files in the application's
+ executable.
+
+ Use the QImageReader::supportedImageFormats() and
+ QImageWriter::supportedImageFormats() functions to retrieve a
+ complete list of the supported file formats.
+
+ Note: When you add a non-empty filename to a QIcon, the icon becomes
+ non-null, even if the file doesn't exist or points to a corrupt file.
+
+ \sa addPixmap()
+ */
+void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state)
+{
+ if (fileName.isEmpty())
+ return;
+ if (!d) {
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QFileInfo info(fileName);
+ QString suffix = info.suffix();
+ if (!suffix.isEmpty()) {
+ // first try version 2 engines..
+ if (QIconEngineFactoryInterfaceV2 *factory = qobject_cast<QIconEngineFactoryInterfaceV2*>(loaderV2()->instance(suffix))) {
+ if (QIconEngine *engine = factory->create(fileName)) {
+ d = new QIconPrivate;
+ d->engine = engine;
+ }
+ }
+ // ..then fall back and try to load version 1 engines
+ if (!d) {
+ if (QIconEngineFactoryInterface *factory = qobject_cast<QIconEngineFactoryInterface*>(loader()->instance(suffix))) {
+ if (QIconEngine *engine = factory->create(fileName)) {
+ d = new QIconPrivate;
+ d->engine = engine;
+ d->engine_version = 1;
+ d->v1RefCount = new QAtomicInt(1);
+ }
+ }
+ }
+ }
+#endif
+ // ...then fall back to the default engine
+ if (!d) {
+ d = new QIconPrivate;
+ d->engine = new QPixmapIconEngine;
+ }
+ } else {
+ detach();
+ }
+ d->engine->addFile(fileName, size, mode, state);
+}
+
+/*!
+ \since 4.5
+
+ Returns a list of available icon sizes for the specified \a mode and
+ \a state.
+*/
+QList<QSize> QIcon::availableSizes(Mode mode, State state) const
+{
+ if (!d || !d->engine || d->engine_version < 2)
+ return QList<QSize>();
+ QIconEngineV2 *engine = static_cast<QIconEngineV2*>(d->engine);
+ return engine->availableSizes(mode, state);
+}
+
+/*!
+ \since 4.7
+
+ Returns the name used to create the icon, if available.
+
+ Depending on the way the icon was created, it may have an associated
+ name. This is the case for icons created with fromTheme() or icons
+ using a QIconEngine which supports the QIconEngineV2::IconNameHook.
+
+ \sa fromTheme(), QIconEngine
+*/
+QString QIcon::name() const
+{
+ if (!d || !d->engine || d->engine_version < 2)
+ return QString();
+ QIconEngineV2 *engine = static_cast<QIconEngineV2*>(d->engine);
+ return engine->iconName();
+}
+
+/*!
+ \since 4.6
+
+ Sets the search paths for icon themes to \a paths.
+ \sa themeSearchPaths(), fromTheme(), setThemeName()
+*/
+void QIcon::setThemeSearchPaths(const QStringList &paths)
+{
+ QIconLoader::instance()->setThemeSearchPath(paths);
+}
+
+/*!
+ \since 4.6
+
+ Returns the search paths for icon themes.
+
+ The default value will depend on the platform:
+
+ On X11, the search path will use the XDG_DATA_DIRS environment
+ variable if available.
+
+ By default all platforms will have the resource directory
+ \c{:\icons} as a fallback. You can use "rcc -project" to generate a
+ resource file from your icon theme.
+
+ \sa setThemeSearchPaths(), fromTheme(), setThemeName()
+*/
+QStringList QIcon::themeSearchPaths()
+{
+ return QIconLoader::instance()->themeSearchPaths();
+}
+
+/*!
+ \since 4.6
+
+ Sets the current icon theme to \a name.
+
+ The \a name should correspond to a directory name in the
+ themeSearchPath() containing an index.theme
+ file describing it's contents.
+
+ \sa themeSearchPaths(), themeName()
+*/
+void QIcon::setThemeName(const QString &name)
+{
+ QIconLoader::instance()->setThemeName(name);
+}
+
+/*!
+ \since 4.6
+
+ Returns the name of the current icon theme.
+
+ On X11, the current icon theme depends on your desktop
+ settings. On other platforms it is not set by default.
+
+ \sa setThemeName(), themeSearchPaths(), fromTheme(),
+ hasThemeIcon()
+*/
+QString QIcon::themeName()
+{
+ return QIconLoader::instance()->themeName();
+}
+
+/*!
+ \since 4.6
+
+ Returns the QIcon corresponding to \a name in the current
+ icon theme. If no such icon is found in the current theme
+ \a fallback is returned instead.
+
+ The latest version of the freedesktop icon specification and naming
+ specification can be obtained here:
+
+ \list
+ \o \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html}
+ \o \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html}
+ \endlist
+
+ To fetch an icon from the current icon theme:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 3
+
+ Or if you want to provide a guaranteed fallback for platforms that
+ do not support theme icons, you can use the second argument:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 4
+
+ \note By default, only X11 will support themed icons. In order to
+ use themed icons on Mac and Windows, you will have to bundle a
+ compliant theme in one of your themeSearchPaths() and set the
+ appropriate themeName().
+
+ \sa themeName(), setThemeName(), themeSearchPaths()
+*/
+QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
+{
+ QIcon icon;
+
+ if (qtIconCache()->contains(name)) {
+ icon = *qtIconCache()->object(name);
+ } else {
+ QIcon *cachedIcon = new QIcon(new QIconLoaderEngine(name));
+ qtIconCache()->insert(name, cachedIcon);
+ icon = *cachedIcon;
+ }
+
+ // Note the qapp check is to allow lazy loading of static icons
+ // Supporting fallbacks will not work for this case.
+ if (qApp && icon.availableSizes().isEmpty())
+ return fallback;
+
+ return icon;
+}
+
+/*!
+ \since 4.6
+
+ Returns true if there is an icon available for \a name in the
+ current icon theme, otherwise returns false.
+
+ \sa themeSearchPaths(), fromTheme(), setThemeName()
+*/
+bool QIcon::hasThemeIcon(const QString &name)
+{
+ QIcon icon = fromTheme(name);
+
+ return !icon.isNull();
+}
+
+
+/*****************************************************************************
+ QIcon stream functions
+ *****************************************************************************/
+#if !defined(QT_NO_DATASTREAM)
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QIcon &icon)
+ \relates QIcon
+ \since 4.2
+
+ Writes the given \a icon to the given \a stream as a PNG
+ image. If the icon contains more than one image, all images will
+ be written to the stream. Note that writing the stream to a file
+ will not produce a valid image file.
+*/
+
+QDataStream &operator<<(QDataStream &s, const QIcon &icon)
+{
+ if (s.version() >= QDataStream::Qt_4_3) {
+ if (icon.isNull()) {
+ s << QString();
+ } else {
+ if (icon.d->engine_version > 1) {
+ QIconEngineV2 *engine = static_cast<QIconEngineV2 *>(icon.d->engine);
+ s << engine->key();
+ engine->write(s);
+ } else {
+ // not really supported
+ qWarning("QIcon: Cannot stream QIconEngine. Use QIconEngineV2 instead.");
+ }
+ }
+ } else if (s.version() == QDataStream::Qt_4_2) {
+ if (icon.isNull()) {
+ s << 0;
+ } else {
+ QPixmapIconEngine *engine = static_cast<QPixmapIconEngine *>(icon.d->engine);
+ int num_entries = engine->pixmaps.size();
+ s << num_entries;
+ for (int i=0; i < num_entries; ++i) {
+ s << engine->pixmaps.at(i).pixmap;
+ s << engine->pixmaps.at(i).fileName;
+ s << engine->pixmaps.at(i).size;
+ s << (uint) engine->pixmaps.at(i).mode;
+ s << (uint) engine->pixmaps.at(i).state;
+ }
+ }
+ } else {
+ s << QPixmap(icon.pixmap(22,22));
+ }
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QIcon &icon)
+ \relates QIcon
+ \since 4.2
+
+ Reads an image, or a set of images, from the given \a stream into
+ the given \a icon.
+*/
+
+QDataStream &operator>>(QDataStream &s, QIcon &icon)
+{
+ if (s.version() >= QDataStream::Qt_4_3) {
+ icon = QIcon();
+ QString key;
+ s >> key;
+ if (key == QLatin1String("QPixmapIconEngine")) {
+ icon.d = new QIconPrivate;
+ QIconEngineV2 *engine = new QPixmapIconEngine;
+ icon.d->engine = engine;
+ engine->read(s);
+ } else if (key == QLatin1String("QIconLoaderEngine")) {
+ icon.d = new QIconPrivate;
+ QIconEngineV2 *engine = new QIconLoaderEngine();
+ icon.d->engine = engine;
+ engine->read(s);
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ } else if (QIconEngineFactoryInterfaceV2 *factory = qobject_cast<QIconEngineFactoryInterfaceV2*>(loaderV2()->instance(key))) {
+ if (QIconEngineV2 *engine= factory->create()) {
+ icon.d = new QIconPrivate;
+ icon.d->engine = engine;
+ engine->read(s);
+ }
+#endif
+ }
+ } else if (s.version() == QDataStream::Qt_4_2) {
+ icon = QIcon();
+ int num_entries;
+ QPixmap pm;
+ QString fileName;
+ QSize sz;
+ uint mode;
+ uint state;
+
+ s >> num_entries;
+ for (int i=0; i < num_entries; ++i) {
+ s >> pm;
+ s >> fileName;
+ s >> sz;
+ s >> mode;
+ s >> state;
+ if (pm.isNull())
+ icon.addFile(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
+ else
+ icon.addPixmap(pm, QIcon::Mode(mode), QIcon::State(state));
+ }
+ } else {
+ QPixmap pm;
+ s >> pm;
+ icon.addPixmap(pm);
+ }
+ return s;
+}
+
+#endif //QT_NO_DATASTREAM
+
+/*!
+ \fn DataPtr &QIcon::data_ptr()
+ \internal
+*/
+
+/*!
+ \typedef QIcon::DataPtr
+ \internal
+*/
+
+QT_END_NAMESPACE
+#endif //QT_NO_ICON
diff --git a/src/widgets/kernel/qicon.h b/src/widgets/kernel/qicon.h
new file mode 100644
index 0000000000..4e3960925e
--- /dev/null
+++ b/src/widgets/kernel/qicon.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICON_H
+#define QICON_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qpixmap.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QIconPrivate;
+class QIconEngine;
+class QIconEngineV2;
+
+class Q_GUI_EXPORT QIcon
+{
+public:
+ enum Mode { Normal, Disabled, Active, Selected };
+ enum State { On, Off };
+
+ QIcon();
+ QIcon(const QPixmap &pixmap);
+ QIcon(const QIcon &other);
+ explicit QIcon(const QString &fileName); // file or resource name
+ explicit QIcon(QIconEngine *engine);
+ explicit QIcon(QIconEngineV2 *engine);
+ ~QIcon();
+ QIcon &operator=(const QIcon &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QIcon &operator=(QIcon &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QIcon &other) { qSwap(d, other.d); }
+
+ operator QVariant() const;
+
+ QPixmap pixmap(const QSize &size, Mode mode = Normal, State state = Off) const;
+ inline QPixmap pixmap(int w, int h, Mode mode = Normal, State state = Off) const
+ { return pixmap(QSize(w, h), mode, state); }
+ inline QPixmap pixmap(int extent, Mode mode = Normal, State state = Off) const
+ { return pixmap(QSize(extent, extent), mode, state); }
+
+ QSize actualSize(const QSize &size, Mode mode = Normal, State state = Off) const;
+
+ QString name() const;
+
+ void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const;
+ inline void paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const
+ { paint(painter, QRect(x, y, w, h), alignment, mode, state); }
+
+ bool isNull() const;
+ bool isDetached() const;
+ void detach();
+
+ int serialNumber() const;
+ qint64 cacheKey() const;
+
+ void addPixmap(const QPixmap &pixmap, Mode mode = Normal, State state = Off);
+ void addFile(const QString &fileName, const QSize &size = QSize(), Mode mode = Normal, State state = Off);
+
+ QList<QSize> availableSizes(Mode mode = Normal, State state = Off) const;
+
+ static QIcon fromTheme(const QString &name, const QIcon &fallback = QIcon());
+ static bool hasThemeIcon(const QString &name);
+
+ static QStringList themeSearchPaths();
+ static void setThemeSearchPaths(const QStringList &searchpath);
+
+ static QString themeName();
+ static void setThemeName(const QString &path);
+
+ Q_DUMMY_COMPARISON_OPERATOR(QIcon)
+
+private:
+ QIconPrivate *d;
+#if !defined(QT_NO_DATASTREAM)
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QIcon &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QIcon &);
+#endif
+
+public:
+ typedef QIconPrivate * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+Q_DECLARE_SHARED(QIcon)
+Q_DECLARE_TYPEINFO(QIcon, Q_MOVABLE_TYPE);
+
+#if !defined(QT_NO_DATASTREAM)
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QIcon &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QIcon &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QICON_H
diff --git a/src/widgets/kernel/qicon_p.h b/src/widgets/kernel/qicon_p.h
new file mode 100644
index 0000000000..0bf7e65cc1
--- /dev/null
+++ b/src/widgets/kernel/qicon_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICON_P_H
+#define QICON_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 <QtCore/qglobal.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qiconengine.h>
+
+#ifndef QT_NO_ICON
+QT_BEGIN_NAMESPACE
+
+class QIconPrivate
+{
+public:
+ QIconPrivate();
+
+ ~QIconPrivate() {
+ if (engine_version == 1) {
+ if (!v1RefCount->deref()) {
+ delete engine;
+ delete v1RefCount;
+ }
+ } else if (engine_version == 2) {
+ delete engine;
+ }
+ }
+
+ QIconEngine *engine;
+
+ QAtomicInt ref;
+ int serialNum;
+ int detach_no;
+ int engine_version;
+
+ QAtomicInt *v1RefCount;
+};
+
+
+struct QPixmapIconEngineEntry
+{
+ QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){}
+ QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
+ :pixmap(pm), size(pm.size()), mode(m), state(s){}
+ QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
+ :fileName(file), size(sz), mode(m), state(s){}
+ QPixmap pixmap;
+ QString fileName;
+ QSize size;
+ QIcon::Mode mode;
+ QIcon::State state;
+ bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
+};
+
+
+
+class QPixmapIconEngine : public QIconEngineV2 {
+public:
+ QPixmapIconEngine();
+ QPixmapIconEngine(const QPixmapIconEngine &);
+ ~QPixmapIconEngine();
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly);
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
+ void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state);
+
+ // v2 functions
+ QString key() const;
+ QIconEngineV2 *clone() const;
+ bool read(QDataStream &in);
+ bool write(QDataStream &out) const;
+ void virtual_hook(int id, void *data);
+
+private:
+ QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QVector<QPixmapIconEngineEntry> pixmaps;
+
+ friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);
+ friend class QIconThemeEngine;
+};
+
+QT_END_NAMESPACE
+#endif //QT_NO_ICON
+#endif // QICON_P_H
diff --git a/src/widgets/kernel/qiconengine.cpp b/src/widgets/kernel/qiconengine.cpp
new file mode 100644
index 0000000000..6168a83940
--- /dev/null
+++ b/src/widgets/kernel/qiconengine.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiconengine.h"
+#include "qpainter.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QIconEngine
+
+ \brief The QIconEngine class provides an abstract base class for QIcon renderers.
+
+ \ingroup painting
+
+ \bold {Use QIconEngineV2 instead.}
+
+ An icon engine provides the rendering functions for a QIcon. Each icon has a
+ corresponding icon engine that is responsible for drawing the icon with a
+ requested size, mode and state.
+
+ The icon is rendered by the paint() function, and the icon can additionally be
+ obtained as a pixmap with the pixmap() function (the default implementation
+ simply uses paint() to achieve this). The addPixmap() function can be used to
+ add new pixmaps to the icon engine, and is used by QIcon to add specialized
+ custom pixmaps.
+
+ The paint(), pixmap(), and addPixmap() functions are all virtual, and can
+ therefore be reimplemented in subclasses of QIconEngine.
+
+ \sa QIconEngineV2, QIconEnginePlugin
+
+*/
+
+/*!
+ \fn virtual void QIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
+
+ Uses the given \a painter to paint the icon with the required \a mode and
+ \a state into the rectangle \a rect.
+*/
+
+/*! Returns the actual size of the icon the engine provides for the
+ requested \a size, \a mode and \a state. The default implementation
+ returns the given \a size.
+ */
+QSize QIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::State /*state*/)
+{
+ return size;
+}
+
+
+/*!
+ Destroys the icon engine.
+ */
+QIconEngine::~QIconEngine()
+{
+}
+
+
+/*!
+ Returns the icon as a pixmap with the required \a size, \a mode,
+ and \a state. The default implementation creates a new pixmap and
+ calls paint() to fill it.
+*/
+QPixmap QIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ QPixmap pm(size);
+ {
+ QPainter p(&pm);
+ paint(&p, QRect(QPoint(0,0),size), mode, state);
+ }
+ return pm;
+}
+
+/*!
+ Called by QIcon::addPixmap(). Adds a specialized \a pixmap for the given
+ \a mode and \a state. The default pixmap-based engine stores any supplied
+ pixmaps, and it uses them instead of scaled pixmaps if the size of a pixmap
+ matches the size of icon requested. Custom icon engines that implement
+ scalable vector formats are free to ignores any extra pixmaps.
+ */
+void QIconEngine::addPixmap(const QPixmap &/*pixmap*/, QIcon::Mode /*mode*/, QIcon::State /*state*/)
+{
+}
+
+
+/*! Called by QIcon::addFile(). Adds a specialized pixmap from the
+ file with the given \a fileName, \a size, \a mode and \a state. The
+ default pixmap-based engine stores any supplied file names, and it
+ loads the pixmaps on demand instead of using scaled pixmaps if the
+ size of a pixmap matches the size of icon requested. Custom icon
+ engines that implement scalable vector formats are free to ignores
+ any extra files.
+ */
+void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QIcon::Mode /*mode*/, QIcon::State /*state*/)
+{
+}
+
+
+
+// version 2 functions
+
+
+/*!
+ \class QIconEngineV2
+
+ \brief The QIconEngineV2 class provides an abstract base class for QIcon renderers.
+
+ \ingroup painting
+ \since 4.3
+
+ An icon engine renders \l{QIcon}s. With icon engines, you can
+ customize icons. Qt provides a default engine that makes icons
+ adhere to the current style by scaling the icons and providing a
+ disabled appearance.
+
+ An engine is installed on an icon either through a QIcon
+ constructor or through a QIconEnginePluginV2. The plugins are used
+ by Qt if a specific engine is not given when the icon is created.
+ See the QIconEngineV2 class description to learn how to create
+ icon engine plugins.
+
+ An icon engine provides the rendering functions for a QIcon. Each
+ icon has a corresponding icon engine that is responsible for drawing
+ the icon with a requested size, mode and state.
+
+ QIconEngineV2 extends the API of QIconEngine to allow streaming of
+ the icon engine contents, and should be used instead of QIconEngine
+ for implementing new icon engines.
+
+ \sa QIconEnginePluginV2
+
+*/
+
+/*!
+ \enum QIconEngineV2::IconEngineHook
+ \since 4.5
+
+ These enum values are used for virtual_hook() to allow additional
+ queries to icon engine without breaking binary compatibility.
+
+ \value AvailableSizesHook Allows to query the sizes of the
+ contained pixmaps for pixmap-based engines. The \a data argument
+ of the virtual_hook() function is a AvailableSizesArgument pointer
+ that should be filled with icon sizes. Engines that work in terms
+ of a scalable, vectorial format normally return an empty list.
+
+ \value IconNameHook Allows to query the name used to create the
+ icon, for example when instantiating an icon using
+ QIcon::fromTheme().
+
+ \sa virtual_hook()
+ */
+
+/*!
+ \class QIconEngineV2::AvailableSizesArgument
+ \since 4.5
+
+ This struct represents arguments to virtual_hook() function when
+ \a id parameter is QIconEngineV2::AvailableSizesHook.
+
+ \sa virtual_hook(), QIconEngineV2::IconEngineHook
+ */
+
+/*!
+ \variable QIconEngineV2::AvailableSizesArgument::mode
+ \brief the requested mode of an image.
+
+ \sa QIcon::Mode
+*/
+
+/*!
+ \variable QIconEngineV2::AvailableSizesArgument::state
+ \brief the requested state of an image.
+
+ \sa QIcon::State
+*/
+
+/*!
+ \variable QIconEngineV2::AvailableSizesArgument::sizes
+
+ \brief image sizes that are available with specified \a mode and
+ \a state. This is an output parameter and is filled after call to
+ virtual_hook(). Engines that work in terms of a scalable,
+ vectorial format normally return an empty list.
+*/
+
+
+/*!
+ Returns a key that identifies this icon engine.
+ */
+QString QIconEngineV2::key() const
+{
+ return QString();
+}
+
+/*!
+ Returns a clone of this icon engine.
+ */
+QIconEngineV2 *QIconEngineV2::clone() const
+{
+ return 0;
+}
+
+/*!
+ Reads icon engine contents from the QDataStream \a in. Returns
+ true if the contents were read; otherwise returns false.
+
+ QIconEngineV2's default implementation always return false.
+ */
+bool QIconEngineV2::read(QDataStream &)
+{
+ return false;
+}
+
+/*!
+ Writes the contents of this engine to the QDataStream \a out.
+ Returns true if the contents were written; otherwise returns false.
+
+ QIconEngineV2's default implementation always return false.
+ */
+bool QIconEngineV2::write(QDataStream &) const
+{
+ return false;
+}
+
+/*!
+ \since 4.5
+
+ Additional method to allow extending QIconEngineV2 without
+ adding new virtual methods (and without breaking binary compatibility).
+ The actual action and format of \a data depends on \a id argument
+ which is in fact a constant from IconEngineHook enum.
+
+ \sa IconEngineHook
+*/
+void QIconEngineV2::virtual_hook(int id, void *data)
+{
+ switch (id) {
+ case QIconEngineV2::AvailableSizesHook: {
+ QIconEngineV2::AvailableSizesArgument &arg =
+ *reinterpret_cast<QIconEngineV2::AvailableSizesArgument*>(data);
+ arg.sizes.clear();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/*!
+ \since 4.5
+
+ Returns sizes of all images that are contained in the engine for the
+ specific \a mode and \a state.
+
+ \note This is a helper method and the actual work is done by
+ virtual_hook() method, hence this method depends on icon engine support
+ and may not work with all icon engines.
+ */
+QList<QSize> QIconEngineV2::availableSizes(QIcon::Mode mode, QIcon::State state)
+{
+ AvailableSizesArgument arg;
+ arg.mode = mode;
+ arg.state = state;
+ virtual_hook(QIconEngineV2::AvailableSizesHook, reinterpret_cast<void*>(&arg));
+ return arg.sizes;
+}
+
+/*!
+ \since 4.7
+
+ Returns the name used to create the engine, if available.
+
+ \note This is a helper method and the actual work is done by
+ virtual_hook() method, hence this method depends on icon engine support
+ and may not work with all icon engines.
+ */
+QString QIconEngineV2::iconName()
+{
+ QString name;
+ virtual_hook(QIconEngineV2::IconNameHook, reinterpret_cast<void*>(&name));
+ return name;
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qiconengine.h b/src/widgets/kernel/qiconengine.h
new file mode 100644
index 0000000000..12caea8a20
--- /dev/null
+++ b/src/widgets/kernel/qiconengine.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICONENGINE_H
+#define QICONENGINE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qicon.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QIconEngine
+{
+public:
+ virtual ~QIconEngine();
+ virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
+ virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+
+ virtual void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
+ virtual void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state);
+
+#if 0
+ virtual int frameCount(QIcon::Mode fromMode, QIcon::State fromState, QIcon::Mode toMode, QIcon::State toState);
+ virtual void paintFrame(QPainter *painter, const QRect &rect, int frameNumber, QIcon::Mode fromMode, QIcon::State fromState, QIcon::Mode toMode, QIcon::State toState);
+#endif
+};
+
+// ### Qt 5: move the below into QIconEngine
+class Q_GUI_EXPORT QIconEngineV2 : public QIconEngine
+{
+public:
+ virtual QString key() const;
+ virtual QIconEngineV2 *clone() const;
+ virtual bool read(QDataStream &in);
+ virtual bool write(QDataStream &out) const;
+ virtual void virtual_hook(int id, void *data);
+
+public:
+ enum IconEngineHook { AvailableSizesHook = 1, IconNameHook };
+
+ struct AvailableSizesArgument
+ {
+ QIcon::Mode mode;
+ QIcon::State state;
+ QList<QSize> sizes;
+ };
+
+ // ### Qt 5: make this function const and virtual.
+ QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal,
+ QIcon::State state = QIcon::Off);
+
+ // ### Qt 5: make this function const and virtual.
+ QString iconName();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QICONENGINE_H
diff --git a/src/widgets/kernel/qiconengineplugin.cpp b/src/widgets/kernel/qiconengineplugin.cpp
new file mode 100644
index 0000000000..7c8c3a3c1a
--- /dev/null
+++ b/src/widgets/kernel/qiconengineplugin.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiconengineplugin.h"
+#include "qiconengine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QIconEnginePlugin
+ \brief The QIconEnginePlugin class provides an abstract base for custom QIconEngine plugins.
+
+ \ingroup plugins
+
+ \bold {Use QIconEnginePluginV2 instead.}
+
+ The icon engine plugin is a simple plugin interface that makes it easy to
+ create custom icon engines that can be loaded dynamically into applications
+ through QIcon. QIcon uses the file or resource name's suffix to determine
+ what icon engine to use.
+
+ Writing a icon engine plugin is achieved by subclassing this base class,
+ reimplementing the pure virtual functions keys() and create(), and
+ exporting the class with the Q_EXPORT_PLUGIN2() macro.
+
+ \sa {How to Create Qt Plugins}
+*/
+
+/*!
+ \fn QStringList QIconEnginePlugin::keys() const
+
+ Returns a list of icon engine keys that this plugin supports. The keys correspond
+ to the suffix of the file or resource name used when the plugin was created.
+ Keys are case insensitive.
+
+ \sa create()
+*/
+
+/*!
+ \fn QIconEngine* QIconEnginePlugin::create(const QString& filename)
+
+ Creates and returns a QIconEngine object for the icon with the given
+ \a filename.
+
+ \sa keys()
+*/
+
+/*!
+ Constructs a icon engine plugin with the given \a parent. This is invoked
+ automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QIconEnginePlugin::QIconEnginePlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the icon engine plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QIconEnginePlugin::~QIconEnginePlugin()
+{
+}
+
+// version 2
+
+/*!
+ \class QIconEnginePluginV2
+ \brief The QIconEnginePluginV2 class provides an abstract base for custom QIconEngineV2 plugins.
+
+ \ingroup plugins
+ \since 4.3
+
+ Icon engine plugins produces \l{QIconEngine}s for \l{QIcon}s; an
+ icon engine is used to render the icon. The keys that identifies
+ the engines the plugin can create are suffixes of
+ icon filenames; they are returned by keys(). The create() function
+ receives the icon filename to return an engine for; it should
+ return 0 if it cannot produce an engine for the file.
+
+ Writing an icon engine plugin is achieved by inheriting
+ QIconEnginePluginV2, reimplementing keys() and create(), and
+ adding the Q_EXPORT_PLUGIN2() macro.
+
+ You should ensure that you do not duplicate keys. Qt will query
+ the plugins for icon engines in the order in which the plugins are
+ found during plugin search (see the plugins \l{How to Create Qt
+ Plugins}{overview document}).
+
+ \sa {How to Create Qt Plugins}
+*/
+
+/*!
+ \fn QStringList QIconEnginePluginV2::keys() const
+
+ Returns a list of icon engine keys that this plugin supports. The keys correspond
+ to the suffix of the file or resource name used when the plugin was created.
+ Keys are case insensitive.
+
+ \sa create()
+*/
+
+/*!
+ \fn QIconEngineV2* QIconEnginePluginV2::create(const QString& filename = QString())
+
+ Creates and returns a QIconEngine object for the icon with the given
+ \a filename.
+
+ \sa keys()
+*/
+
+/*!
+ Constructs a icon engine plugin with the given \a parent. This is invoked
+ automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QIconEnginePluginV2::QIconEnginePluginV2(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the icon engine plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QIconEnginePluginV2::~QIconEnginePluginV2()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qiconengineplugin.h b/src/widgets/kernel/qiconengineplugin.h
new file mode 100644
index 0000000000..e892a38f7b
--- /dev/null
+++ b/src/widgets/kernel/qiconengineplugin.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICONENGINEPLUGIN_H
+#define QICONENGINEPLUGIN_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QIconEngine;
+class QIconEngineV2;
+
+struct Q_GUI_EXPORT QIconEngineFactoryInterface : public QFactoryInterface
+{
+ virtual QIconEngine *create(const QString &filename) = 0;
+};
+
+#define QIconEngineFactoryInterface_iid \
+ "com.trolltech.Qt.QIconEngineFactoryInterface"
+Q_DECLARE_INTERFACE(QIconEngineFactoryInterface, QIconEngineFactoryInterface_iid)
+
+class Q_GUI_EXPORT QIconEnginePlugin : public QObject, public QIconEngineFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QIconEngineFactoryInterface:QFactoryInterface)
+public:
+ QIconEnginePlugin(QObject *parent = 0);
+ ~QIconEnginePlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QIconEngine *create(const QString &filename) = 0;
+};
+
+// ### Qt 5: remove version 2
+struct Q_GUI_EXPORT QIconEngineFactoryInterfaceV2 : public QFactoryInterface
+{
+ virtual QIconEngineV2 *create(const QString &filename = QString()) = 0;
+};
+
+#define QIconEngineFactoryInterfaceV2_iid \
+ "com.trolltech.Qt.QIconEngineFactoryInterfaceV2"
+Q_DECLARE_INTERFACE(QIconEngineFactoryInterfaceV2, QIconEngineFactoryInterfaceV2_iid)
+
+class Q_GUI_EXPORT QIconEnginePluginV2 : public QObject, public QIconEngineFactoryInterfaceV2
+{
+ Q_OBJECT
+ Q_INTERFACES(QIconEngineFactoryInterfaceV2:QFactoryInterface)
+public:
+ QIconEnginePluginV2(QObject *parent = 0);
+ ~QIconEnginePluginV2();
+
+ virtual QStringList keys() const = 0;
+ virtual QIconEngineV2 *create(const QString &filename = QString()) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QICONENGINEPLUGIN_H
diff --git a/src/widgets/kernel/qiconloader.cpp b/src/widgets/kernel/qiconloader.cpp
new file mode 100644
index 0000000000..19be636e9c
--- /dev/null
+++ b/src/widgets/kernel/qiconloader.cpp
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT_NO_ICON
+#include <private/qiconloader_p.h>
+
+#include <private/qguiapplication_p.h>
+#include <private/qicon_p.h>
+#include <private/qguiplatformplugin_p.h>
+
+#include <QtGui/QIconEnginePlugin>
+#include <QtGui/QPixmapCache>
+#include <QtGui/QIconEngine>
+#include <QtGui/QStyleOption>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QDir>
+#include <QtCore/QSettings>
+#include <QtGui/QPainter>
+
+#ifdef Q_WS_MAC
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+#include <private/qhexstring_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
+
+/* Theme to use in last resort, if the theme does not have the icon, neither the parents */
+static QString fallbackTheme()
+{
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_GNOME) {
+ return QLatin1String("gnome");
+ } else if (X11->desktopEnvironment == DE_KDE) {
+ return X11->desktopVersion >= 4
+ ? QString::fromLatin1("oxygen")
+ : QString::fromLatin1("crystalsvg");
+ } else {
+ return QLatin1String("hicolor");
+ }
+#endif
+ return QString();
+}
+
+QIconLoader::QIconLoader() :
+ m_themeKey(1), m_supportsSvg(false), m_initialized(false)
+{
+}
+
+// We lazily initialize the loader to make static icons
+// work. Though we do not officially support this.
+void QIconLoader::ensureInitialized()
+{
+ if (!m_initialized) {
+ m_initialized = true;
+
+ Q_ASSERT(qApp);
+
+ m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName();
+ if (m_systemTheme.isEmpty())
+ m_systemTheme = fallbackTheme();
+#ifndef QT_NO_LIBRARY
+ QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid,
+ QLatin1String("/iconengines"),
+ Qt::CaseInsensitive);
+ if (iconFactoryLoader.keys().contains(QLatin1String("svg")))
+ m_supportsSvg = true;
+#endif //QT_NO_LIBRARY
+ }
+}
+
+QIconLoader *QIconLoader::instance()
+{
+ return iconLoaderInstance();
+}
+
+// Queries the system theme and invalidates existing
+// icons if the theme has changed.
+void QIconLoader::updateSystemTheme()
+{
+ // Only change if this is not explicitly set by the user
+ if (m_userTheme.isEmpty()) {
+ QString theme = qt_guiPlatformPlugin()->systemIconThemeName();
+ if (theme.isEmpty())
+ theme = fallbackTheme();
+ if (theme != m_systemTheme) {
+ m_systemTheme = theme;
+ invalidateKey();
+ }
+ }
+}
+
+void QIconLoader::setThemeName(const QString &themeName)
+{
+ m_userTheme = themeName;
+ invalidateKey();
+}
+
+void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
+{
+ m_iconDirs = searchPaths;
+ themeList.clear();
+ invalidateKey();
+}
+
+QStringList QIconLoader::themeSearchPaths() const
+{
+ if (m_iconDirs.isEmpty()) {
+ m_iconDirs = qt_guiPlatformPlugin()->iconThemeSearchPaths();
+ // Always add resource directory as search path
+ m_iconDirs.append(QLatin1String(":/icons"));
+ }
+ return m_iconDirs;
+}
+
+QIconTheme::QIconTheme(const QString &themeName)
+ : m_valid(false)
+{
+ QFile themeIndex;
+
+ QList <QIconDirInfo> keyList;
+ QStringList iconDirs = QIcon::themeSearchPaths();
+ for ( int i = 0 ; i < iconDirs.size() ; ++i) {
+ QDir iconDir(iconDirs[i]);
+ QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
+ themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
+ if (themeIndex.exists()) {
+ m_contentDir = themeDir;
+ m_valid = true;
+ break;
+ }
+ }
+#ifndef QT_NO_SETTINGS
+ if (themeIndex.exists()) {
+ const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
+ QStringListIterator keyIterator(indexReader.allKeys());
+ while (keyIterator.hasNext()) {
+
+ const QString key = keyIterator.next();
+ if (key.endsWith(QLatin1String("/Size"))) {
+ // Note the QSettings ini-format does not accept
+ // slashes in key names, hence we have to cheat
+ if (int size = indexReader.value(key).toInt()) {
+ QString directoryKey = key.left(key.size() - 5);
+ QIconDirInfo dirInfo(directoryKey);
+ dirInfo.size = size;
+ QString type = indexReader.value(directoryKey +
+ QLatin1String("/Type")
+ ).toString();
+
+ if (type == QLatin1String("Fixed"))
+ dirInfo.type = QIconDirInfo::Fixed;
+ else if (type == QLatin1String("Scalable"))
+ dirInfo.type = QIconDirInfo::Scalable;
+ else
+ dirInfo.type = QIconDirInfo::Threshold;
+
+ dirInfo.threshold = indexReader.value(directoryKey +
+ QLatin1String("/Threshold"),
+ 2).toInt();
+
+ dirInfo.minSize = indexReader.value(directoryKey +
+ QLatin1String("/MinSize"),
+ size).toInt();
+
+ dirInfo.maxSize = indexReader.value(directoryKey +
+ QLatin1String("/MaxSize"),
+ size).toInt();
+ m_keyList.append(dirInfo);
+ }
+ }
+ }
+
+ // Parent themes provide fallbacks for missing icons
+ m_parents = indexReader.value(
+ QLatin1String("Icon Theme/Inherits")).toStringList();
+
+ // Ensure a default platform fallback for all themes
+ if (m_parents.isEmpty())
+ m_parents.append(fallbackTheme());
+
+ // Ensure that all themes fall back to hicolor
+ if (!m_parents.contains(QLatin1String("hicolor")))
+ m_parents.append(QLatin1String("hicolor"));
+ }
+#endif //QT_NO_SETTINGS
+}
+
+QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const
+{
+ QThemeIconEntries entries;
+ Q_ASSERT(!themeName.isEmpty());
+
+ QPixmap pixmap;
+
+ // Used to protect against potential recursions
+ visited << themeName;
+
+ QIconTheme theme = themeList.value(themeName);
+ if (!theme.isValid()) {
+ theme = QIconTheme(themeName);
+ if (!theme.isValid())
+ theme = QIconTheme(fallbackTheme());
+
+ themeList.insert(themeName, theme);
+ }
+
+ QString contentDir = theme.contentDir() + QLatin1Char('/');
+ QList<QIconDirInfo> subDirs = theme.keyList();
+
+ const QString svgext(QLatin1String(".svg"));
+ const QString pngext(QLatin1String(".png"));
+
+ // Add all relevant files
+ for (int i = 0; i < subDirs.size() ; ++i) {
+ const QIconDirInfo &dirInfo = subDirs.at(i);
+ QString subdir = dirInfo.path;
+ QDir currentDir(contentDir + subdir);
+ if (currentDir.exists(iconName + pngext)) {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + pngext);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ entries.prepend(iconEntry);
+ } else if (m_supportsSvg &&
+ currentDir.exists(iconName + svgext)) {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + svgext);
+ entries.append(iconEntry);
+ }
+ }
+
+ if (entries.isEmpty()) {
+ const QStringList parents = theme.parents();
+ // Search recursively through inherited themes
+ for (int i = 0 ; i < parents.size() ; ++i) {
+
+ const QString parentTheme = parents.at(i).trimmed();
+
+ if (!visited.contains(parentTheme)) // guard against recursion
+ entries = findIconHelper(parentTheme, iconName, visited);
+
+ if (!entries.isEmpty()) // success
+ break;
+ }
+ }
+ return entries;
+}
+
+QThemeIconEntries QIconLoader::loadIcon(const QString &name) const
+{
+ if (!themeName().isEmpty()) {
+ QStringList visited;
+ return findIconHelper(themeName(), name, visited);
+ }
+
+ return QThemeIconEntries();
+}
+
+
+// -------- Icon Loader Engine -------- //
+
+
+QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
+ : m_iconName(iconName), m_key(0)
+{
+}
+
+QIconLoaderEngine::~QIconLoaderEngine()
+{
+ while (!m_entries.isEmpty())
+ delete m_entries.takeLast();
+ Q_ASSERT(m_entries.size() == 0);
+}
+
+QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
+ : QIconEngineV2(other),
+ m_iconName(other.m_iconName),
+ m_key(0)
+{
+}
+
+QIconEngineV2 *QIconLoaderEngine::clone() const
+{
+ return new QIconLoaderEngine(*this);
+}
+
+bool QIconLoaderEngine::read(QDataStream &in) {
+ in >> m_iconName;
+ return true;
+}
+
+bool QIconLoaderEngine::write(QDataStream &out) const
+{
+ out << m_iconName;
+ return true;
+}
+
+bool QIconLoaderEngine::hasIcon() const
+{
+ return !(m_entries.isEmpty());
+}
+
+// Lazily load the icon
+void QIconLoaderEngine::ensureLoaded()
+{
+
+ iconLoaderInstance()->ensureInitialized();
+
+ if (!(iconLoaderInstance()->themeKey() == m_key)) {
+
+ while (!m_entries.isEmpty())
+ delete m_entries.takeLast();
+
+ Q_ASSERT(m_entries.size() == 0);
+ m_entries = iconLoaderInstance()->loadIcon(m_iconName);
+ m_key = iconLoaderInstance()->themeKey();
+ }
+}
+
+void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
+ QIcon::Mode mode, QIcon::State state)
+{
+ QSize pixmapSize = rect.size();
+#if defined(Q_WS_MAC)
+ pixmapSize *= qt_mac_get_scalefactor();
+#endif
+ painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
+}
+
+/*
+ * This algorithm is defined by the freedesktop spec:
+ * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+ */
+static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize)
+{
+ if (dir.type == QIconDirInfo::Fixed) {
+ return dir.size == iconsize;
+
+ } else if (dir.type == QIconDirInfo::Scalable) {
+ return dir.size <= dir.maxSize &&
+ iconsize >= dir.minSize;
+
+ } else if (dir.type == QIconDirInfo::Threshold) {
+ return iconsize >= dir.size - dir.threshold &&
+ iconsize <= dir.size + dir.threshold;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return false;
+}
+
+/*
+ * This algorithm is defined by the freedesktop spec:
+ * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+ */
+static int directorySizeDistance(const QIconDirInfo &dir, int iconsize)
+{
+ if (dir.type == QIconDirInfo::Fixed) {
+ return qAbs(dir.size - iconsize);
+
+ } else if (dir.type == QIconDirInfo::Scalable) {
+ if (iconsize < dir.minSize)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.maxSize)
+ return iconsize - dir.maxSize;
+ else
+ return 0;
+
+ } else if (dir.type == QIconDirInfo::Threshold) {
+ if (iconsize < dir.size - dir.threshold)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.size + dir.threshold)
+ return iconsize - dir.maxSize;
+ else return 0;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return INT_MAX;
+}
+
+QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
+{
+ int iconsize = qMin(size.width(), size.height());
+
+ // Note that m_entries are sorted so that png-files
+ // come first
+
+ // Search for exact matches first
+ for (int i = 0; i < m_entries.count(); ++i) {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ if (directoryMatchesSize(entry->dir, iconsize)) {
+ return entry;
+ }
+ }
+
+ // Find the minimum distance icon
+ int minimalSize = INT_MAX;
+ QIconLoaderEngineEntry *closestMatch = 0;
+ for (int i = 0; i < m_entries.count(); ++i) {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ int distance = directorySizeDistance(entry->dir, iconsize);
+ if (distance < minimalSize) {
+ minimalSize = distance;
+ closestMatch = entry;
+ }
+ }
+ return closestMatch;
+}
+
+/*
+ * Returns the actual icon size. For scalable svg's this is equivalent
+ * to the requested size. Otherwise the closest match is returned but
+ * we can never return a bigger size than the requested size.
+ *
+ */
+QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ ensureLoaded();
+
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry) {
+ const QIconDirInfo &dir = entry->dir;
+ if (dir.type == QIconDirInfo::Scalable)
+ return size;
+ else {
+ int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
+ return QSize(result, result);
+ }
+ }
+ return QIconEngineV2::actualSize(size, mode, state);
+}
+
+QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ Q_UNUSED(state);
+
+ // Ensure that basePixmap is lazily initialized before generating the
+ // key, otherwise the cache key is not unique
+ if (basePixmap.isNull())
+ basePixmap.load(filename);
+
+#if 0 // ### Qt5
+ int actualSize = qMin(size.width(), size.height());
+ QString key = QLatin1Literal("$qt_theme_")
+ % HexString<qint64>(basePixmap.cacheKey())
+ % HexString<int>(mode)
+ % HexString<qint64>(qApp->palette().cacheKey())
+ % HexString<int>(actualSize);
+
+ QPixmap cachedPixmap;
+ if (QPixmapCache::find(key, &cachedPixmap)) {
+ return cachedPixmap;
+ } else {
+ QStyleOption opt(0);
+ opt.palette = qApp->palette();
+ cachedPixmap = qApp->style()->generatedIconPixmap(mode, basePixmap, &opt);
+ QPixmapCache::insert(key, cachedPixmap);
+ }
+ return cachedPixmap;
+#else
+ return basePixmap;
+#endif
+}
+
+QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ if (svgIcon.isNull())
+ svgIcon = QIcon(filename);
+
+ // Simply reuse svg icon engine
+ return svgIcon.pixmap(size, mode, state);
+}
+
+QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ ensureLoaded();
+
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry)
+ return entry->pixmap(size, mode, state);
+
+ return QPixmap();
+}
+
+QString QIconLoaderEngine::key() const
+{
+ return QLatin1String("QIconLoaderEngine");
+}
+
+void QIconLoaderEngine::virtual_hook(int id, void *data)
+{
+ ensureLoaded();
+
+ switch (id) {
+ case QIconEngineV2::AvailableSizesHook:
+ {
+ QIconEngineV2::AvailableSizesArgument &arg
+ = *reinterpret_cast<QIconEngineV2::AvailableSizesArgument*>(data);
+ const QList<QIconDirInfo> directoryKey = iconLoaderInstance()->theme().keyList();
+ arg.sizes.clear();
+
+ // Gets all sizes from the DirectoryInfo entries
+ for (int i = 0 ; i < m_entries.size() ; ++i) {
+ int size = m_entries.at(i)->dir.size;
+ arg.sizes.append(QSize(size, size));
+ }
+ }
+ break;
+ case QIconEngineV2::IconNameHook:
+ {
+ QString &name = *reinterpret_cast<QString*>(data);
+ name = m_iconName;
+ }
+ break;
+ default:
+ QIconEngineV2::virtual_hook(id, data);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ICON
diff --git a/src/widgets/kernel/qiconloader_p.h b/src/widgets/kernel/qiconloader_p.h
new file mode 100644
index 0000000000..00a3976b40
--- /dev/null
+++ b/src/widgets/kernel/qiconloader_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESKTOPICON_P_H
+#define QDESKTOPICON_P_H
+
+#ifndef QT_NO_ICON
+//
+// 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 <QtGui/QIcon>
+#include <QtGui/QIconEngine>
+#include <QtGui/QPixmapCache>
+#include <private/qicon_p.h>
+#include <private/qfactoryloader_p.h>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QIconLoader;
+
+struct QIconDirInfo
+{
+ enum Type { Fixed, Scalable, Threshold };
+ QIconDirInfo(const QString &_path = QString()) :
+ path(_path),
+ size(0),
+ maxSize(0),
+ minSize(0),
+ threshold(0),
+ type(Threshold) {}
+ QString path;
+ short size;
+ short maxSize;
+ short minSize;
+ short threshold;
+ Type type : 4;
+};
+
+class QIconLoaderEngineEntry
+ {
+public:
+ virtual ~QIconLoaderEngineEntry() {}
+ virtual QPixmap pixmap(const QSize &size,
+ QIcon::Mode mode,
+ QIcon::State state) = 0;
+ QString filename;
+ QIconDirInfo dir;
+ static int count;
+};
+
+struct ScalableEntry : public QIconLoaderEngineEntry
+{
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QIcon svgIcon;
+};
+
+struct PixmapEntry : public QIconLoaderEngineEntry
+{
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap basePixmap;
+};
+
+typedef QList<QIconLoaderEngineEntry*> QThemeIconEntries;
+
+class QIconLoaderEngine : public QIconEngineV2
+{
+public:
+ QIconLoaderEngine(const QString& iconName = QString());
+ ~QIconLoaderEngine();
+
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QIconEngineV2 *clone() const;
+ bool read(QDataStream &in);
+ bool write(QDataStream &out) const;
+
+private:
+ QString key() const;
+ bool hasIcon() const;
+ void ensureLoaded();
+ void virtual_hook(int id, void *data);
+ QIconLoaderEngineEntry *entryForSize(const QSize &size);
+ QIconLoaderEngine(const QIconLoaderEngine &other);
+ QThemeIconEntries m_entries;
+ QString m_iconName;
+ uint m_key;
+
+ friend class QIconLoader;
+};
+
+class QIconTheme
+{
+public:
+ QIconTheme(const QString &name);
+ QIconTheme() : m_valid(false) {}
+ QStringList parents() { return m_parents; }
+ QList <QIconDirInfo> keyList() { return m_keyList; }
+ QString contentDir() { return m_contentDir; }
+ bool isValid() { return m_valid; }
+
+private:
+ QString m_contentDir;
+ QList <QIconDirInfo> m_keyList;
+ QStringList m_parents;
+ bool m_valid;
+};
+
+class QIconLoader : public QObject
+{
+public:
+ QIconLoader();
+ QThemeIconEntries loadIcon(const QString &iconName) const;
+ uint themeKey() const { return m_themeKey; }
+
+ QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
+ void setThemeName(const QString &themeName);
+ QIconTheme theme() { return themeList.value(themeName()); }
+ void setThemeSearchPath(const QStringList &searchPaths);
+ QStringList themeSearchPaths() const;
+ QIconDirInfo dirInfo(int dirindex);
+ static QIconLoader *instance();
+ void updateSystemTheme();
+ void invalidateKey() { m_themeKey++; }
+ void ensureInitialized();
+
+private:
+ QThemeIconEntries findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const;
+ uint m_themeKey;
+ bool m_supportsSvg;
+ bool m_initialized;
+
+ mutable QString m_userTheme;
+ mutable QString m_systemTheme;
+ mutable QStringList m_iconDirs;
+ mutable QHash <QString, QIconTheme> themeList;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESKTOPICON_P_H
+
+#endif //QT_NO_ICON
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
new file mode 100644
index 0000000000..e014ec855f
--- /dev/null
+++ b/src/widgets/kernel/qlayout.cpp
@@ -0,0 +1,1632 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+
+#include "qapplication.h"
+#include "qlayoutengine_p.h"
+#include "qmenubar.h"
+#include "qtoolbar.h"
+#include "qsizegrip.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+#include "qlayout_p.h"
+#include "qformlayout.h"
+
+QT_BEGIN_NAMESPACE
+
+static int menuBarHeightForWidth(QWidget *menubar, int w)
+{
+ if (menubar && !menubar->isHidden() && !menubar->isWindow()) {
+ int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth()));
+ if (result != -1)
+ return result;
+ result = menubar->sizeHint()
+ .expandedTo(menubar->minimumSize())
+ .expandedTo(menubar->minimumSizeHint())
+ .boundedTo(menubar->maximumSize()).height();
+ if (result != -1)
+ return result;
+ }
+ return 0;
+}
+
+/*!
+ \class QLayout
+ \brief The QLayout class is the base class of geometry managers.
+
+ \ingroup geomanagement
+
+ This is an abstract base class inherited by the concrete classes
+ QBoxLayout, QGridLayout, QFormLayout, and QStackedLayout.
+
+ For users of QLayout subclasses or of QMainWindow there is seldom
+ any need to use the basic functions provided by QLayout, such as
+ setSizeConstraint() or setMenuBar(). See \l{Layout Management}
+ for more information.
+
+ To make your own layout manager, implement the functions
+ addItem(), sizeHint(), setGeometry(), itemAt() and takeAt(). You
+ should also implement minimumSize() to ensure your layout isn't
+ resized to zero size if there is too little space. To support
+ children whose heights depend on their widths, implement
+ hasHeightForWidth() and heightForWidth(). See the
+ \l{layouts/borderlayout}{Border Layout} and
+ \l{layouts/flowlayout}{Flow Layout} examples for
+ more information about implementing custom layout managers.
+
+ Geometry management stops when the layout manager is deleted.
+
+ \sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
+ {Border Layout Example}, {Flow Layout Example}
+*/
+
+
+/*!
+ Constructs a new top-level QLayout, with parent \a parent.
+ \a parent may not be 0.
+
+ There can be only one top-level layout for a widget. It is
+ returned by QWidget::layout().
+*/
+QLayout::QLayout(QWidget *parent)
+ : QObject(*new QLayoutPrivate, parent)
+{
+ if (!parent)
+ return;
+ parent->setLayout(this);
+}
+
+/*!
+ Constructs a new child QLayout.
+
+ This layout has to be inserted into another layout before geometry
+ management will work.
+*/
+QLayout::QLayout()
+ : QObject(*new QLayoutPrivate, 0)
+{
+}
+
+
+/*! \internal
+ */
+QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
+ : QObject(dd, lay ? static_cast<QObject*>(lay) : static_cast<QObject*>(w))
+{
+ Q_D(QLayout);
+ if (lay) {
+ lay->addItem(this);
+ } else if (w) {
+ if (w->layout()) {
+ qWarning("QLayout: Attempting to add QLayout \"%s\" to %s \"%s\", which"
+ " already has a layout",
+ qPrintable(QObject::objectName()), w->metaObject()->className(),
+ w->objectName().toLocal8Bit().data());
+ setParent(0);
+ } else {
+ d->topLevel = true;
+ w->d_func()->layout = this;
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ w->d_func()->layout = 0;
+ QT_RETHROW;
+ }
+ }
+ }
+}
+
+QLayoutPrivate::QLayoutPrivate()
+ : QObjectPrivate(), insideSpacing(-1), userLeftMargin(-1), userTopMargin(-1), userRightMargin(-1),
+ userBottomMargin(-1), topLevel(false), enabled(true), activated(true), autoNewChild(false),
+ constraint(QLayout::SetDefaultConstraint), menubar(0)
+{
+}
+
+void QLayoutPrivate::getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const
+{
+ if (!result)
+ return;
+
+ Q_Q(const QLayout);
+ if (userMargin >= 0) {
+ *result = userMargin;
+ } else if (!topLevel) {
+ *result = 0;
+ } else if (QWidget *pw = q->parentWidget()) {
+ *result = pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ *result = 0;
+ }
+}
+
+// Static item factory functions that allow for hooking things in Designer
+
+QLayoutPrivate::QWidgetItemFactoryMethod QLayoutPrivate::widgetItemFactoryMethod = 0;
+QLayoutPrivate::QSpacerItemFactoryMethod QLayoutPrivate::spacerItemFactoryMethod = 0;
+
+QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *widget)
+{
+ if (widgetItemFactoryMethod)
+ if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
+ return wi;
+ return new QWidgetItemV2(widget);
+}
+
+QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
+{
+ if (spacerItemFactoryMethod)
+ if (QSpacerItem *si = (*spacerItemFactoryMethod)(layout, w, h, hPolicy, vPolicy))
+ return si;
+ return new QSpacerItem(w, h, hPolicy, vPolicy);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level QLayout called \a name, with parent
+ widget \a parent. \a parent may not be 0.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and the managed children. The \a spacing sets the value of
+ spacing(), which gives the spacing between the managed widgets. If
+ \a spacing is -1 (the default), spacing is set to the value of \a
+ margin.
+
+ There can be only one top-level layout for a widget. It is
+ returned by QWidget::layout()
+
+ \sa QWidget::setLayout()
+*/
+QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name)
+ : QObject(*new QLayoutPrivate,parent)
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ setMargin(margin);
+ if (spacing < 0)
+ d->insideSpacing = margin;
+ else
+ d->insideSpacing = spacing;
+ if (parent) {
+ if (parent->layout()) {
+ qWarning("QLayout \"%s\" added to %s \"%s\", which already has a layout",
+ QObject::objectName().toLocal8Bit().data(), parent->metaObject()->className(),
+ parent->objectName().toLocal8Bit().data());
+ parent->layout()->setParent(0);
+ } else {
+ d->topLevel = true;
+ parent->d_func()->layout = this;
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ parent->d_func()->layout = 0;
+ QT_RETHROW;
+ }
+ }
+ }
+}
+
+/*!
+ Constructs a new child QLayout called \a name, and places it
+ inside \a parentLayout by using the default placement defined by
+ addItem().
+
+ If \a spacing is -1, this QLayout inherits \a parentLayout's
+ spacing(), otherwise the value of \a spacing is used.
+*/
+QLayout::QLayout(QLayout *parentLayout, int spacing, const char *name)
+ : QObject(*new QLayoutPrivate,parentLayout)
+
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ d->insideSpacing = spacing;
+ parentLayout->addItem(this);
+}
+
+/*!
+ Constructs a new child QLayout called \a name. If \a spacing is
+ -1, this QLayout inherits its parent's spacing(); otherwise the
+ value of \a spacing is used.
+
+ This layout has to be inserted into another layout before geometry
+ management will work.
+*/
+QLayout::QLayout(int spacing, const char *name)
+ : QObject(*new QLayoutPrivate, 0)
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ d->insideSpacing = spacing;
+}
+
+/*!
+ Automatically adding widgets is deprecated. Use addWidget() or
+ addLayout() instead.
+*/
+void QLayout::setAutoAdd(bool a) { Q_D(QLayout); d->autoNewChild = a; }
+
+/*!
+ Automatically adding widgets is deprecated. Use addWidget() or
+ addLayout() instead.
+*/
+bool QLayout::autoAdd() const { Q_D(const QLayout); return d->autoNewChild; }
+#endif
+
+
+/*!
+ \fn void QLayout::addItem(QLayoutItem *item)
+
+ Implemented in subclasses to add an \a item. How it is added is
+ specific to each subclass.
+
+ This function is not usually called in application code. To add a widget
+ to a layout, use the addWidget() function; to add a child layout, use the
+ addLayout() function provided by the relevant QLayout subclass.
+
+ \bold{Note:} The ownership of \a item is transferred to the layout, and it's
+ the layout's responsibility to delete it.
+
+ \sa addWidget(), QBoxLayout::addLayout(), QGridLayout::addLayout()
+*/
+
+/*!
+ Adds widget \a w to this layout in a manner specific to the
+ layout. This function uses addItem().
+*/
+void QLayout::addWidget(QWidget *w)
+{
+ addChildWidget(w);
+ addItem(QLayoutPrivate::createWidgetItem(this, w));
+}
+
+
+
+/*!
+ Sets the alignment for widget \a w to \a alignment and returns
+ true if \a w is found in this layout (not including child
+ layouts); otherwise returns false.
+*/
+bool QLayout::setAlignment(QWidget *w, Qt::Alignment alignment)
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->widget() == w) {
+ item->setAlignment(alignment);
+ invalidate();
+ return true;
+ }
+ ++i;
+ item = itemAt(i);
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets the alignment for the layout \a l to \a alignment and
+ returns true if \a l is found in this layout (not including child
+ layouts); otherwise returns false.
+*/
+bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->layout() == l) {
+ item->setAlignment(alignment);
+ invalidate();
+ return true;
+ }
+ ++i;
+ item = itemAt(i);
+ }
+ return false;
+}
+
+/*!
+ \fn void QLayout::setAlignment(Qt::Alignment alignment)
+
+ Sets the alignment of this item to \a alignment.
+
+ \sa QLayoutItem::setAlignment()
+*/
+
+/*!
+ \fn bool QLayout::isTopLevel() const
+
+ Returns true if this layout is a top-level layout, i.e. not a
+ child of another layout; otherwise returns false.
+*/
+
+/*!
+ \property QLayout::margin
+ \brief the width of the outside border of the layout
+ \obsolete
+
+ Use setContentsMargins() and getContentsMargins() instead.
+
+ \sa contentsRect(), spacing
+*/
+
+/*!
+ \obsolete
+*/
+int QLayout::margin() const
+{
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ if (left == top && top == right && right == bottom) {
+ return left;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ \property QLayout::spacing
+ \brief the spacing between widgets inside the layout
+
+ If no value is explicitly set, the layout's spacing is inherited
+ from the parent layout, or from the style settings for the parent
+ widget.
+
+ For QGridLayout and QFormLayout, it is possible to set different horizontal and
+ vertical spacings using \l{QGridLayout::}{setHorizontalSpacing()}
+ and \l{QGridLayout::}{setVerticalSpacing()}. In that case,
+ spacing() returns -1.
+
+ \sa contentsRect(), getContentsMargins(), QStyle::layoutSpacing(),
+ QStyle::pixelMetric()
+*/
+
+int QLayout::spacing() const
+{
+ if (const QBoxLayout* boxlayout = qobject_cast<const QBoxLayout*>(this)) {
+ return boxlayout->spacing();
+ } else if (const QGridLayout* gridlayout = qobject_cast<const QGridLayout*>(this)) {
+ return gridlayout->spacing();
+ } else if (const QFormLayout* formlayout = qobject_cast<const QFormLayout*>(this)) {
+ return formlayout->spacing();
+ } else {
+ Q_D(const QLayout);
+ if (d->insideSpacing >=0) {
+ return d->insideSpacing;
+ } else {
+ // arbitrarily prefer horizontal spacing to vertical spacing
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+ }
+}
+
+/*!
+ \obsolete
+*/
+void QLayout::setMargin(int margin)
+{
+ setContentsMargins(margin, margin, margin, margin);
+}
+
+void QLayout::setSpacing(int spacing)
+{
+ if (QBoxLayout* boxlayout = qobject_cast<QBoxLayout*>(this)) {
+ boxlayout->setSpacing(spacing);
+ } else if (QGridLayout* gridlayout = qobject_cast<QGridLayout*>(this)) {
+ gridlayout->setSpacing(spacing);
+ } else if (QFormLayout* formlayout = qobject_cast<QFormLayout*>(this)) {
+ formlayout->setSpacing(spacing);
+ } else {
+ Q_D(QLayout);
+ d->insideSpacing = spacing;
+ invalidate();
+ }
+}
+
+/*!
+ \since 4.3
+
+ Sets the \a left, \a top, \a right, and \a bottom margins to use
+ around the layout.
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa getContentsMargins(), QStyle::pixelMetric(),
+ {QStyle::}{PM_LayoutLeftMargin},
+ {QStyle::}{PM_LayoutTopMargin},
+ {QStyle::}{PM_LayoutRightMargin},
+ {QStyle::}{PM_LayoutBottomMargin}
+*/
+void QLayout::setContentsMargins(int left, int top, int right, int bottom)
+{
+ Q_D(QLayout);
+
+ if (d->userLeftMargin == left && d->userTopMargin == top &&
+ d->userRightMargin == right && d->userBottomMargin == bottom)
+ return;
+
+ d->userLeftMargin = left;
+ d->userTopMargin = top;
+ d->userRightMargin = right;
+ d->userBottomMargin = bottom;
+ invalidate();
+}
+
+/*!
+ \since 4.6
+
+ Sets the \a margins to use around the layout.
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa contentsMargins()
+*/
+void QLayout::setContentsMargins(const QMargins &margins)
+{
+ setContentsMargins(margins.left(), margins.top(), margins.right(), margins.bottom());
+}
+
+/*!
+ \since 4.3
+
+ Extracts the left, top, right, and bottom margins used around the
+ layout, and assigns them to *\a left, *\a top, *\a right, and *\a
+ bottom (unless they are null pointers).
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa setContentsMargins(), QStyle::pixelMetric(),
+ {QStyle::}{PM_LayoutLeftMargin},
+ {QStyle::}{PM_LayoutTopMargin},
+ {QStyle::}{PM_LayoutRightMargin},
+ {QStyle::}{PM_LayoutBottomMargin}
+*/
+void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) const
+{
+ Q_D(const QLayout);
+ d->getMargin(left, d->userLeftMargin, QStyle::PM_LayoutLeftMargin);
+ d->getMargin(top, d->userTopMargin, QStyle::PM_LayoutTopMargin);
+ d->getMargin(right, d->userRightMargin, QStyle::PM_LayoutRightMargin);
+ d->getMargin(bottom, d->userBottomMargin, QStyle::PM_LayoutBottomMargin);
+}
+
+/*!
+ \since 4.6
+
+ Returns the margins used around the layout.
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa setContentsMargins()
+*/
+QMargins QLayout::contentsMargins() const
+{
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ return QMargins(left, top, right, bottom);
+}
+
+/*!
+ \since 4.3
+
+ Returns the layout's geometry() rectangle, but taking into account the
+ contents margins.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+QRect QLayout::contentsRect() const
+{
+ Q_D(const QLayout);
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ return d->rect.adjusted(+left, +top, -right, -bottom);
+}
+
+#ifdef QT3_SUPPORT
+bool QLayout::isTopLevel() const
+{
+ Q_D(const QLayout);
+ return d->topLevel;
+}
+#endif
+
+/*!
+ Returns the parent widget of this layout, or 0 if this layout is
+ not installed on any widget.
+
+ If the layout is a sub-layout, this function returns the parent
+ widget of the parent layout.
+
+ \sa parent()
+*/
+QWidget *QLayout::parentWidget() const
+{
+ Q_D(const QLayout);
+ if (!d->topLevel) {
+ if (parent()) {
+ QLayout *parentLayout = qobject_cast<QLayout*>(parent());
+ if (!parentLayout) {
+ qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
+ return 0;
+ }
+ return parentLayout->parentWidget();
+ } else {
+ return 0;
+ }
+ } else {
+ Q_ASSERT(parent() && parent()->isWidgetType());
+ return static_cast<QWidget *>(parent());
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QLayout::isEmpty() const
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (!item->isEmpty())
+ return false;
+ ++i;
+ item = itemAt(i);
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+void QLayout::setGeometry(const QRect &r)
+{
+ Q_D(QLayout);
+ d->rect = r;
+}
+
+/*!
+ \reimp
+*/
+QRect QLayout::geometry() const
+{
+ Q_D(const QLayout);
+ return d->rect;
+}
+
+/*!
+ \reimp
+*/
+void QLayout::invalidate()
+{
+ Q_D(QLayout);
+ d->rect = QRect();
+ update();
+}
+
+static bool removeWidgetRecursively(QLayoutItem *li, QWidget *w)
+{
+ QLayout *lay = li->layout();
+ if (!lay)
+ return false;
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = lay->itemAt(i))) {
+ if (child->widget() == w) {
+ delete lay->takeAt(i);
+ lay->invalidate();
+ return true;
+ } else if (removeWidgetRecursively(child, w)) {
+ return true;
+ } else {
+ ++i;
+ }
+ }
+ return false;
+}
+
+
+void QLayoutPrivate::doResize(const QSize &r)
+{
+ Q_Q(QLayout);
+ int mbh = menuBarHeightForWidth(menubar, r.width());
+ QWidget *mw = q->parentWidget();
+ QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
+ rect.setTop(rect.top() + mbh);
+ q->setGeometry(rect);
+#ifndef QT_NO_MENUBAR
+ if (menubar)
+ menubar->setGeometry(0,0,r.width(), mbh);
+#endif
+}
+
+
+/*!
+ \internal
+ Performs child widget layout when the parent widget is
+ resized. Also handles removal of widgets. \a e is the
+ event
+*/
+void QLayout::widgetEvent(QEvent *e)
+{
+ Q_D(QLayout);
+ if (!d->enabled)
+ return;
+
+ switch (e->type()) {
+ case QEvent::Resize:
+ if (d->activated) {
+ QResizeEvent *r = (QResizeEvent *)e;
+ d->doResize(r->size());
+ } else {
+ activate();
+ }
+ break;
+ case QEvent::ChildRemoved:
+ {
+ QChildEvent *c = (QChildEvent *)e;
+ if (c->child()->isWidgetType()) {
+ QWidget *w = (QWidget *)c->child();
+#ifndef QT_NO_MENUBAR
+ if (w == d->menubar)
+ d->menubar = 0;
+#endif
+ removeWidgetRecursively(this, w);
+ }
+ }
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInserted:
+ if (d->topLevel && d->autoNewChild) {
+ QChildEvent *c = (QChildEvent *)e;
+ if (c->child()->isWidgetType()) {
+ QWidget *w = (QWidget *)c->child();
+ if (!w->isWindow()) {
+#if !defined(QT_NO_MENUBAR) && !defined(QT_NO_TOOLBAR)
+ if (qobject_cast<QMenuBar*>(w) && !qobject_cast<QToolBar*>(w->parentWidget())) {
+ d->menubar = (QMenuBar *)w;
+ invalidate();
+ } else
+#endif
+#ifndef QT_NO_SIZEGRIP
+ if (qobject_cast<QSizeGrip*>(w) ) {
+ //SizeGrip is handled by the dialog itself.
+ } else
+#endif
+ addItem(QLayoutPrivate::createWidgetItem(this, w));
+ }
+ }
+ }
+ break;
+ case QEvent::LayoutHint:
+ d->activated = false;
+ // fall through
+#endif
+ case QEvent::LayoutRequest:
+ if (static_cast<QWidget *>(parent())->isVisible())
+ activate();
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QLayout::childEvent(QChildEvent *e)
+{
+ Q_D(QLayout);
+ if (!d->enabled)
+ return;
+
+ if (e->type() == QEvent::ChildRemoved) {
+ QChildEvent *c = (QChildEvent*)e;
+ int i = 0;
+
+ QLayoutItem *item;
+ while ((item = itemAt(i))) {
+ if (item == static_cast<QLayout*>(c->child())) {
+ takeAt(i);
+ invalidate();
+ break;
+ } else {
+ ++i;
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+int QLayout::totalHeightForWidth(int w) const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *parent = parentWidget();
+ parent->ensurePolished();
+ QWidgetPrivate *wd = parent->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+ int h = heightForWidth(w - side) + top;
+#ifndef QT_NO_MENUBAR
+ h += menuBarHeightForWidth(d->menubar, w);
+#endif
+ return h;
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalMinimumSize() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = minimumSize();
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width() + side);
+#endif
+ return s + QSize(side, top);
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalSizeHint() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = sizeHint();
+ if (hasHeightForWidth())
+ s.setHeight(heightForWidth(s.width() + side));
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width());
+#endif
+ return s + QSize(side, top);
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalMaximumSize() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = maximumSize();
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width());
+#endif
+
+ if (d->topLevel)
+ s = QSize(qMin(s.width() + side, QLAYOUTSIZE_MAX),
+ qMin(s.height() + top, QLAYOUTSIZE_MAX));
+ return s;
+}
+
+/*!
+ \internal
+ Destroys the layout, deleting all child layouts.
+ Geometry management stops when a top-level layout is deleted.
+
+ The layout classes will probably be fatally confused if you delete
+ a sublayout.
+*/
+QLayout::~QLayout()
+{
+ Q_D(QLayout);
+ /*
+ This function may be called during the QObject destructor,
+ when the parent no longer is a QWidget.
+ */
+ if (d->topLevel && parent() && parent()->isWidgetType() &&
+ ((QWidget*)parent())->layout() == this)
+ ((QWidget*)parent())->d_func()->layout = 0;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Removes and deletes all items in this layout.
+*/
+void QLayout::deleteAllItems()
+{
+ QLayoutItem *l;
+ while ((l = takeAt(0)))
+ delete l;
+}
+#endif
+
+/*!
+ This function is called from \c addLayout() or \c insertLayout() functions in
+ subclasses to add layout \a l as a sub-layout.
+
+ The only scenario in which you need to call it directly is if you
+ implement a custom layout that supports nested layouts.
+
+ \sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
+*/
+void QLayout::addChildLayout(QLayout *l)
+{
+ if (l->parent()) {
+ qWarning("QLayout::addChildLayout: layout \"%s\" already has a parent",
+ l->objectName().toLocal8Bit().data());
+ return;
+ }
+ l->setParent(this);
+
+ if (QWidget *mw = parentWidget()) {
+ l->d_func()->reparentChildWidgets(mw);
+ }
+
+}
+
+#ifdef QT_DEBUG
+static bool layoutDebug()
+{
+ static int checked_env = -1;
+ if(checked_env == -1)
+ checked_env = !!qgetenv("QT_LAYOUT_DEBUG").toInt();
+
+ return checked_env;
+}
+#endif
+
+void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
+{
+ Q_Q(QLayout);
+ int n = q->count();
+
+#ifndef QT_NO_MENUBAR
+ if (menubar && menubar->parentWidget() != mw) {
+ menubar->setParent(mw);
+ }
+#endif
+ bool mwVisible = mw && mw->isVisible();
+ for (int i = 0; i < n; ++i) {
+ QLayoutItem *item = q->itemAt(i);
+ if (QWidget *w = item->widget()) {
+ QWidget *pw = w->parentWidget();
+#ifdef QT_DEBUG
+ if (pw && pw != mw && layoutDebug()) {
+ qWarning("QLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+ }
+#endif
+ bool needShow = mwVisible && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ if (pw != mw)
+ w->setParent(mw);
+ if (needShow)
+ QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
+ } else if (QLayout *l = item->layout()) {
+ l->d_func()->reparentChildWidgets(mw);
+ }
+ }
+}
+
+/*!
+ This function is called from \c addWidget() functions in
+ subclasses to add \a w as a managed widget of a layout.
+
+ If \a w is already managed by a layout, this function will give a warning
+ and remove \a w from that layout. This function must therefore be
+ called before adding \a w to the layout's data structure.
+*/
+void QLayout::addChildWidget(QWidget *w)
+{
+ QWidget *mw = parentWidget();
+ QWidget *pw = w->parentWidget();
+
+ //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
+ //been in a layout.
+ if (pw && w->testAttribute(Qt::WA_LaidOut)) {
+ QLayout *l = pw->layout();
+ if (l && removeWidgetRecursively(l, w)) {
+#ifdef QT_DEBUG
+ if (layoutDebug())
+ qWarning("QLayout::addChildWidget: %s \"%s\" is already in a layout; moved to new layout",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+#endif
+ }
+ }
+ if (pw && mw && pw != mw) {
+#ifdef QT_DEBUG
+ if (layoutDebug())
+ qWarning("QLayout::addChildWidget: %s \"%s\" in wrong parent; moved to correct parent",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+#endif
+ pw = 0;
+ }
+ bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ if (!pw && mw)
+ w->setParent(mw);
+ w->setAttribute(Qt::WA_LaidOut);
+ if (needShow)
+ QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \compat
+
+ Sets this layout's parent widget to a fixed size with width \a w
+ and height \a h, stopping the user from resizing it, and also
+ prevents the layout from resizing it, even if the layout's size
+ hint should change. Does nothing if this is not a top-level
+ layout (i.e., if parent()->isWidgetType()).
+
+ As a special case, if both \a w and \a h are 0, then the layout's
+ current sizeHint() is used.
+
+ Use \c setResizeMode(Fixed) to stop the widget from being resized
+ by the user, while still allowing the layout to resize it when
+ the sizeHint() changes.
+
+ Use \c setResizeMode(FreeResize) to allow the user to resize the
+ widget, while preventing the layout from resizing it.
+
+*/
+void QLayout::freeze(int w, int h)
+{
+ Q_D(QLayout);
+ if (!d->topLevel)
+ return;
+ if (w <= 0 || h <= 0) {
+ QSize s = totalSizeHint();
+ w = s.width();
+ h = s.height();
+ }
+ setSizeConstraint(SetNoConstraint); // layout will not change min/max size
+ QWidget *parent = parentWidget();
+ if (parent)
+ parent->setFixedSize(w, h);
+}
+
+#endif
+
+
+
+
+
+
+
+/*!
+ Tells the geometry manager to place the menu bar \a widget at the
+ top of parentWidget(), outside QWidget::contentsMargins(). All
+ child widgets are placed below the bottom edge of the menu bar.
+*/
+void QLayout::setMenuBar(QWidget *widget)
+{
+ Q_D(QLayout);
+
+#ifdef Q_OS_WINCE_WM
+ if (widget && widget->size().height() > 0)
+#else
+ if (widget)
+#endif
+ addChildWidget(widget);
+ d->menubar = widget;
+}
+
+/*!
+ Returns the menu bar set for this layout, or 0 if no menu bar is
+ set.
+*/
+
+QWidget *QLayout::menuBar() const
+{
+ Q_D(const QLayout);
+ return d->menubar;
+}
+
+
+/*!
+ Returns the minimum size of this layout. This is the smallest
+ size that the layout can have while still respecting the
+ specifications.
+
+ The returned value doesn't include the space required by
+ QWidget::setContentsMargins() or menuBar().
+
+ The default implementation allows unlimited resizing.
+*/
+QSize QLayout::minimumSize() const
+{
+ return QSize(0, 0);
+}
+
+/*!
+ Returns the maximum size of this layout. This is the largest size
+ that the layout can have while still respecting the
+ specifications.
+
+ The returned value doesn't include the space required by
+ QWidget::setContentsMargins() or menuBar().
+
+ The default implementation allows unlimited resizing.
+*/
+QSize QLayout::maximumSize() const
+{
+ return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
+}
+
+/*!
+ Returns whether this layout can make use of more space than
+ sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
+ it wants to grow in only one dimension, whereas Qt::Vertical |
+ Qt::Horizontal means that it wants to grow in both dimensions.
+
+ The default implementation returns Qt::Horizontal | Qt::Vertical.
+ Subclasses reimplement it to return a meaningful value based on
+ their child widgets's \l{QSizePolicy}{size policies}.
+
+ \sa sizeHint()
+*/
+Qt::Orientations QLayout::expandingDirections() const
+{
+ return Qt::Horizontal | Qt::Vertical;
+}
+
+void QLayout::activateRecursiveHelper(QLayoutItem *item)
+{
+ item->invalidate();
+ QLayout *layout = item->layout();
+ if (layout) {
+ QLayoutItem *child;
+ int i=0;
+ while ((child = layout->itemAt(i++)))
+ activateRecursiveHelper(child);
+ layout->d_func()->activated = true;
+ }
+}
+
+/*!
+ Updates the layout for parentWidget().
+
+ You should generally not need to call this because it is
+ automatically called at the most appropriate times.
+
+ \sa activate(), invalidate()
+*/
+
+void QLayout::update()
+{
+ QLayout *layout = this;
+ while (layout && layout->d_func()->activated) {
+ layout->d_func()->activated = false;
+ if (layout->d_func()->topLevel) {
+ Q_ASSERT(layout->parent()->isWidgetType());
+ QWidget *mw = static_cast<QWidget*>(layout->parent());
+ QApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest));
+ break;
+ }
+ layout = static_cast<QLayout*>(layout->parent());
+ }
+}
+
+/*!
+ Redoes the layout for parentWidget() if necessary.
+
+ You should generally not need to call this because it is
+ automatically called at the most appropriate times. It returns
+ true if the layout was redone.
+
+ \sa update(), QWidget::updateGeometry()
+*/
+bool QLayout::activate()
+{
+ Q_D(QLayout);
+ if (!d->enabled || !parent())
+ return false;
+ if (!d->topLevel)
+ return static_cast<QLayout*>(parent())->activate();
+ if (d->activated)
+ return false;
+ QWidget *mw = static_cast<QWidget*>(parent());
+ if (mw == 0) {
+ qWarning("QLayout::activate: %s \"%s\" does not have a main widget",
+ QObject::metaObject()->className(), QObject::objectName().toLocal8Bit().data());
+ return false;
+ }
+ activateRecursiveHelper(this);
+
+ QWidgetPrivate *md = mw->d_func();
+ uint explMin = md->extra ? md->extra->explicitMinSize : 0;
+ uint explMax = md->extra ? md->extra->explicitMaxSize : 0;
+
+ switch (d->constraint) {
+ case SetFixedSize:
+ // will trigger resize
+ mw->setFixedSize(totalSizeHint());
+ break;
+ case SetMinimumSize:
+ mw->setMinimumSize(totalMinimumSize());
+ break;
+ case SetMaximumSize:
+ mw->setMaximumSize(totalMaximumSize());
+ break;
+ case SetMinAndMaxSize:
+ mw->setMinimumSize(totalMinimumSize());
+ mw->setMaximumSize(totalMaximumSize());
+ break;
+ case SetDefaultConstraint: {
+ bool widthSet = explMin & Qt::Horizontal;
+ bool heightSet = explMin & Qt::Vertical;
+ if (mw->isWindow()) {
+ QSize ms = totalMinimumSize();
+ if (widthSet)
+ ms.setWidth(mw->minimumSize().width());
+ if (heightSet)
+ ms.setHeight(mw->minimumSize().height());
+ if ((!heightSet || !widthSet) && hasHeightForWidth()) {
+ int h = minimumHeightForWidth(ms.width());
+ if (h > ms.height()) {
+ if (!heightSet)
+ ms.setHeight(0);
+ if (!widthSet)
+ ms.setWidth(0);
+ }
+ }
+ mw->setMinimumSize(ms);
+ } else if (!widthSet || !heightSet) {
+ QSize ms = mw->minimumSize();
+ if (!widthSet)
+ ms.setWidth(0);
+ if (!heightSet)
+ ms.setHeight(0);
+ mw->setMinimumSize(ms);
+ }
+ break;
+ }
+ case SetNoConstraint:
+ break;
+ }
+
+ d->doResize(mw->size());
+
+ if (md->extra) {
+ md->extra->explicitMinSize = explMin;
+ md->extra->explicitMaxSize = explMax;
+ }
+ // ideally only if sizeHint() or sizePolicy() has changed
+ mw->updateGeometry();
+ return true;
+}
+
+/*!
+ \fn QLayoutItem *QLayout::itemAt(int index) const
+
+ Must be implemented in subclasses to return the layout item at \a
+ index. If there is no such item, the function must return 0.
+ Items are numbered consecutively from 0. If an item is deleted, other items will be renumbered.
+
+ This function can be used to iterate over a layout. The following
+ code will draw a rectangle for each layout item in the layout structure of the widget.
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 0
+
+ \sa count(), takeAt()
+*/
+
+/*!
+ \fn QLayoutItem *QLayout::takeAt(int index)
+
+ Must be implemented in subclasses to remove the layout item at \a
+ index from the layout, and return the item. If there is no such
+ item, the function must do nothing and return 0. Items are numbered
+ consecutively from 0. If an item is removed, other items will be
+ renumbered.
+
+ The following code fragment shows a safe way to remove all items
+ from a layout:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 1
+
+ \sa itemAt(), count()
+*/
+
+/*!
+ \fn int *QLayout::count() const
+
+ Must be implemented in subclasses to return the number of items
+ in the layout.
+
+ \sa itemAt()
+*/
+
+/*!
+ Searches for widget \a widget in this layout (not including child
+ layouts).
+
+ Returns the index of \a widget, or -1 if \a widget is not found.
+
+ The default implementation iterates over all items using itemAt()
+*/
+int QLayout::indexOf(QWidget *widget) const
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->widget() == widget)
+ return i;
+ ++i;
+ item = itemAt(i);
+ }
+ return -1;
+}
+
+/*!
+ \enum QLayout::SizeConstraint
+
+ The possible values are:
+
+ \value SetDefaultConstraint The main widget's minimum size is set
+ to minimumSize(), unless the widget already has
+ a minimum size.
+
+ \value SetFixedSize The main widget's size is set to sizeHint(); it
+ cannot be resized at all.
+ \value SetMinimumSize The main widget's minimum size is set to
+ minimumSize(); it cannot be smaller.
+
+ \value SetMaximumSize The main widget's maximum size is set to
+ maximumSize(); it cannot be larger.
+
+ \value SetMinAndMaxSize The main widget's minimum size is set to
+ minimumSize() and its maximum size is set to
+ maximumSize().
+
+ \value SetNoConstraint The widget is not constrained.
+
+ \omitvalue Auto
+ \omitvalue FreeResize
+ \omitvalue Minimum
+ \omitvalue Fixed
+
+ \sa setSizeConstraint()
+*/
+
+/*!
+ \property QLayout::sizeConstraint
+ \brief the resize mode of the layout
+
+ The default mode is \l {QLayout::SetDefaultConstraint}
+ {SetDefaultConstraint}.
+*/
+void QLayout::setSizeConstraint(SizeConstraint constraint)
+{
+ Q_D(QLayout);
+ if (constraint == d->constraint)
+ return;
+
+ d->constraint = constraint;
+ invalidate();
+}
+
+QLayout::SizeConstraint QLayout::sizeConstraint() const
+{
+ Q_D(const QLayout);
+ return d->constraint;
+}
+
+/*!
+ Returns the rectangle that should be covered when the geometry of
+ this layout is set to \a r, provided that this layout supports
+ setAlignment().
+
+ The result is derived from sizeHint() and expanding(). It is never
+ larger than \a r.
+*/
+QRect QLayout::alignmentRect(const QRect &r) const
+{
+ QSize s = sizeHint();
+ Qt::Alignment a = alignment();
+
+ /*
+ This is a hack to obtain the real maximum size, not
+ QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX), the value consistently
+ returned by QLayoutItems that have an alignment.
+ */
+ QLayout *that = const_cast<QLayout *>(this);
+ that->setAlignment(0);
+ QSize ms = that->maximumSize();
+ that->setAlignment(a);
+
+ if ((expandingDirections() & Qt::Horizontal) ||
+ !(a & Qt::AlignHorizontal_Mask)) {
+ s.setWidth(qMin(r.width(), ms.width()));
+ }
+ if ((expandingDirections() & Qt::Vertical) ||
+ !(a & Qt::AlignVertical_Mask)) {
+ s.setHeight(qMin(r.height(), ms.height()));
+ } else if (hasHeightForWidth()) {
+ int hfw = heightForWidth(s.width());
+ if (hfw < s.height())
+ s.setHeight(qMin(hfw, ms.height()));
+ }
+
+ s = s.boundedTo(r.size());
+ int x = r.x();
+ int y = r.y();
+
+ if (a & Qt::AlignBottom)
+ y += (r.height() - s.height());
+ else if (!(a & Qt::AlignTop))
+ y += (r.height() - s.height()) / 2;
+
+ QWidget *parent = parentWidget();
+ a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QApplication::layoutDirection(), a);
+ if (a & Qt::AlignRight)
+ x += (r.width() - s.width());
+ else if (!(a & Qt::AlignLeft))
+ x += (r.width() - s.width()) / 2;
+
+ return QRect(x, y, s.width(), s.height());
+}
+
+/*!
+ Removes the widget \a widget from the layout. After this call, it
+ is the caller's responsibility to give the widget a reasonable
+ geometry or to put the widget back into a layout.
+
+ \bold{Note:} The ownership of \a widget remains the same as
+ when it was added.
+
+ \sa removeItem(), QWidget::setGeometry(), addWidget()
+*/
+void QLayout::removeWidget(QWidget *widget)
+{
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = itemAt(i))) {
+ if (child->widget() == widget) {
+ delete takeAt(i);
+ invalidate();
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Removes the layout item \a item from the layout. It is the
+ caller's responsibility to delete the item.
+
+ Notice that \a item can be a layout (since QLayout inherits
+ QLayoutItem).
+
+ \sa removeWidget(), addItem()
+*/
+void QLayout::removeItem(QLayoutItem *item)
+{
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = itemAt(i))) {
+ if (child == item) {
+ takeAt(i);
+ invalidate();
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Enables this layout if \a enable is true, otherwise disables it.
+
+ An enabled layout adjusts dynamically to changes; a disabled
+ layout acts as if it did not exist.
+
+ By default all layouts are enabled.
+
+ \sa isEnabled()
+*/
+void QLayout::setEnabled(bool enable)
+{
+ Q_D(QLayout);
+ d->enabled = enable;
+}
+
+/*!
+ Returns true if the layout is enabled; otherwise returns false.
+
+ \sa setEnabled()
+*/
+bool QLayout::isEnabled() const
+{
+ Q_D(const QLayout);
+ return d->enabled;
+}
+
+/*!
+ Returns a size that satisfies all size constraints on \a widget,
+ including heightForWidth() and that is as close as possible to \a
+ size.
+*/
+
+QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
+{
+ QSize result = size.boundedTo(qSmartMaxSize(widget));
+ result = result.expandedTo(qSmartMinSize(widget));
+ QLayout *l = widget->layout();
+ if (l && l->hasHeightForWidth() && result.height() < l->minimumHeightForWidth(result.width()) ) {
+ QSize current = widget->size();
+ int currentHfw = l->minimumHeightForWidth(current.width());
+ int newHfw = l->minimumHeightForWidth(result.width());
+ if (current.height() < currentHfw || currentHfw == newHfw) {
+ //handle the constant hfw case and the vertical-only case, as well as the
+ // current-size-is-not-correct case
+ result.setHeight(newHfw);
+ } else {
+ // binary search; assume hfw is decreasing ###
+
+ int maxw = qMax(widget->width(),result.width());
+ int maxh = qMax(widget->height(), result.height());
+ int minw = qMin(widget->width(),result.width());
+ int minh = qMin(widget->height(), result.height());
+
+ int minhfw = l->minimumHeightForWidth(minw);
+ int maxhfw = l->minimumHeightForWidth(maxw);
+ while (minw < maxw) {
+ if (minhfw > maxh) { //assume decreasing
+ minw = maxw - (maxw-minw)/2;
+ minhfw = l->minimumHeightForWidth(minw);
+ } else if (maxhfw < minh ) { //assume decreasing
+ maxw = minw + (maxw-minw)/2;
+ maxhfw = l->minimumHeightForWidth(maxw);
+ } else {
+ break;
+ }
+ }
+ result = result.expandedTo(QSize(minw, minhfw));
+ }
+ }
+ return result;
+}
+
+/*!
+ \fn void QLayout::setResizeMode(SizeConstraint constraint)
+
+ Use setSizeConstraint(\a constraint) instead.
+*/
+
+/*!
+ \fn QLayout::SizeConstraint QLayout::resizeMode() const
+
+ Use sizeConstraint() instead.
+*/
+
+void QSizePolicy::setControlType(ControlType type)
+{
+ /*
+ The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
+ etc. In memory, we pack it onto the available bits (CTSize) in
+ setControlType(), and unpack it here.
+
+ Example:
+
+ 0x00000001 maps to 0x00000000
+ 0x00000002 maps to 0x00000200
+ 0x00000004 maps to 0x00000400
+ 0x00000008 maps to 0x00000600
+ etc.
+ */
+
+ int i = 0;
+ while (true) {
+ if (type & (0x1 << i)) {
+ data = (data & ~CTMask) | (i << CTShift);
+ return;
+ }
+ ++i;
+ }
+}
+
+QSizePolicy::ControlType QSizePolicy::controlType() const
+{
+ return QSizePolicy::ControlType(0x1 << ((data & CTMask) >> CTShift));
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QSizePolicy
+ \since 4.2
+
+ Writes the size \a policy to the data stream \a stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
+{
+ return stream << policy.data;
+}
+
+/*!
+ \relates QSizePolicy
+ \since 4.2
+
+ Reads the size \a policy from the data stream \a stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
+{
+ return stream >> policy.data;
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h
new file mode 100644
index 0000000000..5333150072
--- /dev/null
+++ b/src/widgets/kernel/qlayout.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUT_H
+#define QLAYOUT_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qlayoutitem.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qmargins.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QLayout;
+class QSize;
+
+#ifdef QT3_SUPPORT
+class Q_GUI_EXPORT QLayoutIterator
+{
+public:
+ inline QT3_SUPPORT_CONSTRUCTOR QLayoutIterator(QLayout *i) : layout(i), index(0) {}
+ inline QLayoutIterator(const QLayoutIterator &i)
+ : layout(i.layout), index(i.index) {}
+ inline QLayoutIterator &operator=(const QLayoutIterator &i) {
+ layout = i.layout;
+ index = i.index;
+ return *this;
+ }
+ inline QT3_SUPPORT QLayoutItem *operator++();
+ inline QT3_SUPPORT QLayoutItem *current();
+ inline QT3_SUPPORT QLayoutItem *takeCurrent();
+ inline QT3_SUPPORT void deleteCurrent();
+
+private:
+ // hack to avoid deprecated warning
+ friend class QLayout;
+ inline QLayoutIterator(QLayout *i, bool) : layout(i), index(0) {}
+ QLayout *layout;
+ int index;
+};
+#endif
+
+class QLayoutPrivate;
+
+class Q_GUI_EXPORT QLayout : public QObject, public QLayoutItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QLayout)
+
+ Q_ENUMS(SizeConstraint)
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(SizeConstraint sizeConstraint READ sizeConstraint WRITE setSizeConstraint)
+public:
+ enum SizeConstraint {
+ SetDefaultConstraint,
+ SetNoConstraint,
+ SetMinimumSize,
+ SetFixedSize,
+ SetMaximumSize,
+ SetMinAndMaxSize
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ , Auto = SetDefaultConstraint,
+ FreeResize = SetNoConstraint,
+ Minimum = SetMinimumSize,
+ Fixed = SetFixedSize
+#endif
+ };
+
+ QLayout(QWidget *parent);
+ QLayout();
+ ~QLayout();
+
+ int margin() const;
+ int spacing() const;
+
+ void setMargin(int);
+ void setSpacing(int);
+
+ void setContentsMargins(int left, int top, int right, int bottom);
+ void setContentsMargins(const QMargins &margins);
+ void getContentsMargins(int *left, int *top, int *right, int *bottom) const;
+ QMargins contentsMargins() const;
+ QRect contentsRect() const;
+
+ bool setAlignment(QWidget *w, Qt::Alignment alignment);
+ bool setAlignment(QLayout *l, Qt::Alignment alignment);
+#ifdef Q_NO_USING_KEYWORD
+ inline void setAlignment(Qt::Alignment alignment) { QLayoutItem::setAlignment(alignment); }
+#else
+ using QLayoutItem::setAlignment;
+#endif
+
+ void setSizeConstraint(SizeConstraint);
+ SizeConstraint sizeConstraint() const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setResizeMode(SizeConstraint s) {setSizeConstraint(s);}
+ inline QT3_SUPPORT SizeConstraint resizeMode() const {return sizeConstraint();}
+#endif
+ void setMenuBar(QWidget *w);
+ QWidget *menuBar() const;
+
+ QWidget *parentWidget() const;
+
+ void invalidate();
+ QRect geometry() const;
+ bool activate();
+ void update();
+
+ void addWidget(QWidget *w);
+ virtual void addItem(QLayoutItem *) = 0;
+
+ void removeWidget(QWidget *w);
+ void removeItem(QLayoutItem *);
+
+ Qt::Orientations expandingDirections() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ virtual void setGeometry(const QRect&);
+ virtual QLayoutItem *itemAt(int index) const = 0;
+ virtual QLayoutItem *takeAt(int index) = 0;
+ virtual int indexOf(QWidget *) const;
+ virtual int count() const = 0;
+ bool isEmpty() const;
+
+ int totalHeightForWidth(int w) const;
+ QSize totalMinimumSize() const;
+ QSize totalMaximumSize() const;
+ QSize totalSizeHint() const;
+ QLayout *layout();
+
+ void setEnabled(bool);
+ bool isEnabled() const;
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void freeze(int w=0, int h=0);
+ QT3_SUPPORT bool isTopLevel() const;
+#endif
+
+ static QSize closestAcceptableSize(const QWidget *w, const QSize &s);
+
+protected:
+ void widgetEvent(QEvent *);
+ void childEvent(QChildEvent *e);
+ void addChildLayout(QLayout *l);
+ void addChildWidget(QWidget *w);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void deleteAllItems();
+#endif
+
+ QRect alignmentRect(const QRect&) const;
+protected:
+ QLayout(QLayoutPrivate &d, QLayout*, QWidget*);
+
+private:
+ Q_DISABLE_COPY(QLayout)
+
+ static void activateRecursiveHelper(QLayoutItem *item);
+
+ friend class QApplicationPrivate;
+ friend class QWidget;
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QLayout(QWidget *parent, int margin, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QLayout(QLayout *parentLayout, int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QLayout(int spacing, const char *name = 0);
+ inline QT3_SUPPORT QWidget *mainWidget() const { return parentWidget(); }
+ inline QT3_SUPPORT void remove(QWidget *w) { removeWidget(w); }
+ inline QT3_SUPPORT void add(QWidget *w) { addWidget(w); }
+
+ QT3_SUPPORT void setAutoAdd(bool a);
+ QT3_SUPPORT bool autoAdd() const;
+ inline QT3_SUPPORT QLayoutIterator iterator() { return QLayoutIterator(this,true); }
+
+ inline QT3_SUPPORT int defaultBorder() const { return spacing(); }
+#endif
+};
+
+#ifdef QT3_SUPPORT
+inline QLayoutItem *QLayoutIterator::operator++() { return layout->itemAt(++index); }
+inline QLayoutItem *QLayoutIterator::current() { return layout->itemAt(index); }
+inline QLayoutItem *QLayoutIterator::takeCurrent() { return layout->takeAt(index); }
+inline void QLayoutIterator::deleteCurrent() { delete layout->takeAt(index); }
+#endif
+
+//### support old includes
+#if 1 //def QT3_SUPPORT
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qgridlayout.h>
+QT_END_INCLUDE_NAMESPACE
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLAYOUT_H
diff --git a/src/widgets/kernel/qlayout_p.h b/src/widgets/kernel/qlayout_p.h
new file mode 100644
index 0000000000..342333954c
--- /dev/null
+++ b/src/widgets/kernel/qlayout_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUT_P_H
+#define QLAYOUT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qlayout*.cpp, and qabstractlayout.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "qstyle.h"
+#include "qsizepolicy.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidgetItem;
+class QSpacerItem;
+
+class Q_GUI_EXPORT QLayoutPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QLayout)
+
+public:
+ typedef QWidgetItem * (*QWidgetItemFactoryMethod)(const QLayout *layout, QWidget *widget);
+ typedef QSpacerItem * (*QSpacerItemFactoryMethod)(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy);
+
+ QLayoutPrivate();
+
+ void getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const;
+ void doResize(const QSize &);
+ void reparentChildWidgets(QWidget *mw);
+
+ static QWidgetItem *createWidgetItem(const QLayout *layout, QWidget *widget);
+ static QSpacerItem *createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum);
+
+ static QWidgetItemFactoryMethod widgetItemFactoryMethod;
+ static QSpacerItemFactoryMethod spacerItemFactoryMethod;
+
+ int insideSpacing;
+ int userLeftMargin;
+ int userTopMargin;
+ int userRightMargin;
+ int userBottomMargin;
+ uint topLevel : 1;
+ uint enabled : 1;
+ uint activated : 1;
+ uint autoNewChild : 1;
+ QLayout::SizeConstraint constraint;
+ QRect rect;
+ QWidget *menubar;
+};
+
+QT_END_NAMESPACE
+
+#endif // QLAYOUT_P_H
diff --git a/src/widgets/kernel/qlayoutengine.cpp b/src/widgets/kernel/qlayoutengine.cpp
new file mode 100644
index 0000000000..fdabd8ae1f
--- /dev/null
+++ b/src/widgets/kernel/qlayoutengine.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+#include "private/qlayoutengine_p.h"
+
+#include "qvector.h"
+#include "qwidget.h"
+
+#include <qlist.h>
+#include <qalgorithms.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define QLAYOUT_EXTRA_DEBUG
+
+typedef qint64 Fixed64;
+static inline Fixed64 toFixed(int i) { return (Fixed64)i * 256; }
+static inline int fRound(Fixed64 i) {
+ return (i % 256 < 128) ? i / 256 : 1 + i / 256;
+}
+
+/*
+ This is the main workhorse of the QGridLayout. It portions out
+ available space to the chain's children.
+
+ The calculation is done in fixed point: "fixed" variables are
+ scaled by a factor of 256.
+
+ If the layout runs "backwards" (i.e. RightToLeft or Up) the layout
+ is computed mirror-reversed, and it's the caller's responsibility
+ do reverse the values before use.
+
+ chain contains input and output parameters describing the geometry.
+ count is the count of items in the chain; pos and space give the
+ interval (relative to parentWidget topLeft).
+*/
+void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
+ int pos, int space, int spacer)
+{
+ int cHint = 0;
+ int cMin = 0;
+ int cMax = 0;
+ int sumStretch = 0;
+ int sumSpacing = 0;
+
+ bool wannaGrow = false; // anyone who really wants to grow?
+ // bool canShrink = false; // anyone who could be persuaded to shrink?
+
+ bool allEmptyNonstretch = true;
+ int pendingSpacing = -1;
+ int spacerCount = 0;
+ int i;
+
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+
+ data->done = false;
+ cHint += data->smartSizeHint();
+ cMin += data->minimumSize;
+ cMax += data->maximumSize;
+ sumStretch += data->stretch;
+ if (!data->empty) {
+ /*
+ Using pendingSpacing, we ensure that the spacing for the last
+ (non-empty) item is ignored.
+ */
+ if (pendingSpacing >= 0) {
+ sumSpacing += pendingSpacing;
+ ++spacerCount;
+ }
+ pendingSpacing = data->effectiveSpacer(spacer);
+ }
+ wannaGrow = wannaGrow || data->expansive || data->stretch > 0;
+ allEmptyNonstretch = allEmptyNonstretch && !wannaGrow && data->empty;
+ }
+
+ int extraspace = 0;
+
+ if (space < cMin + sumSpacing) {
+ /*
+ Less space than minimumSize; take from the biggest first
+ */
+
+ int minSize = cMin + sumSpacing;
+
+ // shrink the spacers proportionally
+ if (spacer >= 0) {
+ spacer = minSize > 0 ? spacer * space / minSize : 0;
+ sumSpacing = spacer * spacerCount;
+ }
+
+ QList<int> list;
+
+ for (i = start; i < start + count; i++)
+ list << chain.at(i).minimumSize;
+
+ qSort(list);
+
+ int space_left = space - sumSpacing;
+
+ int sum = 0;
+ int idx = 0;
+ int space_used=0;
+ int current = 0;
+ while (idx < count && space_used < space_left) {
+ current = list.at(idx);
+ space_used = sum + current * (count - idx);
+ sum += current;
+ ++idx;
+ }
+ --idx;
+ int deficit = space_used - space_left;
+
+ int items = count - idx;
+ /*
+ * If we truncate all items to "current", we would get "deficit" too many pixels. Therefore, we have to remove
+ * deficit/items from each item bigger than maxval. The actual value to remove is deficitPerItem + remainder/items
+ * "rest" is the accumulated error from using integer arithmetic.
+ */
+ int deficitPerItem = deficit/items;
+ int remainder = deficit % items;
+ int maxval = current - deficitPerItem;
+
+ int rest = 0;
+ for (i = start; i < start + count; i++) {
+ int maxv = maxval;
+ rest += remainder;
+ if (rest >= items) {
+ maxv--;
+ rest-=items;
+ }
+ QLayoutStruct *data = &chain[i];
+ data->size = qMin(data->minimumSize, maxv);
+ data->done = true;
+ }
+ } else if (space < cHint + sumSpacing) {
+ /*
+ Less space than smartSizeHint(), but more than minimumSize.
+ Currently take space equally from each, as in Qt 2.x.
+ Commented-out lines will give more space to stretchier
+ items.
+ */
+ int n = count;
+ int space_left = space - sumSpacing;
+ int overdraft = cHint - space_left;
+
+ // first give to the fixed ones:
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done
+ && data->minimumSize >= data->smartSizeHint()) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->smartSizeHint();
+ // sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ bool finished = n == 0;
+ while (!finished) {
+ finished = true;
+ Fixed64 fp_over = toFixed(overdraft);
+ Fixed64 fp_w = 0;
+
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->done)
+ continue;
+ // if (sumStretch <= 0)
+ fp_w += fp_over / n;
+ // else
+ // fp_w += (fp_over * data->stretch) / sumStretch;
+ int w = fRound(fp_w);
+ data->size = data->smartSizeHint() - w;
+ fp_w -= toFixed(w); // give the difference to the next
+ if (data->size < data->minimumSize) {
+ data->done = true;
+ data->size = data->minimumSize;
+ finished = false;
+ overdraft -= data->smartSizeHint() - data->minimumSize;
+ // sumStretch -= data->stretch;
+ n--;
+ break;
+ }
+ }
+ }
+ } else { // extra space
+ int n = count;
+ int space_left = space - sumSpacing;
+ // first give to the fixed ones, and handle non-expansiveness
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done
+ && (data->maximumSize <= data->smartSizeHint()
+ || (wannaGrow && !data->expansive && data->stretch == 0)
+ || (!allEmptyNonstretch && data->empty &&
+ !data->expansive && data->stretch == 0))) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->size;
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ extraspace = space_left;
+
+ /*
+ Do a trial distribution and calculate how much it is off.
+ If there are more deficit pixels than surplus pixels, give
+ the minimum size items what they need, and repeat.
+ Otherwise give to the maximum size items, and repeat.
+
+ Paul Olav Tvete has a wonderful mathematical proof of the
+ correctness of this principle, but unfortunately this
+ comment is too small to contain it.
+ */
+ int surplus, deficit;
+ do {
+ surplus = deficit = 0;
+ Fixed64 fp_space = toFixed(space_left);
+ Fixed64 fp_w = 0;
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->done)
+ continue;
+ extraspace = 0;
+ if (sumStretch <= 0)
+ fp_w += fp_space / n;
+ else
+ fp_w += (fp_space * data->stretch) / sumStretch;
+ int w = fRound(fp_w);
+ data->size = w;
+ fp_w -= toFixed(w); // give the difference to the next
+ if (w < data->smartSizeHint()) {
+ deficit += data->smartSizeHint() - w;
+ } else if (w > data->maximumSize) {
+ surplus += w - data->maximumSize;
+ }
+ }
+ if (deficit > 0 && surplus <= deficit) {
+ // give to the ones that have too little
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done && data->size < data->smartSizeHint()) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->smartSizeHint();
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+ if (surplus > 0 && surplus >= deficit) {
+ // take from the ones that have too much
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done && data->size > data->maximumSize) {
+ data->size = data->maximumSize;
+ data->done = true;
+ space_left -= data->maximumSize;
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+ } while (n > 0 && surplus != deficit);
+ if (n == 0)
+ extraspace = space_left;
+ }
+
+ /*
+ As a last resort, we distribute the unwanted space equally
+ among the spacers (counting the start and end of the chain). We
+ could, but don't, attempt a sub-pixel allocation of the extra
+ space.
+ */
+ int extra = extraspace / (spacerCount + 2);
+ int p = pos + extra;
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ data->pos = p;
+ p += data->size;
+ if (!data->empty)
+ p += data->effectiveSpacer(spacer) + extra;
+ }
+
+#ifdef QLAYOUT_EXTRA_DEBUG
+ qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos
+ << "space" << space << "spacer" << spacer;
+ for (i = start; i < start + count; ++i) {
+ qDebug() << i << ':' << chain[i].minimumSize << chain[i].smartSizeHint()
+ << chain[i].maximumSize << "stretch" << chain[i].stretch
+ << "empty" << chain[i].empty << "expansive" << chain[i].expansive
+ << "spacing" << chain[i].spacing;
+ qDebug() << "result pos" << chain[i].pos << "size" << chain[i].size;
+ }
+#endif
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy)
+{
+ QSize s(0, 0);
+
+ if (sizePolicy.horizontalPolicy() != QSizePolicy::Ignored) {
+ if (sizePolicy.horizontalPolicy() & QSizePolicy::ShrinkFlag)
+ s.setWidth(minSizeHint.width());
+ else
+ s.setWidth(qMax(sizeHint.width(), minSizeHint.width()));
+ }
+
+ if (sizePolicy.verticalPolicy() != QSizePolicy::Ignored) {
+ if (sizePolicy.verticalPolicy() & QSizePolicy::ShrinkFlag) {
+ s.setHeight(minSizeHint.height());
+ } else {
+ s.setHeight(qMax(sizeHint.height(), minSizeHint.height()));
+ }
+ }
+
+ s = s.boundedTo(maxSize);
+ if (minSize.width() > 0)
+ s.setWidth(minSize.width());
+ if (minSize.height() > 0)
+ s.setHeight(minSize.height());
+
+ return s.expandedTo(QSize(0,0));
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidgetItem *i)
+{
+ QWidget *w = ((QWidgetItem *)i)->widget();
+ return qSmartMinSize(w->sizeHint(), w->minimumSizeHint(),
+ w->minimumSize(), w->maximumSize(),
+ w->sizePolicy());
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidget *w)
+{
+ return qSmartMinSize(w->sizeHint(), w->minimumSizeHint(),
+ w->minimumSize(), w->maximumSize(),
+ w->sizePolicy());
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy, Qt::Alignment align)
+{
+ if (align & Qt::AlignHorizontal_Mask && align & Qt::AlignVertical_Mask)
+ return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
+ QSize s = maxSize;
+ QSize hint = sizeHint.expandedTo(minSize);
+ if (s.width() == QWIDGETSIZE_MAX && !(align & Qt::AlignHorizontal_Mask))
+ if (!(sizePolicy.horizontalPolicy() & QSizePolicy::GrowFlag))
+ s.setWidth(hint.width());
+
+ if (s.height() == QWIDGETSIZE_MAX && !(align & Qt::AlignVertical_Mask))
+ if (!(sizePolicy.verticalPolicy() & QSizePolicy::GrowFlag))
+ s.setHeight(hint.height());
+
+ if (align & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (align & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align)
+{
+ QWidget *w = ((QWidgetItem*)i)->widget();
+
+ return qSmartMaxSize(w->sizeHint().expandedTo(w->minimumSizeHint()), w->minimumSize(), w->maximumSize(),
+ w->sizePolicy(), align);
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align)
+{
+ return qSmartMaxSize(w->sizeHint().expandedTo(w->minimumSizeHint()), w->minimumSize(), w->maximumSize(),
+ w->sizePolicy(), align);
+}
+
+Q_GUI_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm)
+{
+ QObject *parent = layout->parent();
+ if (!parent) {
+ return -1;
+ } else if (parent->isWidgetType()) {
+ QWidget *pw = static_cast<QWidget *>(parent);
+ return pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ return static_cast<QLayout *>(parent)->spacing();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qlayoutengine_p.h b/src/widgets/kernel/qlayoutengine_p.h
new file mode 100644
index 0000000000..da07f3bab1
--- /dev/null
+++ b/src/widgets/kernel/qlayoutengine_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUTENGINE_P_H
+#define QLAYOUTENGINE_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 "QtGui/qlayoutitem.h"
+#include "QtGui/qstyle.h"
+
+QT_BEGIN_NAMESPACE
+
+template <typename T> class QVector;
+
+struct QLayoutStruct
+{
+ inline void init(int stretchFactor = 0, int minSize = 0) {
+ stretch = stretchFactor;
+ minimumSize = sizeHint = minSize;
+ maximumSize = QLAYOUTSIZE_MAX;
+ expansive = false;
+ empty = true;
+ spacing = 0;
+ }
+
+ int smartSizeHint() {
+ return (stretch > 0) ? minimumSize : sizeHint;
+ }
+ int effectiveSpacer(int uniformSpacer) const {
+ Q_ASSERT(uniformSpacer >= 0 || spacing >= 0);
+ return (uniformSpacer >= 0) ? uniformSpacer : spacing;
+ }
+
+ // parameters
+ int stretch;
+ int sizeHint;
+ int maximumSize;
+ int minimumSize;
+ bool expansive;
+ bool empty;
+ int spacing;
+
+ // temporary storage
+ bool done;
+
+ // result
+ int pos;
+ int size;
+};
+
+
+Q_GUI_EXPORT void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
+ int pos, int space, int spacer = -1);
+Q_GUI_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy);
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidgetItem *i);
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidget *w);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy, Qt::Alignment align = 0);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = 0);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = 0);
+
+Q_GUI_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm);
+
+/*
+ Modify total maximum (max), total expansion (exp), and total empty
+ when adding boxmax/boxexp.
+
+ Expansive boxes win over non-expansive boxes.
+ Non-empty boxes win over empty boxes.
+*/
+static inline void qMaxExpCalc(int & max, bool &exp, bool &empty,
+ int boxmax, bool boxexp, bool boxempty)
+{
+ if (exp) {
+ if (boxexp)
+ max = qMax(max, boxmax);
+ } else {
+ if (boxexp || (empty && (!boxempty || max == 0)))
+ max = boxmax;
+ else if (empty == boxempty)
+ max = qMin(max, boxmax);
+ }
+ exp = exp || boxexp;
+ empty = empty && boxempty;
+}
+
+QT_END_NAMESPACE
+
+#endif // QLAYOUTENGINE_P_H
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
new file mode 100644
index 0000000000..aeb96e9ef5
--- /dev/null
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -0,0 +1,834 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+
+#include "qapplication.h"
+#include "qlayoutengine_p.h"
+#include "qmenubar.h"
+#include "qtoolbar.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
+ -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
+}
+
+inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
+ priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
+}
+
+inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+/*!
+ Returns a QVariant storing this QSizePolicy.
+*/
+QSizePolicy::operator QVariant() const
+{
+ return QVariant(QVariant::SizePolicy, this);
+}
+
+/*!
+ \class QLayoutItem
+ \brief The QLayoutItem class provides an abstract item that a
+ QLayout manipulates.
+
+ \ingroup geomanagement
+
+ This is used by custom layouts.
+
+ Pure virtual functions are provided to return information about
+ the layout, including, sizeHint(), minimumSize(), maximumSize()
+ and expanding().
+
+ The layout's geometry can be set and retrieved with setGeometry()
+ and geometry(), and its alignment with setAlignment() and
+ alignment().
+
+ isEmpty() returns whether the layout item is empty. If the
+ concrete item is a QWidget, it can be retrieved using widget().
+ Similarly for layout() and spacerItem().
+
+ Some layouts have width and height interdependencies. These can
+ be expressed using hasHeightForWidth(), heightForWidth(), and
+ minimumHeightForWidth(). For more explanation see the \e{Qt
+ Quarterly} article
+ \l{http://qt.nokia.com/doc/qq/qq04-height-for-width.html}{Trading
+ Height for Width}.
+
+ \sa QLayout
+*/
+
+/*!
+ \class QSpacerItem
+ \ingroup geomanagement
+ \brief The QSpacerItem class provides blank space in a layout.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating empty space in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QHBoxLayout
+ \o \l{QBoxLayout::addSpacing()}{addSpacing()},
+ \l{QBoxLayout::addStretch()}{addStretch()},
+ \l{QBoxLayout::insertSpacing()}{insertSpacing()},
+ \l{QBoxLayout::insertStretch()}{insertStretch()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()},
+ \l{QGridLayout::setRowStretch()}{setRowStretch()},
+ \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()},
+ \l{QGridLayout::setColumnStretch()}{setColumnStretch()}
+ \endtable
+
+ \sa QLayout, QWidgetItem, QLayoutItem::spacerItem()
+*/
+
+/*!
+ \class QWidgetItem
+ \ingroup geomanagement
+ \brief The QWidgetItem class is a layout item that represents a widget.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating widgets in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QBoxLayout
+ \o \l{QBoxLayout::addWidget()}{addWidget()},
+ \l{QBoxLayout::insertWidget()}{insertWidget()},
+ \l{QBoxLayout::setStretchFactor()}{setStretchFactor()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::addWidget()}{addWidget()}
+ \row \o QStackedLayout
+ \o \l{QStackedLayout::addWidget()}{addWidget()},
+ \l{QStackedLayout::insertWidget()}{insertWidget()},
+ \l{QStackedLayout::currentWidget()}{currentWidget()},
+ \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()},
+ \l{QStackedLayout::widget()}{widget()}
+ \endtable
+
+ \sa QLayout, QSpacerItem, QLayoutItem::widget()
+*/
+
+/*!
+ \fn QLayoutItem::QLayoutItem(Qt::Alignment alignment)
+
+ Constructs a layout item with an \a alignment.
+ Not all subclasses support alignment.
+*/
+
+/*!
+ \fn Qt::Alignment QLayoutItem::alignment() const
+
+ Returns the alignment of this item.
+*/
+
+/*!
+ Sets the alignment of this item to \a alignment.
+
+ \bold{Note:} Item alignment is only supported by QLayoutItem subclasses
+ where it would have a visual effect. Except for QSpacerItem, which provides
+ blank space for layouts, all public Qt classes that inherit QLayoutItem
+ support item alignment.
+*/
+void QLayoutItem::setAlignment(Qt::Alignment alignment)
+{
+ align = alignment;
+}
+
+/*!
+ \fn QSize QLayoutItem::maximumSize() const
+
+ Implemented in subclasses to return the maximum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::minimumSize() const
+
+ Implemented in subclasses to return the minimum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::sizeHint() const
+
+ Implemented in subclasses to return the preferred size of this item.
+*/
+
+/*!
+ \fn Qt::Orientations QLayoutItem::expandingDirections() const
+
+ Returns whether this layout item can make use of more space than
+ sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
+ it wants to grow in only one dimension, whereas Qt::Vertical |
+ Qt::Horizontal means that it wants to grow in both dimensions.
+*/
+
+/*!
+ \fn void QLayoutItem::setGeometry(const QRect &r)
+
+ Implemented in subclasses to set this item's geometry to \a r.
+
+ \sa geometry()
+*/
+
+/*!
+ \fn QRect QLayoutItem::geometry() const
+
+ Returns the rectangle covered by this layout item.
+
+ \sa setGeometry()
+*/
+
+/*!
+ \fn virtual bool QLayoutItem::isEmpty() const
+
+ Implemented in subclasses to return whether this item is empty,
+ i.e. whether it contains any widgets.
+*/
+
+/*!
+ \fn QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
+
+ Constructs a spacer item with preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+*/
+
+/*!
+ Changes this spacer item to have preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+
+ Note that if changeSize() is called after the spacer item has been added
+ to a layout, it is necessary to invalidate the layout in order for the
+ spacer item's new size to take effect.
+
+ \sa QSpacerItem::invalidate()
+*/
+void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
+ QSizePolicy::Policy vPolicy)
+{
+ width = w;
+ height = h;
+ sizeP = QSizePolicy(hPolicy, vPolicy);
+}
+
+/*!
+ \fn QWidgetItem::QWidgetItem(QWidget *widget)
+
+ Creates an item containing the given \a widget.
+*/
+
+/*!
+ Destroys the QLayoutItem.
+*/
+QLayoutItem::~QLayoutItem()
+{
+}
+
+/*!
+ Invalidates any cached information in this layout item.
+*/
+void QLayoutItem::invalidate()
+{
+}
+
+/*!
+ If this item is a QLayout, it is returned as a QLayout; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QLayout * QLayoutItem::layout()
+{
+ return 0;
+}
+
+/*!
+ If this item is a QSpacerItem, it is returned as a QSpacerItem;
+ otherwise 0 is returned. This function provides type-safe casting.
+*/
+QSpacerItem * QLayoutItem::spacerItem()
+{
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayout * QLayout::layout()
+{
+ return this;
+}
+
+/*!
+ Returns a pointer to this object.
+*/
+QSpacerItem * QSpacerItem::spacerItem()
+{
+ return this;
+}
+
+/*!
+ If this item is a QWidget, it is returned as a QWidget; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QWidget * QLayoutItem::widget()
+{
+ return 0;
+}
+
+/*!
+ Returns the widget managed by this item.
+*/
+QWidget *QWidgetItem::widget()
+{
+ return wid;
+}
+
+/*!
+ Returns true if this layout's preferred height depends on its
+ width; otherwise returns false. The default implementation returns
+ false.
+
+ Reimplement this function in layout managers that support height
+ for width.
+
+ \sa heightForWidth(), QWidget::heightForWidth()
+*/
+bool QLayoutItem::hasHeightForWidth() const
+{
+ return false;
+}
+
+/*!
+ Returns the minimum height this widget needs for the given width,
+ \a w. The default implementation simply returns heightForWidth(\a
+ w).
+*/
+int QLayoutItem::minimumHeightForWidth(int w) const
+{
+ return heightForWidth(w);
+}
+
+
+/*!
+ Returns the preferred height for this layout item, given the width
+ \a w.
+
+ The default implementation returns -1, indicating that the
+ preferred height is independent of the width of the item. Using
+ the function hasHeightForWidth() will typically be much faster
+ than calling this function and testing for -1.
+
+ Reimplement this function in layout managers that support height
+ for width. A typical implementation will look like this:
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayoutitem.cpp 0
+
+ Caching is strongly recommended; without it layout will take
+ exponential time.
+
+ \sa hasHeightForWidth()
+*/
+int QLayoutItem::heightForWidth(int /* w */) const
+{
+ return -1;
+}
+
+/*!
+ Returns the control type(s) for the layout item. For a
+ QWidgetItem, the control type comes from the widget's size
+ policy; for a QLayoutItem, the control types is derived from the
+ layout's contents.
+
+ \sa QSizePolicy::controlType()
+*/
+QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
+{
+ // ### Qt 5: This function should probably be virtual instead
+ if (const QWidget *widget = const_cast<QLayoutItem*>(this)->widget()) {
+ return widget->sizePolicy().controlType();
+ } else if (const QLayout *layout = const_cast<QLayoutItem*>(this)->layout()) {
+ if (layout->count() == 0)
+ return QSizePolicy::DefaultType;
+ QSizePolicy::ControlTypes types;
+ for (int i = layout->count() - 1; i >= 0; --i)
+ types |= layout->itemAt(i)->controlTypes();
+ return types;
+ }
+ return QSizePolicy::DefaultType;
+}
+
+/*!
+ \reimp
+*/
+void QSpacerItem::setGeometry(const QRect &r)
+{
+ rect = r;
+}
+
+/*!
+ \reimp
+*/
+void QWidgetItem::setGeometry(const QRect &rect)
+{
+ if (isEmpty())
+ return;
+
+ QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemRect(wid->d_func(), rect)
+ : rect;
+ const QSize widgetRectSurplus = r.size() - rect.size();
+
+ /*
+ For historical reasons, this code is done using widget rect
+ coordinates, not layout item rect coordinates. However,
+ QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
+ all work in terms of layout item rect coordinates, so we have to
+ add or subtract widgetRectSurplus here and there. The code could
+ be much simpler if we did everything using layout item rect
+ coordinates and did the conversion right before the call to
+ QWidget::setGeometry().
+ */
+
+ QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
+ int x = r.x();
+ int y = r.y();
+ if (align & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)) {
+ QSize pref(sizeHint());
+ QSizePolicy sp = wid->sizePolicy();
+ if (sp.horizontalPolicy() == QSizePolicy::Ignored)
+ pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
+ if (sp.verticalPolicy() == QSizePolicy::Ignored)
+ pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
+ pref += widgetRectSurplus;
+ if (align & Qt::AlignHorizontal_Mask)
+ s.setWidth(qMin(s.width(), pref.width()));
+ if (align & Qt::AlignVertical_Mask) {
+ if (hasHeightForWidth())
+ s.setHeight(qMin(s.height(),
+ heightForWidth(s.width() - widgetRectSurplus.width())
+ + widgetRectSurplus.height()));
+ else
+ s.setHeight(qMin(s.height(), pref.height()));
+ }
+ }
+ Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
+ if (alignHoriz & Qt::AlignRight)
+ x = x + (r.width() - s.width());
+ else if (!(alignHoriz & Qt::AlignLeft))
+ x = x + (r.width() - s.width()) / 2;
+
+ if (align & Qt::AlignBottom)
+ y = y + (r.height() - s.height());
+ else if (!(align & Qt::AlignTop))
+ y = y + (r.height() - s.height()) / 2;
+
+ wid->setGeometry(x, y, s.width(), s.height());
+}
+
+/*!
+ \reimp
+*/
+QRect QSpacerItem::geometry() const
+{
+ return rect;
+}
+
+/*!
+ \reimp
+*/
+QRect QWidgetItem::geometry() const
+{
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemRect(wid->d_func(), wid->geometry())
+ : wid->geometry();
+}
+
+
+/*!
+ \reimp
+*/
+bool QWidgetItem::hasHeightForWidth() const
+{
+ if (isEmpty())
+ return false;
+ return wid->d_func()->hasHeightForWidth();
+}
+
+/*!
+ \reimp
+*/
+int QWidgetItem::heightForWidth(int w) const
+{
+ if (isEmpty())
+ return -1;
+
+ w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
+ : w;
+
+ int hfw;
+ if (wid->layout())
+ hfw = wid->layout()->totalHeightForWidth(w);
+ else
+ hfw = wid->heightForWidth(w);
+
+ if (hfw > wid->maximumHeight())
+ hfw = wid->maximumHeight();
+ if (hfw < wid->minimumHeight())
+ hfw = wid->minimumHeight();
+
+ hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
+ : hfw;
+
+ if (hfw < 0)
+ hfw = 0;
+ return hfw;
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QSpacerItem::expandingDirections() const
+{
+ return sizeP.expandingDirections();
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QWidgetItem::expandingDirections() const
+{
+ if (isEmpty())
+ return Qt::Orientations(0);
+
+ Qt::Orientations e = wid->sizePolicy().expandingDirections();
+ /*
+ ### Qt 4.0:
+ If the layout is expanding, we make the widget expanding, even if
+ its own size policy isn't expanding. This behavior should be
+ reconsidered.
+ */
+ if (wid->layout()) {
+ if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Horizontal))
+ e |= Qt::Horizontal;
+ if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Vertical))
+ e |= Qt::Vertical;
+ }
+
+ if (align & Qt::AlignHorizontal_Mask)
+ e &= ~Qt::Horizontal;
+ if (align & Qt::AlignVertical_Mask)
+ e &= ~Qt::Vertical;
+ return e;
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::minimumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
+ sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
+ : qSmartMinSize(this);
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::maximumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
+ sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::maximumSize() const
+{
+ if (isEmpty()) {
+ return QSize(0, 0);
+ } else {
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
+ : qSmartMaxSize(this, align);
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::sizeHint() const
+{
+ return QSize(width, height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::sizeHint() const
+{
+ QSize s(0, 0);
+ if (!isEmpty()) {
+ s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
+ s = s.boundedTo(wid->maximumSize())
+ .expandedTo(wid->minimumSize());
+ s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), s)
+ : s;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ s.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ s.setHeight(0);
+ }
+ return s;
+}
+
+/*!
+ Returns true.
+*/
+bool QSpacerItem::isEmpty() const
+{
+ return true;
+}
+
+/*!
+ Returns true if the widget is hidden; otherwise returns false.
+
+ \sa QWidget::isHidden()
+*/
+bool QWidgetItem::isEmpty() const
+{
+ return wid->isHidden() || wid->isWindow();
+}
+
+/*!
+ \class QWidgetItemV2
+ \internal
+*/
+
+inline bool QWidgetItemV2::useSizeCache() const
+{
+ return wid->d_func()->widgetItem == this;
+}
+
+void QWidgetItemV2::updateCacheIfNecessary() const
+{
+ if (q_cachedMinimumSize.width() != Dirty)
+ return;
+
+ const QSize sizeHint(wid->sizeHint());
+ const QSize minimumSizeHint(wid->minimumSizeHint());
+ const QSize minimumSize(wid->minimumSize());
+ const QSize maximumSize(wid->maximumSize());
+ const QSizePolicy sizePolicy(wid->sizePolicy());
+ const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
+
+ const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
+ const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
+
+ const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+ q_cachedMinimumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMinSize)
+ : smartMinSize;
+
+ q_cachedSizeHint = expandedSizeHint;
+ q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
+ .expandedTo(minimumSize);
+ q_cachedSizeHint = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
+ : q_cachedSizeHint;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setHeight(0);
+
+ q_cachedMaximumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMaxSize)
+ : smartMaxSize;
+}
+
+QWidgetItemV2::QWidgetItemV2(QWidget *widget)
+ : QWidgetItem(widget),
+ q_cachedMinimumSize(Dirty, Dirty),
+ q_cachedSizeHint(Dirty, Dirty),
+ q_cachedMaximumSize(Dirty, Dirty),
+ q_firstCachedHfw(0),
+ q_hfwCacheSize(0),
+ d(0)
+{
+ QWidgetPrivate *wd = wid->d_func();
+ if (!wd->widgetItem)
+ wd->widgetItem = this;
+}
+
+QWidgetItemV2::~QWidgetItemV2()
+{
+ if (wid) {
+ QWidgetPrivate *wd = wid->d_func();
+ if (wd->widgetItem == this)
+ wd->widgetItem = 0;
+ }
+}
+
+QSize QWidgetItemV2::sizeHint() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedSizeHint;
+ } else {
+ return QWidgetItem::sizeHint();
+ }
+}
+
+QSize QWidgetItemV2::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMinimumSize;
+ } else {
+ return QWidgetItem::minimumSize();
+ }
+}
+
+QSize QWidgetItemV2::maximumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMaximumSize;
+ } else {
+ return QWidgetItem::maximumSize();
+ }
+}
+
+/*
+ The height-for-width cache is organized as a circular buffer. The entries
+
+ q_hfwCachedHfws[q_firstCachedHfw],
+ ...,
+ q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
+
+ contain the last cached values. When the cache is full, the first entry to
+ be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
+ values are looked up, we try to move q_firstCachedHfw to point to that new
+ entry (unless the cache is not full, in which case it would leave the cache
+ in a broken state), so that the most recently used entry is also the last
+ to be erased.
+*/
+
+int QWidgetItemV2::heightForWidth(int width) const
+{
+ if (isEmpty())
+ return -1;
+
+ for (int i = 0; i < q_hfwCacheSize; ++i) {
+ int offset = q_firstCachedHfw + i;
+ const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
+ if (size.width() == width) {
+ if (q_hfwCacheSize == HfwCacheMaxSize)
+ q_firstCachedHfw = offset;
+ return size.height();
+ }
+ }
+
+ if (q_hfwCacheSize < HfwCacheMaxSize)
+ ++q_hfwCacheSize;
+ q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
+
+ int height = QWidgetItem::heightForWidth(width);
+ q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
+ return height;
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qlayoutitem.h b/src/widgets/kernel/qlayoutitem.h
new file mode 100644
index 0000000000..a75011f3ff
--- /dev/null
+++ b/src/widgets/kernel/qlayoutitem.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUTITEM_H
+#define QLAYOUTITEM_H
+
+#include <QtGui/qsizepolicy.h>
+#include <QtCore/qrect.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+static const int QLAYOUTSIZE_MAX = INT_MAX/256/16;
+
+class QLayout;
+class QLayoutItem;
+class QSpacerItem;
+class QWidget;
+class QSize;
+
+class Q_GUI_EXPORT QLayoutItem
+{
+public:
+ inline explicit QLayoutItem(Qt::Alignment alignment = 0);
+ virtual ~QLayoutItem();
+ virtual QSize sizeHint() const = 0;
+ virtual QSize minimumSize() const = 0;
+ virtual QSize maximumSize() const = 0;
+ virtual Qt::Orientations expandingDirections() const = 0;
+ virtual void setGeometry(const QRect&) = 0;
+ virtual QRect geometry() const = 0;
+ virtual bool isEmpty() const = 0;
+ virtual bool hasHeightForWidth() const;
+ virtual int heightForWidth(int) const;
+ virtual int minimumHeightForWidth(int) const;
+ virtual void invalidate();
+
+ virtual QWidget *widget();
+ virtual QLayout *layout();
+ virtual QSpacerItem *spacerItem();
+
+ Qt::Alignment alignment() const { return align; }
+ void setAlignment(Qt::Alignment a);
+ QSizePolicy::ControlTypes controlTypes() const;
+
+protected:
+ Qt::Alignment align;
+};
+
+inline QLayoutItem::QLayoutItem(Qt::Alignment aalignment)
+ : align(aalignment) { }
+
+class Q_GUI_EXPORT QSpacerItem : public QLayoutItem
+{
+public:
+ QSpacerItem(int w, int h,
+ QSizePolicy::Policy hData = QSizePolicy::Minimum,
+ QSizePolicy::Policy vData = QSizePolicy::Minimum)
+ : width(w), height(h), sizeP(hData, vData) { }
+ void changeSize(int w, int h,
+ QSizePolicy::Policy hData = QSizePolicy::Minimum,
+ QSizePolicy::Policy vData = QSizePolicy::Minimum);
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ Qt::Orientations expandingDirections() const;
+ bool isEmpty() const;
+ void setGeometry(const QRect&);
+ QRect geometry() const;
+ QSpacerItem *spacerItem();
+
+private:
+ int width;
+ int height;
+ QSizePolicy sizeP;
+ QRect rect;
+};
+
+class Q_GUI_EXPORT QWidgetItem : public QLayoutItem
+{
+ Q_DISABLE_COPY(QWidgetItem)
+
+public:
+ explicit QWidgetItem(QWidget *w) : wid(w) { }
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ Qt::Orientations expandingDirections() const;
+ bool isEmpty() const;
+ void setGeometry(const QRect&);
+ QRect geometry() const;
+ virtual QWidget *widget();
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+
+protected:
+ QWidget *wid;
+};
+
+class Q_GUI_EXPORT QWidgetItemV2 : public QWidgetItem
+{
+public:
+ explicit QWidgetItemV2(QWidget *widget);
+ ~QWidgetItemV2();
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ int heightForWidth(int width) const;
+
+private:
+ enum { Dirty = -123, HfwCacheMaxSize = 3 };
+
+ inline bool useSizeCache() const;
+ void updateCacheIfNecessary() const;
+ inline void invalidateSizeCache() {
+ q_cachedMinimumSize.setWidth(Dirty);
+ q_hfwCacheSize = 0;
+ }
+
+ mutable QSize q_cachedMinimumSize;
+ mutable QSize q_cachedSizeHint;
+ mutable QSize q_cachedMaximumSize;
+ mutable QSize q_cachedHfws[HfwCacheMaxSize];
+ mutable short q_firstCachedHfw;
+ mutable short q_hfwCacheSize;
+ void *d;
+
+ friend class QWidgetPrivate;
+
+ Q_DISABLE_COPY(QWidgetItemV2)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLAYOUTITEM_H
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
new file mode 100644
index 0000000000..c0a8cc1f18
--- /dev/null
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIZEPOLICY_H
+#define QSIZEPOLICY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVariant;
+
+class Q_GUI_EXPORT QSizePolicy
+{
+ Q_GADGET
+ Q_ENUMS(Policy)
+
+private:
+ enum SizePolicyMasks {
+ HSize = 4,
+ HMask = 0x0f,
+ VMask = HMask << HSize,
+ CTShift = 9,
+ CTSize = 5,
+ CTMask = ((0x1 << CTSize) - 1) << CTShift,
+ WFHShift = CTShift + CTSize,
+ UnusedShift = WFHShift + 1,
+ UnusedSize = 1
+ };
+
+public:
+ enum PolicyFlag {
+ GrowFlag = 1,
+ ExpandFlag = 2,
+ ShrinkFlag = 4,
+ IgnoreFlag = 8
+ };
+
+ enum Policy {
+ Fixed = 0,
+ Minimum = GrowFlag,
+ Maximum = ShrinkFlag,
+ Preferred = GrowFlag | ShrinkFlag,
+ MinimumExpanding = GrowFlag | ExpandFlag,
+ Expanding = GrowFlag | ShrinkFlag | ExpandFlag,
+ Ignored = ShrinkFlag | GrowFlag | IgnoreFlag
+ };
+
+ enum ControlType {
+ DefaultType = 0x00000001,
+ ButtonBox = 0x00000002,
+ CheckBox = 0x00000004,
+ ComboBox = 0x00000008,
+ Frame = 0x00000010,
+ GroupBox = 0x00000020,
+ Label = 0x00000040,
+ Line = 0x00000080,
+ LineEdit = 0x00000100,
+ PushButton = 0x00000200,
+ RadioButton = 0x00000400,
+ Slider = 0x00000800,
+ SpinBox = 0x00001000,
+ TabWidget = 0x00002000,
+ ToolButton = 0x00004000
+ };
+ Q_DECLARE_FLAGS(ControlTypes, ControlType)
+
+ QSizePolicy() : data(0) { }
+
+ // ### Qt 5: merge these two constructors (with type == DefaultType)
+ QSizePolicy(Policy horizontal, Policy vertical)
+ : data(horizontal | (vertical << HSize)) { }
+ QSizePolicy(Policy horizontal, Policy vertical, ControlType type)
+ : data(horizontal | (vertical << HSize)) { setControlType(type); }
+
+ Policy horizontalPolicy() const { return static_cast<Policy>(data & HMask); }
+ Policy verticalPolicy() const { return static_cast<Policy>((data & VMask) >> HSize); }
+ ControlType controlType() const;
+
+ void setHorizontalPolicy(Policy d) { data = (data & ~HMask) | d; }
+ void setVerticalPolicy(Policy d) { data = (data & ~(HMask << HSize)) | (d << HSize); }
+ void setControlType(ControlType type);
+
+ Qt::Orientations expandingDirections() const {
+ Qt::Orientations result;
+ if (verticalPolicy() & ExpandFlag)
+ result |= Qt::Vertical;
+ if (horizontalPolicy() & ExpandFlag)
+ result |= Qt::Horizontal;
+ return result;
+ }
+
+ void setHeightForWidth(bool b) { data = b ? (data | (1 << 2*HSize)) : (data & ~(1 << 2*HSize)); }
+ bool hasHeightForWidth() const { return data & (1 << 2*HSize); }
+ void setWidthForHeight(bool b) { data = b ? (data | (1 << (WFHShift))) : (data & ~(1 << (WFHShift))); }
+ bool hasWidthForHeight() const { return data & (1 << (WFHShift)); }
+
+ bool operator==(const QSizePolicy& s) const { return data == s.data; }
+ bool operator!=(const QSizePolicy& s) const { return data != s.data; }
+ operator QVariant() const; // implemented in qabstractlayout.cpp
+
+ int horizontalStretch() const { return data >> 24; }
+ int verticalStretch() const { return (data >> 16) & 0xff; }
+ void setHorizontalStretch(uchar stretchFactor) { data = (data&0x00ffffff) | (uint(stretchFactor)<<24); }
+ void setVerticalStretch(uchar stretchFactor) { data = (data&0xff00ffff) | (uint(stretchFactor)<<16); }
+
+ void transpose();
+
+#ifdef QT3_SUPPORT
+ typedef Policy SizeType;
+#ifndef qdoc
+ typedef Qt::Orientations ExpandData;
+ enum {
+ NoDirection = 0,
+ Horizontally = 1,
+ Vertically = 2,
+ BothDirections = Horizontally | Vertically
+ };
+#else
+ enum ExpandData {
+ NoDirection = 0x0,
+ Horizontally = 0x1,
+ Vertically = 0x2,
+ BothDirections = 0x3
+ };
+#endif // qdoc
+
+ inline QT3_SUPPORT bool mayShrinkHorizontally() const
+ { return horizontalPolicy() & ShrinkFlag; }
+ inline QT3_SUPPORT bool mayShrinkVertically() const { return verticalPolicy() & ShrinkFlag; }
+ inline QT3_SUPPORT bool mayGrowHorizontally() const { return horizontalPolicy() & GrowFlag; }
+ inline QT3_SUPPORT bool mayGrowVertically() const { return verticalPolicy() & GrowFlag; }
+ inline QT3_SUPPORT Qt::Orientations expanding() const { return expandingDirections(); }
+
+ QT3_SUPPORT_CONSTRUCTOR QSizePolicy(Policy hor, Policy ver, bool hfw)
+ : data(hor | (ver<<HSize) | (hfw ? (1U<<2*HSize) : 0)) { }
+
+ QT3_SUPPORT_CONSTRUCTOR QSizePolicy(Policy hor, Policy ver, uchar hors, uchar vers, bool hfw = false)
+ : data(hor | (ver<<HSize) | (hfw ? (1U<<2*HSize) : 0)) {
+ setHorizontalStretch(hors);
+ setVerticalStretch(vers);
+ }
+
+ inline QT3_SUPPORT Policy horData() const { return static_cast<Policy>(data & HMask); }
+ inline QT3_SUPPORT Policy verData() const { return static_cast<Policy>((data & VMask) >> HSize); }
+ inline QT3_SUPPORT void setHorData(Policy d) { setHorizontalPolicy(d); }
+ inline QT3_SUPPORT void setVerData(Policy d) { setVerticalPolicy(d); }
+
+ inline QT3_SUPPORT uint horStretch() const { return horizontalStretch(); }
+ inline QT3_SUPPORT uint verStretch() const { return verticalStretch(); }
+ inline QT3_SUPPORT void setHorStretch(uchar sf) { setHorizontalStretch(sf); }
+ inline QT3_SUPPORT void setVerStretch(uchar sf) { setVerticalStretch(sf); }
+#endif
+
+private:
+#ifndef QT_NO_DATASTREAM
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+#endif
+ QSizePolicy(int i) : data(i) { }
+
+ quint32 data;
+/* Qt5: Use bit flags instead, keep it here for improved readability for now.
+ We can maybe change it for Qt4, but we'd have to be careful, since the behaviour
+ is implementation defined. It usually varies between little- and big-endian compilers, but
+ it might also not vary.
+ quint32 horzPolicy : 4;
+ quint32 vertPolicy : 4;
+ quint32 hfw : 1;
+ quint32 ctype : 5;
+ quint32 wfh : 1;
+ quint32 padding : 1; // we cannot use the highest bit
+ quint32 verStretch : 8;
+ quint32 horStretch : 8;
+*/
+
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
+
+#ifndef QT_NO_DATASTREAM
+// implemented in qlayout.cpp
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+#endif
+
+inline void QSizePolicy::transpose() {
+ Policy hData = horizontalPolicy();
+ Policy vData = verticalPolicy();
+ uchar hStretch = uchar(horizontalStretch());
+ uchar vStretch = uchar(verticalStretch());
+ setHorizontalPolicy(vData);
+ setVerticalPolicy(hData);
+ setHorizontalStretch(vStretch);
+ setVerticalStretch(hStretch);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIZEPOLICY_H
diff --git a/src/widgets/kernel/qsizepolicy.qdoc b/src/widgets/kernel/qsizepolicy.qdoc
new file mode 100644
index 0000000000..80e9f20f74
--- /dev/null
+++ b/src/widgets/kernel/qsizepolicy.qdoc
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSizePolicy
+ \brief The QSizePolicy class is a layout attribute describing horizontal
+ and vertical resizing policy.
+
+ \ingroup geomanagement
+
+ The size policy of a widget is an expression of its willingness to
+ be resized in various ways, and affects how the widget is treated
+ by the \l{Layout Management}{layout engine}. Each widget returns a
+ QSizePolicy that describes the horizontal and vertical resizing
+ policy it prefers when being laid out. You can change this for
+ a specific widget by changing its QWidget::sizePolicy property.
+
+ QSizePolicy contains two independent QSizePolicy::Policy values
+ and two stretch factors; one describes the widgets's horizontal
+ size policy, and the other describes its vertical size policy. It
+ also contains a flag to indicate whether the height and width of
+ its preferred size are related.
+
+ The horizontal and vertical policies can be set in the
+ constructor, and altered using the setHorizontalPolicy() and
+ setVerticalPolicy() functions. The stretch factors can be set
+ using the setHorizontalStretch() and setVerticalStretch()
+ functions. The flag indicating whether the widget's
+ \l{QWidget::sizeHint()}{sizeHint()} is width-dependent (such as a
+ menu bar or a word-wrapping label) can be set using the
+ setHeightForWidth() function.
+
+ The current size policies and stretch factors be retrieved using
+ the horizontalPolicy(), verticalPolicy(), horizontalStretch() and
+ verticalStretch() functions. Alternatively, use the transpose()
+ function to swap the horizontal and vertical policies and
+ stretches. The hasHeightForWidth() function returns the current
+ status of the flag indicating the size hint dependencies.
+
+ Use the expandingDirections() function to determine whether the
+ associated widget can make use of more space than its
+ \l{QWidget::sizeHint()}{sizeHint()} function indicates, as well as
+ find out in which directions it can expand.
+
+ Finally, the QSizePolicy class provides operators comparing this
+ size policy to a given policy, as well as a QVariant operator
+ storing this QSizePolicy as a QVariant object.
+
+ \sa QSize, QWidget::sizeHint(), QWidget::sizePolicy,
+ QLayoutItem::sizeHint()
+*/
+
+/*!
+ \enum QSizePolicy::PolicyFlag
+
+ These flags are combined together to form the various \l{Policy}
+ values:
+
+ \value GrowFlag The widget can grow beyond its size hint if necessary.
+ \value ExpandFlag The widget should get as much space as possible.
+ \value ShrinkFlag The widget can shrink below its size hint if necessary.
+ \value IgnoreFlag The widget's size hint is ignored. The widget will get
+ as much space as possible.
+
+ \sa Policy
+*/
+
+/*!
+ \enum QSizePolicy::Policy
+
+ This enum describes the various per-dimension sizing types used
+ when constructing a QSizePolicy.
+
+ \value Fixed The QWidget::sizeHint() is the only acceptable
+ alternative, so the widget can never grow or shrink (e.g. the
+ vertical direction of a push button).
+
+ \value Minimum The sizeHint() is minimal, and sufficient. The
+ widget can be expanded, but there is no advantage to it being
+ larger (e.g. the horizontal direction of a push button).
+ It cannot be smaller than the size provided by sizeHint().
+
+ \value Maximum The sizeHint() is a maximum. The widget can be
+ shrunk any amount without detriment if other widgets need the
+ space (e.g. a separator line).
+ It cannot be larger than the size provided by sizeHint().
+
+ \value Preferred The sizeHint() is best, but the widget can be
+ shrunk and still be useful. The widget can be expanded, but there
+ is no advantage to it being larger than sizeHint() (the default
+ QWidget policy).
+
+ \value Expanding The sizeHint() is a sensible size, but the
+ widget can be shrunk and still be useful. The widget can make use
+ of extra space, so it should get as much space as possible (e.g.
+ the horizontal direction of a horizontal slider).
+
+ \value MinimumExpanding The sizeHint() is minimal, and sufficient.
+ The widget can make use of extra space, so it should get as much
+ space as possible (e.g. the horizontal direction of a horizontal
+ slider).
+
+ \value Ignored The sizeHint() is ignored. The widget will get as
+ much space as possible.
+
+ \sa PolicyFlag, setHorizontalPolicy(), setVerticalPolicy()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy()
+
+ Constructs a QSizePolicy object with \l Fixed as its horizontal
+ and vertical policies.
+
+ The policies can be altered using the setHorizontalPolicy() and
+ setVerticalPolicy() functions. Use the setHeightForWidth()
+ function if the preferred height of the widget is dependent on the
+ width of the widget (for example, a QLabel with line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical)
+
+ Constructs a QSizePolicy object with the given \a horizontal and
+ \a vertical policies, and DefaultType as the control type.
+
+ Use setHeightForWidth() if the preferred height of the widget is
+ dependent on the width of the widget (for example, a QLabel with
+ line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, ControlType type)
+ \since 4.3
+
+ Constructs a QSizePolicy object with the given \a horizontal and
+ \a vertical policies, and the specified control \a type.
+
+ Use setHeightForWidth() if the preferred height of the widget is
+ dependent on the width of the widget (for example, a QLabel with
+ line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch(), controlType()
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::horizontalPolicy() const
+
+ Returns the horizontal component of the size policy.
+
+ \sa setHorizontalPolicy(), verticalPolicy(), horizontalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::verticalPolicy() const
+
+ Returns the vertical component of the size policy.
+
+ \sa setVerticalPolicy(), horizontalPolicy(), verticalStretch()
+*/
+
+/*!
+ \fn void QSizePolicy::setHorizontalPolicy(Policy policy)
+
+ Sets the horizontal component to the given \a policy.
+
+ \sa horizontalPolicy(), setVerticalPolicy(), setHorizontalStretch()
+*/
+
+/*!
+ \fn void QSizePolicy::setVerticalPolicy(Policy policy)
+
+ Sets the vertical component to the given \a policy.
+
+ \sa verticalPolicy(), setHorizontalPolicy(), setVerticalStretch()
+*/
+
+/*!
+ \fn Qt::Orientations QSizePolicy::expandingDirections() const
+
+ Returns whether a widget can make use of more space than the
+ QWidget::sizeHint() function indicates.
+
+ A value of Qt::Horizontal or Qt::Vertical means that the widget
+ can grow horizontally or vertically (i.e., the horizontal or
+ vertical policy is \l Expanding or \l MinimumExpanding), whereas
+ Qt::Horizontal | Qt::Vertical means that it can grow in both
+ dimensions.
+
+ \sa horizontalPolicy(), verticalPolicy()
+*/
+
+/*!
+ \fn ControlType QSizePolicy::controlType() const
+ \since 4.3
+
+ Returns the control type associated with the widget for which
+ this size policy applies.
+*/
+
+/*!
+ \fn void QSizePolicy::setControlType(ControlType type)
+ \since 4.3
+
+ Sets the control type associated with the widget for which this
+ size policy applies to \a type.
+
+ The control type specifies the type of the widget for which this
+ size policy applies. It is used by some styles, notably
+ QMacStyle, to insert proper spacing between widgets. For example,
+ the Mac OS X Aqua guidelines specify that push buttons should be
+ separated by 12 pixels, whereas vertically stacked radio buttons
+ only require 6 pixels.
+
+ \sa QStyle::layoutSpacing()
+*/
+
+/*!
+ \fn void QSizePolicy::setHeightForWidth(bool dependent)
+
+ Sets the flag determining whether the widget's preferred height
+ depends on its width, to \a dependent.
+
+ \sa hasHeightForWidth(), setWidthForHeight()
+*/
+
+/*!
+ \fn bool QSizePolicy::hasHeightForWidth() const
+
+ Returns true if the widget's preferred height depends on its
+ width; otherwise returns false.
+
+ \sa setHeightForWidth()
+*/
+
+/*!
+ \fn void QSizePolicy::setWidthForHeight(bool dependent)
+
+ Sets the flag determining whether the widget's width
+ depends on its height, to \a dependent.
+
+ This is only supported for QGraphicsLayout's subclasses.
+ It is not possible to have a layout with both height-for-width
+ and width-for-height constraints at the same time.
+
+ \sa hasWidthForHeight(), setHeightForWidth()
+*/
+
+/*!
+ \fn bool QSizePolicy::hasWidthForHeight() const
+
+ Returns true if the widget's width depends on its
+ height; otherwise returns false.
+
+ \sa setWidthForHeight()
+*/
+
+/*!
+ \fn bool QSizePolicy::operator==(const QSizePolicy &other) const
+
+ Returns true if this policy is equal to \a other; otherwise
+ returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSizePolicy::operator!=(const QSizePolicy &other) const
+
+ Returns true if this policy is different from \a other; otherwise
+ returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn int QSizePolicy::horizontalStretch() const
+
+ Returns the horizontal stretch factor of the size policy.
+
+ \sa setHorizontalStretch(), verticalStretch(), horizontalPolicy()
+*/
+
+/*!
+ \fn int QSizePolicy::verticalStretch() const
+
+ Returns the vertical stretch factor of the size policy.
+
+ \sa setVerticalStretch(), horizontalStretch(), verticalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::setHorizontalStretch(uchar stretchFactor)
+
+ Sets the horizontal stretch factor of the size policy to the given \a
+ stretchFactor.
+
+ \sa horizontalStretch(), setVerticalStretch(), setHorizontalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::setVerticalStretch(uchar stretchFactor)
+
+ Sets the vertical stretch factor of the size policy to the given
+ \a stretchFactor.
+
+ \sa verticalStretch(), setHorizontalStretch(), setVerticalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::transpose()
+
+ Swaps the horizontal and vertical policies and stretches.
+*/
+
+/*!
+ \enum QSizePolicy::ControlType
+ \since 4.3
+
+ This enum specifies the different types of widgets in terms of
+ layout interaction:
+
+ \value DefaultType The default type, when none is specified.
+ \value ButtonBox A QDialogButtonBox instance.
+ \value CheckBox A QCheckBox instance.
+ \value ComboBox A QComboBox instance.
+ \value Frame A QFrame instance.
+ \value GroupBox A QGroupBox instance.
+ \value Label A QLabel instance.
+ \value Line A QFrame instance with QFrame::HLine or QFrame::VLine.
+ \value LineEdit A QLineEdit instance.
+ \value PushButton A QPushButton instance.
+ \value RadioButton A QRadioButton instance.
+ \value Slider A QAbstractSlider instance.
+ \value SpinBox A QAbstractSpinBox instance.
+ \value TabWidget A QTabWidget instance.
+ \value ToolButton A QToolButton instance.
+
+ \sa setControlType(), controlType()
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ \typedef QSizePolicy::SizeType
+ \compat
+
+ Use the QSizePolicy::Policy enum instead.
+*/
+
+/*!
+ \enum QSizePolicy::ExpandData
+ \compat
+
+ Use the Qt::Orientations enum instead.
+
+ \value NoDirection Use 0 instead.
+ \value Horizontally Use Qt::Horizontal instead.
+ \value Vertically Use Qt::Vertical instead.
+ \value BothDirections Use Qt::Horizontal | Qt::Vertical instead.
+*/
+
+/*!
+ \fn bool QSizePolicy::mayShrinkHorizontally() const
+
+ Use the horizontalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayShrinkHorizontally();
+ \newcode
+ bool policy = horizontalPolicy() & QSizePolicy::ShrinkFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayShrinkVertically() const
+
+ Use the verticalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayShrinkVertically();
+ \newcode
+ bool policy = verticalPolicy() & QSizePolicy::ShrinkFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayGrowHorizontally() const
+
+ Use the horizontalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayGrowHorizontally();
+ \newcode
+ bool policy = horizontalPolicy() & QSizePolicy::GrowFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayGrowVertically() const
+
+ Use the verticalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayGrowVertically();
+ \newcode
+ bool policy = verticalPolicy() & QSizePolicy::GrowFlag;
+ \endcode
+*/
+
+/*!
+ \fn Qt::QSizePolicy::Orientations QSizePolicy::expanding() const
+
+ Use expandingDirections() instead.
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, bool dependent)
+
+ Use the QSizePolicy() constructor and the setHeightForWidth()
+ function instead.
+
+ \oldcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical, dependent);
+ \newcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical);
+ policy->setHeightForWidth(dependent);
+ \endcode
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, uchar horizontalStretch,
+ uchar verticalStretch, bool dependent)
+
+ Use the QSizePolicy() constructor and call the
+ setHorizontalStretch(), setVerticalStretch(), and
+ setHeightForWidth() functions instead.
+
+ \oldcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical,
+ horizontalStretch, verticalStretch,
+ dependent);
+ \newcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical);
+ policy->setHorizontalStretch(horizontalStretch);
+ policy->setVerticalStretch(verticalStretch);
+ policy->setHeightForWidth(dependent);
+ \endcode
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::horData() const
+
+ Use horizontalPolicy() instead.
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::verData() const
+
+ Use verticalPolicy() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setHorData(Policy policy)
+
+ Use setHorizontalPolicy() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setVerData(Policy policy)
+
+ Use setVerticalPolicy() instead.
+*/
+
+/*!
+ \fn uint QSizePolicy::horStretch() const
+
+ Use horizontalStretch() instead.
+*/
+
+/*!
+ \fn uint QSizePolicy::verStretch() const
+
+ Use verticalStretch() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setHorStretch(uchar stretch)
+
+ Use setHorizontalStretch() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setVerStretch(uchar stretch)
+
+ Use setVerticalStretch() instead.
+*/
+#endif
diff --git a/src/widgets/kernel/qsoftkeymanager.cpp b/src/widgets/kernel/qsoftkeymanager.cpp
new file mode 100644
index 0000000000..204efe9ee9
--- /dev/null
+++ b/src/widgets/kernel/qsoftkeymanager.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qevent.h"
+#include "qbitmap.h"
+#include "private/qsoftkeymanager_p.h"
+#include "private/qaction_p.h"
+#include "private/qsoftkeymanager_common_p.h"
+
+#ifdef Q_WS_S60
+#include "private/qsoftkeymanager_s60_p.h"
+#endif
+
+#ifdef SYMBIAN_VERSION_SYMBIAN3
+#include "private/qt_s60_p.h"
+#endif
+
+#ifndef QT_NO_SOFTKEYMANAGER
+QT_BEGIN_NAMESPACE
+
+QSoftKeyManager *QSoftKeyManagerPrivate::self = 0;
+
+QString QSoftKeyManager::standardSoftKeyText(StandardSoftKey standardKey)
+{
+ QString softKeyText;
+ switch (standardKey) {
+ case OkSoftKey:
+ softKeyText = QSoftKeyManager::tr("Ok");
+ break;
+ case SelectSoftKey:
+ softKeyText = QSoftKeyManager::tr("Select");
+ break;
+ case DoneSoftKey:
+ softKeyText = QSoftKeyManager::tr("Done");
+ break;
+ case MenuSoftKey:
+ softKeyText = QSoftKeyManager::tr("Options");
+ break;
+ case CancelSoftKey:
+ softKeyText = QSoftKeyManager::tr("Cancel");
+ break;
+ default:
+ break;
+ };
+
+ return softKeyText;
+}
+
+QSoftKeyManager *QSoftKeyManager::instance()
+{
+ if (!QSoftKeyManagerPrivate::self)
+ QSoftKeyManagerPrivate::self = new QSoftKeyManager;
+
+ return QSoftKeyManagerPrivate::self;
+}
+
+QSoftKeyManager::QSoftKeyManager() :
+#ifdef Q_WS_S60
+ QObject(*(new QSoftKeyManagerPrivateS60), 0)
+#else
+ QObject(*(new QSoftKeyManagerPrivate), 0)
+#endif
+{
+}
+
+QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget)
+{
+ QAction *action = new QAction(standardSoftKeyText(standardKey), actionWidget);
+#ifdef SYMBIAN_VERSION_SYMBIAN3
+ int key = 0;
+ switch (standardKey) {
+ case OkSoftKey:
+ key = EAknSoftkeyOk;
+ break;
+ case SelectSoftKey:
+ key = EAknSoftkeySelect;
+ break;
+ case DoneSoftKey:
+ key = EAknSoftkeyDone;
+ break;
+ case MenuSoftKey:
+ key = EAknSoftkeyOptions;
+ break;
+ case CancelSoftKey:
+ key = EAknSoftkeyCancel;
+ break;
+ default:
+ break;
+ };
+ if (key != 0)
+ QSoftKeyManager::instance()->d_func()->softKeyCommandActions.insert(action, key);
+#endif
+ QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey;
+ switch (standardKey) {
+ case MenuSoftKey: // FALL-THROUGH
+ QActionPrivate::get(action)->menuActionSoftkeys = true;
+ case OkSoftKey:
+ case SelectSoftKey:
+ case DoneSoftKey:
+ softKeyRole = QAction::PositiveSoftKey;
+ break;
+ case CancelSoftKey:
+ softKeyRole = QAction::NegativeSoftKey;
+ break;
+ }
+ action->setSoftKeyRole(softKeyRole);
+ action->setVisible(false);
+ setForceEnabledInSoftkeys(action);
+ return action;
+}
+
+/*! \internal
+
+ Creates a QAction and registers the 'triggered' signal to send the given key event to
+ \a actionWidget as a convenience.
+
+*/
+QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget)
+{
+#ifndef QT_NO_ACTION
+ QScopedPointer<QAction> action(createAction(standardKey, actionWidget));
+
+ connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent()));
+ connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*)));
+ QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key);
+ return action.take();
+#endif //QT_NO_ACTION
+}
+
+void QSoftKeyManager::cleanupHash(QObject *obj)
+{
+ Q_D(QSoftKeyManager);
+ QAction *action = qobject_cast<QAction*>(obj);
+ d->keyedActions.remove(action);
+#ifdef SYMBIAN_VERSION_SYMBIAN3
+ d->softKeyCommandActions.remove(action);
+#endif
+}
+
+void QSoftKeyManager::sendKeyEvent()
+{
+ Q_D(QSoftKeyManager);
+ QAction *action = qobject_cast<QAction*>(sender());
+
+ if (!action)
+ return;
+
+ Qt::Key keyToSend = d->keyedActions.value(action, Qt::Key_unknown);
+
+ if (keyToSend != Qt::Key_unknown)
+ QApplication::postEvent(action->parentWidget(),
+ new QKeyEvent(QEvent::KeyPress, keyToSend, Qt::NoModifier));
+}
+
+void QSoftKeyManager::updateSoftKeys()
+{
+ QSoftKeyManager::instance()->d_func()->pendingUpdate = true;
+ QEvent *event = new QEvent(QEvent::UpdateSoftKeys);
+ QApplication::postEvent(QSoftKeyManager::instance(), event);
+}
+
+bool QSoftKeyManager::appendSoftkeys(const QWidget &source, int level)
+{
+ Q_D(QSoftKeyManager);
+ bool ret = false;
+ foreach(QAction *action, source.actions()) {
+ if (action->softKeyRole() != QAction::NoSoftKey
+ && (action->isVisible() || isForceEnabledInSofkeys(action))) {
+ d->requestedSoftKeyActions.insert(level, action);
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+
+static bool isChildOf(const QWidget *c, const QWidget *p)
+{
+ while (c) {
+ if (c == p)
+ return true;
+ c = c->parentWidget();
+ }
+ return false;
+}
+
+QWidget *QSoftKeyManager::softkeySource(QWidget *previousSource, bool& recursiveMerging)
+{
+ Q_D(QSoftKeyManager);
+ QWidget *source = NULL;
+ if (!previousSource) {
+ // Initial source is primarily focuswidget and secondarily activeWindow
+ QWidget *focus = QApplication::focusWidget();
+ QWidget *popup = QApplication::activePopupWidget();
+ if (popup) {
+ if (isChildOf(focus, popup))
+ source = focus;
+ else
+ source = popup;
+ }
+ if (!source) {
+ QWidget *modal = QApplication::activeModalWidget();
+ if (modal) {
+ if (isChildOf(focus, modal))
+ source = focus;
+ else
+ source = modal;
+ }
+ }
+ if (!source) {
+ source = focus;
+ if (!source)
+ source = QApplication::activeWindow();
+ }
+ } else {
+ // Softkey merging is based on four criterias
+ // 1. Implicit merging is used whenever focus widget does not specify any softkeys
+ bool implicitMerging = d->requestedSoftKeyActions.isEmpty();
+ // 2. Explicit merging with parent is used whenever WA_MergeSoftkeys widget attribute is set
+ bool explicitMerging = previousSource->testAttribute(Qt::WA_MergeSoftkeys);
+ // 3. Explicit merging with all parents
+ recursiveMerging |= previousSource->testAttribute(Qt::WA_MergeSoftkeysRecursively);
+ // 4. Implicit and explicit merging always stops at window boundary
+ bool merging = (implicitMerging || explicitMerging || recursiveMerging) && !previousSource->isWindow();
+
+ source = merging ? previousSource->parentWidget() : NULL;
+ }
+ return source;
+}
+
+bool QSoftKeyManager::handleUpdateSoftKeys()
+{
+ Q_D(QSoftKeyManager);
+ int level = 0;
+ d->requestedSoftKeyActions.clear();
+ bool recursiveMerging = false;
+ QWidget *source = softkeySource(NULL, recursiveMerging);
+ d->initialSoftKeySource = source;
+ while (source) {
+ if (appendSoftkeys(*source, level))
+ ++level;
+ source = softkeySource(source, recursiveMerging);
+ }
+
+ d->updateSoftKeys_sys();
+ d->pendingUpdate = false;
+ return true;
+}
+
+void QSoftKeyManager::setForceEnabledInSoftkeys(QAction *action)
+{
+ QActionPrivate::get(action)->forceEnabledInSoftkeys = true;
+}
+
+bool QSoftKeyManager::isForceEnabledInSofkeys(QAction *action)
+{
+ return QActionPrivate::get(action)->forceEnabledInSoftkeys;
+}
+
+bool QSoftKeyManager::event(QEvent *e)
+{
+#ifndef QT_NO_ACTION
+ if (e->type() == QEvent::UpdateSoftKeys)
+ return handleUpdateSoftKeys();
+#endif //QT_NO_ACTION
+ return false;
+}
+
+#ifdef Q_WS_S60
+bool QSoftKeyManager::handleCommand(int command)
+{
+ if (QSoftKeyManager::instance()->d_func()->pendingUpdate)
+ (void)QSoftKeyManager::instance()->handleUpdateSoftKeys();
+
+ return static_cast<QSoftKeyManagerPrivateS60*>(QSoftKeyManager::instance()->d_func())->handleCommand(command);
+}
+#endif
+
+QT_END_NAMESPACE
+#endif //QT_NO_SOFTKEYMANAGER
diff --git a/src/widgets/kernel/qsoftkeymanager_common_p.h b/src/widgets/kernel/qsoftkeymanager_common_p.h
new file mode 100644
index 0000000000..02ae697eef
--- /dev/null
+++ b/src/widgets/kernel/qsoftkeymanager_common_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOFTKEYMANAGER_COMMON_P_H
+#define QSOFTKEYMANAGER_COMMON_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.
+//
+
+QT_BEGIN_HEADER
+
+#ifndef QT_NO_SOFTKEYMANAGER
+
+QT_BEGIN_NAMESPACE
+
+class QSoftKeyManagerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSoftKeyManager)
+
+public:
+ virtual void updateSoftKeys_sys() {};
+
+protected:
+ static QSoftKeyManager *self;
+ QHash<QAction*, Qt::Key> keyedActions;
+ QMultiHash<int, QAction*> requestedSoftKeyActions;
+ QWidget *initialSoftKeySource;
+ bool pendingUpdate;
+#ifdef SYMBIAN_VERSION_SYMBIAN3
+ QHash<QAction*, int> softKeyCommandActions;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_SOFTKEYMANAGER
+
+QT_END_HEADER
+
+#endif // QSOFTKEYMANAGER_COMMON_P_H
diff --git a/src/widgets/kernel/qsoftkeymanager_p.h b/src/widgets/kernel/qsoftkeymanager_p.h
new file mode 100644
index 0000000000..78999a97bd
--- /dev/null
+++ b/src/widgets/kernel/qsoftkeymanager_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOFTKEYMANAGER_P_H
+#define QSOFTKEYMANAGER_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 <QtCore/qobject.h>
+#include "QtGui/qaction.h"
+
+QT_BEGIN_HEADER
+
+#ifndef QT_NO_SOFTKEYMANAGER
+QT_BEGIN_NAMESPACE
+
+class QSoftKeyManagerPrivate;
+
+class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSoftKeyManager)
+
+public:
+
+ enum StandardSoftKey {
+ OkSoftKey,
+ SelectSoftKey,
+ DoneSoftKey,
+ MenuSoftKey,
+ CancelSoftKey
+ };
+
+ static void updateSoftKeys();
+#ifdef Q_WS_S60
+ static bool handleCommand(int);
+#endif
+
+ static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget);
+ static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget);
+ static QString standardSoftKeyText(StandardSoftKey standardKey);
+ static void setForceEnabledInSoftkeys(QAction *action);
+ static bool isForceEnabledInSofkeys(QAction *action);
+
+protected:
+ bool event(QEvent *e);
+
+private:
+ QSoftKeyManager();
+ static QSoftKeyManager *instance();
+ bool appendSoftkeys(const QWidget &source, int level);
+ QWidget *softkeySource(QWidget *previousSource, bool& recursiveMerging);
+ bool handleUpdateSoftKeys();
+
+private Q_SLOTS:
+ void cleanupHash(QObject* obj);
+ void sendKeyEvent();
+
+private:
+ Q_DISABLE_COPY(QSoftKeyManager)
+};
+
+QT_END_NAMESPACE
+#endif //QT_NO_SOFTKEYMANAGER
+
+QT_END_HEADER
+
+#endif //QSOFTKEYMANAGER_P_H
diff --git a/src/widgets/kernel/qsound.cpp b/src/widgets/kernel/qsound.cpp
new file mode 100644
index 0000000000..55a98758c3
--- /dev/null
+++ b/src/widgets/kernel/qsound.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsound.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qlist.h"
+#include <private/qobject_p.h>
+#include "qsound_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QList<QAuServer*> *servers=0;
+
+QAuServer::QAuServer(QObject* parent)
+ : QObject(parent)
+{
+ if (!servers)
+ servers = new QList<QAuServer*>;
+ servers->prepend(this);
+}
+
+QAuServer::~QAuServer()
+{
+ servers->removeAll(this);
+ if (servers->count() == 0) {
+ delete servers;
+ servers = 0;
+ }
+}
+
+void QAuServer::play(const QString& filename)
+{
+ QSound s(filename);
+ play(&s);
+}
+
+extern QAuServer* qt_new_audio_server();
+
+static QAuServer& server()
+{
+ if (!servers) qt_new_audio_server();
+ return *servers->first();
+}
+
+class QSoundPrivate : public QObjectPrivate
+{
+public:
+ QSoundPrivate(const QString& fname)
+ : filename(fname), bucket(0), looprem(0), looptotal(1)
+ {
+ }
+
+ ~QSoundPrivate()
+ {
+ delete bucket;
+ }
+
+ QString filename;
+ QAuBucket* bucket;
+ int looprem;
+ int looptotal;
+};
+
+/*!
+ \class QSound
+ \brief The QSound class provides access to the platform audio facilities.
+
+ \ingroup multimedia
+
+
+ Qt provides the most commonly required audio operation in GUI
+ applications: asynchronously playing a sound file. This is most
+ easily accomplished using the static play() function:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qsound.cpp 0
+
+ Alternatively, create a QSound object from the sound file first
+ and then call the play() slot:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qsound.cpp 1
+
+ Once created a QSound object can be queried for its fileName() and
+ total number of loops() (i.e. the number of times the sound will
+ play). The number of repetitions can be altered using the
+ setLoops() function. While playing the sound, the loopsRemaining()
+ function returns the remaining number of repetitions. Use the
+ isFinished() function to determine whether the sound has finished
+ playing.
+
+ Sounds played using a QSound object may use more memory than the
+ static play() function, but it may also play more immediately
+ (depending on the underlying platform audio facilities). Use the
+ static isAvailable() function to determine whether sound
+ facilities exist on the platform. Which facilities that are
+ actually used varies:
+
+ \table
+ \header \o Platform \o Audio Facility
+ \row
+ \o Microsoft Windows
+ \o The underlying multimedia system is used; only WAVE format sound files
+ are supported.
+ \row
+ \o X11
+ \o The \l{ftp://ftp.x.org/contrib/audio/nas/}{Network Audio System}
+ is used if available, otherwise all operations work silently. NAS
+ supports WAVE and AU files.
+ \row
+ \o Mac OS X
+ \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
+ are supported by Qt for Mac OS X.
+ \row
+ \o Qt for Embedded Linux
+ \o A built-in mixing sound server is used, accessing \c /dev/dsp
+ directly. Only the WAVE format is supported.
+ \row
+ \o Symbian
+ \o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support
+ are supported also by Qt.
+ \endtable
+
+ Note that QSound does not support \l{resources.html}{resources}.
+ This might be fixed in a future Qt version.
+*/
+
+/*!
+ Plays the sound stored in the file specified by the given \a filename.
+
+ \sa stop(), loopsRemaining(), isFinished()
+*/
+void QSound::play(const QString& filename)
+{
+ server().play(filename);
+}
+
+/*!
+ Constructs a QSound object from the file specified by the given \a
+ filename and with the given \a parent.
+
+ This may use more memory than the static play() function, but it
+ may also play more immediately (depending on the underlying
+ platform audio facilities).
+
+ \sa play()
+*/
+QSound::QSound(const QString& filename, QObject* parent)
+ : QObject(*new QSoundPrivate(filename), parent)
+{
+ server().init(this);
+}
+
+/*!
+ Destroys this sound object. If the sound is not finished playing,
+ the stop() function is called before the sound object is
+ destructed.
+
+ \sa stop(), isFinished()
+*/
+QSound::~QSound()
+{
+ if (!isFinished())
+ stop();
+}
+
+/*!
+ Returns true if the sound has finished playing; otherwise returns false.
+
+ \warning On Windows this function always returns true for unlooped sounds.
+*/
+bool QSound::isFinished() const
+{
+ Q_D(const QSound);
+ return d->looprem == 0;
+}
+
+/*!
+ \overload
+
+ Starts playing the sound specified by this QSound object.
+
+ The function returns immediately. Depending on the platform audio
+ facilities, other sounds may stop or be mixed with the new
+ sound. The sound can be played again at any time, possibly mixing
+ or replacing previous plays of the sound.
+
+ \sa fileName()
+*/
+void QSound::play()
+{
+ Q_D(QSound);
+ d->looprem = d->looptotal;
+ server().play(this);
+}
+
+/*!
+ Returns the number of times the sound will play.
+
+ \sa loopsRemaining(), setLoops()
+*/
+int QSound::loops() const
+{
+ Q_D(const QSound);
+ return d->looptotal;
+}
+
+/*!
+ Returns the remaining number of times the sound will loop (this
+ value decreases each time the sound is played).
+
+ \sa loops(), isFinished()
+*/
+int QSound::loopsRemaining() const
+{
+ Q_D(const QSound);
+ return d->looprem;
+}
+
+/*!
+ \fn void QSound::setLoops(int number)
+
+ Sets the sound to repeat the given \a number of times when it is
+ played.
+
+ Note that passing the value -1 will cause the sound to loop
+ indefinitely.
+
+ \sa loops()
+*/
+void QSound::setLoops(int n)
+{
+ Q_D(QSound);
+ d->looptotal = n;
+}
+
+/*!
+ Returns the filename associated with this QSound object.
+
+ \sa QSound()
+*/
+QString QSound::fileName() const
+{
+ Q_D(const QSound);
+ return d->filename;
+}
+
+/*!
+ Stops the sound playing.
+
+ Note that on Windows the current loop will finish if a sound is
+ played in a loop.
+
+ \sa play()
+*/
+void QSound::stop()
+{
+ Q_D(QSound);
+ server().stop(this);
+ d->looprem = 0;
+}
+
+
+/*!
+ Returns true if sound facilities exist on the platform; otherwise
+ returns false.
+
+ If no sound is available, all QSound operations work silently and
+ quickly. An application may choose either to notify the user if
+ sound is crucial to the application or to operate silently without
+ bothering the user.
+
+ Note: On Windows this always returns true because some sound card
+ drivers do not implement a way to find out whether it is available
+ or not.
+*/
+bool QSound::isAvailable()
+{
+ return server().okay();
+}
+
+/*!
+ Sets the internal bucket record of sound \a s to \a b, deleting
+ any previous setting.
+*/
+void QAuServer::setBucket(QSound* s, QAuBucket* b)
+{
+ delete s->d_func()->bucket;
+ s->d_func()->bucket = b;
+}
+
+/*!
+ Returns the internal bucket record of sound \a s.
+*/
+QAuBucket* QAuServer::bucket(QSound* s)
+{
+ return s->d_func()->bucket;
+}
+
+/*!
+ Decrements the QSound::loopRemaining() value for sound \a s,
+ returning the result.
+*/
+int QAuServer::decLoop(QSound* s)
+{
+ if (s->d_func()->looprem > 0)
+ --s->d_func()->looprem;
+ return s->d_func()->looprem;
+}
+
+/*!
+ Initializes the sound. The default implementation does nothing.
+*/
+void QAuServer::init(QSound*)
+{
+}
+
+QAuBucket::~QAuBucket()
+{
+}
+/*!
+ \fn bool QSound::available()
+
+ Use the isAvailable() function instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SOUND
diff --git a/src/widgets/kernel/qsound.h b/src/widgets/kernel/qsound.h
new file mode 100644
index 0000000000..a0d058011a
--- /dev/null
+++ b/src/widgets/kernel/qsound.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUND_H
+#define QSOUND_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_SOUND
+
+class QSoundPrivate;
+
+class Q_GUI_EXPORT QSound : public QObject
+{
+ Q_OBJECT
+
+public:
+ static bool isAvailable();
+ static void play(const QString& filename);
+
+ explicit QSound(const QString& filename, QObject* parent = 0);
+ ~QSound();
+
+ int loops() const;
+ int loopsRemaining() const;
+ void setLoops(int);
+ QString fileName() const;
+
+ bool isFinished() const;
+
+public Q_SLOTS:
+ void play();
+ void stop();
+
+private:
+ Q_DECLARE_PRIVATE(QSound)
+ friend class QAuServer;
+};
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOUND_H
diff --git a/src/widgets/kernel/qsound_p.h b/src/widgets/kernel/qsound_p.h
new file mode 100644
index 0000000000..dfdbfff063
--- /dev/null
+++ b/src/widgets/kernel/qsound_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUND_P_H
+#define QSOUND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SOUND
+
+class QSound;
+/*
+ QAuServer is an INTERNAL class. If you wish to provide support for
+ additional audio servers, you can make a subclass of QAuServer to do
+ so, HOWEVER, your class may need to be re-engineered to some degree
+ with each new Qt release, including minor releases.
+
+ QAuBucket is whatever you want.
+*/
+
+class QAuBucket {
+public:
+ virtual ~QAuBucket();
+};
+
+class QAuServer : public QObject {
+ Q_OBJECT
+
+public:
+ explicit QAuServer(QObject* parent);
+ ~QAuServer();
+
+ virtual void init(QSound*);
+ virtual void play(const QString& filename);
+ virtual void play(QSound*)=0;
+ virtual void stop(QSound*)=0;
+ virtual bool okay()=0;
+
+protected:
+ void setBucket(QSound*, QAuBucket*);
+ QAuBucket* bucket(QSound*);
+ int decLoop(QSound*);
+};
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
+
+#endif // QSOUND_P_H
diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp
new file mode 100644
index 0000000000..c5ce238958
--- /dev/null
+++ b/src/widgets/kernel/qstackedlayout.cpp
@@ -0,0 +1,543 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstackedlayout.h"
+#include "qlayout_p.h"
+
+#include <qlist.h>
+#include <qwidget.h>
+#include "private/qlayoutengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QStackedLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QStackedLayout)
+public:
+ QStackedLayoutPrivate() : index(-1), stackingMode(QStackedLayout::StackOne) {}
+ QList<QLayoutItem *> list;
+ int index;
+ QStackedLayout::StackingMode stackingMode;
+};
+
+/*!
+ \class QStackedLayout
+
+ \brief The QStackedLayout class provides a stack of widgets where
+ only one widget is visible at a time.
+
+ \ingroup geomanagement
+
+ QStackedLayout can be used to create a user interface similar to
+ the one provided by QTabWidget. There is also a convenience
+ QStackedWidget class built on top of QStackedLayout.
+
+ A QStackedLayout can be populated with a number of child widgets
+ ("pages"). For example:
+
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 0
+ \codeline
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 2
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 3
+
+ QStackedLayout provides no intrinsic means for the user to switch
+ page. This is typically done through a QComboBox or a QListWidget
+ that stores the titles of the QStackedLayout's pages. For
+ example:
+
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 1
+
+ When populating a layout, the widgets are added to an internal
+ list. The indexOf() function returns the index of a widget in that
+ list. The widgets can either be added to the end of the list using
+ the addWidget() function, or inserted at a given index using the
+ insertWidget() function. The removeWidget() function removes the
+ widget at the given index from the layout. The number of widgets
+ contained in the layout, can be obtained using the count()
+ function.
+
+ The widget() function returns the widget at a given index
+ position. The index of the widget that is shown on screen is given
+ by currentIndex() and can be changed using setCurrentIndex(). In a
+ similar manner, the currently shown widget can be retrieved using
+ the currentWidget() function, and altered using the
+ setCurrentWidget() function.
+
+ Whenever the current widget in the layout changes or a widget is
+ removed from the layout, the currentChanged() and widgetRemoved()
+ signals are emitted respectively.
+
+ \sa QStackedWidget, QTabWidget
+*/
+
+/*!
+ \fn void QStackedLayout::currentChanged(int index)
+
+ This signal is emitted whenever the current widget in the layout
+ changes. The \a index specifies the index of the new current
+ widget, or -1 if there isn't a new one (for example, if there
+ are no widgets in the QStackedLayout)
+
+ \sa currentWidget(), setCurrentWidget()
+*/
+
+/*!
+ \fn void QStackedLayout::widgetRemoved(int index)
+
+ This signal is emitted whenever a widget is removed from the
+ layout. The widget's \a index is passed as parameter.
+
+ \sa removeWidget()
+*/
+
+/*!
+ \fn QWidget *QStackedLayout::widget()
+ \internal
+*/
+
+/*!
+ Constructs a QStackedLayout with no parent.
+
+ This QStackedLayout must be installed on a widget later on to
+ become effective.
+
+ \sa addWidget(), insertWidget()
+*/
+QStackedLayout::QStackedLayout()
+ : QLayout(*new QStackedLayoutPrivate, 0, 0)
+{
+}
+
+/*!
+ Constructs a new QStackedLayout with the given \a parent.
+
+ This layout will install itself on the \a parent widget and
+ manage the geometry of its children.
+*/
+QStackedLayout::QStackedLayout(QWidget *parent)
+ : QLayout(*new QStackedLayoutPrivate, 0, parent)
+{
+}
+
+/*!
+ Constructs a new QStackedLayout and inserts it into
+ the given \a parentLayout.
+*/
+QStackedLayout::QStackedLayout(QLayout *parentLayout)
+ : QLayout(*new QStackedLayoutPrivate, parentLayout, 0)
+{
+}
+
+/*!
+ Destroys this QStackedLayout. Note that the layout's widgets are
+ \e not destroyed.
+*/
+QStackedLayout::~QStackedLayout()
+{
+ Q_D(QStackedLayout);
+ qDeleteAll(d->list);
+}
+
+/*!
+ Adds the given \a widget to the end of this layout and returns the
+ index position of the \a widget.
+
+ If the QStackedLayout is empty before this function is called,
+ the given \a widget becomes the current widget.
+
+ \sa insertWidget(), removeWidget(), setCurrentWidget()
+*/
+int QStackedLayout::addWidget(QWidget *widget)
+{
+ Q_D(QStackedLayout);
+ return insertWidget(d->list.count(), widget);
+}
+
+/*!
+ Inserts the given \a widget at the given \a index in this
+ QStackedLayout. If \a index is out of range, the widget is
+ appended (in which case it is the actual index of the \a widget
+ that is returned).
+
+ If the QStackedLayout is empty before this function is called, the
+ given \a widget becomes the current widget.
+
+ Inserting a new widget at an index less than or equal to the current index
+ will increment the current index, but keep the current widget.
+
+ \sa addWidget(), removeWidget(), setCurrentWidget()
+*/
+int QStackedLayout::insertWidget(int index, QWidget *widget)
+{
+ Q_D(QStackedLayout);
+ addChildWidget(widget);
+ index = qMin(index, d->list.count());
+ if (index < 0)
+ index = d->list.count();
+ QWidgetItem *wi = QLayoutPrivate::createWidgetItem(this, widget);
+ d->list.insert(index, wi);
+ invalidate();
+ if (d->index < 0) {
+ setCurrentIndex(index);
+ } else {
+ if (index <= d->index)
+ ++d->index;
+ if (d->stackingMode == StackOne)
+ widget->hide();
+ widget->lower();
+ }
+ return index;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QStackedLayout::itemAt(int index) const
+{
+ Q_D(const QStackedLayout);
+ return d->list.value(index);
+}
+
+// Code that enables proper handling of the case that takeAt() is
+// called somewhere inside QObject destructor (can't call hide()
+// on the object then)
+
+class QtFriendlyLayoutWidget : public QWidget
+{
+public:
+ inline bool wasDeleted() const { return d_ptr->wasDeleted; }
+};
+
+static bool qt_wasDeleted(const QWidget *w) { return static_cast<const QtFriendlyLayoutWidget*>(w)->wasDeleted(); }
+
+
+/*!
+ \reimp
+*/
+QLayoutItem *QStackedLayout::takeAt(int index)
+{
+ Q_D(QStackedLayout);
+ if (index <0 || index >= d->list.size())
+ return 0;
+ QLayoutItem *item = d->list.takeAt(index);
+ if (index == d->index) {
+ d->index = -1;
+ if ( d->list.count() > 0 ) {
+ int newIndex = (index == d->list.count()) ? index-1 : index;
+ setCurrentIndex(newIndex);
+ } else {
+ emit currentChanged(-1);
+ }
+ } else if (index < d->index) {
+ --d->index;
+ }
+ emit widgetRemoved(index);
+ if (item->widget() && !qt_wasDeleted(item->widget()))
+ item->widget()->hide();
+ return item;
+}
+
+/*!
+ \property QStackedLayout::currentIndex
+ \brief the index position of the widget that is visible
+
+ The current index is -1 if there is no current widget.
+
+ \sa currentWidget(), indexOf()
+*/
+void QStackedLayout::setCurrentIndex(int index)
+{
+ Q_D(QStackedLayout);
+ QWidget *prev = currentWidget();
+ QWidget *next = widget(index);
+ if (!next || next == prev)
+ return;
+
+ bool reenableUpdates = false;
+ QWidget *parent = parentWidget();
+
+ if (parent && parent->updatesEnabled()) {
+ reenableUpdates = true;
+ parent->setUpdatesEnabled(false);
+ }
+
+ QWidget *fw = parent ? parent->window()->focusWidget() : 0;
+ if (prev) {
+ prev->clearFocus();
+ if (d->stackingMode == StackOne)
+ prev->hide();
+ }
+
+ d->index = index;
+ next->raise();
+ next->show();
+
+ // try to move focus onto the incoming widget if focus
+ // was somewhere on the outgoing widget.
+
+ if (parent) {
+ if (fw && (prev && prev->isAncestorOf(fw))) { // focus was on old page
+ // look for the best focus widget we can find
+ if (QWidget *nfw = next->focusWidget())
+ nfw->setFocus();
+ else {
+ // 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(next) && i->isEnabled()
+ && next->isAncestorOf(i)) {
+ i->setFocus();
+ break;
+ }
+ }
+ // third best: incoming widget
+ if (i == fw )
+ next->setFocus();
+ }
+ }
+ }
+ if (reenableUpdates)
+ parent->setUpdatesEnabled(true);
+ emit currentChanged(index);
+}
+
+int QStackedLayout::currentIndex() const
+{
+ Q_D(const QStackedLayout);
+ return d->index;
+}
+
+
+/*!
+ \fn void QStackedLayout::setCurrentWidget(QWidget *widget)
+
+ Sets the current widget to be the specified \a widget. The new
+ current widget must already be contained in this stacked layout.
+
+ \sa setCurrentIndex(), currentWidget()
+ */
+void QStackedLayout::setCurrentWidget(QWidget *widget)
+{
+ int index = indexOf(widget);
+ if (index == -1) {
+ qWarning("QStackedLayout::setCurrentWidget: Widget %p not contained in stack", widget);
+ return;
+ }
+ setCurrentIndex(index);
+}
+
+
+/*!
+ Returns the current widget, or 0 if there are no widgets in this
+ layout.
+
+ \sa currentIndex(), setCurrentWidget()
+*/
+QWidget *QStackedLayout::currentWidget() const
+{
+ Q_D(const QStackedLayout);
+ return d->index >= 0 ? d->list.at(d->index)->widget() : 0;
+}
+
+/*!
+ Returns the widget at the given \a index, or 0 if there is no
+ widget at the given position.
+
+ \sa currentWidget(), indexOf()
+*/
+QWidget *QStackedLayout::widget(int index) const
+{
+ Q_D(const QStackedLayout);
+ if (index < 0 || index >= d->list.size())
+ return 0;
+ return d->list.at(index)->widget();
+}
+
+/*!
+ \property QStackedLayout::count
+ \brief the number of widgets contained in the layout
+
+ \sa currentIndex(), widget()
+*/
+int QStackedLayout::count() const
+{
+ Q_D(const QStackedLayout);
+ return d->list.size();
+}
+
+
+/*!
+ \reimp
+*/
+void QStackedLayout::addItem(QLayoutItem *item)
+{
+ QWidget *widget = item->widget();
+ if (widget) {
+ addWidget(widget);
+ delete item;
+ } else {
+ qWarning("QStackedLayout::addItem: Only widgets can be added");
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QStackedLayout::sizeHint() const
+{
+ Q_D(const QStackedLayout);
+ QSize s(0, 0);
+ int n = d->list.count();
+
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget()) {
+ QSize ws(widget->sizeHint());
+ if (widget->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ ws.setWidth(0);
+ if (widget->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ ws.setHeight(0);
+ s = s.expandedTo(ws);
+ }
+ return s;
+}
+
+/*!
+ \reimp
+*/
+QSize QStackedLayout::minimumSize() const
+{
+ Q_D(const QStackedLayout);
+ QSize s(0, 0);
+ int n = d->list.count();
+
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ s = s.expandedTo(qSmartMinSize(widget));
+ return s;
+}
+
+/*!
+ \reimp
+*/
+void QStackedLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QStackedLayout);
+ switch (d->stackingMode) {
+ case StackOne:
+ if (QWidget *widget = currentWidget())
+ widget->setGeometry(rect);
+ break;
+ case StackAll:
+ if (const int n = d->list.count())
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ widget->setGeometry(rect);
+ break;
+ }
+}
+
+/*!
+ \enum QStackedLayout::StackingMode
+ \since 4.4
+
+ This enum specifies how the layout handles its child widgets
+ regarding their visibility.
+
+ \value StackOne
+ Only the current widget is visible. This is the default.
+
+ \value StackAll
+ All widgets are visible. The current widget is merely raised.
+*/
+
+
+/*!
+ \property QStackedLayout::stackingMode
+ \brief determines the way visibility of child widgets are handled.
+ \since 4.4
+
+ The default value is StackOne. Setting the property to StackAll
+ allows you to make use of the layout for overlay widgets
+ that do additional drawing on top of other widgets, for example,
+ graphical editors.
+*/
+
+QStackedLayout::StackingMode QStackedLayout::stackingMode() const
+{
+ Q_D(const QStackedLayout);
+ return d->stackingMode;
+}
+
+void QStackedLayout::setStackingMode(StackingMode stackingMode)
+{
+ Q_D(QStackedLayout);
+ if (d->stackingMode == stackingMode)
+ return;
+ d->stackingMode = stackingMode;
+
+ const int n = d->list.count();
+ if (n == 0)
+ return;
+
+ switch (d->stackingMode) {
+ case StackOne:
+ if (const int idx = currentIndex())
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ widget->setVisible(i == idx);
+ break;
+ case StackAll: { // Turn overlay on: Make sure all widgets are the same size
+ QRect geometry;
+ if (const QWidget *widget = currentWidget())
+ geometry = widget->geometry();
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget()) {
+ if (!geometry.isNull())
+ widget->setGeometry(geometry);
+ widget->setVisible(true);
+ }
+ }
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qstackedlayout.h b/src/widgets/kernel/qstackedlayout.h
new file mode 100644
index 0000000000..49b80c6445
--- /dev/null
+++ b/src/widgets/kernel/qstackedlayout.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTACKEDLAYOUT_H
+#define QSTACKEDLAYOUT_H
+
+#include <QtGui/qlayout.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QStackedLayoutPrivate;
+
+class Q_GUI_EXPORT QStackedLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QStackedLayout)
+ Q_ENUMS(StackingMode)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged)
+ Q_PROPERTY(StackingMode stackingMode READ stackingMode WRITE setStackingMode)
+ QDOC_PROPERTY(int count READ count)
+
+public:
+ enum StackingMode {
+ StackOne,
+ StackAll
+ };
+
+ QStackedLayout();
+ explicit QStackedLayout(QWidget *parent);
+ explicit QStackedLayout(QLayout *parentLayout);
+ ~QStackedLayout();
+
+ int addWidget(QWidget *w);
+ int insertWidget(int index, QWidget *w);
+
+ QWidget *currentWidget() const;
+ int currentIndex() const;
+#ifdef Q_NO_USING_KEYWORD
+ inline QWidget *widget() { return QLayout::widget(); }
+#else
+ using QLayout::widget;
+#endif
+ QWidget *widget(int) const;
+ int count() const;
+
+ StackingMode stackingMode() const;
+ void setStackingMode(StackingMode stackingMode);
+
+ // abstract virtual functions:
+ void addItem(QLayoutItem *item);
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QLayoutItem *itemAt(int) const;
+ QLayoutItem *takeAt(int);
+ void setGeometry(const QRect &rect);
+
+Q_SIGNALS:
+ void widgetRemoved(int index);
+ void currentChanged(int index);
+
+public Q_SLOTS:
+ void setCurrentIndex(int index);
+ void setCurrentWidget(QWidget *w);
+
+private:
+ Q_DISABLE_COPY(QStackedLayout)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTACKEDLAYOUT_H
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
new file mode 100644
index 0000000000..6338ef7afb
--- /dev/null
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstandardgestures_p.h"
+#include "qgesture.h"
+#include "qgesture_p.h"
+#include "qevent.h"
+#include "qwidget.h"
+#include "qabstractscrollarea.h"
+#include <qgraphicssceneevent.h>
+#include "qdebug.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+QPanGestureRecognizer::QPanGestureRecognizer()
+{
+}
+
+QGesture *QPanGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
+ // for scroll areas on Windows we want to use native gestures instead
+ if (!qobject_cast<QAbstractScrollArea *>(target->parent()))
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+#else
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+#endif
+ }
+ return new QPanGesture;
+}
+
+QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
+{
+ QPanGesture *q = static_cast<QPanGesture *>(state);
+ QPanGesturePrivate *d = q->d_func();
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+
+ QGestureRecognizer::Result result;
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ result = QGestureRecognizer::MayBeGesture;
+ QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
+ d->lastOffset = d->offset = QPointF();
+ break;
+ }
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture) {
+ if (ev->touchPoints().size() == 2) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ d->lastOffset = d->offset;
+ d->offset =
+ QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
+ p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ }
+ result = QGestureRecognizer::FinishGesture;
+ } else {
+ result = QGestureRecognizer::CancelGesture;
+ }
+ break;
+ }
+ case QEvent::TouchUpdate: {
+ if (ev->touchPoints().size() >= 2) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ d->lastOffset = d->offset;
+ d->offset =
+ QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
+ p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ if (d->offset.x() > 10 || d->offset.y() > 10 ||
+ d->offset.x() < -10 || d->offset.y() < -10) {
+ q->setHotSpot(p1.startScreenPos());
+ result = QGestureRecognizer::TriggerGesture;
+ } else {
+ result = QGestureRecognizer::MayBeGesture;
+ }
+ }
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QPanGestureRecognizer::reset(QGesture *state)
+{
+ QPanGesture *pan = static_cast<QPanGesture*>(state);
+ QPanGesturePrivate *d = pan->d_func();
+
+ d->lastOffset = d->offset = QPointF();
+ d->acceleration = 0;
+
+ QGestureRecognizer::reset(state);
+}
+
+
+//
+// QPinchGestureRecognizer
+//
+
+QPinchGestureRecognizer::QPinchGestureRecognizer()
+{
+}
+
+QGesture *QPinchGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ }
+ return new QPinchGesture;
+}
+
+QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
+{
+ QPinchGesture *q = static_cast<QPinchGesture *>(state);
+ QPinchGesturePrivate *d = q->d_func();
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+
+ QGestureRecognizer::Result result;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ result = QGestureRecognizer::MayBeGesture;
+ break;
+ }
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture) {
+ result = QGestureRecognizer::FinishGesture;
+ } else {
+ result = QGestureRecognizer::CancelGesture;
+ }
+ break;
+ }
+ case QEvent::TouchUpdate: {
+ d->changeFlags = 0;
+ if (ev->touchPoints().size() == 2) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+
+ d->hotSpot = p1.screenPos();
+ d->isHotSpotSet = true;
+
+ QPointF centerPoint = (p1.screenPos() + p2.screenPos()) / 2.0;
+ if (d->isNewSequence) {
+ d->startPosition[0] = p1.screenPos();
+ d->startPosition[1] = p2.screenPos();
+ d->lastCenterPoint = centerPoint;
+ } else {
+ d->lastCenterPoint = d->centerPoint;
+ }
+ d->centerPoint = centerPoint;
+
+ d->changeFlags |= QPinchGesture::CenterPointChanged;
+
+ if (d->isNewSequence) {
+ d->scaleFactor = 1.0;
+ d->lastScaleFactor = 1.0;
+ } else {
+ d->lastScaleFactor = d->scaleFactor;
+ QLineF line(p1.screenPos(), p2.screenPos());
+ QLineF lastLine(p1.lastScreenPos(), p2.lastScreenPos());
+ d->scaleFactor = line.length() / lastLine.length();
+ }
+ d->totalScaleFactor = d->totalScaleFactor * d->scaleFactor;
+ d->changeFlags |= QPinchGesture::ScaleFactorChanged;
+
+ qreal angle = QLineF(p1.screenPos(), p2.screenPos()).angle();
+ if (angle > 180)
+ angle -= 360;
+ qreal startAngle = QLineF(p1.startScreenPos(), p2.startScreenPos()).angle();
+ if (startAngle > 180)
+ startAngle -= 360;
+ const qreal rotationAngle = startAngle - angle;
+ if (d->isNewSequence)
+ d->lastRotationAngle = 0.0;
+ else
+ d->lastRotationAngle = d->rotationAngle;
+ d->rotationAngle = rotationAngle;
+ d->totalRotationAngle += d->rotationAngle - d->lastRotationAngle;
+ d->changeFlags |= QPinchGesture::RotationAngleChanged;
+
+ d->totalChangeFlags |= d->changeFlags;
+ d->isNewSequence = false;
+ result = QGestureRecognizer::TriggerGesture;
+ } else {
+ d->isNewSequence = true;
+ if (q->state() == Qt::NoGesture)
+ result = QGestureRecognizer::Ignore;
+ else
+ result = QGestureRecognizer::FinishGesture;
+ }
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QPinchGestureRecognizer::reset(QGesture *state)
+{
+ QPinchGesture *pinch = static_cast<QPinchGesture *>(state);
+ QPinchGesturePrivate *d = pinch->d_func();
+
+ d->totalChangeFlags = d->changeFlags = 0;
+
+ d->startCenterPoint = d->lastCenterPoint = d->centerPoint = QPointF();
+ d->totalScaleFactor = d->lastScaleFactor = d->scaleFactor = 1;
+ d->totalRotationAngle = d->lastRotationAngle = d->rotationAngle = 0;
+
+ d->isNewSequence = true;
+ d->startPosition[0] = d->startPosition[1] = QPointF();
+
+ QGestureRecognizer::reset(state);
+}
+
+//
+// QSwipeGestureRecognizer
+//
+
+QSwipeGestureRecognizer::QSwipeGestureRecognizer()
+{
+}
+
+QGesture *QSwipeGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ }
+ return new QSwipeGesture;
+}
+
+QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
+{
+ QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
+ QSwipeGesturePrivate *d = q->d_func();
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+
+ QGestureRecognizer::Result result;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ d->velocityValue = 1;
+ d->time.start();
+ d->started = true;
+ result = QGestureRecognizer::MayBeGesture;
+ break;
+ }
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture) {
+ result = QGestureRecognizer::FinishGesture;
+ } else {
+ result = QGestureRecognizer::CancelGesture;
+ }
+ break;
+ }
+ case QEvent::TouchUpdate: {
+ if (!d->started)
+ result = QGestureRecognizer::CancelGesture;
+ else if (ev->touchPoints().size() == 3) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2);
+
+ if (d->lastPositions[0].isNull()) {
+ d->lastPositions[0] = p1.startScreenPos().toPoint();
+ d->lastPositions[1] = p2.startScreenPos().toPoint();
+ d->lastPositions[2] = p3.startScreenPos().toPoint();
+ }
+ d->hotSpot = p1.screenPos();
+ d->isHotSpotSet = true;
+
+ int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() +
+ p2.screenPos().x() - d->lastPositions[1].x() +
+ p3.screenPos().x() - d->lastPositions[2].x()) / 3;
+ int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() +
+ p2.screenPos().y() - d->lastPositions[1].y() +
+ p3.screenPos().y() - d->lastPositions[2].y()) / 3;
+
+ const int distance = xDistance >= yDistance ? xDistance : yDistance;
+ int elapsedTime = d->time.restart();
+ if (!elapsedTime)
+ elapsedTime = 1;
+ d->velocityValue = 0.9 * d->velocityValue + distance / elapsedTime;
+ d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
+
+ static const int MoveThreshold = 50;
+ if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
+ // measure the distance to check if the direction changed
+ d->lastPositions[0] = p1.screenPos().toPoint();
+ d->lastPositions[1] = p2.screenPos().toPoint();
+ d->lastPositions[2] = p3.screenPos().toPoint();
+ QSwipeGesture::SwipeDirection horizontal =
+ xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
+ QSwipeGesture::SwipeDirection vertical =
+ yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
+ if (d->verticalDirection == QSwipeGesture::NoDirection)
+ d->verticalDirection = vertical;
+ if (d->horizontalDirection == QSwipeGesture::NoDirection)
+ d->horizontalDirection = horizontal;
+ if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) {
+ // the user has changed the direction!
+ result = QGestureRecognizer::CancelGesture;
+ }
+ result = QGestureRecognizer::TriggerGesture;
+ } else {
+ if (q->state() != Qt::NoGesture)
+ result = QGestureRecognizer::TriggerGesture;
+ else
+ result = QGestureRecognizer::MayBeGesture;
+ }
+ } else if (ev->touchPoints().size() > 3) {
+ result = QGestureRecognizer::CancelGesture;
+ } else { // less than 3 touch points
+ if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed))
+ result = QGestureRecognizer::CancelGesture;
+ else if (d->started)
+ result = QGestureRecognizer::Ignore;
+ else
+ result = QGestureRecognizer::MayBeGesture;
+ }
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QSwipeGestureRecognizer::reset(QGesture *state)
+{
+ QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
+ QSwipeGesturePrivate *d = q->d_func();
+
+ d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection;
+ d->swipeAngle = 0;
+
+ d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
+ d->started = false;
+ d->velocityValue = 0;
+ d->time.invalidate();
+
+ QGestureRecognizer::reset(state);
+}
+
+//
+// QTapGestureRecognizer
+//
+
+QTapGestureRecognizer::QTapGestureRecognizer()
+{
+}
+
+QGesture *QTapGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ }
+ return new QTapGesture;
+}
+
+QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state,
+ QObject *,
+ QEvent *event)
+{
+ QTapGesture *q = static_cast<QTapGesture *>(state);
+ QTapGesturePrivate *d = q->d_func();
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+
+ QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ d->position = ev->touchPoints().at(0).pos();
+ q->setHotSpot(ev->touchPoints().at(0).screenPos());
+ result = QGestureRecognizer::TriggerGesture;
+ break;
+ }
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) {
+ QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
+ QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
+ enum { TapRadius = 40 };
+ if (delta.manhattanLength() <= TapRadius) {
+ if (event->type() == QEvent::TouchEnd)
+ result = QGestureRecognizer::FinishGesture;
+ else
+ result = QGestureRecognizer::TriggerGesture;
+ }
+ }
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QTapGestureRecognizer::reset(QGesture *state)
+{
+ QTapGesture *q = static_cast<QTapGesture *>(state);
+ QTapGesturePrivate *d = q->d_func();
+
+ d->position = QPointF();
+
+ QGestureRecognizer::reset(state);
+}
+
+//
+// QTapAndHoldGestureRecognizer
+//
+
+QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer()
+{
+}
+
+QGesture *QTapAndHoldGestureRecognizer::create(QObject *target)
+{
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ }
+ return new QTapAndHoldGesture;
+}
+
+QGestureRecognizer::Result
+QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object,
+ QEvent *event)
+{
+ QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
+ QTapAndHoldGesturePrivate *d = q->d_func();
+
+ if (object == state && event->type() == QEvent::Timer) {
+ q->killTimer(d->timerId);
+ d->timerId = 0;
+ return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint;
+ }
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
+ const QMouseEvent *me = static_cast<const QMouseEvent *>(event);
+#ifndef QT_NO_GRAPHICSVIEW
+ const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event);
+#endif
+
+ enum { TapRadius = 40 };
+
+ switch (event->type()) {
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMousePress:
+ d->position = gsme->screenPos();
+ q->setHotSpot(d->position);
+ if (d->timerId)
+ q->killTimer(d->timerId);
+ d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout);
+ return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
+#endif
+ case QEvent::MouseButtonPress:
+ d->position = me->globalPos();
+ q->setHotSpot(d->position);
+ if (d->timerId)
+ q->killTimer(d->timerId);
+ d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout);
+ return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
+ case QEvent::TouchBegin:
+ d->position = ev->touchPoints().at(0).startScreenPos();
+ q->setHotSpot(d->position);
+ if (d->timerId)
+ q->killTimer(d->timerId);
+ d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout);
+ return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseRelease:
+#endif
+ case QEvent::MouseButtonRelease:
+ case QEvent::TouchEnd:
+ return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state
+ case QEvent::TouchUpdate:
+ if (d->timerId && ev->touchPoints().size() == 1) {
+ QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
+ QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
+ if (delta.manhattanLength() <= TapRadius)
+ return QGestureRecognizer::MayBeGesture;
+ }
+ return QGestureRecognizer::CancelGesture;
+ case QEvent::MouseMove: {
+ QPoint delta = me->globalPos() - d->position.toPoint();
+ if (d->timerId && delta.manhattanLength() <= TapRadius)
+ return QGestureRecognizer::MayBeGesture;
+ return QGestureRecognizer::CancelGesture;
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseMove: {
+ QPoint delta = gsme->screenPos() - d->position.toPoint();
+ if (d->timerId && delta.manhattanLength() <= TapRadius)
+ return QGestureRecognizer::MayBeGesture;
+ return QGestureRecognizer::CancelGesture;
+ }
+#endif
+ default:
+ return QGestureRecognizer::Ignore;
+ }
+}
+
+void QTapAndHoldGestureRecognizer::reset(QGesture *state)
+{
+ QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
+ QTapAndHoldGesturePrivate *d = q->d_func();
+
+ d->position = QPointF();
+ if (d->timerId)
+ q->killTimer(d->timerId);
+ d->timerId = 0;
+
+ QGestureRecognizer::reset(state);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h
new file mode 100644
index 0000000000..b3c5002565
--- /dev/null
+++ b/src/widgets/kernel/qstandardgestures_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTANDARDGESTURES_P_H
+#define QSTANDARDGESTURES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgesturerecognizer.h"
+#include "private/qgesture_p.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+class QPanGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QPanGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+class QPinchGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QPinchGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+class QSwipeGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QSwipeGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+class QTapGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QTapGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+class QTapAndHoldGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QTapAndHoldGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#endif // QSTANDARDGESTURES_P_H
diff --git a/src/widgets/kernel/qt_gui_pch.h b/src/widgets/kernel/qt_gui_pch.h
new file mode 100644
index 0000000000..368c12d444
--- /dev/null
+++ b/src/widgets/kernel/qt_gui_pch.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This is a precompiled header file for use in Xcode / Mac GCC /
+ * GCC >= 3.4 / VC to greatly speed the building of Qt. It may also be
+ * of use to people developing their own project, but it is probably
+ * better to define your own header. Use of this header is currently
+ * UNSUPPORTED.
+ */
+
+// from corelib/global/qt_pch.h
+#if defined __cplusplus
+#include <qglobal.h>
+
+
+#ifdef Q_WS_WIN
+# define _POSIX_
+# include <limits.h>
+# undef _POSIX_
+#endif
+
+#include <qcoreapplication.h>
+#include <qlist.h>
+#include <qvariant.h> // All moc genereated code has this include
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qimage.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <stdlib.h>
+
+#endif
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
new file mode 100644
index 0000000000..4311df58a6
--- /dev/null
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef Q_WS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qhash.h>
+#include <qlabel.h>
+#include <qpointer.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qstylepainter.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <private/qeffects_p.h>
+#include <qtextdocument.h>
+#include <qdebug.h>
+#include <private/qstylesheetstyle_p.h>
+#ifndef QT_NO_TOOLTIP
+
+#ifdef Q_WS_MAC
+# include <private/qcore_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QToolTip
+
+ \brief The QToolTip class provides tool tips (balloon help) for any
+ widget.
+
+ \ingroup helpsystem
+
+
+ The tip is a short piece of text reminding the user of the
+ widget's function. It is drawn immediately below the given
+ position in a distinctive black-on-yellow color combination. The
+ tip can be any \l{QTextEdit}{rich text} formatted string.
+
+ Rich text displayed in a tool tip is implicitly word-wrapped unless
+ specified differently with \c{<p style='white-space:pre'>}.
+
+ The simplest and most common way to set a widget's tool tip is by
+ calling its QWidget::setToolTip() function.
+
+ It is also possible to show different tool tips for different
+ regions of a widget, by using a QHelpEvent of type
+ QEvent::ToolTip. Intercept the help event in your widget's \l
+ {QWidget::}{event()} function and call QToolTip::showText() with
+ the text you want to display. The \l{widgets/tooltips}{Tooltips}
+ example illustrates this technique.
+
+ If you are calling QToolTip::hideText(), or QToolTip::showText()
+ with an empty string, as a result of a \l{QEvent::}{ToolTip}-event you
+ should also call \l{QEvent::}{ignore()} on the event, to signal
+ that you don't want to start any tooltip specific modes.
+
+ Note that, if you want to show tooltips in an item view, the
+ model/view architecture provides functionality to set an item's
+ tool tip; e.g., the QTableWidgetItem::setToolTip() function.
+ However, if you want to provide custom tool tips in an item view,
+ you must intercept the help event in the
+ QAbstractItemView::viewportEvent() function and handle it yourself.
+
+ The default tool tip color and font can be customized with
+ setPalette() and setFont(). When a tooltip is currently on
+ display, isVisible() returns true and text() the currently visible
+ text.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+
+ \sa QWidget::toolTip, QAction::toolTip, {Tool Tips Example}
+*/
+
+class QTipLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ QTipLabel(const QString &text, QWidget *w);
+ ~QTipLabel();
+ static QTipLabel *instance;
+
+ bool eventFilter(QObject *, QEvent *);
+
+ QBasicTimer hideTimer, expireTimer;
+
+ bool fadingOut;
+
+ void reuseTip(const QString &text);
+ void hideTip();
+ void hideTipImmediately();
+ void setTipRect(QWidget *w, const QRect &r);
+ void restartExpireTimer();
+ bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
+ void placeTip(const QPoint &pos, QWidget *w);
+
+ static int getTipScreen(const QPoint &pos, QWidget *w);
+protected:
+ void timerEvent(QTimerEvent *e);
+ void paintEvent(QPaintEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void resizeEvent(QResizeEvent *e);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+public slots:
+ /** \internal
+ Cleanup the _q_stylesheet_parent propery.
+ */
+ void styleSheetParentDestroyed() {
+ setProperty("_q_stylesheet_parent", QVariant());
+ styleSheetParent = 0;
+ }
+
+private:
+ QWidget *styleSheetParent;
+#endif
+
+private:
+ QWidget *widget;
+ QRect rect;
+};
+
+QTipLabel *QTipLabel::instance = 0;
+
+QTipLabel::QTipLabel(const QString &text, QWidget *w)
+#ifndef QT_NO_STYLE_STYLESHEET
+ : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0)
+#else
+ : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), widget(0)
+#endif
+{
+ delete instance;
+ instance = this;
+ setForegroundRole(QPalette::ToolTipText);
+ setBackgroundRole(QPalette::ToolTipBase);
+ setPalette(QToolTip::palette());
+ ensurePolished();
+ setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
+ setFrameStyle(QFrame::NoFrame);
+ setAlignment(Qt::AlignLeft);
+ setIndent(1);
+ qApp->installEventFilter(this);
+ setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
+ setMouseTracking(true);
+ fadingOut = false;
+ reuseTip(text);
+}
+
+void QTipLabel::restartExpireTimer()
+{
+ int time = 10000 + 40 * qMax(0, text().length()-100);
+ expireTimer.start(time, this);
+ hideTimer.stop();
+}
+
+void QTipLabel::reuseTip(const QString &text)
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (styleSheetParent){
+ disconnect(styleSheetParent, SIGNAL(destroyed()),
+ QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
+ styleSheetParent = 0;
+ }
+#endif
+
+ setWordWrap(Qt::mightBeRichText(text));
+ setText(text);
+ QFontMetrics fm(font());
+ QSize extra(1, 0);
+ // Make it look good with the default ToolTip font on Mac, which has a small descent.
+ if (fm.descent() == 2 && fm.ascent() >= 11)
+ ++extra.rheight();
+ resize(sizeHint() + extra);
+ restartExpireTimer();
+}
+
+void QTipLabel::paintEvent(QPaintEvent *ev)
+{
+ QStylePainter p(this);
+ QStyleOptionFrame opt;
+ opt.init(this);
+ p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
+ p.end();
+
+ QLabel::paintEvent(ev);
+}
+
+void QTipLabel::resizeEvent(QResizeEvent *e)
+{
+ QStyleHintReturnMask frameMask;
+ QStyleOption option;
+ option.init(this);
+ if (style()->styleHint(QStyle::SH_ToolTip_Mask, &option, this, &frameMask))
+ setMask(frameMask.region);
+
+ QLabel::resizeEvent(e);
+}
+
+void QTipLabel::mouseMoveEvent(QMouseEvent *e)
+{
+ if (rect.isNull())
+ return;
+ QPoint pos = e->globalPos();
+ if (widget)
+ pos = widget->mapFromGlobal(pos);
+ if (!rect.contains(pos))
+ hideTip();
+ QLabel::mouseMoveEvent(e);
+}
+
+QTipLabel::~QTipLabel()
+{
+ instance = 0;
+}
+
+void QTipLabel::hideTip()
+{
+ if (!hideTimer.isActive())
+ hideTimer.start(300, this);
+}
+
+void QTipLabel::hideTipImmediately()
+{
+ close(); // to trigger QEvent::Close which stops the animation
+ deleteLater();
+}
+
+void QTipLabel::setTipRect(QWidget *w, const QRect &r)
+{
+ if (!rect.isNull() && !w)
+ qWarning("QToolTip::setTipRect: Cannot pass null widget if rect is set");
+ else{
+ widget = w;
+ rect = r;
+ }
+}
+
+void QTipLabel::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == hideTimer.timerId()
+ || e->timerId() == expireTimer.timerId()){
+ hideTimer.stop();
+ expireTimer.stop();
+#if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS)
+ if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){
+ // Fade out tip on mac (makes it invisible).
+ // The tip will not be deleted until a new tip is shown.
+
+ // DRSWAT - Cocoa
+ macWindowFade(qt_mac_window_for(this));
+ QTipLabel::instance->fadingOut = true; // will never be false again.
+ }
+ else
+ hideTipImmediately();
+#else
+ hideTipImmediately();
+#endif
+ }
+}
+
+bool QTipLabel::eventFilter(QObject *o, QEvent *e)
+{
+ switch (e->type()) {
+#ifdef Q_WS_MAC
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ int key = static_cast<QKeyEvent *>(e)->key();
+ Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers();
+ if (!(mody & Qt::KeyboardModifierMask)
+ && key != Qt::Key_Shift && key != Qt::Key_Control
+ && key != Qt::Key_Alt && key != Qt::Key_Meta)
+ hideTip();
+ break;
+ }
+#endif
+ case QEvent::Leave:
+ hideTip();
+ break;
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::Wheel:
+ hideTipImmediately();
+ break;
+
+ case QEvent::MouseMove:
+ if (o == widget && !rect.isNull() && !rect.contains(static_cast<QMouseEvent*>(e)->pos()))
+ hideTip();
+ default:
+ break;
+ }
+ return false;
+}
+
+int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w)
+{
+ if (QApplication::desktop()->isVirtualDesktop())
+ return QApplication::desktop()->screenNumber(pos);
+ else
+ return QApplication::desktop()->screenNumber(w);
+}
+
+void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) {
+ //the stylesheet need to know the real parent
+ QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w));
+ //we force the style to be the QStyleSheetStyle, and force to clear the cache as well.
+ QTipLabel::instance->setStyleSheet(QLatin1String("/* */"));
+
+ // Set up for cleaning up this later...
+ QTipLabel::instance->styleSheetParent = w;
+ if (w) {
+ connect(w, SIGNAL(destroyed()),
+ QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
+ }
+ }
+#endif //QT_NO_STYLE_STYLESHEET
+
+
+#ifdef Q_WS_MAC
+ // When in full screen mode, there is no Dock nor Menu so we can use
+ // the whole screen for displaying the tooltip. However when not in
+ // full screen mode we need to save space for the dock, so we use
+ // availableGeometry instead.
+ extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
+ QRect screen;
+ if(qt_mac_app_fullscreen)
+ screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+ else
+ screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w));
+#else
+ QRect screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+#endif
+
+ QPoint p = pos;
+ p += QPoint(2,
+#ifdef Q_WS_WIN
+ 21
+#else
+ 16
+#endif
+ );
+ if (p.x() + this->width() > screen.x() + screen.width())
+ p.rx() -= 4 + this->width();
+ if (p.y() + this->height() > screen.y() + screen.height())
+ p.ry() -= 24 + this->height();
+ if (p.y() < screen.y())
+ p.setY(screen.y());
+ if (p.x() + this->width() > screen.x() + screen.width())
+ p.setX(screen.x() + screen.width() - this->width());
+ if (p.x() < screen.x())
+ p.setX(screen.x());
+ if (p.y() + this->height() > screen.y() + screen.height())
+ p.setY(screen.y() + screen.height() - this->height());
+ this->move(p);
+}
+
+bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o)
+{
+ if (QTipLabel::instance->text() != text)
+ return true;
+
+ if (o != widget)
+ return true;
+
+ if (!rect.isNull())
+ return !rect.contains(pos);
+ else
+ return false;
+}
+
+/*!
+ Shows \a text as a tool tip, with the global position \a pos as
+ the point of interest. The tool tip will be shown with a platform
+ specific offset from this point of interest.
+
+ If you specify a non-empty rect the tip will be hidden as soon
+ as you move your cursor out of this area.
+
+ The \a rect is in the coordinates of the widget you specify with
+ \a w. If the \a rect is not empty you must specify a widget.
+ Otherwise this argument can be 0 but it is used to determine the
+ appropriate screen on multi-head systems.
+
+ If \a text is empty the tool tip is hidden. If the text is the
+ same as the currently shown tooltip, the tip will \e not move.
+ You can force moving by first hiding the tip with an empty text,
+ and then showing the new tip at the new position.
+*/
+
+void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
+{
+ if (QTipLabel::instance && QTipLabel::instance->isVisible()){ // a tip does already exist
+ if (text.isEmpty()){ // empty text means hide current tip
+ QTipLabel::instance->hideTip();
+ return;
+ }
+ else if (!QTipLabel::instance->fadingOut){
+ // If the tip has changed, reuse the one
+ // that is showing (removes flickering)
+ QPoint localPos = pos;
+ if (w)
+ localPos = w->mapFromGlobal(pos);
+ if (QTipLabel::instance->tipChanged(localPos, text, w)){
+ QTipLabel::instance->reuseTip(text);
+ QTipLabel::instance->setTipRect(w, rect);
+ QTipLabel::instance->placeTip(pos, w);
+ }
+ return;
+ }
+ }
+
+ if (!text.isEmpty()){ // no tip can be reused, create new tip:
+#ifndef Q_WS_WIN
+ new QTipLabel(text, w); // sets QTipLabel::instance to itself
+#else
+ // On windows, we can't use the widget as parent otherwise the window will be
+ // raised when the tooltip will be shown
+ new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)));
+#endif
+ QTipLabel::instance->setTipRect(w, rect);
+ QTipLabel::instance->placeTip(pos, w);
+ QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label"));
+
+
+#if !defined(QT_NO_EFFECTS) && !defined(Q_WS_MAC)
+ if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip))
+ qFadeEffect(QTipLabel::instance);
+ else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip))
+ qScrollEffect(QTipLabel::instance);
+ else
+ QTipLabel::instance->show();
+#else
+ QTipLabel::instance->show();
+#endif
+ }
+}
+
+/*!
+ \overload
+
+ This is analogous to calling QToolTip::showText(\a pos, \a text, \a w, QRect())
+*/
+
+void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w)
+{
+ QToolTip::showText(pos, text, w, QRect());
+}
+
+
+/*!
+ \fn void QToolTip::hideText()
+ \since 4.2
+
+ Hides the tool tip. This is the same as calling showText() with an
+ empty string.
+
+ \sa showText()
+*/
+
+
+/*!
+ \since 4.4
+
+ Returns true if this tooltip is currently shown.
+
+ \sa showText()
+ */
+bool QToolTip::isVisible()
+{
+ return (QTipLabel::instance != 0 && QTipLabel::instance->isVisible());
+}
+
+/*!
+ \since 4.4
+
+ Returns the tooltip text, if a tooltip is visible, or an
+ empty string if a tooltip is not visible.
+ */
+QString QToolTip::text()
+{
+ if (QTipLabel::instance)
+ return QTipLabel::instance->text();
+ return QString();
+}
+
+
+Q_GLOBAL_STATIC(QPalette, tooltip_palette)
+
+/*!
+ Returns the palette used to render tooltips.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+*/
+QPalette QToolTip::palette()
+{
+ return *tooltip_palette();
+}
+
+/*!
+ \since 4.2
+
+ Returns the font used to render tooltips.
+*/
+QFont QToolTip::font()
+{
+ return QApplication::font("QTipLabel");
+}
+
+/*!
+ \since 4.2
+
+ Sets the \a palette used to render tooltips.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+*/
+void QToolTip::setPalette(const QPalette &palette)
+{
+ *tooltip_palette() = palette;
+ if (QTipLabel::instance)
+ QTipLabel::instance->setPalette(palette);
+}
+
+/*!
+ \since 4.2
+
+ Sets the \a font used to render tooltips.
+*/
+void QToolTip::setFont(const QFont &font)
+{
+ QApplication::setFont(font, "QTipLabel");
+}
+
+
+/*!
+ \fn void QToolTip::add(QWidget *widget, const QString &text)
+
+ Use QWidget::setToolTip() instead.
+
+ \oldcode
+ tip->add(widget, text);
+ \newcode
+ widget->setToolTip(text);
+ \endcode
+*/
+
+/*!
+ \fn void QToolTip::add(QWidget *widget, const QRect &rect, const QString &text)
+
+ Intercept the QEvent::ToolTip events in your widget's
+ QWidget::event() function and call QToolTip::showText() with the
+ text you want to display. The \l{widgets/tooltips}{Tooltips}
+ example illustrates this technique.
+*/
+
+/*!
+ \fn void QToolTip::remove(QWidget *widget)
+
+ Use QWidget::setToolTip() instead.
+
+ \oldcode
+ tip->remove(widget);
+ \newcode
+ widget->setToolTip("");
+ \endcode
+*/
+
+QT_END_NAMESPACE
+
+#include "qtooltip.moc"
+#endif // QT_NO_TOOLTIP
diff --git a/src/widgets/kernel/qtooltip.h b/src/widgets/kernel/qtooltip.h
new file mode 100644
index 0000000000..4195f1cb3e
--- /dev/null
+++ b/src/widgets/kernel/qtooltip.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTOOLTIP_H
+#define QTOOLTIP_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_TOOLTIP
+
+class Q_GUI_EXPORT QToolTip
+{
+ QToolTip();
+public:
+ static void showText(const QPoint &pos, const QString &text, QWidget *w = 0);
+ static void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect);
+ static inline void hideText() { showText(QPoint(), QString()); }
+
+ static bool isVisible();
+ static QString text();
+
+ static QPalette palette();
+ static void setPalette(const QPalette &);
+ static QFont font();
+ static void setFont(const QFont &);
+#ifdef QT3_SUPPORT
+ static inline QT3_SUPPORT void add(QWidget *w, const QString &s) { w->setToolTip(s); }
+ static inline QT3_SUPPORT void add(QWidget *w, const QRect &, const QString &s)
+ { w->setToolTip(s); }
+ static inline QT3_SUPPORT void remove(QWidget *w) { w->setToolTip(QString()); }
+#endif
+};
+
+#endif // QT_NO_TOOLTIP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTOOLTIP_H
diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp
new file mode 100644
index 0000000000..5e47ffa56b
--- /dev/null
+++ b/src/widgets/kernel/qwhatsthis.cpp
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwhatsthis.h"
+#ifndef QT_NO_WHATSTHIS
+#include "qpointer.h"
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qpixmap.h"
+#include "qpainter.h"
+#include "qtimer.h"
+#include "qhash.h"
+#include "qaction.h"
+#include "qcursor.h"
+#include "qbitmap.h"
+#include "qtextdocument.h"
+#include "../text/qtextdocumentlayout_p.h"
+#include "qtoolbutton.h"
+#include "qdebug.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#if defined(Q_WS_WIN)
+#include "qt_windows.h"
+#ifndef SPI_GETDROPSHADOW
+#define SPI_GETDROPSHADOW 0x1024
+#endif
+#endif
+#if defined(Q_WS_X11)
+#include "qx11info_x11.h"
+#include <qwidget.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWhatsThis
+ \brief The QWhatsThis class provides a simple description of any
+ widget, i.e. answering the question "What's This?".
+
+ \ingroup helpsystem
+
+
+ "What's This?" help is part of an application's online help
+ system, and provides users with information about the
+ functionality and usage of a particular widget. "What's This?"
+ help texts are typically longer and more detailed than \link
+ QToolTip tooltips\endlink, but generally provide less information
+ than that supplied by separate help windows.
+
+ QWhatsThis provides a single window with an explanatory text that
+ pops up when the user asks "What's This?". The default way for
+ users to ask the question is to move the focus to the relevant
+ widget and press Shift+F1. The help text appears immediately; it
+ goes away as soon as the user does something else.
+ (Note that if there is a shortcut for Shift+F1, this mechanism
+ will not work.) Some dialogs provide a "?" button that users can
+ click to enter "What's This?" mode; they then click the relevant
+ widget to pop up the "What's This?" window. It is also possible to
+ provide a a menu option or toolbar button to switch into "What's
+ This?" mode.
+
+ To add "What's This?" text to a widget or an action, you simply
+ call QWidget::setWhatsThis() or QAction::setWhatsThis().
+
+ The text can be either rich text or plain text. If you specify a
+ rich text formatted string, it will be rendered using the default
+ stylesheet, making it possible to embed images in the displayed
+ text. To be as fast as possible, the default stylesheet uses a
+ simple method to determine whether the text can be rendered as
+ plain text. See Qt::mightBeRichText() for details.
+
+ \snippet doc/src/snippets/whatsthis/whatsthis.cpp 0
+
+ An alternative way to enter "What's This?" mode is to call
+ createAction(), and add the returned QAction to either a menu or
+ a tool bar. By invoking this context help action (in the picture
+ below, the button with the arrow and question mark icon) the user
+ switches into "What's This?" mode. If they now click on a widget
+ the appropriate help text is shown. The mode is left when help is
+ given or when the user presses Esc.
+
+ \img whatsthis.png
+
+ You can enter "What's This?" mode programmatically with
+ enterWhatsThisMode(), check the mode with inWhatsThisMode(), and
+ return to normal mode with leaveWhatsThisMode().
+
+ If you want to control the "What's This?" behavior of a widget
+ manually see Qt::WA_CustomWhatsThis.
+
+ It is also possible to show different help texts for different
+ regions of a widget, by using a QHelpEvent of type
+ QEvent::WhatsThis. Intercept the help event in your widget's
+ QWidget::event() function and call QWhatsThis::showText() with the
+ text you want to display for the position specified in
+ QHelpEvent::pos(). If the text is rich text and the user clicks
+ on a link, the widget also receives a QWhatsThisClickedEvent with
+ the link's reference as QWhatsThisClickedEvent::href(). If a
+ QWhatsThisClickedEvent is handled (i.e. QWidget::event() returns
+ true), the help window remains visible. Call
+ QWhatsThis::hideText() to hide it explicitly.
+
+ \sa QToolTip
+*/
+
+Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o);
+
+class QWhatsThat : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor);
+ ~QWhatsThat() ;
+
+ static QWhatsThat *instance;
+
+protected:
+ void showEvent(QShowEvent *e);
+ void mousePressEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+ void mouseMoveEvent(QMouseEvent*);
+ void keyPressEvent(QKeyEvent*);
+ void paintEvent(QPaintEvent*);
+
+private:
+ QPointer<QWidget>widget;
+ bool pressed;
+ QString text;
+ QTextDocument* doc;
+ QString anchor;
+ QPixmap background;
+};
+
+QWhatsThat *QWhatsThat::instance = 0;
+
+// shadowWidth not const, for XP drop-shadow-fu turns it to 0
+static int shadowWidth = 6; // also used as '5' and '6' and even '8' below
+static const int vMargin = 8;
+static const int hMargin = 12;
+
+QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor)
+ : QWidget(parent, Qt::Popup),
+ widget(showTextFor), pressed(false), text(txt)
+{
+ delete instance;
+ instance = this;
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ if (parent)
+ setPalette(parent->palette());
+ setMouseTracking(true);
+ setFocusPolicy(Qt::StrongFocus);
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::ArrowCursor);
+#endif
+ QRect r;
+ doc = 0;
+ ensurePolished(); // Ensures style sheet font before size calc
+ if (Qt::mightBeRichText(text)) {
+ doc = new QTextDocument();
+ doc->setUndoRedoEnabled(false);
+ doc->setDefaultFont(QApplication::font(this));
+#ifdef QT_NO_TEXTHTMLPARSER
+ doc->setPlainText(text);
+#else
+ doc->setHtml(text);
+#endif
+ doc->setUndoRedoEnabled(false);
+ doc->adjustSize();
+ r.setTop(0);
+ r.setLeft(0);
+ r.setSize(doc->size().toSize());
+ }
+ else
+ {
+ int sw = QApplication::desktop()->width() / 3;
+ if (sw < 200)
+ sw = 200;
+ else if (sw > 300)
+ sw = 300;
+
+ r = fontMetrics().boundingRect(0, 0, sw, 1000,
+ Qt::AlignLeft + Qt::AlignTop
+ + Qt::TextWordWrap + Qt::TextExpandTabs,
+ text);
+ }
+#if defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ {
+ BOOL shadow;
+ SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
+ shadowWidth = shadow ? 0 : 6;
+ }
+#endif
+ resize(r.width() + 2*hMargin + shadowWidth, r.height() + 2*vMargin + shadowWidth);
+}
+
+QWhatsThat::~QWhatsThat()
+{
+ instance = 0;
+ if (doc)
+ delete doc;
+}
+
+void QWhatsThat::showEvent(QShowEvent *)
+{
+ background = QPixmap::grabWindow(QApplication::desktop()->internalWinId(),
+ x(), y(), width(), height());
+}
+
+void QWhatsThat::mousePressEvent(QMouseEvent* e)
+{
+ pressed = true;
+ if (e->button() == Qt::LeftButton && rect().contains(e->pos())) {
+ if (doc)
+ anchor = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ return;
+ }
+ close();
+}
+
+void QWhatsThat::mouseReleaseEvent(QMouseEvent* e)
+{
+ if (!pressed)
+ return;
+ if (widget && e->button() == Qt::LeftButton && doc && rect().contains(e->pos())) {
+ QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ QString href;
+ if (anchor == a)
+ href = a;
+ anchor.clear();
+ if (!href.isEmpty()) {
+ QWhatsThisClickedEvent e(href);
+ if (QApplication::sendEvent(widget, &e))
+ return;
+ }
+ }
+ close();
+}
+
+void QWhatsThat::mouseMoveEvent(QMouseEvent* e)
+{
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(e);
+#else
+ if (!doc)
+ return;
+ QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ if (!a.isEmpty())
+ setCursor(Qt::PointingHandCursor);
+ else
+ setCursor(Qt::ArrowCursor);
+#endif
+}
+
+void QWhatsThat::keyPressEvent(QKeyEvent*)
+{
+ close();
+}
+
+void QWhatsThat::paintEvent(QPaintEvent*)
+{
+ bool drawShadow = true;
+#if defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ {
+ BOOL shadow;
+ SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
+ drawShadow = !shadow;
+ }
+#elif defined(Q_WS_MAC) || defined(Q_WS_QWS)
+ drawShadow = false; // never draw it on OS X or QWS, as we get it for free
+#endif
+
+ QRect r = rect();
+ r.adjust(0, 0, -1, -1);
+ if (drawShadow)
+ r.adjust(0, 0, -shadowWidth, -shadowWidth);
+ QPainter p(this);
+ p.drawPixmap(0, 0, background);
+ p.setPen(QPen(palette().toolTipText(), 0));
+ p.setBrush(palette().toolTipBase());
+ p.drawRect(r);
+ int w = r.width();
+ int h = r.height();
+ p.setPen(palette().brush(QPalette::Dark).color());
+ p.drawRect(1, 1, w-2, h-2);
+ if (drawShadow) {
+ p.setPen(palette().shadow().color());
+ p.drawPoint(w + 5, 6);
+ p.drawLine(w + 3, 6, w + 5, 8);
+ p.drawLine(w + 1, 6, w + 5, 10);
+ int i;
+ for(i=7; i < h; i += 2)
+ p.drawLine(w, i, w + 5, i + 5);
+ for(i = w - i + h; i > 6; i -= 2)
+ p.drawLine(i, h, i + 5, h + 5);
+ for(; i > 0 ; i -= 2)
+ p.drawLine(6, h + 6 - i, i + 5, h + 5);
+ }
+ r.adjust(0, 0, 1, 1);
+ p.setPen(palette().toolTipText().color());
+ r.adjust(hMargin, vMargin, -hMargin, -vMargin);
+
+ if (doc) {
+ p.translate(r.x(), r.y());
+ QRect rect = r;
+ rect.translate(-r.x(), -r.y());
+ p.setClipRect(rect);
+ QAbstractTextDocumentLayout::PaintContext context;
+ context.palette.setBrush(QPalette::Text, context.palette.toolTipText());
+ doc->documentLayout()->draw(&p, context);
+ }
+ else
+ {
+ p.drawText(r, Qt::AlignLeft + Qt::AlignTop + Qt::TextWordWrap + Qt::TextExpandTabs, text);
+ }
+}
+
+static const char * const button_image[] = {
+"16 16 3 1",
+" c None",
+"o c #000000",
+"a c #000080",
+"o aaaaa ",
+"oo aaa aaa ",
+"ooo aaa aaa",
+"oooo aa aa",
+"ooooo aa aa",
+"oooooo a aaa",
+"ooooooo aaa ",
+"oooooooo aaa ",
+"ooooooooo aaa ",
+"ooooo aaa ",
+"oo ooo ",
+"o ooo aaa ",
+" ooo aaa ",
+" ooo ",
+" ooo ",
+" ooo "};
+
+class QWhatsThisPrivate : public QObject
+{
+ public:
+ QWhatsThisPrivate();
+ ~QWhatsThisPrivate();
+ static QWhatsThisPrivate *instance;
+ bool eventFilter(QObject *, QEvent *);
+ QPointer<QAction> action;
+#ifdef QT3_SUPPORT
+ QPointer<QToolButton> button;
+#endif
+ static void say(QWidget *, const QString &, int x = 0, int y = 0);
+ static void notifyToplevels(QEvent *e);
+ bool leaveOnMouseRelease;
+};
+
+void QWhatsThisPrivate::notifyToplevels(QEvent *e)
+{
+ QWidgetList toplevels = QApplication::topLevelWidgets();
+ for (int i = 0; i < toplevels.count(); ++i) {
+ register QWidget *w = toplevels.at(i);
+ QApplication::sendEvent(w, e);
+ }
+}
+
+QWhatsThisPrivate *QWhatsThisPrivate::instance = 0;
+
+QWhatsThisPrivate::QWhatsThisPrivate()
+ : leaveOnMouseRelease(false)
+{
+ instance = this;
+ qApp->installEventFilter(this);
+
+ QPoint pos = QCursor::pos();
+ if (QWidget *w = QApplication::widgetAt(pos)) {
+ QHelpEvent e(QEvent::QueryWhatsThis, w->mapFromGlobal(pos), pos);
+ bool sentEvent = QApplication::sendEvent(w, &e);
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(sentEvent);
+#else
+ QApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
+ Qt::ForbiddenCursor:Qt::WhatsThisCursor);
+ } else {
+ QApplication::setOverrideCursor(Qt::WhatsThisCursor);
+#endif
+ }
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpStart);
+#endif
+}
+
+QWhatsThisPrivate::~QWhatsThisPrivate()
+{
+ if (action)
+ action->setChecked(false);
+#ifdef QT3_SUPPORT
+ if (button)
+ button->setChecked(false);
+#endif
+#ifndef QT_NO_CURSOR
+ QApplication::restoreOverrideCursor();
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpEnd);
+#endif
+ instance = 0;
+}
+
+bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
+{
+ if (!o->isWidgetType())
+ return false;
+ QWidget * w = static_cast<QWidget *>(o);
+ bool customWhatsThis = w->testAttribute(Qt::WA_CustomWhatsThis);
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::RightButton || customWhatsThis)
+ return false;
+ QHelpEvent e(QEvent::WhatsThis, me->pos(), me->globalPos());
+ if (!QApplication::sendEvent(w, &e) || !e.isAccepted())
+ leaveOnMouseRelease = true;
+
+ } break;
+
+ case QEvent::MouseMove:
+ {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QHelpEvent e(QEvent::QueryWhatsThis, me->pos(), me->globalPos());
+ bool sentEvent = QApplication::sendEvent(w, &e);
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(sentEvent);
+#else
+ QApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())?
+ Qt::ForbiddenCursor:Qt::WhatsThisCursor);
+#endif
+ }
+ // fall through
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ if (leaveOnMouseRelease && e->type() == QEvent::MouseButtonRelease)
+ QWhatsThis::leaveWhatsThisMode();
+ if (static_cast<QMouseEvent*>(e)->button() == Qt::RightButton || customWhatsThis)
+ return false; // ignore RMB release
+ break;
+ case QEvent::KeyPress:
+ {
+ QKeyEvent* kev = (QKeyEvent*)e;
+
+ if (kev->key() == Qt::Key_Escape) {
+ QWhatsThis::leaveWhatsThisMode();
+ return true;
+ } else if (customWhatsThis) {
+ return false;
+ } else if (kev->key() == Qt::Key_Menu ||
+ (kev->key() == Qt::Key_F10 &&
+ kev->modifiers() == Qt::ShiftModifier)) {
+ // we don't react to these keys, they are used for context menus
+ return false;
+ } else if (kev->key() != Qt::Key_Shift && kev->key() != Qt::Key_Alt // not a modifier key
+ && kev->key() != Qt::Key_Control && kev->key() != Qt::Key_Meta) {
+ QWhatsThis::leaveWhatsThisMode();
+ }
+ } break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+class QWhatsThisAction: public QAction
+{
+ Q_OBJECT
+
+public:
+ explicit QWhatsThisAction(QObject* parent = 0);
+
+private slots:
+ void actionTriggered();
+};
+
+QWhatsThisAction::QWhatsThisAction(QObject *parent) : QAction(tr("What's This?"), parent)
+{
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ QPixmap p((const char**)button_image);
+ setIcon(p);
+#endif
+ setCheckable(true);
+ connect(this, SIGNAL(triggered()), this, SLOT(actionTriggered()));
+#ifndef QT_NO_SHORTCUT
+ setShortcut(Qt::ShiftModifier + Qt::Key_F1);
+#endif
+}
+
+void QWhatsThisAction::actionTriggered()
+{
+ if (isChecked()) {
+ QWhatsThis::enterWhatsThisMode();
+ QWhatsThisPrivate::instance->action = this;
+ }
+}
+
+QWhatsThis::QWhatsThis()
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+
+ Sets the What's This text \a s for the widget \a w.
+
+ Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
+*/
+void QWhatsThis::add(QWidget *w, const QString &s)
+{
+ w->setWhatsThis(s);
+}
+
+/*!
+ \obsolete
+
+ Remove's the What's This text for the widget \a w.
+
+ Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
+*/
+void QWhatsThis::remove(QWidget *w)
+{
+ w->setWhatsThis(QString());
+}
+
+class QWhatsThisButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ QWhatsThisButton(QWidget *p) : QToolButton(p) {
+ setCheckable(true);
+ QPixmap pix( const_cast<const char**>(button_image) );
+ setIcon( pix );
+ QObject::connect(this, SIGNAL(toggled(bool)), this, SLOT(whatToggled(bool)));
+ setAutoRaise(true);
+ setFocusPolicy(Qt::NoFocus);
+ }
+
+public slots:
+ void whatToggled(bool b) {
+ if (b) {
+ QWhatsThis::enterWhatsThisMode();
+ QWhatsThisPrivate::instance->button = this;
+ }
+ }
+};
+
+/*!
+ Returns a new "What's This?" QToolButton with the given \a
+ parent. To do this now, create your own QToolButton and a
+ QWhatsThis object and call the QWhatsThis object's showText()
+ function when the QToolButton is invoked.
+
+ Use createAction() instead.
+*/
+QToolButton * QWhatsThis::whatsThisButton(QWidget * parent)
+{
+ return new QWhatsThisButton(parent);
+}
+#endif
+
+/*!
+ This function switches the user interface into "What's This?"
+ mode. The user interface can be switched back into normal mode by
+ the user (e.g. by them clicking or pressing Esc), or
+ programmatically by calling leaveWhatsThisMode().
+
+ When entering "What's This?" mode, a QEvent of type
+ Qt::EnterWhatsThisMode is sent to all toplevel widgets.
+
+ \sa inWhatsThisMode() leaveWhatsThisMode()
+*/
+void QWhatsThis::enterWhatsThisMode()
+{
+ if (QWhatsThisPrivate::instance)
+ return;
+ (void) new QWhatsThisPrivate;
+ QEvent e(QEvent::EnterWhatsThisMode);
+ QWhatsThisPrivate::notifyToplevels(&e);
+ }
+
+/*!
+ Returns true if the user interface is in "What's This?" mode;
+ otherwise returns false.
+
+ \sa enterWhatsThisMode()
+*/
+bool QWhatsThis::inWhatsThisMode()
+{
+ return (QWhatsThisPrivate::instance != 0);
+}
+
+/*!
+ If the user interface is in "What's This?" mode, this function
+ switches back to normal mode; otherwise it does nothing.
+
+ When leaving "What's This?" mode, a QEvent of type
+ Qt::LeaveWhatsThisMode is sent to all toplevel widgets.
+
+ \sa enterWhatsThisMode() inWhatsThisMode()
+*/
+void QWhatsThis::leaveWhatsThisMode()
+{
+ delete QWhatsThisPrivate::instance;
+ QEvent e(QEvent::LeaveWhatsThisMode);
+ QWhatsThisPrivate::notifyToplevels(&e);
+}
+
+void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y)
+{
+ if (text.size() == 0)
+ return;
+ // make a fresh widget, and set it up
+ QWhatsThat *whatsThat = new QWhatsThat(
+ text,
+#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
+ QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()),
+#else
+ 0,
+#endif
+ widget
+ );
+
+
+ // okay, now to find a suitable location
+
+ int scr = (widget ?
+ QApplication::desktop()->screenNumber(widget) :
+#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
+ QCursor::x11Screen()
+#else
+ QApplication::desktop()->screenNumber(QPoint(x,y))
+#endif // Q_WS_X11
+ );
+ QRect screen = QApplication::desktop()->screenGeometry(scr);
+
+ int w = whatsThat->width();
+ int h = whatsThat->height();
+ int sx = screen.x();
+ int sy = screen.y();
+
+ // first try locating the widget immediately above/below,
+ // with nice alignment if possible.
+ QPoint pos;
+ if (widget)
+ pos = widget->mapToGlobal(QPoint(0,0));
+
+ if (widget && w > widget->width() + 16)
+ x = pos.x() + widget->width()/2 - w/2;
+ else
+ x = x - w/2;
+
+ // squeeze it in if that would result in part of what's this
+ // being only partially visible
+ if (x + w + shadowWidth > sx+screen.width())
+ x = (widget? (qMin(screen.width(),
+ pos.x() + widget->width())
+ ) : screen.width())
+ - w;
+
+ if (x < sx)
+ x = sx;
+
+ if (widget && h > widget->height() + 16) {
+ y = pos.y() + widget->height() + 2; // below, two pixels spacing
+ // what's this is above or below, wherever there's most space
+ if (y + h + 10 > sy+screen.height())
+ y = pos.y() + 2 - shadowWidth - h; // above, overlap
+ }
+ y = y + 2;
+
+ // squeeze it in if that would result in part of what's this
+ // being only partially visible
+ if (y + h + shadowWidth > sy+screen.height())
+ y = (widget ? (qMin(screen.height(),
+ pos.y() + widget->height())
+ ) : screen.height())
+ - h;
+ if (y < sy)
+ y = sy;
+
+ whatsThat->move(x, y);
+ whatsThat->show();
+ whatsThat->grabKeyboard();
+}
+
+/*!
+ Shows \a text as a "What's This?" window, at global position \a
+ pos. The optional widget argument, \a w, is used to determine the
+ appropriate screen on multi-head systems.
+
+ \sa hideText()
+*/
+void QWhatsThis::showText(const QPoint &pos, const QString &text, QWidget *w)
+{
+ leaveWhatsThisMode();
+ QWhatsThisPrivate::say(w, text, pos.x(), pos.y());
+}
+
+/*!
+ If a "What's This?" window is showing, this destroys it.
+
+ \sa showText()
+*/
+void QWhatsThis::hideText()
+{
+ qDeleteInEventHandler(QWhatsThat::instance);
+}
+
+/*!
+ Returns a ready-made QAction, used to invoke "What's This?" context
+ help, with the given \a parent.
+
+ The returned QAction provides a convenient way to let users enter
+ "What's This?" mode.
+*/
+QAction *QWhatsThis::createAction(QObject *parent)
+{
+ return new QWhatsThisAction(parent);
+}
+
+QT_END_NAMESPACE
+
+#include "qwhatsthis.moc"
+
+#endif // QT_NO_WHATSTHIS
diff --git a/src/widgets/kernel/qwhatsthis.h b/src/widgets/kernel/qwhatsthis.h
new file mode 100644
index 0000000000..c2e396d0d0
--- /dev/null
+++ b/src/widgets/kernel/qwhatsthis.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWHATSTHIS_H
+#define QWHATSTHIS_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qcursor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_WHATSTHIS
+
+class QAction;
+#ifdef QT3_SUPPORT
+class QToolButton;
+#endif
+
+class Q_GUI_EXPORT QWhatsThis
+{
+ QWhatsThis();
+
+public:
+ static void enterWhatsThisMode();
+ static bool inWhatsThisMode();
+ static void leaveWhatsThisMode();
+
+ static void showText(const QPoint &pos, const QString &text, QWidget *w = 0);
+ static void hideText();
+
+ static QAction *createAction(QObject *parent = 0);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT void add(QWidget *w, const QString &s);
+ static QT3_SUPPORT void remove(QWidget *);
+ static QT3_SUPPORT QToolButton *whatsThisButton(QWidget *parent);
+#endif
+};
+
+#endif // QT_NO_WHATSTHIS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWHATSTHIS_H
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
new file mode 100644
index 0000000000..b6e6a56f4a
--- /dev/null
+++ b/src/widgets/kernel/qwidget.cpp
@@ -0,0 +1,12677 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qbrush.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qhash.h"
+#include "qlayout.h"
+#include "qmenu.h"
+#include "qmetaobject.h"
+#include "qpixmap.h"
+#include "qpointer.h"
+#include "qstack.h"
+#include "qstyle.h"
+#include "qstylefactory.h"
+#include "qvariant.h"
+#include "qwidget.h"
+#include "qstyleoption.h"
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
+#if defined(Q_WS_WIN)
+# include "qt_windows.h"
+#endif
+#ifdef Q_WS_MAC
+# include "qt_mac_p.h"
+# include "qt_cocoa_helpers_mac_p.h"
+# include "qmainwindow.h"
+# include "qtoolbar.h"
+# include <private/qmainwindowlayout_p.h>
+#endif
+#if defined(Q_WS_QWS)
+# include "qwsdisplay_qws.h"
+# include "qwsmanager_qws.h"
+# include "qpaintengine.h" // for PorterDuff
+# include "private/qwindowsurface_qws_p.h"
+#endif
+#if defined(Q_WS_QPA)
+#include "qplatformwindow_qpa.h"
+#include "private/qwidgetwindow_qpa_p.h"
+#endif
+#include "qpainter.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#include "qdebug.h"
+#include "private/qstylesheetstyle_p.h"
+#include "private/qstyle_p.h"
+#include "private/qinputcontext_p.h"
+#include "qfileinfo.h"
+#include "private/qsoftkeymanager_p.h"
+
+#if defined (Q_WS_WIN)
+# include <private/qwininputcontext_p.h>
+#endif
+
+#if defined(Q_WS_X11)
+# include <private/qpaintengine_x11_p.h>
+# include "qx11info_x11.h"
+#endif
+
+#include <private/qgraphicseffect_p.h>
+#include <private/qwindowsurface_p.h>
+#include <private/qbackingstore_p.h>
+#ifdef Q_WS_MAC
+# include <private/qpaintengine_mac_p.h>
+#endif
+#include <private/qpaintengine_raster_p.h>
+
+#if defined(Q_OS_SYMBIAN)
+#include "private/qt_s60_p.h"
+#endif
+
+#include "qwidget_p.h"
+#include "qaction_p.h"
+#include "qlayout_p.h"
+#include "QtGui/qgraphicsproxywidget.h"
+#include "QtGui/qgraphicsscene.h"
+#include "private/qgraphicsproxywidget_p.h"
+#include "QtGui/qabstractscrollarea.h"
+#include "private/qabstractscrollarea_p.h"
+#include "private/qevent_p.h"
+
+#include "private/qgesturemanager_p.h"
+
+#ifdef QT_KEYPAD_NAVIGATION
+#include "qtabwidget.h" // Needed in inTabWidget()
+#endif // QT_KEYPAD_NAVIGATION
+
+#ifdef Q_WS_S60
+#include <aknappui.h>
+#endif
+
+// widget/widget data creation count
+//#define QWIDGET_EXTRA_DEBUG
+//#define ALIEN_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_WS_QWS)
+static bool qt_enable_backingstore = true;
+#endif
+#ifdef Q_WS_X11
+// for compatibility with Qt 4.0
+Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
+{
+ qt_enable_backingstore = enable;
+}
+#endif
+
+#if defined(QT_MAC_USE_COCOA)
+bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false;
+#endif
+
+static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
+{
+ return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
+ qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
+}
+
+static inline bool hasBackingStoreSupport()
+{
+ return true;
+}
+
+#ifdef Q_WS_MAC
+# define QT_NO_PAINT_DEBUG
+#endif
+
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
+extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
+
+/*!
+ \internal
+ \class QWidgetBackingStoreTracker
+ \brief Class which allows tracking of which widgets are using a given backing store
+
+ QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer,
+ which maintains a list of the QWidgets which are currently using the backing
+ store. This list is modified via the registerWidget and unregisterWidget functions.
+ */
+
+QWidgetBackingStoreTracker::QWidgetBackingStoreTracker()
+ : m_ptr(0)
+{
+
+}
+
+QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker()
+{
+ delete m_ptr;
+}
+
+/*!
+ \internal
+ Destroy the contained QWidgetBackingStore, if not null, and clear the list of
+ widgets using the backing store, then create a new QWidgetBackingStore, providing
+ the QWidget.
+ */
+void QWidgetBackingStoreTracker::create(QWidget *widget)
+{
+ destroy();
+ m_ptr = new QWidgetBackingStore(widget);
+}
+
+/*!
+ \internal
+ Destroy the contained QWidgetBackingStore, if not null, and clear the list of
+ widgets using the backing store.
+ */
+void QWidgetBackingStoreTracker::destroy()
+{
+ delete m_ptr;
+ m_ptr = 0;
+ m_widgets.clear();
+}
+
+/*!
+ \internal
+ Add the widget to the list of widgets currently using the backing store.
+ If the widget was already in the list, this function is a no-op.
+ */
+void QWidgetBackingStoreTracker::registerWidget(QWidget *w)
+{
+ Q_ASSERT(m_ptr);
+ Q_ASSERT(w->internalWinId());
+ Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr);
+ m_widgets.insert(w);
+}
+
+/*!
+ \internal
+ Remove the widget from the list of widgets currently using the backing store.
+ If the widget was in the list, and removing it causes the list to be empty,
+ the backing store is deleted.
+ If the widget was not in the list, this function is a no-op.
+ */
+void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w)
+{
+ if (m_widgets.remove(w) && m_widgets.isEmpty()) {
+ delete m_ptr;
+ m_ptr = 0;
+ }
+}
+
+/*!
+ \internal
+ Recursively remove widget and all of its descendents.
+ */
+void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget)
+{
+ unregisterWidget(widget);
+ foreach (QObject *child, widget->children())
+ if (QWidget *childWidget = qobject_cast<QWidget *>(child))
+ unregisterWidgetSubtree(childWidget);
+}
+
+QWidgetPrivate::QWidgetPrivate(int version)
+ : QObjectPrivate(version)
+ , extra(0)
+ , focus_next(0)
+ , focus_prev(0)
+ , focus_child(0)
+ , layout(0)
+ , needsFlush(0)
+ , redirectDev(0)
+ , widgetItem(0)
+ , extraPaintEngine(0)
+ , polished(0)
+ , graphicsEffect(0)
+#if !defined(QT_NO_IM)
+ , imHints(Qt::ImhNone)
+#endif
+ , inheritedFontResolveMask(0)
+ , inheritedPaletteResolveMask(0)
+ , leftmargin(0)
+ , topmargin(0)
+ , rightmargin(0)
+ , bottommargin(0)
+ , leftLayoutItemMargin(0)
+ , topLayoutItemMargin(0)
+ , rightLayoutItemMargin(0)
+ , bottomLayoutItemMargin(0)
+ , hd(0)
+ , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
+ , fg_role(QPalette::NoRole)
+ , bg_role(QPalette::NoRole)
+ , dirtyOpaqueChildren(1)
+ , isOpaque(0)
+ , inDirtyList(0)
+ , isScrolled(0)
+ , isMoved(0)
+ , isGLWidget(0)
+ , usesDoubleBufferedGLContext(0)
+#ifndef QT_NO_IM
+ , inheritsInputMethodHints(0)
+#endif
+#if defined(Q_WS_X11)
+ , picture(0)
+#elif defined(Q_WS_WIN)
+ , noPaintOnScreen(0)
+ #ifndef QT_NO_GESTURES
+ , nativeGesturePanEnabled(0)
+ #endif
+#elif defined(Q_WS_MAC)
+ , needWindowChange(0)
+ , window_event(0)
+ , qd_hd(0)
+#elif defined(Q_OS_SYMBIAN)
+ , symbianScreenNumber(0)
+ , fixNativeOrientationCalled(false)
+#endif
+{
+ if (!qApp) {
+ qFatal("QWidget: Must construct a QApplication before a QPaintDevice");
+ return;
+ }
+
+ if (version != QObjectPrivateVersion)
+ qFatal("Cannot mix incompatible Qt libraries");
+
+ isWidget = true;
+ memset(high_attributes, 0, sizeof(high_attributes));
+#if QT_MAC_USE_COCOA
+ drawRectOriginalAdded = false;
+ originalDrawMethod = true;
+ changeMethods = false;
+ isInUnifiedToolbar = false;
+ unifiedSurface = 0;
+ toolbar_ancestor = 0;
+ flushRequested = false;
+ touchEventsEnabled = false;
+#endif // QT_MAC_USE_COCOA
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "widgets" << ++count;
+#endif
+}
+
+
+QWidgetPrivate::~QWidgetPrivate()
+{
+ if (widgetItem)
+ widgetItem->wid = 0;
+
+ if (extra)
+ deleteExtra();
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ delete graphicsEffect;
+#endif //QT_NO_GRAPHICSEFFECT
+}
+
+class QDummyWindowSurface : public QWindowSurface
+{
+public:
+ QDummyWindowSurface(QWindow *window) : QWindowSurface(window) {}
+ QPaintDevice *paintDevice() { return static_cast<QWidgetWindow *>(window())->widget(); }
+ void flush(QWindow *, const QRegion &, const QPoint &) {}
+};
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
+{
+ Q_Q(QWidget);
+
+ QWindowSurface *surface;
+#ifndef QT_NO_PROPERTIES
+ if (q->property("_q_DummyWindowSurface").toBool()) {
+ surface = new QDummyWindowSurface(q->windowHandle());
+ } else
+#endif
+ {
+ QWindow *win = topData()->window;
+ surface = QGuiApplicationPrivate::platformIntegration()->createWindowSurface(win, win->winId());
+ }
+
+ return surface;
+}
+
+/*!
+ \internal
+*/
+void QWidgetPrivate::scrollChildren(int dx, int dy)
+{
+ Q_Q(QWidget);
+ if (q->children().size() > 0) { // scroll children
+ QPoint pd(dx, dy);
+ QObjectList childObjects = q->children();
+ for (int i = 0; i < childObjects.size(); ++i) { // move all children
+ QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
+ if (w && !w->isWindow()) {
+ QPoint oldp = w->pos();
+ QRect r(w->pos() + pd, w->size());
+ w->data->crect = r;
+#ifndef Q_WS_QWS
+ if (w->testAttribute(Qt::WA_WState_Created))
+ w->d_func()->setWSGeometry();
+#endif
+ w->d_func()->setDirtyOpaqueRegion();
+ QMoveEvent e(r.topLeft(), oldp);
+ QApplication::sendEvent(w, &e);
+ }
+ }
+ }
+}
+
+QInputContext *QWidgetPrivate::assignedInputContext() const
+{
+#ifndef QT_NO_IM
+ const QWidget *widget = q_func();
+ while (widget) {
+ if (QInputContext *qic = widget->d_func()->ic)
+ return qic;
+ widget = widget->parentWidget();
+ }
+#endif
+ return 0;
+}
+
+QInputContext *QWidgetPrivate::inputContext() const
+{
+#ifndef QT_NO_IM
+ if (QInputContext *qic = assignedInputContext())
+ return qic;
+ return qApp->inputContext();
+#else
+ return 0;
+#endif
+}
+
+/*!
+ This function returns the QInputContext for this widget. By
+ default the input context is inherited from the widgets
+ parent. For toplevels it is inherited from QApplication.
+
+ You can override this and set a special input context for this
+ widget by using the setInputContext() method.
+
+ \sa setInputContext()
+*/
+QInputContext *QWidget::inputContext()
+{
+ Q_D(QWidget);
+ if (!testAttribute(Qt::WA_InputMethodEnabled))
+ return 0;
+
+ return d->inputContext();
+}
+
+/*!
+ This function sets the input context \a context
+ on this widget.
+
+ Qt takes ownership of the given input \a context.
+
+ \sa inputContext()
+*/
+void QWidget::setInputContext(QInputContext *context)
+{
+ Q_D(QWidget);
+ if (!testAttribute(Qt::WA_InputMethodEnabled))
+ return;
+#ifndef QT_NO_IM
+ if (context == d->ic)
+ return;
+ if (d->ic)
+ delete d->ic;
+ d->ic = context;
+ if (d->ic)
+ d->ic->setParent(this);
+#endif
+}
+
+
+/*!
+ \obsolete
+
+ This function can be called on the widget that currently has focus
+ to reset the input method operating on it.
+
+ This function is providing for convenience, instead you should use
+ \l{QInputContext::}{reset()} on the input context that was
+ returned by inputContext().
+
+ \sa QInputContext, inputContext(), QInputContext::reset()
+*/
+void QWidget::resetInputContext()
+{
+ if (!hasFocus())
+ return;
+#ifndef QT_NO_IM
+ QInputContext *qic = this->inputContext();
+ if(qic)
+ qic->reset();
+#endif // QT_NO_IM
+}
+
+#ifdef QT_KEYPAD_NAVIGATION
+QPointer<QWidget> QWidgetPrivate::editingWidget;
+
+/*!
+ Returns true if this widget currently has edit focus; otherwise false.
+
+ This feature is only available in Qt for Embedded Linux.
+
+ \sa setEditFocus(), QApplication::keypadNavigationEnabled()
+*/
+bool QWidget::hasEditFocus() const
+{
+ const QWidget* w = this;
+ while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
+ w = w->d_func()->extra->focus_proxy;
+ return QWidgetPrivate::editingWidget == w;
+}
+
+/*!
+ \fn void QWidget::setEditFocus(bool enable)
+
+ If \a enable is true, make this widget have edit focus, in which
+ case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
+ normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
+ change focus.
+
+ This feature is only available in Qt for Embedded Linux and Qt
+ for Symbian.
+
+ \sa hasEditFocus(), QApplication::keypadNavigationEnabled()
+*/
+void QWidget::setEditFocus(bool on)
+{
+ QWidget *f = this;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
+ QWidgetPrivate::editingWidget->setEditFocus(false);
+
+ if (on && !f->hasFocus())
+ f->setFocus();
+
+ if ((!on && !QWidgetPrivate::editingWidget)
+ || (on && QWidgetPrivate::editingWidget == f)) {
+ return;
+ }
+
+ if (!on && QWidgetPrivate::editingWidget == f) {
+ QWidgetPrivate::editingWidget = 0;
+ QEvent event(QEvent::LeaveEditFocus);
+ QApplication::sendEvent(f, &event);
+ QApplication::sendEvent(f->style(), &event);
+ } else if (on) {
+ QWidgetPrivate::editingWidget = f;
+ QEvent event(QEvent::EnterEditFocus);
+ QApplication::sendEvent(f, &event);
+ QApplication::sendEvent(f->style(), &event);
+ }
+}
+#endif
+
+/*!
+ \property QWidget::autoFillBackground
+ \brief whether the widget background is filled automatically
+ \since 4.1
+
+ If enabled, this property will cause Qt to fill the background of the
+ widget before invoking the paint event. The color used is defined by the
+ QPalette::Window color role from the widget's \l{QPalette}{palette}.
+
+ In addition, Windows are always filled with QPalette::Window, unless the
+ WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
+
+ This property cannot be turned off (i.e., set to false) if a widget's
+ parent has a static gradient for its background.
+
+ \warning Use this property with caution in conjunction with
+ \l{Qt Style Sheets}. When a widget has a style sheet with a valid
+ background or a border-image, this property is automatically disabled.
+
+ By default, this property is false.
+
+ \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
+ {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
+*/
+bool QWidget::autoFillBackground() const
+{
+ Q_D(const QWidget);
+ return d->extra && d->extra->autoFillBackground;
+}
+
+void QWidget::setAutoFillBackground(bool enabled)
+{
+ Q_D(QWidget);
+ if (!d->extra)
+ d->createExtra();
+ if (d->extra->autoFillBackground == enabled)
+ return;
+
+ d->extra->autoFillBackground = enabled;
+ d->updateIsOpaque();
+ update();
+ d->updateIsOpaque();
+}
+
+/*!
+ \class QWidget
+ \brief The QWidget class is the base class of all user interface objects.
+
+ \ingroup basicwidgets
+
+ The widget is the atom of the user interface: it receives mouse, keyboard
+ and other events from the window system, and paints a representation of
+ itself on the screen. Every widget is rectangular, and they are sorted in a
+ Z-order. A widget is clipped by its parent and by the widgets in front of
+ it.
+
+ A widget that is not embedded in a parent widget is called a window.
+ Usually, windows have a frame and a title bar, although it is also possible
+ to create windows without such decoration using suitable
+ \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
+ subclasses of QDialog are the most common window types.
+
+ Every widget's constructor accepts one or two standard arguments:
+
+ \list 1
+ \i \c{QWidget *parent = 0} is the parent of the new widget. If it is 0
+ (the default), the new widget will be a window. If not, it will be
+ a child of \e parent, and be constrained by \e parent's geometry
+ (unless you specify Qt::Window as window flag).
+ \i \c{Qt::WindowFlags f = 0} (where available) sets the window flags;
+ the default is suitable for almost all widgets, but to get, for
+ example, a window without a window system frame, you must use
+ special flags.
+ \endlist
+
+ QWidget has many member functions, but some of them have little direct
+ functionality; for example, QWidget has a font property, but never uses
+ this itself. There are many subclasses which provide real functionality,
+ such as QLabel, QPushButton, QListWidget, and QTabWidget.
+
+
+ \section1 Top-Level and Child Widgets
+
+ A widget without a parent widget is always an independent window (top-level
+ widget). For these widgets, setWindowTitle() and setWindowIcon() set the
+ title bar and icon respectively.
+
+ Non-window widgets are child widgets, displayed within their parent
+ widgets. Most widgets in Qt are mainly useful as child widgets. For
+ example, it is possible to display a button as a top-level window, but most
+ people prefer to put their buttons inside other widgets, such as QDialog.
+
+ \image parent-child-widgets.png A parent widget containing various child widgets.
+
+ The diagram above shows a QGroupBox widget being used to hold various child
+ widgets in a layout provided by QGridLayout. The QLabel child widgets have
+ been outlined to indicate their full sizes.
+
+ If you want to use a QWidget to hold child widgets you will usually want to
+ add a layout to the parent QWidget. See \l{Layout Management} for more
+ information.
+
+
+ \section1 Composite Widgets
+
+ When a widget is used as a container to group a number of child widgets, it
+ is known as a composite widget. These can be created by constructing a
+ widget with the required visual properties - a QFrame, for example - and
+ adding child widgets to it, usually managed by a layout. The above diagram
+ shows such a composite widget that was created using \l{Qt Designer}.
+
+ Composite widgets can also be created by subclassing a standard widget,
+ such as QWidget or QFrame, and adding the necessary layout and child
+ widgets in the constructor of the subclass. Many of the \l{Qt Examples}
+ {examples provided with Qt} use this approach, and it is also covered in
+ the Qt \l{Tutorials}.
+
+
+ \section1 Custom Widgets and Painting
+
+ Since QWidget is a subclass of QPaintDevice, subclasses can be used to
+ display custom content that is composed using a series of painting
+ operations with an instance of the QPainter class. This approach contrasts
+ with the canvas-style approach used by the \l{Graphics View}
+ {Graphics View Framework} where items are added to a scene by the
+ application and are rendered by the framework itself.
+
+ Each widget performs all painting operations from within its paintEvent()
+ function. This is called whenever the widget needs to be redrawn, either
+ as a result of some external change or when requested by the application.
+
+ The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
+ can handle paint events.
+
+
+ \section1 Size Hints and Size Policies
+
+ When implementing a new widget, it is almost always useful to reimplement
+ sizeHint() to provide a reasonable default size for the widget and to set
+ the correct size policy with setSizePolicy().
+
+ By default, composite widgets which do not provide a size hint will be
+ sized according to the space requirements of their child widgets.
+
+ The size policy lets you supply good default behavior for the layout
+ management system, so that other widgets can contain and manage yours
+ easily. The default size policy indicates that the size hint represents
+ the preferred size of the widget, and this is often good enough for many
+ widgets.
+
+ \note The size of top-level widgets are constrained to 2/3 of the desktop's
+ height and width. You can resize() the widget manually if these bounds are
+ inadequate.
+
+
+ \section1 Events
+
+ Widgets respond to events that are typically caused by user actions. Qt
+ delivers events to widgets by calling specific event handler functions with
+ instances of QEvent subclasses containing information about each event.
+
+ If your widget only contains child widgets, you probably do not need to
+ implement any event handlers. If you want to detect a mouse click in a
+ child widget call the child's underMouse() function inside the widget's
+ mousePressEvent().
+
+ The \l{widgets/scribble}{Scribble example} implements a wider set of
+ events to handle mouse movement, button presses, and window resizing.
+
+ You will need to supply the behavior and content for your own widgets, but
+ here is a brief overview of the events that are relevant to QWidget,
+ starting with the most common ones:
+
+ \list
+ \i paintEvent() is called whenever the widget needs to be repainted.
+ Every widget displaying custom content must implement it. Painting
+ using a QPainter can only take place in a paintEvent() or a
+ function called by a paintEvent().
+ \i resizeEvent() is called when the widget has been resized.
+ \i mousePressEvent() is called when a mouse button is pressed while
+ the mouse cursor is inside the widget, or when the widget has
+ grabbed the mouse using grabMouse(). Pressing the mouse without
+ releasing it is effectively the same as calling grabMouse().
+ \i mouseReleaseEvent() is called when a mouse button is released. A
+ widget receives mouse release events when it has received the
+ corresponding mouse press event. This means that if the user
+ presses the mouse inside \e your widget, then drags the mouse
+ somewhere else before releasing the mouse button, \e your widget
+ receives the release event. There is one exception: if a popup menu
+ appears while the mouse button is held down, this popup immediately
+ steals the mouse events.
+ \i mouseDoubleClickEvent() is called when the user double-clicks in
+ the widget. If the user double-clicks, the widget receives a mouse
+ press event, a mouse release event and finally this event instead
+ of a second mouse press event. (Some mouse move events may also be
+ received if the mouse is not held steady during this operation.) It
+ is \e{not possible} to distinguish a click from a double-click
+ until the second click arrives. (This is one reason why most GUI
+ books recommend that double-clicks be an extension of
+ single-clicks, rather than trigger a different action.)
+ \endlist
+
+ Widgets that accept keyboard input need to reimplement a few more event
+ handlers:
+
+ \list
+ \i keyPressEvent() is called whenever a key is pressed, and again when
+ a key has been held down long enough for it to auto-repeat. The
+ \key Tab and \key Shift+Tab keys are only passed to the widget if
+ they are not used by the focus-change mechanisms. To force those
+ keys to be processed by your widget, you must reimplement
+ QWidget::event().
+ \i focusInEvent() is called when the widget gains keyboard focus
+ (assuming you have called setFocusPolicy()). Well-behaved widgets
+ indicate that they own the keyboard focus in a clear but discreet
+ way.
+ \i focusOutEvent() is called when the widget loses keyboard focus.
+ \endlist
+
+ You may be required to also reimplement some of the less common event
+ handlers:
+
+ \list
+ \i mouseMoveEvent() is called whenever the mouse moves while a mouse
+ button is held down. This can be useful during drag and drop
+ operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
+ you get mouse move events even when no buttons are held down.
+ (See also the \l{Drag and Drop} guide.)
+ \i keyReleaseEvent() is called whenever a key is released and while it
+ is held down (if the key is auto-repeating). In that case, the
+ widget will receive a pair of key release and key press event for
+ every repeat. The \key Tab and \key Shift+Tab keys are only passed
+ to the widget if they are not used by the focus-change mechanisms.
+ To force those keys to be processed by your widget, you must
+ reimplement QWidget::event().
+ \i wheelEvent() is called whenever the user turns the mouse wheel
+ while the widget has the focus.
+ \i enterEvent() is called when the mouse enters the widget's screen
+ space. (This excludes screen space owned by any of the widget's
+ children.)
+ \i leaveEvent() is called when the mouse leaves the widget's screen
+ space. If the mouse enters a child widget it will not cause a
+ leaveEvent().
+ \i moveEvent() is called when the widget has been moved relative to
+ its parent.
+ \i closeEvent() is called when the user closes the widget (or when
+ close() is called).
+ \endlist
+
+ There are also some rather obscure events described in the documentation
+ for QEvent::Type. To handle these events, you need to reimplement event()
+ directly.
+
+ The default implementation of event() handles \key Tab and \key Shift+Tab
+ (to move the keyboard focus), and passes on most of the other events to
+ one of the more specialized handlers above.
+
+ Events and the mechanism used to deliver them are covered in
+ \l{The Event System}.
+
+ \section1 Groups of Functions and Properties
+
+ \table
+ \header \i Context \i Functions and Properties
+
+ \row \i Window functions \i
+ show(),
+ hide(),
+ raise(),
+ lower(),
+ close().
+
+ \row \i Top-level windows \i
+ \l windowModified, \l windowTitle, \l windowIcon, \l windowIconText,
+ \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
+ \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
+ showNormal().
+
+ \row \i Window contents \i
+ update(),
+ repaint(),
+ scroll().
+
+ \row \i Geometry \i
+ \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
+ \l sizePolicy, sizeHint(), minimumSizeHint(),
+ updateGeometry(), layout(),
+ \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
+ adjustSize(),
+ mapFromGlobal(), mapToGlobal(),
+ mapFromParent(), mapToParent(),
+ \l maximumSize, \l minimumSize, \l sizeIncrement,
+ \l baseSize, setFixedSize()
+
+ \row \i Mode \i
+ \l visible, isVisibleTo(),
+ \l enabled, isEnabledTo(),
+ \l modal,
+ isWindow(),
+ \l mouseTracking,
+ \l updatesEnabled,
+ visibleRegion().
+
+ \row \i Look and feel \i
+ style(),
+ setStyle(),
+ \l styleSheet,
+ \l cursor,
+ \l font,
+ \l palette,
+ backgroundRole(), setBackgroundRole(),
+ fontInfo(), fontMetrics().
+
+ \row \i Keyboard focus functions \i
+ \l focus, \l focusPolicy,
+ setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
+ focusNextChild(), focusPreviousChild().
+
+ \row \i Mouse and keyboard grabbing \i
+ grabMouse(), releaseMouse(),
+ grabKeyboard(), releaseKeyboard(),
+ mouseGrabber(), keyboardGrabber().
+
+ \row \i Event handlers \i
+ event(),
+ mousePressEvent(),
+ mouseReleaseEvent(),
+ mouseDoubleClickEvent(),
+ mouseMoveEvent(),
+ keyPressEvent(),
+ keyReleaseEvent(),
+ focusInEvent(),
+ focusOutEvent(),
+ wheelEvent(),
+ enterEvent(),
+ leaveEvent(),
+ paintEvent(),
+ moveEvent(),
+ resizeEvent(),
+ closeEvent(),
+ dragEnterEvent(),
+ dragMoveEvent(),
+ dragLeaveEvent(),
+ dropEvent(),
+ childEvent(),
+ showEvent(),
+ hideEvent(),
+ customEvent().
+ changeEvent(),
+
+ \row \i System functions \i
+ parentWidget(), window(), setParent(), winId(),
+ find(), metric().
+
+ \row \i Interactive help \i
+ setToolTip(), setWhatsThis()
+
+ \endtable
+
+
+ \section1 Widget Style Sheets
+
+ In addition to the standard widget styles for each platform, widgets can
+ also be styled according to rules specified in a \l{styleSheet}
+ {style sheet}. This feature enables you to customize the appearance of
+ specific widgets to provide visual cues to users about their purpose. For
+ example, a button could be styled in a particular way to indicate that it
+ performs a destructive action.
+
+ The use of widget style sheets is described in more detail in the
+ \l{Qt Style Sheets} document.
+
+
+ \section1 Transparency and Double Buffering
+
+ Since Qt 4.0, QWidget automatically double-buffers its painting, so there
+ is no need to write double-buffering code in paintEvent() to avoid
+ flicker.
+
+ Since Qt 4.1, the Qt::WA_ContentsPropagated widget attribute has been
+ deprecated. Instead, the contents of parent widgets are propagated by
+ default to each of their children as long as Qt::WA_PaintOnScreen is not
+ set. Custom widgets can be written to take advantage of this feature by
+ updating irregular regions (to create non-rectangular child widgets), or
+ painting with colors that have less than full alpha component. The
+ following diagram shows how attributes and properties of a custom widget
+ can be fine-tuned to achieve different effects.
+
+ \image propagation-custom.png
+
+ In the above diagram, a semi-transparent rectangular child widget with an
+ area removed is constructed and added to a parent widget (a QLabel showing
+ a pixmap). Then, different properties and widget attributes are set to
+ achieve different effects:
+
+ \list
+ \i The left widget has no additional properties or widget attributes
+ set. This default state suits most custom widgets using
+ transparency, are irregularly-shaped, or do not paint over their
+ entire area with an opaque brush.
+ \i The center widget has the \l autoFillBackground property set. This
+ property is used with custom widgets that rely on the widget to
+ supply a default background, and do not paint over their entire
+ area with an opaque brush.
+ \i The right widget has the Qt::WA_OpaquePaintEvent widget attribute
+ set. This indicates that the widget will paint over its entire area
+ with opaque colors. The widget's area will initially be
+ \e{uninitialized}, represented in the diagram with a red diagonal
+ grid pattern that shines through the overpainted area. The
+ Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
+ paint their own specialized contents quickly and do not need a
+ default filled background.
+ \endlist
+
+ To rapidly update custom widgets with simple background colors, such as
+ real-time plotting or graphing widgets, it is better to define a suitable
+ background color (using setBackgroundRole() with the
+ QPalette::Window role), set the \l autoFillBackground property, and only
+ implement the necessary drawing functionality in the widget's paintEvent().
+
+ To rapidly update custom widgets that constantly paint over their entire
+ areas with opaque content, e.g., video streaming widgets, it is better to
+ set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
+ associated with repainting the widget's background.
+
+ If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
+ the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
+ attribute takes precedence. Depending on your requirements, you should
+ choose either one of them.
+
+ Since Qt 4.1, the contents of parent widgets are also propagated to
+ standard Qt widgets. This can lead to some unexpected results if the
+ parent widget is decorated in a non-standard way, as shown in the diagram
+ below.
+
+ \image propagation-standard.png
+
+ The scope for customizing the painting behavior of standard Qt widgets,
+ without resorting to subclassing, is slightly less than that possible for
+ custom widgets. Usually, the desired appearance of a standard widget can be
+ achieved by setting its \l autoFillBackground property.
+
+
+ \section1 Creating Translucent Windows
+
+ Since Qt 4.5, it has been possible to create windows with translucent regions
+ on window systems that support compositing.
+
+ To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
+ attribute with setAttribute() and ensure that its background is painted with
+ non-opaque colors in the regions you want to be partially transparent.
+
+ Platform notes:
+
+ \list
+ \o X11: This feature relies on the use of an X server that supports ARGB visuals
+ and a compositing window manager.
+ \o Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
+ for the translucency to work.
+ \endlist
+
+
+ \section1 Native Widgets vs Alien Widgets
+
+ Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
+ system. They do not have a native window handle associated with them. This
+ feature significantly speeds up widget painting, resizing, and removes flicker.
+
+ Should you require the old behavior with native windows, you can choose
+ one of the following options:
+
+ \list 1
+ \i Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
+ \i Set the Qt::AA_NativeWindows attribute on your application. All
+ widgets will be native widgets.
+ \i Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
+ and all of its ancestors will become native (unless
+ Qt::WA_DontCreateNativeAncestors is set).
+ \i Call QWidget::winId to enforce a native window (this implies 3).
+ \i Set the Qt::WA_PaintOnScreen attribute to enforce a native window
+ (this implies 3).
+ \endlist
+
+ \sa QEvent, QPainter, QGridLayout, QBoxLayout
+
+ \section1 Softkeys
+
+ Since Qt 4.6, Softkeys are usually physical keys on a device that have a corresponding label or
+ other visual representation on the screen that is generally located next to its
+ physical counterpart. They are most often found on mobile phone platforms. In
+ modern touch based user interfaces it is also possible to have softkeys that do
+ not correspond to any physical keys. Softkeys differ from other onscreen labels
+ in that they are contextual.
+
+ In Qt, contextual softkeys are added to a widget by calling addAction() and
+ passing a \c QAction with a softkey role set on it. When the widget
+ containing the softkey actions has focus, its softkeys should appear in
+ the user interface. Softkeys are discovered by traversing the widget
+ hierarchy so it is possible to define a single set of softkeys that are
+ present at all times by calling addAction() for a given top level widget.
+
+ On some platforms, this concept overlaps with \c QMenuBar such that if no
+ other softkeys are found and the top level widget is a QMainWindow containing
+ a QMenuBar, the menubar actions may appear on one of the softkeys.
+
+ Note: Currently softkeys are only supported on the Symbian Platform.
+
+ \sa addAction(), QAction, QMenuBar
+
+*/
+
+QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
+QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid
+
+
+/*****************************************************************************
+ QWidget utility functions
+ *****************************************************************************/
+
+QRegion qt_dirtyRegion(QWidget *widget)
+{
+ if (!widget)
+ return QRegion();
+
+ QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore();
+ if (!bs)
+ return QRegion();
+
+ return bs->dirtyRegion(widget);
+}
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+/*
+ Widget state flags:
+ \list
+ \i Qt::WA_WState_Created The widget has a valid winId().
+ \i Qt::WA_WState_Visible The widget is currently visible.
+ \i Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
+ become visible unless you call show() on it. Qt::WA_WState_Hidden
+ implies !Qt::WA_WState_Visible.
+ \i Qt::WA_WState_CompressKeys Compress keyboard events.
+ \i Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
+ \i Qt::WA_WState_InPaintEvent Currently processing a paint event.
+ \i Qt::WA_WState_Reparented The widget has been reparented.
+ \i Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
+ \i Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
+ \endlist
+*/
+
+struct QWidgetExceptionCleaner
+{
+ /* this cleans up when the constructor throws an exception */
+ static inline void cleanup(QWidget *that, QWidgetPrivate *d)
+ {
+#ifdef QT_NO_EXCEPTIONS
+ Q_UNUSED(that);
+ Q_UNUSED(d);
+#else
+ QWidgetPrivate::allWidgets->remove(that);
+ if (d->focus_next != that) {
+ if (d->focus_next)
+ d->focus_next->d_func()->focus_prev = d->focus_prev;
+ if (d->focus_prev)
+ d->focus_prev->d_func()->focus_next = d->focus_next;
+ }
+#endif
+ }
+};
+
+/*!
+ Constructs a widget which is a child of \a parent, with widget
+ flags set to \a f.
+
+ If \a parent is 0, the new widget becomes a window. If
+ \a parent is another widget, this widget becomes a child window
+ inside \a parent. The new widget is deleted when its \a parent is
+ deleted.
+
+ The widget flags argument, \a f, is normally 0, but it can be set
+ to customize the frame of a window (i.e. \a
+ parent must be 0). To customize the frame, use a value composed
+ from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
+
+ If you add a child widget to an already visible widget you must
+ explicitly show the child to make it visible.
+
+ Note that the X11 version of Qt may not be able to deliver all
+ combinations of style flags on all systems. This is because on
+ X11, Qt can only ask the window manager, and the window manager
+ can override the application's settings. On Windows, Qt can set
+ whatever flags you want.
+
+ \sa windowFlags
+*/
+QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
+ : QObject(*new QWidgetPrivate, 0), QPaintDevice()
+{
+ QT_TRY {
+ d_func()->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+ \obsolete
+ */
+QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
+ : QObject(*new QWidgetPrivate, 0), QPaintDevice()
+{
+ QT_TRY {
+ d_func()->init(parent , f);
+ setObjectName(QString::fromAscii(name));
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
+}
+#endif
+
+/*! \internal
+*/
+QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
+ : QObject(dd, 0), QPaintDevice()
+{
+ Q_D(QWidget);
+ QT_TRY {
+ d->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
+}
+
+/*!
+ \internal
+*/
+int QWidget::devType() const
+{
+ return QInternal::Widget;
+}
+
+
+//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
+void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
+{
+ bool customize = (flags & (Qt::CustomizeWindowHint
+ | Qt::FramelessWindowHint
+ | Qt::WindowTitleHint
+ | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint
+ | Qt::WindowMaximizeButtonHint
+ | Qt::WindowCloseButtonHint
+ | Qt::WindowContextHelpButtonHint));
+
+ uint type = (flags & Qt::WindowType_Mask);
+
+ if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
+ type = Qt::Window;
+ flags |= Qt::Window;
+ }
+
+ if (flags & Qt::CustomizeWindowHint) {
+ // modify window flags to make them consistent.
+ // Only enable this on non-Mac platforms. Since the old way of doing this would
+ // interpret WindowSystemMenuHint as a close button and we can't change that behavior
+ // we can't just add this in.
+#ifndef Q_WS_MAC
+ if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) {
+ flags |= Qt::WindowSystemMenuHint;
+#else
+ if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
+ | Qt::WindowSystemMenuHint)) {
+#endif
+ flags |= Qt::WindowTitleHint;
+ flags &= ~Qt::FramelessWindowHint;
+ }
+ } else if (customize && !(flags & Qt::FramelessWindowHint)) {
+ // if any of the window hints that affect the titlebar are set
+ // and the window is supposed to have frame, we add a titlebar
+ // and system menu by default.
+ flags |= Qt::WindowSystemMenuHint;
+ flags |= Qt::WindowTitleHint;
+ }
+ if (customize)
+ ; // don't modify window flags if the user explicitly set them.
+ else if (type == Qt::Dialog || type == Qt::Sheet)
+#ifndef Q_WS_WINCE
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
+#else
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+#endif
+ else if (type == Qt::Tool)
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ else
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint;
+
+
+}
+
+void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ if (QApplication::type() == QApplication::Tty)
+ qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
+
+ Q_ASSERT(allWidgets);
+ if (allWidgets)
+ allWidgets->insert(q);
+
+ QWidget *desktopWidget = 0;
+ if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
+ desktopWidget = parentWidget;
+ parentWidget = 0;
+ }
+
+ q->data = &data;
+
+#ifndef QT_NO_THREAD
+ if (!parent) {
+ Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
+ "Widgets must be created in the GUI thread.");
+ }
+#endif
+
+#if defined(Q_WS_X11)
+ if (desktopWidget) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+ xinfo = desktopWidget->d_func()->xinfo;
+ }
+#elif defined(Q_OS_SYMBIAN)
+ if (desktopWidget) {
+ symbianScreenNumber = qt_widget_private(desktopWidget)->symbianScreenNumber;
+ }
+#elif defined(Q_WS_QPA)
+ if (desktopWidget) {
+ int screen = desktopWidget->d_func()->topData()->screenIndex;
+ QPlatformIntegration *platform = QGuiApplicationPrivate::platformIntegration();
+ platform->moveToScreen(q->windowHandle(), screen);
+ }
+#else
+ Q_UNUSED(desktopWidget);
+#endif
+
+ data.fstrut_dirty = true;
+
+ data.winid = 0;
+ data.widget_attributes = 0;
+ data.window_flags = f;
+ data.window_state = 0;
+ data.focus_policy = 0;
+ data.context_menu_policy = Qt::DefaultContextMenu;
+ data.window_modality = Qt::NonModal;
+
+ data.sizehint_forced = 0;
+ data.is_closing = 0;
+ data.in_show = 0;
+ data.in_set_window_state = 0;
+ data.in_destructor = false;
+
+ // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
+ if (f & Qt::MSWindowsOwnDC)
+ q->setAttribute(Qt::WA_NativeWindow);
+
+//#ifdef Q_WS_MAC
+// q->setAttribute(Qt::WA_NativeWindow);
+//#endif
+
+ q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
+ adjustQuitOnCloseAttribute();
+
+ q->setAttribute(Qt::WA_WState_Hidden);
+
+ //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
+#ifdef Q_OS_SYMBIAN
+ if (isGLWidget) {
+ // Don't waste GPU mem for unnecessary large egl surface until resized by application
+ data.crect = QRect(0,0,1,1);
+ } else {
+ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,360,640);
+ }
+#else
+ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
+#endif
+
+ focus_next = focus_prev = q;
+
+ if ((f & Qt::WindowType_Mask) == Qt::Desktop)
+ q->create();
+ else if (parentWidget)
+ q->setParent(parentWidget, data.window_flags);
+ else {
+ adjustFlags(data.window_flags, q);
+ resolveLayoutDirection();
+ // opaque system background?
+ const QBrush &background = q->palette().brush(QPalette::Window);
+ setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
+ }
+ data.fnt = QFont(data.fnt, q);
+#if defined(Q_WS_X11)
+ data.fnt.x11SetScreen(xinfo.screen());
+#endif // Q_WS_X11
+
+ q->setAttribute(Qt::WA_PendingMoveEvent);
+ q->setAttribute(Qt::WA_PendingResizeEvent);
+
+ if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
+ QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
+
+ if (QApplicationPrivate::app_compile_version < 0x040200
+ || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
+ q->create();
+
+
+ QEvent e(QEvent::Create);
+ QApplication::sendEvent(q, &e);
+ QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
+
+ extraPaintEngine = 0;
+
+#ifdef QT_MAC_USE_COCOA
+ // If we add a child to the unified toolbar, we have to redirect the painting.
+ if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) {
+ if (parentWidget->d_func()->unifiedSurface) {
+ QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor;
+ parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset);
+ }
+ }
+#endif // QT_MAC_USE_COCOA
+}
+
+
+
+void QWidgetPrivate::createRecursively()
+{
+ Q_Q(QWidget);
+ q->create(0, true, true);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
+ child->d_func()->createRecursively();
+ }
+}
+
+
+
+
+/*!
+ Creates a new widget window if \a window is 0, otherwise sets the
+ widget's window to \a window.
+
+ Initializes the window (sets the geometry etc.) if \a
+ initializeWindow is true. If \a initializeWindow is false, no
+ initialization is performed. This parameter only makes sense if \a
+ window is a valid window.
+
+ Destroys the old window if \a destroyOldWindow is true. If \a
+ destroyOldWindow is false, you are responsible for destroying the
+ window yourself (using platform native code).
+
+ The QWidget constructor calls create(0,true,true) to create a
+ window for this widget.
+*/
+
+void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_D(QWidget);
+ if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
+ return;
+
+ if (d->data.in_destructor)
+ return;
+
+ Qt::WindowType type = windowType();
+ Qt::WindowFlags &flags = data->window_flags;
+
+ if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
+ type = Qt::Window;
+ flags |= Qt::Window;
+ }
+
+#ifndef Q_WS_QPA
+ if (QWidget *parent = parentWidget()) {
+ if (type & Qt::Window) {
+ if (!parent->testAttribute(Qt::WA_WState_Created))
+ parent->createWinId();
+ } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
+ && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
+ // We're about to create a native child widget that doesn't have a native parent;
+ // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
+ // attribute is set.
+ d->createWinId(window);
+ // Nothing more to do.
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ Q_ASSERT(internalWinId());
+ return;
+ }
+ }
+#endif //Q_WS_QPA
+
+#ifdef QT3_SUPPORT
+ if (flags & Qt::WStaticContents)
+ setAttribute(Qt::WA_StaticContents);
+ if (flags & Qt::WDestructiveClose)
+ setAttribute(Qt::WA_DeleteOnClose);
+ if (flags & Qt::WShowModal)
+ setWindowModality(Qt::ApplicationModal);
+ if (flags & Qt::WMouseNoMask)
+ setAttribute(Qt::WA_MouseNoMask);
+ if (flags & Qt::WGroupLeader)
+ setAttribute(Qt::WA_GroupLeader);
+ if (flags & Qt::WNoMousePropagation)
+ setAttribute(Qt::WA_NoMousePropagation);
+#endif
+
+ static int paintOnScreenEnv = -1;
+ if (paintOnScreenEnv == -1)
+ paintOnScreenEnv = qgetenv("QT_ONSCREEN_PAINT").toInt() > 0 ? 1 : 0;
+ if (paintOnScreenEnv == 1)
+ setAttribute(Qt::WA_PaintOnScreen);
+
+ if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
+ setAttribute(Qt::WA_NativeWindow);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
+ << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
+#endif
+
+#if defined (Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+ // Unregister the dropsite (if already registered) before we
+ // re-create the widget with a native window.
+ if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
+ && d->extra && d->extra->dropTarget) {
+ d->registerDropSite(false);
+ }
+#endif // defined (Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+
+ d->updateIsOpaque();
+
+ setAttribute(Qt::WA_WState_Created); // set created flag
+ d->create_sys(window, initializeWindow, destroyOldWindow);
+
+ // a real toplevel window needs a backing store
+ if (isWindow() && windowType() != Qt::Desktop) {
+ d->topData()->backingStore.destroy();
+ if (hasBackingStoreSupport())
+ d->topData()->backingStore.create(this);
+ }
+
+ d->setModal_sys();
+
+ if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
+ setAttribute(Qt::WA_DropSiteRegistered, true);
+
+#ifdef QT_EVAL
+ extern void qt_eval_init_widget(QWidget *w);
+ qt_eval_init_widget(this);
+#endif
+
+ // need to force the resting of the icon after changing parents
+ if (testAttribute(Qt::WA_SetWindowIcon))
+ d->setWindowIcon_sys(true);
+ if (isWindow() && !d->topData()->iconText.isEmpty())
+ d->setWindowIconText_helper(d->topData()->iconText);
+ if (isWindow() && !d->topData()->caption.isEmpty())
+ d->setWindowTitle_helper(d->topData()->caption);
+ if (windowType() != Qt::Desktop) {
+ d->updateSystemBackground();
+
+ if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
+ d->setWindowIcon_sys();
+ }
+}
+
+/*!
+ Destroys the widget.
+
+ All this widget's children are deleted first. The application
+ exits if this widget is the main widget.
+*/
+
+QWidget::~QWidget()
+{
+ Q_D(QWidget);
+ d->data.in_destructor = true;
+
+#if defined (QT_CHECK_STATE)
+ if (paintingActive())
+ qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
+#endif
+
+#ifndef QT_NO_GESTURES
+ foreach (Qt::GestureType type, d->gestureContext.keys())
+ ungrabGesture(type);
+#endif
+
+ // force acceptDrops false before winId is destroyed.
+ d->registerDropSite(false);
+
+#ifndef QT_NO_ACTION
+ // remove all actions from this widget
+ for (int i = 0; i < d->actions.size(); ++i) {
+ QActionPrivate *apriv = d->actions.at(i)->d_func();
+ apriv->widgets.removeAll(this);
+ }
+ d->actions.clear();
+#endif
+
+#ifndef QT_NO_SHORTCUT
+ // Remove all shortcuts grabbed by this
+ // widget, unless application is closing
+ if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
+ qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence());
+#endif
+
+ // delete layout while we still are a valid widget
+ delete d->layout;
+ // Remove myself from focus list
+
+ Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
+ Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
+
+ if (d->focus_next != this) {
+ d->focus_next->d_func()->focus_prev = d->focus_prev;
+ d->focus_prev->d_func()->focus_next = d->focus_next;
+ d->focus_next = d->focus_prev = 0;
+ }
+
+#ifdef QT3_SUPPORT
+ if (QApplicationPrivate::main_widget == this) { // reset main widget
+ QApplicationPrivate::main_widget = 0;
+ QApplication::quit();
+ }
+#endif
+
+ QT_TRY {
+ clearFocus();
+ } QT_CATCH(...) {
+ // swallow this problem because we are in a destructor
+ }
+
+ d->setDirtyOpaqueRegion();
+
+ if (isWindow() && isVisible() && internalWinId()) {
+ QT_TRY {
+ d->close_helper(QWidgetPrivate::CloseNoEvent);
+ } QT_CATCH(...) {
+ // if we're out of memory, at least hide the window.
+ QT_TRY {
+ hide();
+ } QT_CATCH(...) {
+ // and if that also doesn't work, then give up
+ }
+ }
+ }
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)|| defined(Q_WS_MAC)
+ else if (!internalWinId() && isVisible()) {
+ qApp->d_func()->sendSyntheticEnterLeave(this);
+ }
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ else if (isVisible()) {
+ qApp->d_func()->sendSyntheticEnterLeave(this);
+ }
+#endif
+
+#ifdef Q_OS_SYMBIAN
+ if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) {
+ // Okay, we are about to destroy the top-level window that owns
+ // the backing store. Make sure we delete the backing store right away
+ // before the window handle is invalid. This is important because
+ // the backing store will delete its window surface, which may or may
+ // not have a reference to this widget that will be used later to
+ // notify the window it no longer has a surface.
+ d->extra->topextra->backingStore.destroy();
+ }
+#endif
+ if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ bs->removeDirtyWidget(this);
+ if (testAttribute(Qt::WA_StaticContents))
+ bs->removeStaticWidget(this);
+ }
+
+ delete d->needsFlush;
+ d->needsFlush = 0;
+
+ // set all QPointers for this object to zero
+ if (d->hasGuards)
+ QObjectPrivate::clearGuards(this);
+
+ if (d->declarativeData) {
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
+ d->declarativeData = 0; // don't activate again in ~QObject
+ }
+
+#ifdef QT_MAC_USE_COCOA
+ // QCocoaView holds a pointer back to this widget. Clear it now
+ // to make sure it's not followed later on. The lifetime of the
+ // QCocoaView might exceed the lifetime of this widget in cases
+ // where Cocoa itself holds references to it.
+ extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
+ qt_mac_clearCocoaViewQWidgetPointers(this);
+#endif
+
+ if (!d->children.isEmpty())
+ d->deleteChildren();
+
+ QApplication::removePostedEvents(this);
+
+ QT_TRY {
+ destroy(); // platform-dependent cleanup
+ } QT_CATCH(...) {
+ // if this fails we can't do anything about it but at least we are not allowed to throw.
+ }
+ --QWidgetPrivate::instanceCounter;
+
+ if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
+ QWidgetPrivate::allWidgets->remove(this);
+
+ QT_TRY {
+ QEvent e(QEvent::Destroy);
+ QCoreApplication::sendEvent(this, &e);
+ } QT_CATCH(const std::exception&) {
+ // if this fails we can't do anything about it but at least we are not allowed to throw.
+ }
+}
+
+int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
+int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
+
+void QWidgetPrivate::setWinId(WId id) // set widget identifier
+{
+ Q_Q(QWidget);
+ // the user might create a widget with Qt::Desktop window
+ // attribute (or create another QDesktopWidget instance), which
+ // will have the same windowid (the root window id) as the
+ // qt_desktopWidget. We should not add the second desktop widget
+ // to the mapper.
+ bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
+ if (mapper && data.winid && !userDesktopWidget) {
+ mapper->remove(data.winid);
+ }
+
+ const WId oldWinId = data.winid;
+
+ data.winid = id;
+#if defined(Q_WS_X11)
+ hd = id; // X11: hd == ident
+#endif
+ if (mapper && id && !userDesktopWidget) {
+ mapper->insert(data.winid, q);
+ }
+
+ if(oldWinId != id) {
+ QEvent e(QEvent::WinIdChange);
+ QCoreApplication::sendEvent(q, &e);
+ }
+}
+
+void QWidgetPrivate::createTLExtra()
+{
+ if (!extra)
+ createExtra();
+ if (!extra->topextra) {
+ QTLWExtra* x = extra->topextra = new QTLWExtra;
+ x->icon = 0;
+ x->iconPixmap = 0;
+ x->windowSurface = 0;
+ x->sharedPainter = 0;
+ x->incw = x->inch = 0;
+ x->basew = x->baseh = 0;
+ x->frameStrut.setCoords(0, 0, 0, 0);
+ x->normalGeometry = QRect(0,0,-1,-1);
+ x->savedFlags = 0;
+ x->opacity = 255;
+ x->posFromMove = false;
+ x->sizeAdjusted = false;
+ x->inTopLevelResize = false;
+ x->inRepaint = false;
+ x->embedded = 0;
+#ifdef Q_WS_MAC
+#ifdef QT_MAC_USE_COCOA
+ x->wasMaximized = false;
+#endif // QT_MAC_USE_COCOA
+#endif // Q_WS_MAC
+ createTLSysExtra();
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "tlextra" << ++count;
+#endif
+ }
+}
+
+/*!
+ \internal
+ Creates the widget extra data.
+*/
+
+void QWidgetPrivate::createExtra()
+{
+ if (!extra) { // if not exists
+ extra = new QWExtra;
+ extra->glContext = 0;
+ extra->topextra = 0;
+#ifndef QT_NO_GRAPHICSVIEW
+ extra->proxyWidget = 0;
+#endif
+#ifndef QT_NO_CURSOR
+ extra->curs = 0;
+#endif
+ extra->minw = 0;
+ extra->minh = 0;
+ extra->maxw = QWIDGETSIZE_MAX;
+ extra->maxh = QWIDGETSIZE_MAX;
+ extra->customDpiX = 0;
+ extra->customDpiY = 0;
+ extra->explicitMinSize = 0;
+ extra->explicitMaxSize = 0;
+ extra->autoFillBackground = 0;
+ extra->nativeChildrenForced = 0;
+ extra->inRenderWithPainter = 0;
+ extra->hasMask = 0;
+ createSysExtra();
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "extra" << ++count;
+#endif
+ }
+}
+
+
+/*!
+ \internal
+ Deletes the widget extra data.
+*/
+
+void QWidgetPrivate::deleteExtra()
+{
+ if (extra) { // if exists
+#ifndef QT_NO_CURSOR
+ delete extra->curs;
+#endif
+ deleteSysExtra();
+#ifndef QT_NO_STYLE_STYLESHEET
+ // dereference the stylesheet style
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style))
+ proxy->deref();
+#endif
+ if (extra->topextra) {
+ deleteTLSysExtra();
+ extra->topextra->backingStore.destroy();
+ delete extra->topextra->icon;
+ delete extra->topextra->iconPixmap;
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ delete extra->topextra->qwsManager;
+#endif
+ delete extra->topextra->windowSurface;
+ delete extra->topextra;
+ }
+ delete extra;
+ // extra->xic destroyed in QWidget::destroy()
+ extra = 0;
+ }
+}
+
+/*
+ Returns true if there are widgets above this which overlap with
+ \a rect, which is in parent's coordinate system (same as crect).
+*/
+
+bool QWidgetPrivate::isOverlapped(const QRect &rect) const
+{
+ Q_Q(const QWidget);
+
+ const QWidget *w = q;
+ QRect r = rect;
+ while (w) {
+ if (w->isWindow())
+ return false;
+ QWidgetPrivate *pd = w->parentWidget()->d_func();
+ bool above = false;
+ for (int i = 0; i < pd->children.size(); ++i) {
+ QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
+ if (!sibling || !sibling->isVisible() || sibling->isWindow())
+ continue;
+ if (!above) {
+ above = (sibling == w);
+ continue;
+ }
+
+ if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) {
+ const QWExtra *siblingExtra = sibling->d_func()->extra;
+ if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
+ && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
+ continue;
+ }
+ return true;
+ }
+ }
+ w = w->parentWidget();
+ r.translate(pd->data.crect.topLeft());
+ }
+ return false;
+}
+
+void QWidgetPrivate::syncBackingStore()
+{
+ if (paintOnScreen()) {
+ repaint_sys(dirty);
+ dirty = QRegion();
+ } else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+ bs->sync();
+ }
+}
+
+void QWidgetPrivate::syncBackingStore(const QRegion &region)
+{
+ if (paintOnScreen())
+ repaint_sys(region);
+ else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+ bs->sync(q_func(), region);
+ }
+}
+
+void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
+{
+ Q_Q(QWidget);
+
+ if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
+ return; // nothing we can do
+
+ if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
+ return; // nothing to do
+
+ q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
+ if (enable)
+ q->update();
+
+ Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(attribute))
+ w->d_func()->setUpdatesEnabled_helper(enable);
+ }
+}
+
+/*!
+ \internal
+
+ Propagate this widget's palette to all children, except style sheet
+ widgets, and windows that don't enable window propagation (palettes don't
+ normally propagate to windows).
+*/
+void QWidgetPrivate::propagatePaletteChange()
+{
+ Q_Q(QWidget);
+ // Propagate a new inherited mask to all children.
+#ifndef QT_NO_GRAPHICSVIEW
+ if (!q->parentWidget() && extra && extra->proxyWidget) {
+ QGraphicsProxyWidget *p = extra->proxyWidget;
+ inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
+ } else
+#endif //QT_NO_GRAPHICSVIEW
+ if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
+ inheritedPaletteResolveMask = 0;
+ }
+ int mask = data.pal.resolve() | inheritedPaletteResolveMask;
+
+ QEvent pc(QEvent::PaletteChange);
+ QApplication::sendEvent(q, &pc);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w && !w->testAttribute(Qt::WA_StyleSheet)
+ && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
+ QWidgetPrivate *wd = w->d_func();
+ wd->inheritedPaletteResolveMask = mask;
+ wd->resolvePalette();
+ }
+ }
+#if defined(QT3_SUPPORT)
+ q->paletteChange(q->palette()); // compatibility
+#endif
+}
+
+/*
+ Returns the widget's clipping rectangle.
+*/
+QRect QWidgetPrivate::clipRect() const
+{
+ Q_Q(const QWidget);
+ const QWidget * w = q;
+ if (!w->isVisible())
+ return QRect();
+ QRect r = effectiveRectFor(q->rect());
+ int ox = 0;
+ int oy = 0;
+ while (w
+ && w->isVisible()
+ && !w->isWindow()
+ && w->parentWidget()) {
+ ox -= w->x();
+ oy -= w->y();
+ w = w->parentWidget();
+ r &= QRect(ox, oy, w->width(), w->height());
+ }
+ return r;
+}
+
+/*
+ Returns the widget's clipping region (without siblings).
+*/
+QRegion QWidgetPrivate::clipRegion() const
+{
+ Q_Q(const QWidget);
+ if (!q->isVisible())
+ return QRegion();
+ QRegion r(q->rect());
+ const QWidget * w = q;
+ const QWidget *ignoreUpTo;
+ int ox = 0;
+ int oy = 0;
+ while (w
+ && w->isVisible()
+ && !w->isWindow()
+ && w->parentWidget()) {
+ ox -= w->x();
+ oy -= w->y();
+ ignoreUpTo = w;
+ w = w->parentWidget();
+ r &= QRegion(ox, oy, w->width(), w->height());
+
+ int i = 0;
+ while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
+ ;
+ for ( ; i < w->d_func()->children.size(); ++i) {
+ if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
+ if(sibling->isVisible() && !sibling->isWindow()) {
+ QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
+ sibling->width(), sibling->height());
+ if (qRectIntersects(siblingRect, q->rect()))
+ r -= QRegion(siblingRect);
+ }
+ }
+ }
+ }
+ return r;
+}
+
+#ifndef QT_NO_GRAPHICSEFFECT
+void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
+{
+ Q_Q(QWidget);
+ QWidget *w = q;
+ do {
+ if (w->graphicsEffect()) {
+ QWidgetEffectSourcePrivate *sourced =
+ static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
+ if (!sourced->updateDueToGraphicsEffect)
+ w->graphicsEffect()->source()->d_func()->invalidateCache();
+ }
+ w = w->parentWidget();
+ } while (w);
+}
+#endif //QT_NO_GRAPHICSEFFECT
+
+void QWidgetPrivate::setDirtyOpaqueRegion()
+{
+ Q_Q(QWidget);
+
+ dirtyOpaqueChildren = true;
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ if (q->isWindow())
+ return;
+
+ QWidget *parent = q->parentWidget();
+ if (!parent)
+ return;
+
+ // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
+ QWidgetPrivate *pd = parent->d_func();
+ if (!pd->dirtyOpaqueChildren)
+ pd->setDirtyOpaqueRegion();
+}
+
+const QRegion &QWidgetPrivate::getOpaqueChildren() const
+{
+ if (!dirtyOpaqueChildren)
+ return opaqueChildren;
+
+ QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
+ that->opaqueChildren = QRegion();
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (!child || !child->isVisible() || child->isWindow())
+ continue;
+
+ const QPoint offset = child->geometry().topLeft();
+ QWidgetPrivate *childd = child->d_func();
+ QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
+ if (childd->extra && childd->extra->hasMask)
+ r &= childd->extra->mask;
+ if (r.isEmpty())
+ continue;
+ r.translate(offset);
+ that->opaqueChildren += r;
+ }
+
+ that->opaqueChildren &= q_func()->rect();
+ that->dirtyOpaqueChildren = false;
+
+ return that->opaqueChildren;
+}
+
+void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
+{
+ if (children.isEmpty() || clipRect.isEmpty())
+ return;
+
+ const QRegion &r = getOpaqueChildren();
+ if (!r.isEmpty())
+ source -= (r & clipRect);
+}
+
+//subtract any relatives that are higher up than me --- this is too expensive !!!
+void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
+ bool alsoNonOpaque) const
+{
+ Q_Q(const QWidget);
+ static int disableSubtractOpaqueSiblings = qgetenv("QT_NO_SUBTRACTOPAQUESIBLINGS").toInt();
+ if (disableSubtractOpaqueSiblings || q->isWindow())
+ return;
+
+#ifdef QT_MAC_USE_COCOA
+ if (q->d_func()->isInUnifiedToolbar)
+ return;
+#endif // QT_MAC_USE_COCOA
+
+ QRect clipBoundingRect;
+ bool dirtyClipBoundingRect = true;
+
+ QRegion parentClip;
+ bool dirtyParentClip = true;
+
+ QPoint parentOffset = data.crect.topLeft();
+
+ const QWidget *w = q;
+
+ while (w) {
+ if (w->isWindow())
+ break;
+ QWidgetPrivate *pd = w->parentWidget()->d_func();
+ const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
+ const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
+ for (int i = myIndex + 1; i < pd->children.size(); ++i) {
+ QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
+ if (!sibling || !sibling->isVisible() || sibling->isWindow())
+ continue;
+
+ const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
+ if (!qRectIntersects(siblingGeometry, widgetGeometry))
+ continue;
+
+ if (dirtyClipBoundingRect) {
+ clipBoundingRect = sourceRegion.boundingRect();
+ dirtyClipBoundingRect = false;
+ }
+
+ if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
+ continue;
+
+ if (dirtyParentClip) {
+ parentClip = sourceRegion.translated(parentOffset);
+ dirtyParentClip = false;
+ }
+
+ const QPoint siblingPos(sibling->data->crect.topLeft());
+ const QRect siblingClipRect(sibling->d_func()->clipRect());
+ QRegion siblingDirty(parentClip);
+ siblingDirty &= (siblingClipRect.translated(siblingPos));
+ const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
+ && !sibling->d_func()->graphicsEffect;
+ if (hasMask)
+ siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
+ if (siblingDirty.isEmpty())
+ continue;
+
+ if (sibling->d_func()->isOpaque || alsoNonOpaque) {
+ if (hasMask) {
+ siblingDirty.translate(-parentOffset);
+ sourceRegion -= siblingDirty;
+ } else {
+ sourceRegion -= siblingGeometry.translated(-parentOffset);
+ }
+ } else {
+ if (hasDirtySiblingsAbove)
+ *hasDirtySiblingsAbove = true;
+ if (sibling->d_func()->children.isEmpty())
+ continue;
+ QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
+ opaqueSiblingChildren.translate(-parentOffset + siblingPos);
+ sourceRegion -= opaqueSiblingChildren;
+ }
+ if (sourceRegion.isEmpty())
+ return;
+
+ dirtyClipBoundingRect = true;
+ dirtyParentClip = true;
+ }
+
+ w = w->parentWidget();
+ parentOffset += pd->data.crect.topLeft();
+ dirtyParentClip = true;
+ }
+}
+
+void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
+{
+ Q_Q(const QWidget);
+
+ const QWidget *w = q;
+ QPoint offset;
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (graphicsEffect) {
+ w = q->parentWidget();
+ offset -= data.crect.topLeft();
+ }
+#endif //QT_NO_GRAPHICSEFFECT
+
+ while (w) {
+ const QWidgetPrivate *wd = w->d_func();
+ if (wd->extra && wd->extra->hasMask)
+ region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
+ if (w->isWindow())
+ return;
+ offset -= wd->data.crect.topLeft();
+ w = w->parentWidget();
+ }
+}
+
+bool QWidgetPrivate::paintOnScreen() const
+{
+#if defined(Q_WS_QWS)
+ return false;
+#elif defined(QT_NO_BACKINGSTORE)
+ return true;
+#else
+ Q_Q(const QWidget);
+ if (q->testAttribute(Qt::WA_PaintOnScreen)
+ || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
+ return true;
+ }
+
+ return !qt_enable_backingstore;
+#endif
+}
+
+void QWidgetPrivate::updateIsOpaque()
+{
+ // hw: todo: only needed if opacity actually changed
+ setDirtyOpaqueRegion();
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (graphicsEffect) {
+ // ### We should probably add QGraphicsEffect::isOpaque at some point.
+ setOpaque(false);
+ return;
+ }
+#endif //QT_NO_GRAPHICSEFFECT
+
+ Q_Q(QWidget);
+#ifdef Q_WS_X11
+ if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
+ setOpaque(false);
+ return;
+ }
+#endif
+
+#ifdef Q_WS_S60
+ if (q->windowType() == Qt::Dialog && q->testAttribute(Qt::WA_TranslucentBackground)
+ && S60->avkonComponentsSupportTransparency) {
+ setOpaque(false);
+ return;
+ }
+#endif
+
+ if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
+ setOpaque(true);
+ return;
+ }
+
+ const QPalette &pal = q->palette();
+
+ if (q->autoFillBackground()) {
+ const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
+ if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
+ setOpaque(true);
+ return;
+ }
+ }
+
+ if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+ const QBrush &windowBrush = q->palette().brush(QPalette::Window);
+ if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
+ setOpaque(true);
+ return;
+ }
+ }
+ setOpaque(false);
+}
+
+void QWidgetPrivate::setOpaque(bool opaque)
+{
+ if (isOpaque == opaque)
+ return;
+ isOpaque = opaque;
+#ifdef Q_WS_MAC
+ macUpdateIsOpaque();
+#endif
+#ifdef Q_WS_X11
+ x11UpdateIsOpaque();
+#endif
+#ifdef Q_WS_WIN
+ winUpdateIsOpaque();
+#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
+}
+
+void QWidgetPrivate::updateIsTranslucent()
+{
+#ifdef Q_WS_MAC
+ macUpdateIsOpaque();
+#endif
+#ifdef Q_WS_X11
+ x11UpdateIsOpaque();
+#endif
+#ifdef Q_WS_WIN
+ winUpdateIsOpaque();
+#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
+}
+
+static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
+{
+ Q_ASSERT(painter);
+
+ if (brush.style() == Qt::TexturePattern) {
+#ifdef Q_WS_MAC
+ // Optimize pattern filling on mac by using HITheme directly
+ // when filling with the standard widget background.
+ // Defined in qmacstyle_mac.cpp
+ extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
+ qt_mac_fill_background(painter, rgn, brush);
+#else
+#if !defined(QT_NO_STYLE_S60)
+ // Defined in qs60style.cpp
+ extern bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
+ if (!qt_s60_fill_background(painter, rgn, brush))
+#endif // !defined(QT_NO_STYLE_S60)
+ {
+ const QRect rect(rgn.boundingRect());
+ painter->setClipRegion(rgn);
+ painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
+ }
+#endif // Q_WS_MAC
+
+ } else if (brush.gradient()
+ && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
+ painter->save();
+ painter->setClipRegion(rgn);
+ painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
+ painter->restore();
+ } else {
+ const QVector<QRect> &rects = rgn.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ painter->fillRect(rects.at(i), brush);
+ }
+}
+
+void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
+{
+ Q_Q(const QWidget);
+
+#ifndef QT_NO_SCROLLAREA
+ bool resetBrushOrigin = false;
+ QPointF oldBrushOrigin;
+ //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
+ if (scrollArea && scrollArea->viewport() == q) {
+ QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
+ QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
+ oldBrushOrigin = painter->brushOrigin();
+ resetBrushOrigin = true;
+ painter->setBrushOrigin(-priv->contentsOffset());
+
+ }
+#endif // QT_NO_SCROLLAREA
+
+ const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
+
+ if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
+ const QBrush bg = q->palette().brush(QPalette::Window);
+#ifdef Q_WS_QWS
+ if (!(flags & DontSetCompositionMode) && painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ painter->setCompositionMode(QPainter::CompositionMode_Source); //copy alpha straight in
+#endif
+ fillRegion(painter, rgn, bg);
+ }
+
+ if (q->autoFillBackground())
+ fillRegion(painter, rgn, autoFillBrush);
+
+ if (q->testAttribute(Qt::WA_StyledBackground)) {
+ painter->setClipRegion(rgn);
+ QStyleOption opt;
+ opt.initFrom(q);
+ q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
+ }
+
+#ifndef QT_NO_SCROLLAREA
+ if (resetBrushOrigin)
+ painter->setBrushOrigin(oldBrushOrigin);
+#endif // QT_NO_SCROLLAREA
+}
+
+/*
+ \internal
+ This function is called when a widget is hidden or destroyed.
+ It resets some application global pointers that should only refer active,
+ visible widgets.
+*/
+
+#ifdef Q_WS_MAC
+ extern QPointer<QWidget> qt_button_down;
+#else
+ extern QWidget *qt_button_down;
+#endif
+
+void QWidgetPrivate::deactivateWidgetCleanup()
+{
+ Q_Q(QWidget);
+ // If this was the active application window, reset it
+ if (QApplication::activeWindow() == q)
+ QApplication::setActiveWindow(0);
+ // If the is the active mouse press widget, reset it
+ if (q == qt_button_down)
+ qt_button_down = 0;
+}
+
+
+/*!
+ Returns a pointer to the widget with window identifer/handle \a
+ id.
+
+ The window identifier type depends on the underlying window
+ system, see \c qwindowdefs.h for the actual definition. If there
+ is no widget with this identifier, 0 is returned.
+*/
+
+QWidget *QWidget::find(WId id)
+{
+ return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
+}
+
+
+
+/*!
+ \fn WId QWidget::internalWinId() const
+ \internal
+ Returns the window system identifier of the widget, or 0 if the widget is not created yet.
+
+*/
+
+/*!
+ \fn WId QWidget::winId() const
+
+ Returns the window system identifier of the widget.
+
+ Portable in principle, but if you use it you are probably about to
+ do something non-portable. Be careful.
+
+ If a widget is non-native (alien) and winId() is invoked on it, that widget
+ will be provided a native handle.
+
+ On Mac OS X, the type returned depends on which framework Qt was linked
+ against. If Qt is using Carbon, the {WId} is actually an HIViewRef. If Qt
+ is using Cocoa, {WId} is a pointer to an NSView.
+
+ This value may change at run-time. An event with type QEvent::WinIdChange
+ will be sent to the widget following a change in window system identifier.
+
+ \sa find()
+*/
+WId QWidget::winId() const
+{
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::winId: creating native window for" << this;
+#endif
+ QWidget *that = const_cast<QWidget*>(this);
+#ifndef Q_WS_QPA
+ that->setAttribute(Qt::WA_NativeWindow);
+#endif
+ that->d_func()->createWinId();
+ return that->data->winid;
+ }
+ return data->winid;
+}
+
+
+void QWidgetPrivate::createWinId(WId winid)
+{
+ Q_Q(QWidget);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::createWinId for" << q << winid;
+#endif
+ const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
+ if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
+#ifndef Q_WS_QPA
+ if (!q->isWindow()) {
+ QWidget *parent = q->parentWidget();
+ QWidgetPrivate *pd = parent->d_func();
+ if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
+ parent->setAttribute(Qt::WA_NativeWindow);
+ if (!parent->internalWinId()) {
+ pd->createWinId();
+ }
+
+ for (int i = 0; i < pd->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
+ if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
+ || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
+ if (w!=q) {
+ w->create();
+ } else {
+ w->create(winid);
+ // if the window has already been created, we
+ // need to raise it to its proper stacking position
+ if (winid)
+ w->raise();
+ }
+ }
+ }
+ } else {
+ q->create();
+ }
+#else
+ Q_UNUSED(winid);
+ q->create();
+#endif //Q_WS_QPA
+
+ }
+}
+
+
+/*!
+\internal
+Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
+
+*/
+
+void QWidget::createWinId()
+{
+ Q_D(QWidget);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::createWinId" << this;
+#endif
+// qWarning("QWidget::createWinId is obsolete, please fix your code.");
+ d->createWinId();
+}
+
+/*!
+ \since 4.4
+
+ Returns the effective window system identifier of the widget, i.e. the
+ native parent's window system identifier.
+
+ If the widget is native, this function returns the native widget ID.
+ Otherwise, the window ID of the first native parent widget, i.e., the
+ top-level widget that contains this widget, is returned.
+
+ \note We recommend that you do not store this value as it is likely to
+ change at run-time.
+
+ \sa nativeParentWidget()
+*/
+WId QWidget::effectiveWinId() const
+{
+ WId id = internalWinId();
+ if (id || !testAttribute(Qt::WA_WState_Created))
+ return id;
+ QWidget *realParent = nativeParentWidget();
+ Q_ASSERT(realParent);
+ Q_ASSERT(realParent->internalWinId());
+ return realParent->internalWinId();
+}
+
+#ifndef QT_NO_STYLE_STYLESHEET
+
+/*!
+ \property QWidget::styleSheet
+ \brief the widget's style sheet
+ \since 4.2
+
+ The style sheet contains a textual description of customizations to the
+ widget's style, as described in the \l{Qt Style Sheets} document.
+
+ Since Qt 4.5, Qt style sheets fully supports Mac OS X.
+
+ \warning Qt style sheets are currently not supported for custom QStyle
+ subclasses. We plan to address this in some future release.
+
+ \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
+*/
+QString QWidget::styleSheet() const
+{
+ Q_D(const QWidget);
+ if (!d->extra)
+ return QString();
+ return d->extra->styleSheet;
+}
+
+void QWidget::setStyleSheet(const QString& styleSheet)
+{
+ Q_D(QWidget);
+ d->createExtra();
+
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style);
+ d->extra->styleSheet = styleSheet;
+ if (styleSheet.isEmpty()) { // stylesheet removed
+ if (!proxy)
+ return;
+
+ d->inheritStyle();
+ return;
+ }
+
+ if (proxy) { // style sheet update
+ proxy->repolish(this);
+ return;
+ }
+
+ if (testAttribute(Qt::WA_SetStyle)) {
+ d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
+ } else {
+ d->setStyle_helper(new QStyleSheetStyle(0), true);
+ }
+}
+
+#endif // QT_NO_STYLE_STYLESHEET
+
+/*!
+ \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
+*/
+
+QStyle *QWidget::style() const
+{
+ Q_D(const QWidget);
+
+ if (d->extra && d->extra->style)
+ return d->extra->style;
+ return QApplication::style();
+}
+
+/*!
+ Sets the widget's GUI style to \a style. The ownership of the style
+ object is not transferred.
+
+ If no style is set, the widget uses the application's style,
+ QApplication::style() instead.
+
+ Setting a widget's style has no effect on existing or future child
+ widgets.
+
+ \warning This function is particularly useful for demonstration
+ purposes, where you want to show Qt's styling capabilities. Real
+ applications should avoid it and use one consistent GUI style
+ instead.
+
+ \warning Qt style sheets are currently not supported for custom QStyle
+ subclasses. We plan to address this in some future release.
+
+ \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
+*/
+
+void QWidget::setStyle(QStyle *style)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetStyle, style != 0);
+ d->createExtra();
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) {
+ //if for some reason someone try to set a QStyleSheetStyle, ref it
+ //(this may happen for exemple in QButtonDialogBox which propagates its style)
+ proxy->ref();
+ d->setStyle_helper(style, false);
+ } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) {
+ // if we have an application stylesheet or have a proxy already, propagate
+ d->setStyle_helper(new QStyleSheetStyle(style), true);
+ } else
+#endif
+ d->setStyle_helper(style, false);
+}
+
+void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
+#ifdef Q_WS_MAC
+ metalHack
+#endif
+ )
+{
+ Q_Q(QWidget);
+ QStyle *oldStyle = q->style();
+#ifndef QT_NO_STYLE_STYLESHEET
+ QWeakPointer<QStyle> origStyle;
+#endif
+
+#ifdef Q_WS_MAC
+ // the metalhack boolean allows Qt/Mac to do a proper re-polish depending
+ // on how the Qt::WA_MacBrushedMetal attribute is set. It is only ever
+ // set when changing that attribute and passes the widget's CURRENT style.
+ // therefore no need to do a reassignment.
+ if (!metalHack)
+#endif
+ {
+ createExtra();
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ origStyle = extra->style.data();
+#endif
+ extra->style = newStyle;
+ }
+
+ // repolish
+ if (q->windowType() != Qt::Desktop) {
+ if (polished) {
+ oldStyle->unpolish(q);
+#ifdef Q_WS_MAC
+ if (metalHack)
+ macUpdateMetalAttribute();
+#endif
+ q->style()->polish(q);
+#ifdef Q_WS_MAC
+ } else if (metalHack) {
+ macUpdateMetalAttribute();
+#endif
+ }
+ }
+
+ if (propagate) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *c = qobject_cast<QWidget*>(children.at(i));
+ if (c)
+ c->d_func()->inheritStyle();
+ }
+ }
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!qobject_cast<QStyleSheetStyle*>(newStyle)) {
+ if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) {
+ cssStyle->clearWidgetFont(q);
+ }
+ }
+#endif
+
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->styleChange(*oldStyle);
+#endif
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ // dereference the old stylesheet style
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data()))
+ proxy->deref();
+#endif
+}
+
+// Inherits style from the current parent and propagates it as necessary
+void QWidgetPrivate::inheritStyle()
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_Q(QWidget);
+
+ QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0;
+
+ if (!q->styleSheet().isEmpty()) {
+ Q_ASSERT(proxy);
+ proxy->repolish(q);
+ return;
+ }
+
+ QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0);
+ QWidget *parent = q->parentWidget();
+ QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
+ // If we have stylesheet on app or parent has stylesheet style, we need
+ // to be running a proxy
+ if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) {
+ QStyle *newStyle = parentStyle;
+ if (q->testAttribute(Qt::WA_SetStyle))
+ newStyle = new QStyleSheetStyle(origStyle);
+ else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle))
+ newProxy->ref();
+
+ setStyle_helper(newStyle, true);
+ return;
+ }
+
+ // So, we have no stylesheet on parent/app and we have an empty stylesheet
+ // we just need our original style back
+ if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different?
+ return;
+
+ // We could have inherited the proxy from our parent (which has a custom style)
+ // In such a case we need to start following the application style (i.e revert
+ // the propagation behavior of QStyleSheetStyle)
+ if (!q->testAttribute(Qt::WA_SetStyle))
+ origStyle = 0;
+
+ setStyle_helper(origStyle, true);
+#endif // QT_NO_STYLE_STYLESHEET
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+
+ Sets the widget's GUI style to \a style using the QStyleFactory.
+*/
+QStyle* QWidget::setStyle(const QString &style)
+{
+ QStyle *s = QStyleFactory::create(style);
+ setStyle(s);
+ return s;
+}
+#endif
+
+/*!
+ \fn bool QWidget::isWindow() const
+
+ Returns true if the widget is an independent window, otherwise
+ returns false.
+
+ A window is a widget that isn't visually the child of any other
+ widget and that usually has a frame and a
+ \l{QWidget::setWindowTitle()}{window title}.
+
+ A window can have a \l{QWidget::parentWidget()}{parent widget}.
+ It will then be grouped with its parent and deleted when the
+ parent is deleted, minimized when the parent is minimized etc. If
+ supported by the window manager, it will also have a common
+ taskbar entry with its parent.
+
+ QDialog and QMainWindow widgets are by default windows, even if a
+ parent widget is specified in the constructor. This behavior is
+ specified by the Qt::Window flag.
+
+ \sa window(), isModal(), parentWidget()
+*/
+
+/*!
+ \property QWidget::modal
+ \brief whether the widget is a modal widget
+
+ This property only makes sense for windows. A modal widget
+ prevents widgets in all other windows from getting any input.
+
+ By default, this property is false.
+
+ \sa isWindow(), windowModality, QDialog
+*/
+
+/*!
+ \property QWidget::windowModality
+ \brief which windows are blocked by the modal widget
+ \since 4.1
+
+ This property only makes sense for windows. A modal widget
+ prevents widgets in other windows from getting input. The value of
+ this property controls which windows are blocked when the widget
+ is visible. Changing this property while the window is visible has
+ no effect; you must hide() the widget first, then show() it again.
+
+ By default, this property is Qt::NonModal.
+
+ \sa isWindow(), QWidget::modal, QDialog
+*/
+
+Qt::WindowModality QWidget::windowModality() const
+{
+ return static_cast<Qt::WindowModality>(data->window_modality);
+}
+
+void QWidget::setWindowModality(Qt::WindowModality windowModality)
+{
+ data->window_modality = windowModality;
+ // setModal_sys() will be called by setAttribute()
+ setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
+ setAttribute(Qt::WA_SetWindowModality, true);
+}
+
+/*!
+ \fn bool QWidget::underMouse() const
+
+ Returns true if the widget is under the mouse cursor; otherwise
+ returns false.
+
+ This value is not updated properly during drag and drop
+ operations.
+
+ \sa enterEvent(), leaveEvent()
+*/
+
+/*!
+ \property QWidget::minimized
+ \brief whether this widget is minimized (iconified)
+
+ This property is only relevant for windows.
+
+ By default, this property is false.
+
+ \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
+*/
+bool QWidget::isMinimized() const
+{ return data->window_state & Qt::WindowMinimized; }
+
+/*!
+ Shows the widget minimized, as an icon.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
+ isMinimized()
+*/
+void QWidget::showMinimized()
+{
+ bool isMin = isMinimized();
+ if (isMin && isVisible())
+ return;
+
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ if (!isMin)
+ setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
+ show();
+}
+
+/*!
+ \property QWidget::maximized
+ \brief whether this widget is maximized
+
+ This property is only relevant for windows.
+
+ \note Due to limitations on some window systems, this does not always
+ report the expected results (e.g., if the user on X11 maximizes the
+ window via the window manager, Qt has no way of distinguishing this
+ from any other resize). This is expected to improve as window manager
+ protocols evolve.
+
+ By default, this property is false.
+
+ \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
+*/
+bool QWidget::isMaximized() const
+{ return data->window_state & Qt::WindowMaximized; }
+
+
+
+/*!
+ Returns the current window state. The window state is a OR'ed
+ combination of Qt::WindowState: Qt::WindowMinimized,
+ Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
+
+ \sa Qt::WindowState setWindowState()
+ */
+Qt::WindowStates QWidget::windowState() const
+{
+ return Qt::WindowStates(data->window_state);
+}
+
+/*!\internal
+
+ The function sets the window state on child widgets similar to
+ setWindowState(). The difference is that the window state changed
+ event has the isOverride() flag set. It exists mainly to keep
+ Q3Workspace working.
+ */
+void QWidget::overrideWindowState(Qt::WindowStates newstate)
+{
+ QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
+ data->window_state = newstate;
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ \fn void QWidget::setWindowState(Qt::WindowStates windowState)
+
+ Sets the window state to \a windowState. The window state is a OR'ed
+ combination of Qt::WindowState: Qt::WindowMinimized,
+ Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
+
+ If the window is not visible (i.e. isVisible() returns false), the
+ window state will take effect when show() is called. For visible
+ windows, the change is immediate. For example, to toggle between
+ full-screen and normal mode, use the following code:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 0
+
+ In order to restore and activate a minimized window (while
+ preserving its maximized and/or full-screen state), use the following:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 1
+
+ Calling this function will hide the widget. You must call show() to make
+ the widget visible again.
+
+ \note On some window systems Qt::WindowActive is not immediate, and may be
+ ignored in certain cases.
+
+ When the window state changes, the widget receives a changeEvent()
+ of type QEvent::WindowStateChange.
+
+ \sa Qt::WindowState windowState()
+*/
+
+/*!
+ \property QWidget::fullScreen
+ \brief whether the widget is shown in full screen mode
+
+ A widget in full screen mode occupies the whole screen area and does not
+ display window decorations, such as a title bar.
+
+ By default, this property is false.
+
+ \sa windowState(), minimized, maximized
+*/
+bool QWidget::isFullScreen() const
+{ return data->window_state & Qt::WindowFullScreen; }
+
+/*!
+ Shows the widget in full-screen mode.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ To return from full-screen mode, call showNormal().
+
+ Full-screen mode works fine under Windows, but has certain
+ problems under X. These problems are due to limitations of the
+ ICCCM protocol that specifies the communication between X11
+ clients and the window manager. ICCCM simply does not understand
+ the concept of non-decorated full-screen windows. Therefore, the
+ best we can do is to request a borderless window and place and
+ resize it to fill the entire screen. Depending on the window
+ manager, this may or may not work. The borderless window is
+ requested using MOTIF hints, which are at least partially
+ supported by virtually all modern window managers.
+
+ An alternative would be to bypass the window manager entirely and
+ create a window with the Qt::X11BypassWindowManagerHint flag. This
+ has other severe problems though, like totally broken keyboard focus
+ and very strange effects on desktop changes or when the user raises
+ other windows.
+
+ X11 window managers that follow modern post-ICCCM specifications
+ support full-screen mode properly.
+
+ \sa showNormal(), showMaximized(), show(), hide(), isVisible()
+*/
+void QWidget::showFullScreen()
+{
+#ifdef Q_WS_MAC
+ // If the unified toolbar is enabled, we have to disable it before going fullscreen.
+ QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
+ if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) {
+ mainWindow->setUnifiedTitleAndToolBarOnMac(false);
+ QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
+ mainLayout->activateUnifiedToolbarAfterFullScreen = true;
+ }
+#endif // Q_WS_MAC
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
+ | Qt::WindowFullScreen);
+ show();
+ activateWindow();
+}
+
+/*!
+ Shows the widget maximized.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ On X11, this function may not work properly with certain window
+ managers. See the \l{Window Geometry} documentation for an explanation.
+
+ \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
+*/
+void QWidget::showMaximized()
+{
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
+ | Qt::WindowMaximized);
+#ifdef Q_WS_MAC
+ // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
+ QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
+ if (mainWindow)
+ {
+ QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
+ if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
+ mainWindow->setUnifiedTitleAndToolBarOnMac(true);
+ mainLayout->activateUnifiedToolbarAfterFullScreen = false;
+ }
+ }
+#endif // Q_WS_MAC
+ show();
+}
+
+/*!
+ Restores the widget after it has been maximized or minimized.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
+*/
+void QWidget::showNormal()
+{
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState(windowState() & ~(Qt::WindowMinimized
+ | Qt::WindowMaximized
+ | Qt::WindowFullScreen));
+#ifdef Q_WS_MAC
+ // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
+ QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
+ if (mainWindow)
+ {
+ QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
+ if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
+ mainWindow->setUnifiedTitleAndToolBarOnMac(true);
+ mainLayout->activateUnifiedToolbarAfterFullScreen = false;
+ }
+ }
+#endif // Q_WS_MAC
+ show();
+}
+
+/*!
+ Returns true if this widget would become enabled if \a ancestor is
+ enabled; otherwise returns false.
+
+
+
+ This is the case if neither the widget itself nor every parent up
+ to but excluding \a ancestor has been explicitly disabled.
+
+ isEnabledTo(0) is equivalent to isEnabled().
+
+ \sa setEnabled() enabled
+*/
+
+bool QWidget::isEnabledTo(QWidget* ancestor) const
+{
+ const QWidget * w = this;
+ while (!w->testAttribute(Qt::WA_ForceDisabled)
+ && !w->isWindow()
+ && w->parentWidget()
+ && w->parentWidget() != ancestor)
+ w = w->parentWidget();
+ return !w->testAttribute(Qt::WA_ForceDisabled);
+}
+
+#ifndef QT_NO_ACTION
+/*!
+ Appends the action \a action to this widget's list of actions.
+
+ All QWidgets have a list of \l{QAction}s, however they can be
+ represented graphically in many different ways. The default use of
+ the QAction list (as returned by actions()) is to create a context
+ QMenu.
+
+ A QWidget should only have one of each action and adding an action
+ it already has will not cause the same action to be in the widget twice.
+
+ The ownership of \a action is not transferred to this QWidget.
+
+ \sa removeAction(), insertAction(), actions(), QMenu
+*/
+void QWidget::addAction(QAction *action)
+{
+ insertAction(0, action);
+}
+
+/*!
+ Appends the actions \a actions to this widget's list of actions.
+
+ \sa removeAction(), QMenu, addAction()
+*/
+void QWidget::addActions(QList<QAction*> actions)
+{
+ for(int i = 0; i < actions.count(); i++)
+ insertAction(0, actions.at(i));
+}
+
+/*!
+ Inserts the action \a action to this widget's list of actions,
+ before the action \a before. It appends the action if \a before is 0 or
+ \a before is not a valid action for this widget.
+
+ A QWidget should only have one of each action.
+
+ \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
+*/
+void QWidget::insertAction(QAction *before, QAction *action)
+{
+ if(!action) {
+ qWarning("QWidget::insertAction: Attempt to insert null action");
+ return;
+ }
+
+ Q_D(QWidget);
+ if(d->actions.contains(action))
+ removeAction(action);
+
+ int pos = d->actions.indexOf(before);
+ if (pos < 0) {
+ before = 0;
+ pos = d->actions.size();
+ }
+ d->actions.insert(pos, action);
+
+ QActionPrivate *apriv = action->d_func();
+ apriv->widgets.append(this);
+
+ QActionEvent e(QEvent::ActionAdded, action, before);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ Inserts the actions \a actions to this widget's list of actions,
+ before the action \a before. It appends the action if \a before is 0 or
+ \a before is not a valid action for this widget.
+
+ A QWidget can have at most one of each action.
+
+ \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
+*/
+void QWidget::insertActions(QAction *before, QList<QAction*> actions)
+{
+ for(int i = 0; i < actions.count(); ++i)
+ insertAction(before, actions.at(i));
+}
+
+/*!
+ Removes the action \a action from this widget's list of actions.
+ \sa insertAction(), actions(), insertAction()
+*/
+void QWidget::removeAction(QAction *action)
+{
+ if (!action)
+ return;
+
+ Q_D(QWidget);
+
+ QActionPrivate *apriv = action->d_func();
+ apriv->widgets.removeAll(this);
+
+ if (d->actions.removeAll(action)) {
+ QActionEvent e(QEvent::ActionRemoved, action);
+ QApplication::sendEvent(this, &e);
+ }
+}
+
+/*!
+ Returns the (possibly empty) list of this widget's actions.
+
+ \sa contextMenuPolicy, insertAction(), removeAction()
+*/
+QList<QAction*> QWidget::actions() const
+{
+ Q_D(const QWidget);
+ return d->actions;
+}
+#endif // QT_NO_ACTION
+
+/*!
+ \fn bool QWidget::isEnabledToTLW() const
+ \obsolete
+
+ This function is deprecated. It is equivalent to isEnabled()
+*/
+
+/*!
+ \property QWidget::enabled
+ \brief whether the widget is enabled
+
+ An enabled widget handles keyboard and mouse events; a disabled
+ widget does not.
+
+ Some widgets display themselves differently when they are
+ disabled. For example a button might draw its label grayed out. If
+ your widget needs to know when it becomes enabled or disabled, you
+ can use the changeEvent() with type QEvent::EnabledChange.
+
+ Disabling a widget implicitly disables all its children. Enabling
+ respectively enables all child widgets unless they have been
+ explicitly disabled.
+
+ By default, this property is true.
+
+ \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
+*/
+void QWidget::setEnabled(bool enable)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_ForceDisabled, !enable);
+ d->setEnabled_helper(enable);
+}
+
+void QWidgetPrivate::setEnabled_helper(bool enable)
+{
+ Q_Q(QWidget);
+
+ if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
+ return; // nothing we can do
+
+ if (enable != q->testAttribute(Qt::WA_Disabled))
+ return; // nothing to do
+
+ q->setAttribute(Qt::WA_Disabled, !enable);
+ updateSystemBackground();
+
+ if (!enable && q->window()->focusWidget() == q) {
+ bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
+ if (!parentIsEnabled || !q->focusNextChild())
+ q->clearFocus();
+ }
+
+ Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->testAttribute(attribute))
+ w->d_func()->setEnabled_helper(enable);
+ }
+#if defined(Q_WS_X11)
+ if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
+ // enforce the windows behavior of clearing the cursor on
+ // disabled widgets
+ qt_x11_enforce_cursor(q);
+ }
+#endif
+#if defined(Q_WS_MAC)
+ setEnabled_helper_sys(enable);
+#endif
+#ifndef QT_NO_IM
+ if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
+ QWidget *focusWidget = effectiveFocusWidget();
+ QInputContext *qic = focusWidget->d_func()->inputContext();
+ if (enable) {
+ if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
+ qic->setFocusWidget(focusWidget);
+ } else {
+ qic->reset();
+ qic->setFocusWidget(0);
+ }
+ }
+#endif //QT_NO_IM
+ QEvent e(QEvent::EnabledChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->enabledChange(!enable); // compatibility
+#endif
+}
+
+/*!
+ \property QWidget::acceptDrops
+ \brief whether drop events are enabled for this widget
+
+ Setting this property to true announces to the system that this
+ widget \e may be able to accept drop events.
+
+ If the widget is the desktop (windowType() == Qt::Desktop), this may
+ fail if another application is using the desktop; you can call
+ acceptDrops() to test if this occurs.
+
+ \warning Do not modify this property in a drag and drop event handler.
+
+ By default, this property is false.
+
+ \sa {Drag and Drop}
+*/
+bool QWidget::acceptDrops() const
+{
+ return testAttribute(Qt::WA_AcceptDrops);
+}
+
+void QWidget::setAcceptDrops(bool on)
+{
+ setAttribute(Qt::WA_AcceptDrops, on);
+
+}
+
+/*!
+ \fn void QWidget::enabledChange(bool)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::paletteChange(const QPalette &)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::fontChange(const QFont &)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::windowActivationChange(bool)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::languageChange()
+
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::styleChange(QStyle& style)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ Disables widget input events if \a disable is true; otherwise
+ enables input events.
+
+ See the \l enabled documentation for more information.
+
+ \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
+*/
+void QWidget::setDisabled(bool disable)
+{
+ setEnabled(!disable);
+}
+
+/*!
+ \property QWidget::frameGeometry
+ \brief geometry of the widget relative to its parent including any
+ window frame
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry() x() y() pos()
+*/
+QRect QWidget::frameGeometry() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QRect(data->crect.x() - fs.left(),
+ data->crect.y() - fs.top(),
+ data->crect.width() + fs.left() + fs.right(),
+ data->crect.height() + fs.top() + fs.bottom());
+ }
+ return data->crect;
+}
+
+/*!
+ \property QWidget::x
+
+ \brief the x coordinate of the widget relative to its parent including
+ any window frame
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ By default, this property has a value of 0.
+
+ \sa frameGeometry, y, pos
+*/
+int QWidget::x() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup))
+ return data->crect.x() - d->frameStrut().left();
+ return data->crect.x();
+}
+
+/*!
+ \property QWidget::y
+ \brief the y coordinate of the widget relative to its parent and
+ including any window frame
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ By default, this property has a value of 0.
+
+ \sa frameGeometry, x, pos
+*/
+int QWidget::y() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup))
+ return data->crect.y() - d->frameStrut().top();
+ return data->crect.y();
+}
+
+/*!
+ \property QWidget::pos
+ \brief the position of the widget within its parent widget
+
+ If the widget is a window, the position is that of the widget on
+ the desktop, including its frame.
+
+ When changing the position, the widget, if visible, receives a
+ move event (moveEvent()) immediately. If the widget is not
+ currently visible, it is guaranteed to receive an event before it
+ is shown.
+
+ By default, this property contains a position that refers to the
+ origin.
+
+ \warning Calling move() or setGeometry() inside moveEvent() can
+ lead to infinite recursion.
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ \sa frameGeometry, size x(), y()
+*/
+QPoint QWidget::pos() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QPoint(data->crect.x() - fs.left(), data->crect.y() - fs.top());
+ }
+ return data->crect.topLeft();
+}
+
+/*!
+ \property QWidget::geometry
+ \brief the geometry of the widget relative to its parent and
+ excluding the window frame
+
+ When changing the geometry, the widget, if visible, receives a
+ move event (moveEvent()) and/or a resize event (resizeEvent())
+ immediately. If the widget is not currently visible, it is
+ guaranteed to receive appropriate events before it is shown.
+
+ The size component is adjusted if it lies outside the range
+ defined by minimumSize() and maximumSize().
+
+ \warning Calling setGeometry() inside resizeEvent() or moveEvent()
+ can lead to infinite recursion.
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
+ resizeEvent(), minimumSize(), maximumSize()
+*/
+
+/*!
+ \property QWidget::normalGeometry
+
+ \brief the geometry of the widget as it will appear when shown as
+ a normal (not maximized or full screen) top-level widget
+
+ For child widgets this property always holds an empty rectangle.
+
+ By default, this property contains an empty rectangle.
+
+ \sa QWidget::windowState(), QWidget::geometry
+*/
+
+/*!
+ \property QWidget::size
+ \brief the size of the widget excluding any window frame
+
+ If the widget is visible when it is being resized, it receives a resize event
+ (resizeEvent()) immediately. If the widget is not currently
+ visible, it is guaranteed to receive an event before it is shown.
+
+ The size is adjusted if it lies outside the range defined by
+ minimumSize() and maximumSize().
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \warning Calling resize() or setGeometry() inside resizeEvent() can
+ lead to infinite recursion.
+
+ \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
+ appear on screen. This also applies to windows.
+
+ \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
+*/
+
+/*!
+ \property QWidget::width
+ \brief the width of the widget excluding any window frame
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ \note Do not use this function to find the width of a screen on
+ a \l{QDesktopWidget}{multiple screen desktop}. Read
+ \l{QDesktopWidget#Screen Geometry}{this note} for details.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry, height, size
+*/
+
+/*!
+ \property QWidget::height
+ \brief the height of the widget excluding any window frame
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ \note Do not use this function to find the height of a screen
+ on a \l{QDesktopWidget}{multiple screen desktop}. Read
+ \l{QDesktopWidget#Screen Geometry}{this note} for details.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry, width, size
+*/
+
+/*!
+ \property QWidget::rect
+ \brief the internal geometry of the widget excluding any window
+ frame
+
+ The rect property equals QRect(0, 0, width(), height()).
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa size
+*/
+
+
+QRect QWidget::normalGeometry() const
+{
+ Q_D(const QWidget);
+ if (!d->extra || !d->extra->topextra)
+ return QRect();
+
+ if (!isMaximized() && !isFullScreen())
+ return geometry();
+
+ return d->topData()->normalGeometry;
+}
+
+
+/*!
+ \property QWidget::childrenRect
+ \brief the bounding rectangle of the widget's children
+
+ Hidden children are excluded.
+
+ By default, for a widget with no children, this property contains a
+ rectangle with zero width and height located at the origin.
+
+ \sa childrenRegion() geometry()
+*/
+
+QRect QWidget::childrenRect() const
+{
+ Q_D(const QWidget);
+ QRect r(0, 0, 0, 0);
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden())
+ r |= w->geometry();
+ }
+ return r;
+}
+
+/*!
+ \property QWidget::childrenRegion
+ \brief the combined region occupied by the widget's children
+
+ Hidden children are excluded.
+
+ By default, for a widget with no children, this property contains an
+ empty region.
+
+ \sa childrenRect() geometry() mask()
+*/
+
+QRegion QWidget::childrenRegion() const
+{
+ Q_D(const QWidget);
+ QRegion r;
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden()) {
+ QRegion mask = w->mask();
+ if (mask.isEmpty())
+ r |= w->geometry();
+ else
+ r |= mask.translated(w->pos());
+ }
+ }
+ return r;
+}
+
+
+/*!
+ \property QWidget::minimumSize
+ \brief the widget's minimum size
+
+ The widget cannot be resized to a smaller size than the minimum
+ widget size. The widget's size is forced to the minimum size if
+ the current size is smaller.
+
+ The minimum size set by this function will override the minimum size
+ defined by QLayout. In order to unset the minimum size, use a
+ value of \c{QSize(0, 0)}.
+
+ By default, this property contains a size with zero width and height.
+
+ \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
+*/
+
+QSize QWidget::minimumSize() const
+{
+ Q_D(const QWidget);
+ return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
+}
+
+/*!
+ \property QWidget::maximumSize
+ \brief the widget's maximum size in pixels
+
+ The widget cannot be resized to a larger size than the maximum
+ widget size.
+
+ By default, this property contains a size in which both width and height
+ have values of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
+*/
+
+QSize QWidget::maximumSize() const
+{
+ Q_D(const QWidget);
+ return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
+ : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+}
+
+
+/*!
+ \property QWidget::minimumWidth
+ \brief the widget's minimum width in pixels
+
+ This property corresponds to the width held by the \l minimumSize property.
+
+ By default, this property has a value of 0.
+
+ \sa minimumSize, minimumHeight
+*/
+
+/*!
+ \property QWidget::minimumHeight
+ \brief the widget's minimum height in pixels
+
+ This property corresponds to the height held by the \l minimumSize property.
+
+ By default, this property has a value of 0.
+
+ \sa minimumSize, minimumWidth
+*/
+
+/*!
+ \property QWidget::maximumWidth
+ \brief the widget's maximum width in pixels
+
+ This property corresponds to the width held by the \l maximumSize property.
+
+ By default, this property contains a value of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumSize, maximumHeight
+*/
+
+/*!
+ \property QWidget::maximumHeight
+ \brief the widget's maximum height in pixels
+
+ This property corresponds to the height held by the \l maximumSize property.
+
+ By default, this property contains a value of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumSize, maximumWidth
+*/
+
+/*!
+ \property QWidget::sizeIncrement
+ \brief the size increment of the widget
+
+ When the user resizes the window, the size will move in steps of
+ sizeIncrement().width() pixels horizontally and
+ sizeIncrement.height() pixels vertically, with baseSize() as the
+ basis. Preferred widget sizes are for non-negative integers \e i
+ and \e j:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 2
+
+ Note that while you can set the size increment for all widgets, it
+ only affects windows.
+
+ By default, this property contains a size with zero width and height.
+
+ \warning The size increment has no effect under Windows, and may
+ be disregarded by the window manager on X11.
+
+ \sa size, minimumSize, maximumSize
+*/
+QSize QWidget::sizeIncrement() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra)
+ ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
+ : QSize(0, 0);
+}
+
+/*!
+ \property QWidget::baseSize
+ \brief the base size of the widget
+
+ The base size is used to calculate a proper widget size if the
+ widget defines sizeIncrement().
+
+ By default, for a newly-created widget, this property contains a size with
+ zero width and height.
+
+ \sa setSizeIncrement()
+*/
+
+QSize QWidget::baseSize() const
+{
+ Q_D(const QWidget);
+ return (d->extra != 0 && d->extra->topextra != 0)
+ ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
+ : QSize(0, 0);
+}
+
+bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
+{
+ Q_Q(QWidget);
+
+#ifdef Q_WS_QWS
+ if (q->isWindow()) {
+ const QRect maxWindowRect = QApplication::desktop()->availableGeometry(QApplication::desktop()->screenNumber(q));
+ if (!maxWindowRect.isEmpty()) {
+ // ### This is really just a work-around. Layout shouldn't be
+ // asking for minimum sizes bigger than the screen.
+ if (minw > maxWindowRect.width())
+ minw = maxWindowRect.width();
+ if (minh > maxWindowRect.height())
+ minh = maxWindowRect.height();
+ }
+ }
+#endif
+ int mw = minw, mh = minh;
+ if (mw == QWIDGETSIZE_MAX)
+ mw = 0;
+ if (mh == QWIDGETSIZE_MAX)
+ mh = 0;
+ if (minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX) {
+ qWarning("QWidget::setMinimumSize: (%s/%s) "
+ "The largest allowed size is (%d,%d)",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX);
+ minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
+ minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
+ }
+ if (minw < 0 || minh < 0) {
+ qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
+ "are not possible",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
+ minw = mw = qMax(minw, 0);
+ minh = mh = qMax(minh, 0);
+ }
+ createExtra();
+ if (extra->minw == mw && extra->minh == mh)
+ return false;
+ extra->minw = mw;
+ extra->minh = mh;
+ extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
+ return true;
+}
+
+/*!
+ \overload
+
+ This function corresponds to setMinimumSize(QSize(minw, minh)).
+ Sets the minimum width to \a minw and the minimum height to \a
+ minh.
+*/
+
+void QWidget::setMinimumSize(int minw, int minh)
+{
+ Q_D(QWidget);
+ if (!d->setMinimumSize_helper(minw, minh))
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ if (minw > width() || minh > height()) {
+ bool resized = testAttribute(Qt::WA_Resized);
+ bool maximized = isMaximized();
+ resize(qMax(minw,width()), qMax(minh,height()));
+ setAttribute(Qt::WA_Resized, resized); //not a user resize
+ if (maximized)
+ data->window_state = data->window_state | Qt::WindowMaximized;
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra) {
+ if (d->extra->proxyWidget)
+ d->extra->proxyWidget->setMinimumSize(minw, minh);
+ }
+#endif
+ d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
+}
+
+bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
+{
+ Q_Q(QWidget);
+ if (maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) "
+ "The largest allowed size is (%d,%d)",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX);
+ maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
+ maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
+ }
+ if (maxw < 0 || maxh < 0) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
+ "are not possible",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
+ maxw = qMax(maxw, 0);
+ maxh = qMax(maxh, 0);
+ }
+ createExtra();
+ if (extra->maxw == maxw && extra->maxh == maxh)
+ return false;
+ extra->maxw = maxw;
+ extra->maxh = maxh;
+ extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
+ (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
+ return true;
+}
+
+/*!
+ \overload
+
+ This function corresponds to setMaximumSize(QSize(\a maxw, \a
+ maxh)). Sets the maximum width to \a maxw and the maximum height
+ to \a maxh.
+*/
+void QWidget::setMaximumSize(int maxw, int maxh)
+{
+ Q_D(QWidget);
+ if (!d->setMaximumSize_helper(maxw, maxh))
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ if (maxw < width() || maxh < height()) {
+ bool resized = testAttribute(Qt::WA_Resized);
+ resize(qMin(maxw,width()), qMin(maxh,height()));
+ setAttribute(Qt::WA_Resized, resized); //not a user resize
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra) {
+ if (d->extra->proxyWidget)
+ d->extra->proxyWidget->setMaximumSize(maxw, maxh);
+ }
+#endif
+
+ d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
+}
+
+/*!
+ \overload
+
+ Sets the x (width) size increment to \a w and the y (height) size
+ increment to \a h.
+*/
+void QWidget::setSizeIncrement(int w, int h)
+{
+ Q_D(QWidget);
+ d->createTLExtra();
+ QTLWExtra* x = d->topData();
+ if (x->incw == w && x->inch == h)
+ return;
+ x->incw = w;
+ x->inch = h;
+ if (isWindow())
+ d->setConstraints_sys();
+}
+
+/*!
+ \overload
+
+ This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
+ the widgets base size to width \a basew and height \a baseh.
+*/
+void QWidget::setBaseSize(int basew, int baseh)
+{
+ Q_D(QWidget);
+ d->createTLExtra();
+ QTLWExtra* x = d->topData();
+ if (x->basew == basew && x->baseh == baseh)
+ return;
+ x->basew = basew;
+ x->baseh = baseh;
+ if (isWindow())
+ d->setConstraints_sys();
+}
+
+/*!
+ Sets both the minimum and maximum sizes of the widget to \a s,
+ thereby preventing it from ever growing or shrinking.
+
+ This will override the default size constraints set by QLayout.
+
+ To remove constraints, set the size to QWIDGETSIZE_MAX.
+
+ Alternatively, if you want the widget to have a
+ fixed size based on its contents, you can call
+ QLayout::setSizeConstraint(QLayout::SetFixedSize);
+
+ \sa maximumSize, minimumSize
+*/
+
+void QWidget::setFixedSize(const QSize & s)
+{
+ setFixedSize(s.width(), s.height());
+}
+
+
+/*!
+ \fn void QWidget::setFixedSize(int w, int h)
+ \overload
+
+ Sets the width of the widget to \a w and the height to \a h.
+*/
+
+void QWidget::setFixedSize(int w, int h)
+{
+ Q_D(QWidget);
+#ifdef Q_WS_QWS
+ // temporary fix for 4.3.x.
+ // Should move the embedded spesific contraints in setMinimumSize_helper into QLayout
+ int tmpW = w;
+ int tmpH = h;
+ bool minSizeSet = d->setMinimumSize_helper(tmpW, tmpH);
+#else
+ bool minSizeSet = d->setMinimumSize_helper(w, h);
+#endif
+ bool maxSizeSet = d->setMaximumSize_helper(w, h);
+ if (!minSizeSet && !maxSizeSet)
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ else
+ d->updateGeometry_helper(true);
+
+ if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
+ resize(w, h);
+}
+
+void QWidget::setMinimumWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
+ setMinimumSize(w, minimumSize().height());
+ d->extra->explicitMinSize = expl;
+}
+
+void QWidget::setMinimumHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
+ setMinimumSize(minimumSize().width(), h);
+ d->extra->explicitMinSize = expl;
+}
+
+void QWidget::setMaximumWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
+ setMaximumSize(w, maximumSize().height());
+ d->extra->explicitMaxSize = expl;
+}
+
+void QWidget::setMaximumHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
+ setMaximumSize(maximumSize().width(), h);
+ d->extra->explicitMaxSize = expl;
+}
+
+/*!
+ Sets both the minimum and maximum width of the widget to \a w
+ without changing the heights. Provided for convenience.
+
+ \sa sizeHint() minimumSize() maximumSize() setFixedSize()
+*/
+
+void QWidget::setFixedWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
+ uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
+ setMinimumSize(w, minimumSize().height());
+ setMaximumSize(w, maximumSize().height());
+ d->extra->explicitMinSize = explMin;
+ d->extra->explicitMaxSize = explMax;
+}
+
+
+/*!
+ Sets both the minimum and maximum heights of the widget to \a h
+ without changing the widths. Provided for convenience.
+
+ \sa sizeHint() minimumSize() maximumSize() setFixedSize()
+*/
+
+void QWidget::setFixedHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint explMin = d->extra->explicitMinSize | Qt::Vertical;
+ uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
+ setMinimumSize(minimumSize().width(), h);
+ setMaximumSize(maximumSize().width(), h);
+ d->extra->explicitMinSize = explMin;
+ d->extra->explicitMaxSize = explMax;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos to the coordinate system
+ of \a parent. The \a parent must not be 0 and must be a parent
+ of the calling widget.
+
+ \sa mapFrom() mapToParent() mapToGlobal() underMouse()
+*/
+
+QPoint QWidget::mapTo(QWidget * parent, const QPoint & pos) const
+{
+ QPoint p = pos;
+ if (parent) {
+ const QWidget * w = this;
+ while (w != parent) {
+ Q_ASSERT_X(w, "QWidget::mapTo(QWidget *parent, const QPoint &pos)",
+ "parent must be in parent hierarchy");
+ p = w->mapToParent(p);
+ w = w->parentWidget();
+ }
+ }
+ return p;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos from the coordinate system
+ of \a parent to this widget's coordinate system. The \a parent
+ must not be 0 and must be a parent of the calling widget.
+
+ \sa mapTo() mapFromParent() mapFromGlobal() underMouse()
+*/
+
+QPoint QWidget::mapFrom(QWidget * parent, const QPoint & pos) const
+{
+ QPoint p(pos);
+ if (parent) {
+ const QWidget * w = this;
+ while (w != parent) {
+ Q_ASSERT_X(w, "QWidget::mapFrom(QWidget *parent, const QPoint &pos)",
+ "parent must be in parent hierarchy");
+
+ p = w->mapFromParent(p);
+ w = w->parentWidget();
+ }
+ }
+ return p;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos to a coordinate in the
+ parent widget.
+
+ Same as mapToGlobal() if the widget has no parent.
+
+ \sa mapFromParent() mapTo() mapToGlobal() underMouse()
+*/
+
+QPoint QWidget::mapToParent(const QPoint &pos) const
+{
+ return pos + data->crect.topLeft();
+}
+
+/*!
+ Translates the parent widget coordinate \a pos to widget
+ coordinates.
+
+ Same as mapFromGlobal() if the widget has no parent.
+
+ \sa mapToParent() mapFrom() mapFromGlobal() underMouse()
+*/
+
+QPoint QWidget::mapFromParent(const QPoint &pos) const
+{
+ return pos - data->crect.topLeft();
+}
+
+
+/*!
+ Returns the window for this widget, i.e. the next ancestor widget
+ that has (or could have) a window-system frame.
+
+ If the widget is a window, the widget itself is returned.
+
+ Typical usage is changing the window title:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 3
+
+ \sa isWindow()
+*/
+
+QWidget *QWidget::window() const
+{
+ QWidget *w = (QWidget *)this;
+ QWidget *p = w->parentWidget();
+ while (!w->isWindow() && p) {
+ w = p;
+ p = p->parentWidget();
+ }
+ return w;
+}
+
+/*!
+ \since 4.4
+
+ Returns the native parent for this widget, i.e. the next ancestor widget
+ that has a system identifier, or 0 if it does not have any native parent.
+
+ \sa effectiveWinId()
+*/
+QWidget *QWidget::nativeParentWidget() const
+{
+ QWidget *parent = parentWidget();
+ while (parent && !parent->internalWinId())
+ parent = parent->parentWidget();
+ return parent;
+}
+
+/*! \fn QWidget *QWidget::topLevelWidget() const
+ \obsolete
+
+ Use window() instead.
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ Returns the color role used for painting the widget's background.
+
+ Use QPalette(backgroundRole(()) instead.
+*/
+Qt::BackgroundMode QWidget::backgroundMode() const
+{
+ if (testAttribute(Qt::WA_NoSystemBackground))
+ return Qt::NoBackground;
+ switch(backgroundRole()) {
+ case QPalette::WindowText:
+ return Qt::PaletteForeground;
+ case QPalette::Button:
+ return Qt::PaletteButton;
+ case QPalette::Light:
+ return Qt::PaletteLight;
+ case QPalette::Midlight:
+ return Qt::PaletteMidlight;
+ case QPalette::Dark:
+ return Qt::PaletteDark;
+ case QPalette::Mid:
+ return Qt::PaletteMid;
+ case QPalette::Text:
+ return Qt::PaletteText;
+ case QPalette::BrightText:
+ return Qt::PaletteBrightText;
+ case QPalette::Base:
+ return Qt::PaletteBase;
+ case QPalette::Window:
+ return Qt::PaletteBackground;
+ case QPalette::Shadow:
+ return Qt::PaletteShadow;
+ case QPalette::Highlight:
+ return Qt::PaletteHighlight;
+ case QPalette::HighlightedText:
+ return Qt::PaletteHighlightedText;
+ case QPalette::ButtonText:
+ return Qt::PaletteButtonText;
+ case QPalette::Link:
+ return Qt::PaletteLink;
+ case QPalette::LinkVisited:
+ return Qt::PaletteLinkVisited;
+ default:
+ break;
+ }
+ return Qt::NoBackground;
+}
+
+/*!
+ \fn void QWidget::setBackgroundMode(Qt::BackgroundMode
+ widgetBackground, Qt::BackgroundMode paletteBackground)
+
+ Sets the color role used for painting the widget's background to
+ background mode \a widgetBackground. The \a paletteBackground mode
+ parameter is ignored.
+*/
+void QWidget::setBackgroundMode(Qt::BackgroundMode m, Qt::BackgroundMode)
+{
+ Q_D(QWidget);
+ if(m == Qt::NoBackground) {
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ return;
+ }
+ setAttribute(Qt::WA_NoSystemBackground, false);
+ d->fg_role = QPalette::NoRole;
+ QPalette::ColorRole role = d->bg_role;
+ switch(m) {
+ case Qt::FixedColor:
+ case Qt::FixedPixmap:
+ break;
+ case Qt::PaletteForeground:
+ role = QPalette::WindowText;
+ break;
+ case Qt::PaletteButton:
+ role = QPalette::Button;
+ break;
+ case Qt::PaletteLight:
+ role = QPalette::Light;
+ break;
+ case Qt::PaletteMidlight:
+ role = QPalette::Midlight;
+ break;
+ case Qt::PaletteDark:
+ role = QPalette::Dark;
+ break;
+ case Qt::PaletteMid:
+ role = QPalette::Mid;
+ break;
+ case Qt::PaletteText:
+ role = QPalette::Text;
+ break;
+ case Qt::PaletteBrightText:
+ role = QPalette::BrightText;
+ break;
+ case Qt::PaletteBase:
+ role = QPalette::Base;
+ break;
+ case Qt::PaletteBackground:
+ role = QPalette::Window;
+ break;
+ case Qt::PaletteShadow:
+ role = QPalette::Shadow;
+ break;
+ case Qt::PaletteHighlight:
+ role = QPalette::Highlight;
+ break;
+ case Qt::PaletteHighlightedText:
+ role = QPalette::HighlightedText;
+ break;
+ case Qt::PaletteButtonText:
+ role = QPalette::ButtonText;
+ break;
+ case Qt::PaletteLink:
+ role = QPalette::Link;
+ break;
+ case Qt::PaletteLinkVisited:
+ role = QPalette::LinkVisited;
+ break;
+ case Qt::X11ParentRelative:
+ d->fg_role = role = QPalette::NoRole;
+ default:
+ break;
+ }
+ setBackgroundRole(role);
+}
+
+/*!
+ The widget mapper is no longer part of the public API.
+*/
+QT3_SUPPORT QWidgetMapper *QWidget::wmapper() { return QWidgetPrivate::mapper; }
+
+#endif
+
+
+/*!
+ Returns the background role of the widget.
+
+ The background role defines the brush from the widget's \l palette that
+ is used to render the background.
+
+ If no explicit background role is set, the widget inherts its parent
+ widget's background role.
+
+ \sa setBackgroundRole(), foregroundRole()
+ */
+QPalette::ColorRole QWidget::backgroundRole() const
+{
+
+ const QWidget *w = this;
+ do {
+ QPalette::ColorRole role = w->d_func()->bg_role;
+ if (role != QPalette::NoRole)
+ return role;
+ if (w->isWindow() || w->windowType() == Qt::SubWindow)
+ break;
+ w = w->parentWidget();
+ } while (w);
+ return QPalette::Window;
+}
+
+/*!
+ Sets the background role of the widget to \a role.
+
+ The background role defines the brush from the widget's \l palette that
+ is used to render the background.
+
+ If \a role is QPalette::NoRole, then the widget inherits its
+ parent's background role.
+
+ Note that styles are free to choose any color from the palette.
+ You can modify the palette or set a style sheet if you don't
+ achieve the result you want with setBackgroundRole().
+
+ \sa backgroundRole(), foregroundRole()
+ */
+
+void QWidget::setBackgroundRole(QPalette::ColorRole role)
+{
+ Q_D(QWidget);
+ d->bg_role = role;
+ d->updateSystemBackground();
+ d->propagatePaletteChange();
+ d->updateIsOpaque();
+}
+
+/*!
+ Returns the foreground role.
+
+ The foreground role defines the color from the widget's \l palette that
+ is used to draw the foreground.
+
+ If no explicit foreground role is set, the function returns a role
+ that contrasts with the background role.
+
+ \sa setForegroundRole(), backgroundRole()
+ */
+QPalette::ColorRole QWidget::foregroundRole() const
+{
+ Q_D(const QWidget);
+ QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
+ if (rl != QPalette::NoRole)
+ return rl;
+ QPalette::ColorRole role = QPalette::WindowText;
+ switch (backgroundRole()) {
+ case QPalette::Button:
+ role = QPalette::ButtonText;
+ break;
+ case QPalette::Base:
+ role = QPalette::Text;
+ break;
+ case QPalette::Dark:
+ case QPalette::Shadow:
+ role = QPalette::Light;
+ break;
+ case QPalette::Highlight:
+ role = QPalette::HighlightedText;
+ break;
+ case QPalette::ToolTipBase:
+ role = QPalette::ToolTipText;
+ break;
+ default:
+ ;
+ }
+ return role;
+}
+
+/*!
+ Sets the foreground role of the widget to \a role.
+
+ The foreground role defines the color from the widget's \l palette that
+ is used to draw the foreground.
+
+ If \a role is QPalette::NoRole, the widget uses a foreground role
+ that contrasts with the background role.
+
+ Note that styles are free to choose any color from the palette.
+ You can modify the palette or set a style sheet if you don't
+ achieve the result you want with setForegroundRole().
+
+ \sa foregroundRole(), backgroundRole()
+ */
+void QWidget::setForegroundRole(QPalette::ColorRole role)
+{
+ Q_D(QWidget);
+ d->fg_role = role;
+ d->updateSystemBackground();
+ d->propagatePaletteChange();
+}
+
+/*!
+ \property QWidget::palette
+ \brief the widget's palette
+
+ This property describes the widget's palette. The palette is used by the
+ widget's style when rendering standard components, and is available as a
+ means to ensure that custom widgets can maintain consistency with the
+ native platform's look and feel. It's common that different platforms, or
+ different styles, have different palettes.
+
+ When you assign a new palette to a widget, the color roles from this
+ palette are combined with the widget's default palette to form the
+ widget's final palette. The palette entry for the widget's background role
+ is used to fill the widget's background (see QWidget::autoFillBackground),
+ and the foreground role initializes QPainter's pen.
+
+ The default depends on the system environment. QApplication maintains a
+ system/theme palette which serves as a default for all widgets. There may
+ also be special palette defaults for certain types of widgets (e.g., on
+ Windows XP and Vista, all classes that derive from QMenuBar have a special
+ default palette). You can also define default palettes for widgets
+ yourself by passing a custom palette and the name of a widget to
+ QApplication::setPalette(). Finally, the style always has the option of
+ polishing the palette as it's assigned (see QStyle::polish()).
+
+ QWidget propagates explicit palette roles from parent to child. If you
+ assign a brush or color to a specific role on a palette and assign that
+ palette to a widget, that role will propagate to all the widget's
+ children, overriding any system defaults for that role. Note that palettes
+ by default don't propagate to windows (see isWindow()) unless the
+ Qt::WA_WindowPropagation attribute is enabled.
+
+ QWidget's palette propagation is similar to its font propagation.
+
+ The current style, which is used to render the content of all standard Qt
+ widgets, is free to choose colors and brushes from the widget palette, or
+ in some cases, to ignore the palette (partially, or completely). In
+ particular, certain styles like GTK style, Mac style, Windows XP, and
+ Vista style, depend on third party APIs to render the content of widgets,
+ and these styles typically do not follow the palette. Because of this,
+ assigning roles to a widget's palette is not guaranteed to change the
+ appearance of the widget. Instead, you may choose to apply a \l
+ styleSheet. You can refer to our Knowledge Base article
+ \l{http://qt.nokia.com/developer/knowledgebase/22}{here} for more
+ information.
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ When using style sheets, the palette of a widget can be customized using
+ the "color", "background-color", "selection-color",
+ "selection-background-color" and "alternate-background-color".
+
+ \sa QApplication::palette(), QWidget::font()
+*/
+const QPalette &QWidget::palette() const
+{
+ if (!isEnabled()) {
+ data->pal.setCurrentColorGroup(QPalette::Disabled);
+ } else if ((!isVisible() || isActiveWindow())
+#if defined(Q_OS_WIN) && !defined(Q_WS_WINCE)
+ && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
+#endif
+ ) {
+ data->pal.setCurrentColorGroup(QPalette::Active);
+ } else {
+#ifdef Q_WS_MAC
+ extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
+ if (qt_mac_can_clickThrough(this))
+ data->pal.setCurrentColorGroup(QPalette::Active);
+ else
+#endif
+ data->pal.setCurrentColorGroup(QPalette::Inactive);
+ }
+ return data->pal;
+}
+
+void QWidget::setPalette(const QPalette &palette)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
+
+ // Determine which palette is inherited from this widget's ancestors and
+ // QApplication::palette, resolve this against \a palette (attributes from
+ // the inherited palette are copied over this widget's palette). Then
+ // propagate this palette to this widget's children.
+ QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
+ QPalette resolvedPalette = palette.resolve(naturalPalette);
+ d->setPalette_helper(resolvedPalette);
+}
+
+/*!
+ \internal
+
+ Returns the palette that the widget \a w inherits from its ancestors and
+ QApplication::palette. \a inheritedMask is the combination of the widget's
+ ancestors palette request masks (i.e., which attributes from the parent
+ widget's palette are implicitly imposed on this widget by the user). Note
+ that this font does not take into account the palette set on \a w itself.
+*/
+QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
+{
+ Q_Q(const QWidget);
+ QPalette naturalPalette = QApplication::palette(q);
+ if (!q->testAttribute(Qt::WA_StyleSheet)
+ && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
+#ifndef QT_NO_GRAPHICSVIEW
+ || (extra && extra->proxyWidget)
+#endif //QT_NO_GRAPHICSVIEW
+ )) {
+ if (QWidget *p = q->parentWidget()) {
+ if (!p->testAttribute(Qt::WA_StyleSheet)) {
+ if (!naturalPalette.isCopyOf(QApplication::palette())) {
+ QPalette inheritedPalette = p->palette();
+ inheritedPalette.resolve(inheritedMask);
+ naturalPalette = inheritedPalette.resolve(naturalPalette);
+ } else {
+ naturalPalette = p->palette();
+ }
+ }
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ else if (extra && extra->proxyWidget) {
+ QPalette inheritedPalette = extra->proxyWidget->palette();
+ inheritedPalette.resolve(inheritedMask);
+ naturalPalette = inheritedPalette.resolve(naturalPalette);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ naturalPalette.resolve(0);
+ return naturalPalette;
+}
+/*!
+ \internal
+
+ Determine which palette is inherited from this widget's ancestors and
+ QApplication::palette, resolve this against this widget's palette
+ (attributes from the inherited palette are copied over this widget's
+ palette). Then propagate this palette to this widget's children.
+*/
+void QWidgetPrivate::resolvePalette()
+{
+ QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
+ QPalette resolvedPalette = data.pal.resolve(naturalPalette);
+ setPalette_helper(resolvedPalette);
+}
+
+void QWidgetPrivate::setPalette_helper(const QPalette &palette)
+{
+ Q_Q(QWidget);
+ if (data.pal == palette && data.pal.resolve() == palette.resolve())
+ return;
+ data.pal = palette;
+ updateSystemBackground();
+ propagatePaletteChange();
+ updateIsOpaque();
+ q->update();
+ updateIsOpaque();
+}
+
+/*!
+ \property QWidget::font
+ \brief the font currently set for the widget
+
+ This property describes the widget's requested font. The font is used by
+ the widget's style when rendering standard components, and is available as
+ a means to ensure that custom widgets can maintain consistency with the
+ native platform's look and feel. It's common that different platforms, or
+ different styles, define different fonts for an application.
+
+ When you assign a new font to a widget, the properties from this font are
+ combined with the widget's default font to form the widget's final
+ font. You can call fontInfo() to get a copy of the widget's final
+ font. The final font is also used to initialize QPainter's font.
+
+ The default depends on the system environment. QApplication maintains a
+ system/theme font which serves as a default for all widgets. There may
+ also be special font defaults for certain types of widgets. You can also
+ define default fonts for widgets yourself by passing a custom font and the
+ name of a widget to QApplication::setFont(). Finally, the font is matched
+ against Qt's font database to find the best match.
+
+ QWidget propagates explicit font properties from parent to child. If you
+ change a specific property on a font and assign that font to a widget,
+ that property will propagate to all the widget's children, overriding any
+ system defaults for that property. Note that fonts by default don't
+ propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
+ attribute is enabled.
+
+ QWidget's font propagation is similar to its palette propagation.
+
+ The current style, which is used to render the content of all standard Qt
+ widgets, is free to choose to use the widget font, or in some cases, to
+ ignore it (partially, or completely). In particular, certain styles like
+ GTK style, Mac style, Windows XP, and Vista style, apply special
+ modifications to the widget font to match the platform's native look and
+ feel. Because of this, assigning properties to a widget's font is not
+ guaranteed to change the appearance of the widget. Instead, you may choose
+ to apply a \l styleSheet.
+
+ \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
+ style sheets will take precedence if the settings conflict.
+
+ \sa fontInfo(), fontMetrics()
+*/
+
+void QWidget::setFont(const QFont &font)
+{
+ Q_D(QWidget);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ const QStyleSheetStyle* style;
+ if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) {
+ style->saveWidgetFont(this, font);
+ }
+#endif
+
+ setAttribute(Qt::WA_SetFont, font.resolve() != 0);
+
+ // Determine which font is inherited from this widget's ancestors and
+ // QApplication::font, resolve this against \a font (attributes from the
+ // inherited font are copied over). Then propagate this font to this
+ // widget's children.
+ QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
+ QFont resolvedFont = font.resolve(naturalFont);
+ d->setFont_helper(resolvedFont);
+}
+
+/*
+ \internal
+
+ Returns the font that the widget \a w inherits from its ancestors and
+ QApplication::font. \a inheritedMask is the combination of the widget's
+ ancestors font request masks (i.e., which attributes from the parent
+ widget's font are implicitly imposed on this widget by the user). Note
+ that this font does not take into account the font set on \a w itself.
+
+ ### Stylesheet has a different font propagation mechanism. When a stylesheet
+ is applied, fonts are not propagated anymore
+*/
+QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
+{
+ Q_Q(const QWidget);
+ QFont naturalFont = QApplication::font(q);
+ if (!q->testAttribute(Qt::WA_StyleSheet)
+ && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
+#ifndef QT_NO_GRAPHICSVIEW
+ || (extra && extra->proxyWidget)
+#endif //QT_NO_GRAPHICSVIEW
+ )) {
+ if (QWidget *p = q->parentWidget()) {
+ if (!p->testAttribute(Qt::WA_StyleSheet)) {
+ if (!naturalFont.isCopyOf(QApplication::font())) {
+ QFont inheritedFont = p->font();
+ inheritedFont.resolve(inheritedMask);
+ naturalFont = inheritedFont.resolve(naturalFont);
+ } else {
+ naturalFont = p->font();
+ }
+ }
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ else if (extra && extra->proxyWidget) {
+ QFont inheritedFont = extra->proxyWidget->font();
+ inheritedFont.resolve(inheritedMask);
+ naturalFont = inheritedFont.resolve(naturalFont);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ naturalFont.resolve(0);
+ return naturalFont;
+}
+
+/*!
+ \internal
+
+ Determine which font is implicitly imposed on this widget by its ancestors
+ and QApplication::font, resolve this against its own font (attributes from
+ the implicit font are copied over). Then propagate this font to this
+ widget's children.
+*/
+void QWidgetPrivate::resolveFont()
+{
+ QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
+ QFont resolvedFont = data.fnt.resolve(naturalFont);
+ setFont_helper(resolvedFont);
+}
+
+/*!
+ \internal
+
+ Assign \a font to this widget, and propagate it to all children, except
+ style sheet widgets (handled differently) and windows that don't enable
+ window propagation. \a implicitMask is the union of all ancestor widgets'
+ font request masks, and determines which attributes from this widget's
+ font should propagate.
+*/
+void QWidgetPrivate::updateFont(const QFont &font)
+{
+ Q_Q(QWidget);
+#ifndef QT_NO_STYLE_STYLESHEET
+ const QStyleSheetStyle* cssStyle;
+ cssStyle = extra ? qobject_cast<const QStyleSheetStyle*>(extra->style) : 0;
+#endif
+
+#ifdef QT3_SUPPORT
+ QFont old = data.fnt;
+#endif
+ data.fnt = QFont(font, q);
+#if defined(Q_WS_X11)
+ // make sure the font set on this widget is associated with the correct screen
+ data.fnt.x11SetScreen(xinfo.screen());
+#endif
+ // Combine new mask with natural mask and propagate to children.
+#ifndef QT_NO_GRAPHICSVIEW
+ if (!q->parentWidget() && extra && extra->proxyWidget) {
+ QGraphicsProxyWidget *p = extra->proxyWidget;
+ inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve();
+ } else
+#endif //QT_NO_GRAPHICSVIEW
+ if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
+ inheritedFontResolveMask = 0;
+ }
+ uint newMask = data.fnt.resolve() | inheritedFontResolveMask;
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w) {
+ if (0) {
+#ifndef QT_NO_STYLE_STYLESHEET
+ } else if (w->testAttribute(Qt::WA_StyleSheet)) {
+ // Style sheets follow a different font propagation scheme.
+ if (cssStyle)
+ cssStyle->updateStyleSheetFont(w);
+#endif
+ } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
+ // Propagate font changes.
+ QWidgetPrivate *wd = w->d_func();
+ wd->inheritedFontResolveMask = newMask;
+ wd->resolveFont();
+ }
+ }
+ }
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (cssStyle) {
+ cssStyle->updateStyleSheetFont(q);
+ }
+#endif
+
+ QEvent e(QEvent::FontChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->fontChange(old);
+#endif
+}
+
+void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
+{
+ Q_Q(QWidget);
+
+ if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
+ return;
+ q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
+ if (!children.isEmpty()) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
+ w->d_func()->setLayoutDirection_helper(direction);
+ }
+ }
+ QEvent e(QEvent::LayoutDirectionChange);
+ QApplication::sendEvent(q, &e);
+}
+
+void QWidgetPrivate::resolveLayoutDirection()
+{
+ Q_Q(const QWidget);
+ if (!q->testAttribute(Qt::WA_SetLayoutDirection))
+ setLayoutDirection_helper(q->isWindow() ? QApplication::layoutDirection() : q->parentWidget()->layoutDirection());
+}
+
+/*!
+ \property QWidget::layoutDirection
+
+ \brief the layout direction for this widget
+
+ By default, this property is set to Qt::LeftToRight.
+
+ When the layout direction is set on a widget, it will propagate to
+ the widget's children, but not to a child that is a window and not
+ to a child for which setLayoutDirection() has been explicitly
+ called. Also, child widgets added \e after setLayoutDirection()
+ has been called for the parent do not inherit the parent's layout
+ direction.
+
+ This method no longer affects text layout direction since Qt 4.7.
+
+ \sa QApplication::layoutDirection
+*/
+void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
+{
+ Q_D(QWidget);
+
+ if (direction == Qt::LayoutDirectionAuto) {
+ unsetLayoutDirection();
+ return;
+ }
+
+ setAttribute(Qt::WA_SetLayoutDirection);
+ d->setLayoutDirection_helper(direction);
+}
+
+Qt::LayoutDirection QWidget::layoutDirection() const
+{
+ return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
+}
+
+void QWidget::unsetLayoutDirection()
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetLayoutDirection, false);
+ d->resolveLayoutDirection();
+}
+
+/*!
+ \fn QFontMetrics QWidget::fontMetrics() const
+
+ Returns the font metrics for the widget's current font.
+ Equivalent to QFontMetrics(widget->font()).
+
+ \sa font(), fontInfo(), setFont()
+*/
+
+/*!
+ \fn QFontInfo QWidget::fontInfo() const
+
+ Returns the font info for the widget's current font.
+ Equivalent to QFontInto(widget->font()).
+
+ \sa font(), fontMetrics(), setFont()
+*/
+
+
+/*!
+ \property QWidget::cursor
+ \brief the cursor shape for this widget
+
+ The mouse cursor will assume this shape when it's over this
+ widget. See the \link Qt::CursorShape list of predefined cursor
+ objects\endlink for a range of useful shapes.
+
+ An editor widget might use an I-beam cursor:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 6
+
+ If no cursor has been set, or after a call to unsetCursor(), the
+ parent's cursor is used.
+
+ By default, this property contains a cursor with the Qt::ArrowCursor
+ shape.
+
+ Some underlying window implementations will reset the cursor if it
+ leaves a widget even if the mouse is grabbed. If you want to have
+ a cursor set for all widgets, even when outside the window, consider
+ QApplication::setOverrideCursor().
+
+ \sa QApplication::setOverrideCursor()
+*/
+
+#ifndef QT_NO_CURSOR
+QCursor QWidget::cursor() const
+{
+ Q_D(const QWidget);
+ if (testAttribute(Qt::WA_SetCursor))
+ return (d->extra && d->extra->curs)
+ ? *d->extra->curs
+ : QCursor(Qt::ArrowCursor);
+ if (isWindow() || !parentWidget())
+ return QCursor(Qt::ArrowCursor);
+ return parentWidget()->cursor();
+}
+
+void QWidget::setCursor(const QCursor &cursor)
+{
+ Q_D(QWidget);
+// On Mac we must set the cursor even if it is the ArrowCursor.
+#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS)
+ if (cursor.shape() != Qt::ArrowCursor
+ || (d->extra && d->extra->curs))
+#endif
+ {
+ d->createExtra();
+ QCursor *newCursor = new QCursor(cursor);
+ delete d->extra->curs;
+ d->extra->curs = newCursor;
+ }
+ setAttribute(Qt::WA_SetCursor);
+ d->setCursor_sys(cursor);
+
+ QEvent event(QEvent::CursorChange);
+ QApplication::sendEvent(this, &event);
+}
+
+void QWidget::unsetCursor()
+{
+ Q_D(QWidget);
+ if (d->extra) {
+ delete d->extra->curs;
+ d->extra->curs = 0;
+ }
+ if (!isWindow())
+ setAttribute(Qt::WA_SetCursor, false);
+ d->unsetCursor_sys();
+
+ QEvent event(QEvent::CursorChange);
+ QApplication::sendEvent(this, &event);
+}
+
+#endif
+
+/*!
+ \enum QWidget::RenderFlag
+
+ This enum describes how to render the widget when calling QWidget::render().
+
+ \value DrawWindowBackground If you enable this option, the widget's background
+ is rendered into the target even if autoFillBackground is not set. By default,
+ this option is enabled.
+
+ \value DrawChildren If you enable this option, the widget's children
+ are rendered recursively into the target. By default, this option is enabled.
+
+ \value IgnoreMask If you enable this option, the widget's QWidget::mask()
+ is ignored when rendering into the target. By default, this option is disabled.
+
+ \since 4.3
+*/
+
+/*!
+ \since 4.3
+
+ Renders the \a sourceRegion of this widget into the \a target
+ using \a renderFlags to determine how to render. Rendering
+ starts at \a targetOffset in the \a target. For example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 7
+
+ If \a sourceRegion is a null region, this function will use QWidget::rect() as
+ the region, i.e. the entire widget.
+
+ Ensure that you call QPainter::end() for the \a target device's
+ active painter (if any) before rendering. For example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 8
+
+ \note To obtain the contents of an OpenGL widget, use QGLWidget::grabFrameBuffer()
+ or QGLWidget::renderPixmap() instead.
+*/
+void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
+ const QRegion &sourceRegion, RenderFlags renderFlags)
+{
+ d_func()->render(target, targetOffset, sourceRegion, renderFlags, false);
+}
+
+/*!
+ \overload
+
+ Renders the widget into the \a painter's QPainter::device().
+
+ Transformations and settings applied to the \a painter will be used
+ when rendering.
+
+ \note The \a painter must be active. On Mac OS X the widget will be
+ rendered into a QPixmap and then drawn by the \a painter.
+
+ \sa QPainter::device()
+*/
+void QWidget::render(QPainter *painter, const QPoint &targetOffset,
+ const QRegion &sourceRegion, RenderFlags renderFlags)
+{
+ if (!painter) {
+ qWarning("QWidget::render: Null pointer to painter");
+ return;
+ }
+
+ if (!painter->isActive()) {
+ qWarning("QWidget::render: Cannot render with an inactive painter");
+ return;
+ }
+
+ const qreal opacity = painter->opacity();
+ if (qFuzzyIsNull(opacity))
+ return; // Fully transparent.
+
+ Q_D(QWidget);
+ const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
+ const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (toBePainted.isEmpty())
+ return;
+
+ if (!d->extra)
+ d->createExtra();
+ d->extra->inRenderWithPainter = true;
+
+#ifdef Q_WS_MAC
+ d->render_helper(painter, targetOffset, toBePainted, renderFlags);
+#else
+ QPaintEngine *engine = painter->paintEngine();
+ Q_ASSERT(engine);
+ QPaintEnginePrivate *enginePriv = engine->d_func();
+ Q_ASSERT(enginePriv);
+ QPaintDevice *target = engine->paintDevice();
+ Q_ASSERT(target);
+
+ // Render via a pixmap when dealing with non-opaque painters or printers.
+ if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
+ d->render_helper(painter, targetOffset, toBePainted, renderFlags);
+ d->extra->inRenderWithPainter = false;
+ return;
+ }
+
+ // Set new shared painter.
+ QPainter *oldPainter = d->sharedPainter();
+ d->setSharedPainter(painter);
+
+ // Save current system clip, viewport and transform,
+ const QTransform oldTransform = enginePriv->systemTransform;
+ const QRegion oldSystemClip = enginePriv->systemClip;
+ const QRegion oldSystemViewport = enginePriv->systemViewport;
+
+ // This ensures that all painting triggered by render() is clipped to the current engine clip.
+ if (painter->hasClipping()) {
+ const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
+ enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
+ } else {
+ enginePriv->setSystemViewport(oldSystemClip);
+ }
+
+ render(target, targetOffset, toBePainted, renderFlags);
+
+ // Restore system clip, viewport and transform.
+ enginePriv->systemClip = oldSystemClip;
+ enginePriv->setSystemViewport(oldSystemViewport);
+ enginePriv->setSystemTransform(oldTransform);
+
+ // Restore shared painter.
+ d->setSharedPainter(oldPainter);
+#endif
+
+ d->extra->inRenderWithPainter = false;
+}
+
+/*!
+ \brief The graphicsEffect function returns a pointer to the
+ widget's graphics effect.
+
+ If the widget has no graphics effect, 0 is returned.
+
+ \since 4.6
+
+ \sa setGraphicsEffect()
+*/
+#ifndef QT_NO_GRAPHICSEFFECT
+QGraphicsEffect *QWidget::graphicsEffect() const
+{
+ Q_D(const QWidget);
+ return d->graphicsEffect;
+}
+#endif //QT_NO_GRAPHICSEFFECT
+
+/*!
+
+ \brief The setGraphicsEffect function is for setting the widget's graphics effect.
+
+ Sets \a effect as the widget's effect. If there already is an effect installed
+ on this widget, QWidget will delete the existing effect before installing
+ the new \a effect.
+
+ If \a effect is the installed on a different widget, setGraphicsEffect() will remove
+ the effect from the widget and install it on this widget.
+
+ QWidget takes ownership of \a effect.
+
+ \note This function will apply the effect on itself and all its children.
+
+ \since 4.6
+
+ \sa graphicsEffect()
+*/
+#ifndef QT_NO_GRAPHICSEFFECT
+void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
+{
+ Q_D(QWidget);
+ if (d->graphicsEffect == effect)
+ return;
+
+ if (d->graphicsEffect) {
+ d->invalidateBuffer(rect());
+ delete d->graphicsEffect;
+ d->graphicsEffect = 0;
+ }
+
+ if (effect) {
+ // Set new effect.
+ QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
+ QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
+ d->graphicsEffect = effect;
+ effect->d_func()->setGraphicsEffectSource(source);
+ update();
+ }
+
+ d->updateIsOpaque();
+}
+#endif //QT_NO_GRAPHICSEFFECT
+
+bool QWidgetPrivate::isAboutToShow() const
+{
+ if (data.in_show)
+ return true;
+
+ Q_Q(const QWidget);
+ if (q->isHidden())
+ return false;
+
+ // The widget will be shown if any of its ancestors are about to show.
+ QWidget *parent = q->parentWidget();
+ return parent ? parent->d_func()->isAboutToShow() : false;
+}
+
+QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
+{
+ Q_Q(QWidget);
+ const bool isVisible = q->isVisible();
+
+ // Make sure the widget is laid out correctly.
+ if (!isVisible && !isAboutToShow()) {
+ QWidget *topLevel = q->window();
+ (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
+ topLevel->ensurePolished();
+
+ // Invalidate the layout of hidden ancestors (incl. myself) and pretend
+ // they're not explicitly hidden.
+ QWidget *widget = q;
+ QWidgetList hiddenWidgets;
+ while (widget) {
+ if (widget->isHidden()) {
+ widget->setAttribute(Qt::WA_WState_Hidden, false);
+ hiddenWidgets.append(widget);
+ if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
+ widget->d_func()->updateGeometry_helper(true);
+ }
+ widget = widget->parentWidget();
+ }
+
+ // Activate top-level layout.
+ if (topLevel->d_func()->layout)
+ topLevel->d_func()->layout->activate();
+
+ // Adjust size if necessary.
+ QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
+ if (topLevelExtra && !topLevelExtra->sizeAdjusted
+ && !topLevel->testAttribute(Qt::WA_Resized)) {
+ topLevel->adjustSize();
+ topLevel->setAttribute(Qt::WA_Resized, false);
+ }
+
+ // Activate child layouts.
+ topLevel->d_func()->activateChildLayoutsRecursively();
+
+ // We're not cheating with WA_WState_Hidden anymore.
+ for (int i = 0; i < hiddenWidgets.size(); ++i) {
+ QWidget *widget = hiddenWidgets.at(i);
+ widget->setAttribute(Qt::WA_WState_Hidden);
+ if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
+ widget->parentWidget()->d_func()->layout->invalidate();
+ }
+ } else if (isVisible) {
+ q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
+ }
+
+ // Calculate the region to be painted.
+ QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
+ if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
+ toBePainted &= extra->mask;
+ return toBePainted;
+}
+
+void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
+ QWidget::RenderFlags renderFlags)
+{
+ Q_ASSERT(painter);
+ Q_ASSERT(!toBePainted.isEmpty());
+
+ Q_Q(QWidget);
+#ifndef Q_WS_MAC
+ const QTransform originalTransform = painter->worldTransform();
+ const bool useDeviceCoordinates = originalTransform.isScaling();
+ if (!useDeviceCoordinates) {
+#endif
+ // Render via a pixmap.
+ const QRect rect = toBePainted.boundingRect();
+ const QSize size = rect.size();
+ if (size.isNull())
+ return;
+
+ QPixmap pixmap(size);
+ if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
+ pixmap.fill(Qt::transparent);
+ q->render(&pixmap, QPoint(), toBePainted, renderFlags);
+
+ const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
+ painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
+
+ painter->drawPixmap(targetOffset, pixmap);
+
+ if (restore)
+ painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
+
+#ifndef Q_WS_MAC
+ } else {
+ // Render via a pixmap in device coordinates (to avoid pixmap scaling).
+ QTransform transform = originalTransform;
+ transform.translate(targetOffset.x(), targetOffset.y());
+
+ QPaintDevice *device = painter->device();
+ Q_ASSERT(device);
+
+ // Calculate device rect.
+ const QRectF rect(toBePainted.boundingRect());
+ QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
+ deviceRect &= QRect(0, 0, device->width(), device->height());
+
+ QPixmap pixmap(deviceRect.size());
+ pixmap.fill(Qt::transparent);
+
+ // Create a pixmap device coordinate painter.
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setRenderHints(painter->renderHints());
+ transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+ pixmapPainter.setTransform(transform);
+
+ q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
+ pixmapPainter.end();
+
+ // And then draw the pixmap.
+ painter->setTransform(QTransform());
+ painter->drawPixmap(deviceRect.topLeft(), pixmap);
+ painter->setTransform(originalTransform);
+ }
+#endif
+}
+
+void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
+ QPainter *sharedPainter, QWidgetBackingStore *backingStore)
+{
+ if (rgn.isEmpty())
+ return;
+
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ if (qt_mac_clearDirtyOnWidgetInsideDrawWidget)
+ dirtyOnWidget = QRegion();
+
+ // We disable the rendering of QToolBar in the backingStore if
+ // it's supposed to be in the unified toolbar on Mac OS X.
+ if (backingStore && isInUnifiedToolbar)
+ return;
+#endif // Q_WS_MAC && QT_MAC_USE_COCOA
+
+
+ Q_Q(QWidget);
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (graphicsEffect && graphicsEffect->isEnabled()) {
+ QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
+ QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
+ (source->d_func());
+ if (!sourced->context) {
+ QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
+ sourced->context = &context;
+ if (!sharedPainter) {
+ QPaintEngine *paintEngine = pdev->paintEngine();
+ paintEngine->d_func()->systemClip = rgn.translated(offset);
+ QPainter p(pdev);
+ p.translate(offset);
+ context.painter = &p;
+ graphicsEffect->draw(&p);
+ paintEngine->d_func()->systemClip = QRegion();
+ } else {
+ context.painter = sharedPainter;
+ if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
+ sourced->invalidateCache();
+ sourced->lastEffectTransform = sharedPainter->worldTransform();
+ }
+ sharedPainter->save();
+ sharedPainter->translate(offset);
+ graphicsEffect->draw(sharedPainter);
+ sharedPainter->restore();
+ }
+ sourced->context = 0;
+ return;
+ }
+ }
+#endif //QT_NO_GRAFFICSEFFECT
+
+ const bool asRoot = flags & DrawAsRoot;
+ const bool alsoOnScreen = flags & DrawPaintOnScreen;
+ const bool recursive = flags & DrawRecursive;
+ const bool alsoInvisible = flags & DrawInvisible;
+
+ Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
+
+ QRegion toBePainted(rgn);
+ if (asRoot && !alsoInvisible)
+ toBePainted &= clipRect(); //(rgn & visibleRegion());
+ if (!(flags & DontSubtractOpaqueChildren))
+ subtractOpaqueChildren(toBePainted, q->rect());
+
+ if (!toBePainted.isEmpty()) {
+ bool onScreen = paintOnScreen();
+ if (!onScreen || alsoOnScreen) {
+ //update the "in paint event" flag
+ if (q->testAttribute(Qt::WA_WState_InPaintEvent))
+ qWarning("QWidget::repaint: Recursive repaint detected");
+ q->setAttribute(Qt::WA_WState_InPaintEvent);
+
+ //clip away the new area
+#ifndef QT_NO_PAINT_DEBUG
+ bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted);
+#endif
+ QPaintEngine *paintEngine = pdev->paintEngine();
+ if (paintEngine) {
+ setRedirected(pdev, -offset);
+
+#ifdef Q_WS_MAC
+ // (Alien support) Special case for Mac when redirecting: If the paint device
+ // is of the Widget type we need to set WA_WState_InPaintEvent since painting
+ // outside the paint event is not supported on QWidgets. The attributeis
+ // restored further down.
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent);
+
+#endif
+ if (sharedPainter)
+ paintEngine->d_func()->systemClip = toBePainted;
+ else
+ paintEngine->d_func()->systemRect = q->data->crect;
+
+ //paint the background
+ if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
+ && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+ QPainter p(q);
+ paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0);
+ }
+
+ if (!sharedPainter)
+ paintEngine->d_func()->systemClip = toBePainted.translated(offset);
+
+ if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
+ QPainter p(q);
+ QColor tint = q->palette().window().color();
+ tint.setAlphaF(qreal(.6));
+ p.fillRect(toBePainted.boundingRect(), tint);
+ }
+ }
+
+#if 0
+ qDebug() << "painting" << q << "opaque ==" << isOpaque();
+ qDebug() << "clipping to" << toBePainted << "location == " << offset
+ << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
+#endif
+
+ //actually send the paint event
+ QPaintEvent e(toBePainted);
+ QCoreApplication::sendSpontaneousEvent(q, &e);
+#if !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
+ if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
+ backingStore->markDirtyOnScreen(toBePainted, q, offset);
+#endif
+
+ //restore
+ if (paintEngine) {
+#ifdef Q_WS_MAC
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent, false);
+#endif
+ restoreRedirected();
+ if (!sharedPainter)
+ paintEngine->d_func()->systemRect = QRect();
+ else
+ paintEngine->d_func()->currentClipDevice = 0;
+ paintEngine->d_func()->systemClip = QRegion();
+ }
+ q->setAttribute(Qt::WA_WState_InPaintEvent, false);
+ if (q->paintingActive() && !q->testAttribute(Qt::WA_PaintOutsidePaintEvent))
+ qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
+
+ if (paintEngine && paintEngine->autoDestruct()) {
+ delete paintEngine;
+ }
+
+#ifndef QT_NO_PAINT_DEBUG
+ if (flushed)
+ QWidgetBackingStore::unflushPaint(q, toBePainted);
+#endif
+ } else if (q->isWindow()) {
+ QPaintEngine *engine = pdev->paintEngine();
+ if (engine) {
+ QPainter p(pdev);
+ p.setClipRegion(toBePainted);
+ const QBrush bg = q->palette().brush(QPalette::Window);
+ if (bg.style() == Qt::TexturePattern)
+ p.drawTiledPixmap(q->rect(), bg.texture());
+ else
+ p.fillRect(q->rect(), bg);
+
+ if (engine->autoDestruct())
+ delete engine;
+ }
+ }
+ }
+
+ if (recursive && !children.isEmpty()) {
+ paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , q->windowSurface()
+#endif
+ , sharedPainter, backingStore);
+ }
+}
+
+void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
+ const QRegion &sourceRegion, QWidget::RenderFlags renderFlags,
+ bool readyToRender)
+{
+ if (!target) {
+ qWarning("QWidget::render: null pointer to paint device");
+ return;
+ }
+
+ const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
+ QRegion paintRegion = !inRenderWithPainter && !readyToRender
+ ? prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (paintRegion.isEmpty())
+ return;
+
+#ifndef Q_WS_MAC
+ QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0;
+
+ // Use the target's shared painter if set (typically set when doing
+ // "other->render(widget);" in the widget's paintEvent.
+ if (target->devType() == QInternal::Widget) {
+ QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
+ if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
+ QPainter *targetPainter = targetPrivate->sharedPainter();
+ if (targetPainter && targetPainter->isActive())
+ setSharedPainter(targetPainter);
+ }
+ }
+#endif
+
+ // Use the target's redirected device if set and adjust offset and paint
+ // region accordingly. This is typically the case when people call render
+ // from the paintEvent.
+ QPoint offset = targetOffset;
+ offset -= paintRegion.boundingRect().topLeft();
+ QPoint redirectionOffset;
+ QPaintDevice *redirected = 0;
+
+ if (target->devType() == QInternal::Widget)
+ redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
+ if (!redirected)
+ redirected = QPainter::redirected(target, &redirectionOffset);
+
+ if (redirected) {
+ target = redirected;
+ offset -= redirectionOffset;
+ }
+
+ if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
+ if (QPaintEngine *targetEngine = target->paintEngine()) {
+ const QRegion targetSystemClip = targetEngine->systemClip();
+ if (!targetSystemClip.isEmpty())
+ paintRegion &= targetSystemClip.translated(-offset);
+ }
+ }
+
+ // Set backingstore flags.
+ int flags = DrawPaintOnScreen | DrawInvisible;
+ if (renderFlags & QWidget::DrawWindowBackground)
+ flags |= DrawAsRoot;
+
+ if (renderFlags & QWidget::DrawChildren)
+ flags |= DrawRecursive;
+ else
+ flags |= DontSubtractOpaqueChildren;
+
+#ifdef Q_WS_QWS
+ flags |= DontSetCompositionMode;
+#endif
+
+ if (target->devType() == QInternal::Printer) {
+ QPainter p(target);
+ render_helper(&p, targetOffset, paintRegion, renderFlags);
+ return;
+ }
+
+#ifndef Q_WS_MAC
+ // Render via backingstore.
+ drawWidget(target, paintRegion, offset, flags, sharedPainter());
+
+ // Restore shared painter.
+ if (oldSharedPainter)
+ setSharedPainter(oldSharedPainter);
+#else
+ // Render via backingstore (no shared painter).
+ drawWidget(target, paintRegion, offset, flags, 0);
+#endif
+}
+
+void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
+ const QPoint &offset, int flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , const QWindowSurface *currentSurface
+#endif
+ , QPainter *sharedPainter, QWidgetBackingStore *backingStore)
+{
+ QWidget *w = 0;
+ QRect boundingRect;
+ bool dirtyBoundingRect = true;
+ const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
+ const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
+
+ do {
+ QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
+ if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
+ && !(excludeNativeChildren && x->internalWinId())) {
+ if (dirtyBoundingRect) {
+ boundingRect = rgn.boundingRect();
+ dirtyBoundingRect = false;
+ }
+
+ if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ if (x->windowSurface() == currentSurface)
+#endif
+ {
+ w = x;
+ break;
+ }
+ }
+ }
+ --index;
+ } while (index >= 0);
+
+ if (!w)
+ return;
+
+ QWidgetPrivate *wd = w->d_func();
+ const QPoint widgetPos(w->data->crect.topLeft());
+ const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
+ if (index > 0) {
+ QRegion wr(rgn);
+ if (wd->isOpaque)
+ wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
+ paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , currentSurface
+#endif
+ , sharedPainter, backingStore);
+ }
+
+ if (w->updatesEnabled()
+#ifndef QT_NO_GRAPHICSVIEW
+ && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
+#endif //QT_NO_GRAPHICSVIEW
+ ) {
+ QRegion wRegion(rgn);
+ wRegion &= wd->effectiveRectFor(w->data->crect);
+ wRegion.translate(-widgetPos);
+ if (hasMask)
+ wRegion &= wd->extra->mask;
+ wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, backingStore);
+ }
+}
+
+#ifndef QT_NO_GRAPHICSEFFECT
+QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
+{
+ if (system != Qt::DeviceCoordinates)
+ return m_widget->rect();
+
+ if (!context) {
+ // Device coordinates without context not yet supported.
+ qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
+ return QRectF();
+ }
+
+ return context->painter->worldTransform().mapRect(m_widget->rect());
+}
+
+void QWidgetEffectSourcePrivate::draw(QPainter *painter)
+{
+ if (!context || context->painter != painter) {
+ m_widget->render(painter);
+ return;
+ }
+
+ // The region saved in the context is neither clipped to the rect
+ // nor the mask, so we have to clip it here before calling drawWidget.
+ QRegion toBePainted = context->rgn;
+ toBePainted &= m_widget->rect();
+ QWidgetPrivate *wd = qt_widget_private(m_widget);
+ if (wd->extra && wd->extra->hasMask)
+ toBePainted &= wd->extra->mask;
+
+ wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
+ context->sharedPainter, context->backingStore);
+}
+
+QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffect::PixmapPadMode mode) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ if (!context && deviceCoordinates) {
+ // Device coordinates without context not yet supported.
+ qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ return QPixmap();
+ }
+
+ QPoint pixmapOffset;
+ QRectF sourceRect = m_widget->rect();
+
+ if (deviceCoordinates) {
+ const QTransform &painterTransform = context->painter->worldTransform();
+ sourceRect = painterTransform.mapRect(sourceRect);
+ pixmapOffset = painterTransform.map(pixmapOffset);
+ }
+
+ QRect effectRect;
+
+ if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
+ effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ else if (mode == QGraphicsEffect::PadToTransparentBorder)
+ effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
+ else
+ effectRect = sourceRect.toAlignedRect();
+
+ if (offset)
+ *offset = effectRect.topLeft();
+
+ pixmapOffset -= effectRect.topLeft();
+
+ QPixmap pixmap(effectRect.size());
+ pixmap.fill(Qt::transparent);
+ m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
+ return pixmap;
+}
+#endif //QT_NO_GRAPHICSEFFECT
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ \internal
+
+ Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
+ widget and its ancestors. The search starts at \a origin (inclusive).
+ If successful, the function returns the proxy that embeds the widget, or 0 if no embedded
+ widget was found.
+*/
+QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
+{
+ if (origin) {
+ QWExtra *extra = origin->d_func()->extra;
+ if (extra && extra->proxyWidget)
+ return extra->proxyWidget;
+ return nearestGraphicsProxyWidget(origin->parentWidget());
+ }
+ return 0;
+}
+#endif
+
+/*!
+ \property QWidget::locale
+ \brief the widget's locale
+ \since 4.3
+
+ As long as no special locale has been set, this is either
+ the parent's locale or (if this widget is a top level widget),
+ the default locale.
+
+ If the widget displays dates or numbers, these should be formatted
+ using the widget's locale.
+
+ \sa QLocale QLocale::setDefault()
+*/
+
+void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
+{
+ Q_Q(QWidget);
+ if (locale == loc && !forceUpdate)
+ return;
+
+ locale = loc;
+
+ if (!children.isEmpty()) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (!w)
+ continue;
+ if (w->testAttribute(Qt::WA_SetLocale))
+ continue;
+ if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
+ continue;
+ w->d_func()->setLocale_helper(loc, forceUpdate);
+ }
+ }
+ QEvent e(QEvent::LocaleChange);
+ QApplication::sendEvent(q, &e);
+}
+
+void QWidget::setLocale(const QLocale &locale)
+{
+ Q_D(QWidget);
+
+ setAttribute(Qt::WA_SetLocale);
+ d->setLocale_helper(locale);
+}
+
+QLocale QWidget::locale() const
+{
+ Q_D(const QWidget);
+
+ return d->locale;
+}
+
+void QWidgetPrivate::resolveLocale()
+{
+ Q_Q(const QWidget);
+
+ if (!q->testAttribute(Qt::WA_SetLocale)) {
+ setLocale_helper(q->isWindow()
+ ? QLocale()
+ : q->parentWidget()->locale());
+ }
+}
+
+void QWidget::unsetLocale()
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetLocale, false);
+ d->resolveLocale();
+}
+
+static QString constructWindowTitleFromFilePath(const QString &filePath)
+{
+ QFileInfo fi(filePath);
+ QString windowTitle = fi.fileName() + QLatin1String("[*]");
+#ifndef Q_WS_MAC
+ QString appName = QApplication::applicationName();
+ if (!appName.isEmpty())
+ windowTitle += QLatin1Char(' ') + QChar(0x2014) + QLatin1Char(' ') + appName;
+#endif
+ return windowTitle;
+}
+
+/*!
+ \property QWidget::windowTitle
+ \brief the window title (caption)
+
+ This property only makes sense for top-level widgets, such as
+ windows and dialogs. If no caption has been set, the title is based of the
+ \l windowFilePath. If neither of these is set, then the title is
+ an empty string.
+
+ If you use the \l windowModified mechanism, the window title must
+ contain a "[*]" placeholder, which indicates where the '*' should
+ appear. Normally, it should appear right after the file name
+ (e.g., "document1.txt[*] - Text Editor"). If the \l
+ windowModified property is false (the default), the placeholder
+ is simply removed.
+
+ \sa windowIcon, windowIconText, windowModified, windowFilePath
+*/
+QString QWidget::windowTitle() const
+{
+ Q_D(const QWidget);
+ if (d->extra && d->extra->topextra) {
+ if (!d->extra->topextra->caption.isEmpty())
+ return d->extra->topextra->caption;
+ if (!d->extra->topextra->filePath.isEmpty())
+ return constructWindowTitleFromFilePath(d->extra->topextra->filePath);
+ }
+ return QString();
+}
+
+/*!
+ Returns a modified window title with the [*] place holder
+ replaced according to the rules described in QWidget::setWindowTitle
+
+ This function assumes that "[*]" can be quoted by another
+ "[*]", so it will replace two place holders by one and
+ a single last one by either "*" or nothing depending on
+ the modified flag.
+
+ \internal
+*/
+QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
+{
+ Q_ASSERT(widget);
+
+#ifdef QT_EVAL
+ extern QString qt_eval_adapt_window_title(const QString &title);
+ QString cap = qt_eval_adapt_window_title(title);
+#else
+ QString cap = title;
+#endif
+
+ if (cap.isEmpty())
+ return cap;
+
+ QLatin1String placeHolder("[*]");
+ int placeHolderLength = 3; // QLatin1String doesn't have length()
+
+ int index = cap.indexOf(placeHolder);
+
+ // here the magic begins
+ while (index != -1) {
+ index += placeHolderLength;
+ int count = 1;
+ while (cap.indexOf(placeHolder, index) == index) {
+ ++count;
+ index += placeHolderLength;
+ }
+
+ if (count%2) { // odd number of [*] -> replace last one
+ int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
+ if (widget->isWindowModified()
+ && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, widget))
+ cap.replace(lastIndex, 3, QWidget::tr("*"));
+ else
+ cap.remove(lastIndex, 3);
+ }
+
+ index = cap.indexOf(placeHolder, index);
+ }
+
+ cap.replace(QLatin1String("[*][*]"), placeHolder);
+
+ return cap;
+}
+
+void QWidgetPrivate::setWindowTitle_helper(const QString &title)
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
+}
+
+void QWidgetPrivate::setWindowIconText_helper(const QString &title)
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
+}
+
+void QWidget::setWindowIconText(const QString &iconText)
+{
+ if (QWidget::windowIconText() == iconText)
+ return;
+
+ Q_D(QWidget);
+ d->topData()->iconText = iconText;
+ d->setWindowIconText_helper(iconText);
+
+ QEvent e(QEvent::IconTextChange);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidget::setWindowTitle(const QString &title)
+{
+ if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
+ return;
+
+ Q_D(QWidget);
+ d->topData()->caption = title;
+ d->setWindowTitle_helper(title);
+
+ QEvent e(QEvent::WindowTitleChange);
+ QApplication::sendEvent(this, &e);
+}
+
+
+/*!
+ \property QWidget::windowIcon
+ \brief the widget's icon
+
+ This property only makes sense for windows. If no icon
+ has been set, windowIcon() returns the application icon
+ (QApplication::windowIcon()).
+
+ \sa windowIconText, windowTitle
+*/
+QIcon QWidget::windowIcon() const
+{
+ const QWidget *w = this;
+ while (w) {
+ const QWidgetPrivate *d = w->d_func();
+ if (d->extra && d->extra->topextra && d->extra->topextra->icon)
+ return *d->extra->topextra->icon;
+ w = w->parentWidget();
+ }
+ return QApplication::windowIcon();
+}
+
+void QWidgetPrivate::setWindowIcon_helper()
+{
+ QEvent e(QEvent::WindowIconChange);
+ QApplication::sendEvent(q_func(), &e);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->isWindow())
+ QApplication::sendEvent(w, &e);
+ }
+}
+
+void QWidget::setWindowIcon(const QIcon &icon)
+{
+ Q_D(QWidget);
+
+ setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
+ d->createTLExtra();
+
+ if (!d->extra->topextra->icon)
+ d->extra->topextra->icon = new QIcon();
+ *d->extra->topextra->icon = icon;
+
+ delete d->extra->topextra->iconPixmap;
+ d->extra->topextra->iconPixmap = 0;
+
+ d->setWindowIcon_sys();
+ d->setWindowIcon_helper();
+}
+
+
+/*!
+ \property QWidget::windowIconText
+ \brief the widget's icon text
+
+ This property only makes sense for windows. If no icon
+ text has been set, this functions returns an empty string.
+
+ \sa windowIcon, windowTitle
+*/
+
+QString QWidget::windowIconText() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
+}
+
+/*!
+ \property QWidget::windowFilePath
+ \since 4.4
+ \brief the file path associated with a widget
+
+ This property only makes sense for windows. It associates a file path with
+ a window. If you set the file path, but have not set the window title, Qt
+ sets the window title to contain a string created using the following
+ components.
+
+ On Mac OS X:
+
+ \list
+ \o The file name of the specified path, obtained using QFileInfo::fileName().
+ \endlist
+
+ On Windows and X11:
+
+ \list
+ \o The file name of the specified path, obtained using QFileInfo::fileName().
+ \o An optional \c{*} character, if the \l windowModified property is set.
+ \o The \c{0x2014} unicode character, padded either side by spaces.
+ \o The application name, obtained from the application's
+ \l{QCoreApplication::}{applicationName} property.
+ \endlist
+
+ If the window title is set at any point, then the window title takes precedence and
+ will be shown instead of the file path string.
+
+ Additionally, on Mac OS X, this has an added benefit that it sets the
+ \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
+ for the window, assuming that the file path exists.
+
+ If no file path is set, this property contains an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa windowTitle, windowIcon
+*/
+
+QString QWidget::windowFilePath() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
+}
+
+void QWidget::setWindowFilePath(const QString &filePath)
+{
+ if (filePath == windowFilePath())
+ return;
+
+ Q_D(QWidget);
+
+ d->createTLExtra();
+ d->extra->topextra->filePath = filePath;
+ d->setWindowFilePath_helper(filePath);
+}
+
+void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
+{
+ if (extra->topextra && extra->topextra->caption.isEmpty()) {
+#ifdef Q_WS_MAC
+ setWindowTitle_helper(QFileInfo(filePath).fileName());
+#else
+ Q_Q(QWidget);
+ Q_UNUSED(filePath);
+ setWindowTitle_helper(q->windowTitle());
+#endif
+ }
+#ifdef Q_WS_MAC
+ setWindowFilePath_sys(filePath);
+#endif
+}
+
+/*!
+ Returns the window's role, or an empty string.
+
+ \sa windowIcon, windowTitle
+*/
+
+QString QWidget::windowRole() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
+}
+
+/*!
+ Sets the window's role to \a role. This only makes sense for
+ windows on X11.
+*/
+void QWidget::setWindowRole(const QString &role)
+{
+#if defined(Q_WS_X11)
+ Q_D(QWidget);
+ d->topData()->role = role;
+ d->setWindowRole();
+#else
+ Q_UNUSED(role)
+#endif
+}
+
+/*!
+ \property QWidget::mouseTracking
+ \brief whether mouse tracking is enabled for the widget
+
+ If mouse tracking is disabled (the default), the widget only
+ receives mouse move events when at least one mouse button is
+ pressed while the mouse is being moved.
+
+ If mouse tracking is enabled, the widget receives mouse move
+ events even if no buttons are pressed.
+
+ \sa mouseMoveEvent()
+*/
+
+
+/*!
+ Sets the widget's focus proxy to widget \a w. If \a w is 0, the
+ function resets this widget to have no focus proxy.
+
+ Some widgets can "have focus", but create a child widget, such as
+ QLineEdit, to actually handle the focus. In this case, the widget
+ can set the line edit to be its focus proxy.
+
+ setFocusProxy() sets the widget which will actually get focus when
+ "this widget" gets it. If there is a focus proxy, setFocus() and
+ hasFocus() operate on the focus proxy.
+
+ \sa focusProxy()
+*/
+
+void QWidget::setFocusProxy(QWidget * w)
+{
+ Q_D(QWidget);
+ if (!w && !d->extra)
+ return;
+
+ for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
+ if (fp == this) {
+ qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
+ return;
+ }
+ }
+
+ d->createExtra();
+ d->extra->focus_proxy = w;
+}
+
+
+/*!
+ Returns the focus proxy, or 0 if there is no focus proxy.
+
+ \sa setFocusProxy()
+*/
+
+QWidget * QWidget::focusProxy() const
+{
+ Q_D(const QWidget);
+ return d->extra ? (QWidget *)d->extra->focus_proxy : 0;
+}
+
+
+/*!
+ \property QWidget::focus
+ \brief whether this widget (or its focus proxy) has the keyboard
+ input focus
+
+ By default, this property is false.
+
+ \note Obtaining the value of this property for a widget is effectively equivalent
+ to checking whether QApplication::focusWidget() refers to the widget.
+
+ \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
+*/
+bool QWidget::hasFocus() const
+{
+ const QWidget* w = this;
+ while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
+ w = w->d_func()->extra->focus_proxy;
+ if (QWidget *window = w->window()) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QWExtra *e = window->d_func()->extra;
+ if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
+ return true;
+#endif
+ }
+ return (QApplication::focusWidget() == w);
+}
+
+/*!
+ Gives the keyboard input focus to this widget (or its focus
+ proxy) if this widget or one of its parents is the \link
+ isActiveWindow() active window\endlink. The \a reason argument will
+ be passed into any focus event sent from this function, it is used
+ to give an explanation of what caused the widget to get focus.
+ If the window is not active, the widget will be given the focus when
+ the window becomes active.
+
+ First, a focus out event is sent to the focus widget (if any) to
+ tell it that it is about to lose the focus. Then a focus in event
+ is sent to this widget to tell it that it just received the focus.
+ (Nothing happens if the focus in and focus out widgets are the
+ same.)
+
+ \note On embedded platforms, setFocus() will not cause an input panel
+ to be opened by the input method. If you want this to happen, you
+ have to send a QEvent::RequestSoftwareInputPanel event to the
+ widget yourself.
+
+ setFocus() gives focus to a widget regardless of its focus policy,
+ but does not clear any keyboard grab (see grabKeyboard()).
+
+ Be aware that if the widget is hidden, it will not accept focus
+ until it is shown.
+
+ \warning If you call setFocus() in a function which may itself be
+ called from focusOutEvent() or focusInEvent(), you may get an
+ infinite recursion.
+
+ \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
+ setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
+ grabMouse(), {Keyboard Focus}, QEvent::RequestSoftwareInputPanel
+*/
+
+void QWidget::setFocus(Qt::FocusReason reason)
+{
+ if (!isEnabled())
+ return;
+
+ QWidget *f = this;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if (QApplication::focusWidget() == f
+#if defined(Q_WS_WIN)
+ && GetFocus() == f->internalWinId()
+#endif
+ )
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ QWidget *previousProxyFocus = 0;
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
+ previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
+ if (previousProxyFocus && previousProxyFocus->focusProxy())
+ previousProxyFocus = previousProxyFocus->focusProxy();
+ if (previousProxyFocus == this && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
+ return;
+ }
+ }
+#endif
+
+ QWidget *w = f;
+ if (isHidden()) {
+ while (w && w->isHidden()) {
+ w->d_func()->focus_child = f;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ } else {
+ while (w) {
+ w->d_func()->focus_child = f;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Update proxy state
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
+ topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
+ topData->proxyWidget->setFocus(reason);
+ topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
+ }
+ }
+#endif
+
+ if (f->isActiveWindow()) {
+ QApplicationPrivate::setFocusWidget(f, reason);
+#ifndef QT_NO_ACCESSIBILITY
+# ifdef Q_OS_WIN
+ // The negation of the condition in setFocus_sys
+ if (!(testAttribute(Qt::WA_WState_Created) && window()->windowType() != Qt::Popup && internalWinId()))
+ //setFocusWidget will already post a focus event for us (that the AT client receives) on Windows
+# endif
+ QAccessible::updateAccessibility(f, 0, QAccessible::Focus);
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget) {
+ if (previousProxyFocus && previousProxyFocus != f) {
+ // Send event to self
+ QFocusEvent event(QEvent::FocusOut, reason);
+ QPointer<QWidget> that = previousProxyFocus;
+ QApplication::sendEvent(previousProxyFocus, &event);
+ if (that)
+ QApplication::sendEvent(that->style(), &event);
+ }
+ if (!isHidden()) {
+#ifndef QT_NO_GRAPHICSVIEW
+ // Update proxy state
+ if (QWExtra *topData = window()->d_func()->extra)
+ if (topData->proxyWidget && topData->proxyWidget->hasFocus())
+ topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
+#endif
+ // Send event to self
+ QFocusEvent event(QEvent::FocusIn, reason);
+ QPointer<QWidget> that = f;
+ QApplication::sendEvent(f, &event);
+ if (that)
+ QApplication::sendEvent(that->style(), &event);
+ }
+ }
+ }
+#endif
+ }
+}
+
+/*!
+ \fn void QWidget::setFocus()
+ \overload
+
+ Gives the keyboard input focus to this widget (or its focus
+ proxy) if this widget or one of its parents is the
+ \l{isActiveWindow()}{active window}.
+*/
+
+/*!
+ Takes keyboard input focus from the widget.
+
+ If the widget has active focus, a \link focusOutEvent() focus out
+ event\endlink is sent to this widget to tell it that it is about
+ to lose the focus.
+
+ This widget must enable focus setting in order to get the keyboard
+ input focus, i.e. it must call setFocusPolicy().
+
+ \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
+ setFocusPolicy(), QApplication::focusWidget()
+*/
+
+void QWidget::clearFocus()
+{
+ QWidget *w = this;
+ while (w) {
+ if (w->d_func()->focus_child == this)
+ w->d_func()->focus_child = 0;
+ w = w->parentWidget();
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ QWExtra *topData = d_func()->extra;
+ if (topData && topData->proxyWidget)
+ topData->proxyWidget->clearFocus();
+#endif
+
+ if (hasFocus()) {
+ // Update proxy state
+ QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
+#if defined(Q_WS_WIN)
+ if (!(windowType() == Qt::Popup) && GetFocus() == internalWinId())
+ SetFocus(0);
+ else
+#endif
+ {
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::Focus);
+#endif
+ }
+ }
+}
+
+
+/*!
+ \fn bool QWidget::focusNextChild()
+
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for \key Tab, and returns true if it can find a new widget, or
+ false if it can't.
+
+ \sa focusPreviousChild()
+*/
+
+/*!
+ \fn bool QWidget::focusPreviousChild()
+
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for \key Shift+Tab, and returns true if it can find a new widget,
+ or false if it can't.
+
+ \sa focusNextChild()
+*/
+
+/*!
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for Tab and Shift+Tab, and returns true if it can find a new
+ widget, or false if it can't.
+
+ If \a next is true, this function searches forward, if \a next
+ is false, it searches backward.
+
+ Sometimes, you will want to reimplement this function. For
+ example, a web browser might reimplement it to move its "current
+ active link" forward or backward, and call
+ focusNextPrevChild() only when it reaches the last or
+ first link on the "page".
+
+ Child widgets call focusNextPrevChild() on their parent widgets,
+ but only the window that contains the child widgets decides where
+ to redirect focus. By reimplementing this function for an object,
+ you thus gain control of focus traversal for all child widgets.
+
+ \sa focusNextChild(), focusPreviousChild()
+*/
+
+bool QWidget::focusNextPrevChild(bool next)
+{
+ Q_D(QWidget);
+ QWidget* p = parentWidget();
+ bool isSubWindow = (windowType() == Qt::SubWindow);
+ if (!isWindow() && !isSubWindow && p)
+ return p->focusNextPrevChild(next);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra && d->extra->proxyWidget)
+ return d->extra->proxyWidget->focusNextPrevChild(next);
+#endif
+ QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next);
+ if (!w) return false;
+
+ w->setFocus(next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+}
+
+/*!
+ Returns the last child of this widget that setFocus had been
+ called on. For top level widgets this is the widget that will get
+ focus in case this window gets activated
+
+ This is not the same as QApplication::focusWidget(), which returns
+ the focus widget in the currently active window.
+*/
+
+QWidget *QWidget::focusWidget() const
+{
+ return const_cast<QWidget *>(d_func()->focus_child);
+}
+
+/*!
+ Returns the next widget in this widget's focus chain.
+
+ \sa previousInFocusChain()
+*/
+QWidget *QWidget::nextInFocusChain() const
+{
+ return const_cast<QWidget *>(d_func()->focus_next);
+}
+
+/*!
+ \brief The previousInFocusChain function returns the previous
+ widget in this widget's focus chain.
+
+ \sa nextInFocusChain()
+
+ \since 4.6
+*/
+QWidget *QWidget::previousInFocusChain() const
+{
+ return const_cast<QWidget *>(d_func()->focus_prev);
+}
+
+/*!
+ \property QWidget::isActiveWindow
+ \brief whether this widget's window is the active window
+
+ The active window is the window that contains the widget that has
+ keyboard focus (The window may still have focus if it has no
+ widgets or none of its widgets accepts keyboard focus).
+
+ When popup windows are visible, this property is true for both the
+ active window \e and for the popup.
+
+ By default, this property is false.
+
+ \sa activateWindow(), QApplication::activeWindow()
+*/
+bool QWidget::isActiveWindow() const
+{
+ QWidget *tlw = window();
+ if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
+ return true;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *tlwExtra = tlw->d_func()->extra) {
+ if (isVisible() && tlwExtra->proxyWidget)
+ return tlwExtra->proxyWidget->isActiveWindow();
+ }
+#endif
+
+#ifdef Q_WS_MAC
+ extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
+ if(qt_mac_is_macdrawer(tlw) &&
+ tlw->parentWidget() && tlw->parentWidget()->isActiveWindow())
+ return true;
+
+ extern bool qt_mac_insideKeyWindow(const QWidget *); //qwidget_mac.cpp
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication) && qt_mac_insideKeyWindow(tlw))
+ return true;
+#endif
+ if(style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, this)) {
+ if(tlw->windowType() == Qt::Tool &&
+ !tlw->isModal() &&
+ (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
+ return true;
+ QWidget *w = QApplication::activeWindow();
+ while(w && tlw->windowType() == Qt::Tool &&
+ !w->isModal() && w->parentWidget()) {
+ w = w->parentWidget()->window();
+ if(w == tlw)
+ return true;
+ }
+ }
+#if defined(Q_WS_WIN32)
+ HWND active = GetActiveWindow();
+ if (!tlw->testAttribute(Qt::WA_WState_Created))
+ return false;
+ return active == tlw->internalWinId() || ::IsChild(active, tlw->internalWinId());
+#else
+ return false;
+#endif
+}
+
+/*!
+ Puts the \a second widget after the \a first widget in the focus order.
+
+ Note that since the tab order of the \a second widget is changed, you
+ should order a chain like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 9
+
+ \e not like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 10
+
+ If \a first or \a second has a focus proxy, setTabOrder()
+ correctly substitutes the proxy.
+
+ \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus}
+*/
+void QWidget::setTabOrder(QWidget* first, QWidget *second)
+{
+ if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus)
+ return;
+
+ if (first->window() != second->window()) {
+ qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
+ return;
+ }
+
+ QWidget *fp = first->focusProxy();
+ if (fp) {
+ // If first is redirected, set first to the last child of first
+ // that can take keyboard focus so that second is inserted after
+ // that last child, and the focus order within first is (more
+ // likely to be) preserved.
+ QList<QWidget *> l = first->findChildren<QWidget *>();
+ for (int i = l.size()-1; i >= 0; --i) {
+ QWidget * next = l.at(i);
+ if (next->window() == fp->window()) {
+ fp = next;
+ if (fp->focusPolicy() != Qt::NoFocus)
+ break;
+ }
+ }
+ first = fp;
+ }
+
+ if (fp == second)
+ return;
+
+ if (QWidget *sp = second->focusProxy())
+ second = sp;
+
+// QWidget *fp = first->d_func()->focus_prev;
+ QWidget *fn = first->d_func()->focus_next;
+
+ if (fn == second || first == second)
+ return;
+
+ QWidget *sp = second->d_func()->focus_prev;
+ QWidget *sn = second->d_func()->focus_next;
+
+ fn->d_func()->focus_prev = second;
+ first->d_func()->focus_next = second;
+
+ second->d_func()->focus_next = fn;
+ second->d_func()->focus_prev = first;
+
+ sp->d_func()->focus_next = sn;
+ sn->d_func()->focus_prev = sp;
+
+
+ Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first);
+ Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first);
+
+ Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second);
+ Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second);
+}
+
+/*!\internal
+
+ Moves the relevant subwidgets of this widget from the \a oldtlw's
+ tab chain to that of the new parent, if there's anything to move and
+ we're really moving
+
+ This function is called from QWidget::reparent() *after* the widget
+ has been reparented.
+
+ \sa reparent()
+*/
+
+void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
+{
+ Q_Q(QWidget);
+ if (oldtlw == q->window())
+ return; // nothing to do
+
+ if(focus_child)
+ focus_child->clearFocus();
+
+ // separate the focus chain into new (children of myself) and old (the rest)
+ QWidget *firstOld = 0;
+ //QWidget *firstNew = q; //invariant
+ QWidget *o = 0; // last in the old list
+ QWidget *n = q; // last in the new list
+
+ bool prevWasNew = true;
+ QWidget *w = focus_next;
+
+ //Note: for efficiency, we do not maintain the list invariant inside the loop
+ //we append items to the relevant list, and we optimize by not changing pointers
+ //when subsequent items are going into the same list.
+ while (w != q) {
+ bool currentIsNew = q->isAncestorOf(w);
+ if (currentIsNew) {
+ if (!prevWasNew) {
+ //prev was old -- append to new list
+ n->d_func()->focus_next = w;
+ w->d_func()->focus_prev = n;
+ }
+ n = w;
+ } else {
+ if (prevWasNew) {
+ //prev was new -- append to old list, if there is one
+ if (o) {
+ o->d_func()->focus_next = w;
+ w->d_func()->focus_prev = o;
+ } else {
+ // "create" the old list
+ firstOld = w;
+ }
+ }
+ o = w;
+ }
+ w = w->d_func()->focus_next;
+ prevWasNew = currentIsNew;
+ }
+
+ //repair the old list:
+ if (firstOld) {
+ o->d_func()->focus_next = firstOld;
+ firstOld->d_func()->focus_prev = o;
+ }
+
+ if (!q->isWindow()) {
+ QWidget *topLevel = q->window();
+ //insert new chain into toplevel's chain
+
+ QWidget *prev = topLevel->d_func()->focus_prev;
+
+ topLevel->d_func()->focus_prev = n;
+ prev->d_func()->focus_next = q;
+
+ focus_prev = prev;
+ n->d_func()->focus_next = topLevel;
+ } else {
+ //repair the new list
+ n->d_func()->focus_next = q;
+ focus_prev = n;
+ }
+
+}
+
+/*!\internal
+
+ Measures the shortest distance from a point to a rect.
+
+ This function is called from QDesktopwidget::screen(QPoint) to find the
+ closest screen for a point.
+ In directional KeypadNavigation, it is called to find the closest
+ widget to the current focus widget center.
+*/
+int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
+{
+ int dx = 0;
+ int dy = 0;
+ if (p.x() < r.left())
+ dx = r.left() - p.x();
+ else if (p.x() > r.right())
+ dx = p.x() - r.right();
+ if (p.y() < r.top())
+ dy = r.top() - p.y();
+ else if (p.y() > r.bottom())
+ dy = p.y() - r.bottom();
+ return dx + dy;
+}
+
+/*!
+ \property QWidget::frameSize
+ \brief the size of the widget including any window frame
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+*/
+QSize QWidget::frameSize() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && !(windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QSize(data->crect.width() + fs.left() + fs.right(),
+ data->crect.height() + fs.top() + fs.bottom());
+ }
+ return data->crect.size();
+}
+
+/*! \fn void QWidget::move(int x, int y)
+
+ \overload
+
+ This corresponds to move(QPoint(\a x, \a y)).
+*/
+
+void QWidget::move(const QPoint &p)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Moved);
+ if (isWindow())
+ d->topData()->posFromMove = true;
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
+ p.y() + geometry().y() - QWidget::y(),
+ width(), height(), true);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.moveTopLeft(p); // no frame yet
+ setAttribute(Qt::WA_PendingMoveEvent);
+ }
+}
+
+/*! \fn void QWidget::resize(int w, int h)
+ \overload
+
+ This corresponds to resize(QSize(\a w, \a h)).
+*/
+
+void QWidget::resize(const QSize &s)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Resized);
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
+ setAttribute(Qt::WA_PendingResizeEvent);
+ }
+}
+
+void QWidget::setGeometry(const QRect &r)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Resized);
+ setAttribute(Qt::WA_Moved);
+ if (isWindow())
+ d->topData()->posFromMove = false;
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.setTopLeft(r.topLeft());
+ data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
+ setAttribute(Qt::WA_PendingMoveEvent);
+ setAttribute(Qt::WA_PendingResizeEvent);
+ }
+}
+
+/*!
+ \since 4.2
+ Saves the current geometry and state for top-level widgets.
+
+ To save the geometry when the window closes, you can
+ implement a close event like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 11
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ Use QMainWindow::saveState() to save the geometry and the state of
+ toolbars and dock widgets.
+
+ \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
+*/
+QByteArray QWidget::saveGeometry() const
+{
+#ifdef QT_MAC_USE_COCOA
+ // We check if the window was maximized during this invocation. If so, we need to record the
+ // starting position as 0,0.
+ Q_D(const QWidget);
+ QRect newFramePosition = frameGeometry();
+ QRect newNormalPosition = normalGeometry();
+ if(d->topData()->wasMaximized && !(windowState() & Qt::WindowMaximized)) {
+ // Change the starting position
+ newFramePosition.moveTo(0, 0);
+ newNormalPosition.moveTo(0, 0);
+ }
+#endif // QT_MAC_USE_COCOA
+ QByteArray array;
+ QDataStream stream(&array, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_4_0);
+ const quint32 magicNumber = 0x1D9D0CB;
+ quint16 majorVersion = 1;
+ quint16 minorVersion = 0;
+ stream << magicNumber
+ << majorVersion
+ << minorVersion
+#ifdef QT_MAC_USE_COCOA
+ << newFramePosition
+ << newNormalPosition
+#else
+ << frameGeometry()
+ << normalGeometry()
+#endif // QT_MAC_USE_COCOA
+ << qint32(QApplication::desktop()->screenNumber(this))
+ << quint8(windowState() & Qt::WindowMaximized)
+ << quint8(windowState() & Qt::WindowFullScreen);
+ return array;
+}
+
+/*!
+ \since 4.2
+
+ Restores the geometry and state top-level widgets stored in the
+ byte array \a geometry. Returns true on success; otherwise
+ returns false.
+
+ If the restored geometry is off-screen, it will be modified to be
+ inside the available screen geometry.
+
+ To restore geometry saved using QSettings, you can use code like
+ this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 12
+
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
+
+ Use QMainWindow::restoreState() to restore the geometry and the
+ state of toolbars and dock widgets.
+
+ \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
+*/
+bool QWidget::restoreGeometry(const QByteArray &geometry)
+{
+ if (geometry.size() < 4)
+ return false;
+ QDataStream stream(geometry);
+ stream.setVersion(QDataStream::Qt_4_0);
+
+ const quint32 magicNumber = 0x1D9D0CB;
+ quint32 storedMagicNumber;
+ stream >> storedMagicNumber;
+ if (storedMagicNumber != magicNumber)
+ return false;
+
+ const quint16 currentMajorVersion = 1;
+ quint16 majorVersion = 0;
+ quint16 minorVersion = 0;
+
+ stream >> majorVersion >> minorVersion;
+
+ if (majorVersion != currentMajorVersion)
+ return false;
+ // (Allow all minor versions.)
+
+ QRect restoredFrameGeometry;
+ QRect restoredNormalGeometry;
+ qint32 restoredScreenNumber;
+ quint8 maximized;
+ quint8 fullScreen;
+
+ stream >> restoredFrameGeometry
+ >> restoredNormalGeometry
+ >> restoredScreenNumber
+ >> maximized
+ >> fullScreen;
+
+ const int frameHeight = 20;
+ if (!restoredFrameGeometry.isValid())
+ restoredFrameGeometry = QRect(QPoint(0,0), sizeHint());
+
+ if (!restoredNormalGeometry.isValid())
+ restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
+ if (!restoredNormalGeometry.isValid()) {
+ // use the widget's adjustedSize if the sizeHint() doesn't help
+ restoredNormalGeometry.setSize(restoredNormalGeometry
+ .size()
+ .expandedTo(d_func()->adjustedSize()));
+ }
+
+ const QDesktopWidget * const desktop = QApplication::desktop();
+ if (restoredScreenNumber >= desktop->numScreens())
+ restoredScreenNumber = desktop->primaryScreen();
+
+ const QRect availableGeometry = desktop->availableGeometry(restoredScreenNumber);
+
+ // Modify the restored geometry if we are about to restore to coordinates
+ // that would make the window "lost". This happens if:
+ // - The restored geometry is completely oustside the available geometry
+ // - The title bar is outside the available geometry.
+ // - (Mac only) The window is higher than the available geometry. It must
+ // be possible to bring the size grip on screen by moving the window.
+#ifdef Q_WS_MAC
+ restoredFrameGeometry.setHeight(qMin(restoredFrameGeometry.height(), availableGeometry.height()));
+ restoredNormalGeometry.setHeight(qMin(restoredNormalGeometry.height(), availableGeometry.height() - frameHeight));
+#endif
+
+ if (!restoredFrameGeometry.intersects(availableGeometry)) {
+ restoredFrameGeometry.moveBottom(qMin(restoredFrameGeometry.bottom(), availableGeometry.bottom()));
+ restoredFrameGeometry.moveLeft(qMax(restoredFrameGeometry.left(), availableGeometry.left()));
+ restoredFrameGeometry.moveRight(qMin(restoredFrameGeometry.right(), availableGeometry.right()));
+ }
+ restoredFrameGeometry.moveTop(qMax(restoredFrameGeometry.top(), availableGeometry.top()));
+
+ if (!restoredNormalGeometry.intersects(availableGeometry)) {
+ restoredNormalGeometry.moveBottom(qMin(restoredNormalGeometry.bottom(), availableGeometry.bottom()));
+ restoredNormalGeometry.moveLeft(qMax(restoredNormalGeometry.left(), availableGeometry.left()));
+ restoredNormalGeometry.moveRight(qMin(restoredNormalGeometry.right(), availableGeometry.right()));
+ }
+ restoredNormalGeometry.moveTop(qMax(restoredNormalGeometry.top(), availableGeometry.top() + frameHeight));
+
+ if (maximized || fullScreen) {
+ // set geomerty before setting the window state to make
+ // sure the window is maximized to the right screen.
+ // Skip on windows: the window is restored into a broken
+ // half-maximized state.
+#ifndef Q_WS_WIN
+ setGeometry(restoredNormalGeometry);
+#endif
+ Qt::WindowStates ws = windowState();
+ if (maximized)
+ ws |= Qt::WindowMaximized;
+ if (fullScreen)
+ ws |= Qt::WindowFullScreen;
+ setWindowState(ws);
+ d_func()->topData()->normalGeometry = restoredNormalGeometry;
+ } else {
+ QPoint offset;
+#ifdef Q_WS_X11
+ if (isFullScreen())
+ offset = d_func()->topData()->fullScreenOffset;
+#endif
+ setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
+ move(restoredFrameGeometry.topLeft() + offset);
+ resize(restoredNormalGeometry.size());
+ }
+ return true;
+}
+
+/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
+ \overload
+
+ This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
+*/
+
+/*!
+ Sets the margins around the contents of the widget to have the sizes
+ \a left, \a top, \a right, and \a bottom. The margins are used by
+ the layout system, and may be used by subclasses to specify the area
+ to draw in (e.g. excluding the frame).
+
+ Changing the margins will trigger a resizeEvent().
+
+ \sa contentsRect(), getContentsMargins()
+*/
+void QWidget::setContentsMargins(int left, int top, int right, int bottom)
+{
+ Q_D(QWidget);
+ if (left == d->leftmargin && top == d->topmargin
+ && right == d->rightmargin && bottom == d->bottommargin)
+ return;
+ d->leftmargin = left;
+ d->topmargin = top;
+ d->rightmargin = right;
+ d->bottommargin = bottom;
+
+ if (QLayout *l=d->layout)
+ l->update(); //force activate; will do updateGeometry
+ else
+ updateGeometry();
+
+ // ### Qt 5: compat, remove
+ if (isVisible()) {
+ update();
+ QResizeEvent e(data->crect.size(), data->crect.size());
+ QApplication::sendEvent(this, &e);
+ } else {
+ setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+
+ QEvent e(QEvent::ContentsRectChange);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ \brief The setContentsMargins function sets the margins around the
+ widget's contents.
+
+ Sets the margins around the contents of the widget to have the
+ sizes determined by \a margins. The margins are
+ used by the layout system, and may be used by subclasses to
+ specify the area to draw in (e.g. excluding the frame).
+
+ Changing the margins will trigger a resizeEvent().
+
+ \sa contentsRect(), getContentsMargins()
+*/
+void QWidget::setContentsMargins(const QMargins &margins)
+{
+ setContentsMargins(margins.left(), margins.top(),
+ margins.right(), margins.bottom());
+}
+
+/*!
+ Returns the widget's contents margins for \a left, \a top, \a
+ right, and \a bottom.
+
+ \sa setContentsMargins(), contentsRect()
+ */
+void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) const
+{
+ Q_D(const QWidget);
+ if (left)
+ *left = d->leftmargin;
+ if (top)
+ *top = d->topmargin;
+ if (right)
+ *right = d->rightmargin;
+ if (bottom)
+ *bottom = d->bottommargin;
+}
+
+/*!
+ \since 4.6
+
+ \brief The contentsMargins function returns the widget's contents margins.
+
+ \sa getContentsMargins(), setContentsMargins(), contentsRect()
+ */
+QMargins QWidget::contentsMargins() const
+{
+ Q_D(const QWidget);
+ return QMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
+}
+
+
+/*!
+ Returns the area inside the widget's margins.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+QRect QWidget::contentsRect() const
+{
+ Q_D(const QWidget);
+ return QRect(QPoint(d->leftmargin, d->topmargin),
+ QPoint(data->crect.width() - 1 - d->rightmargin,
+ data->crect.height() - 1 - d->bottommargin));
+
+}
+
+
+
+/*!
+ \fn void QWidget::customContextMenuRequested(const QPoint &pos)
+
+ This signal is emitted when the widget's \l contextMenuPolicy is
+ Qt::CustomContextMenu, and the user has requested a context menu on
+ the widget. The position \a pos is the position of the context menu
+ event that the widget receives. Normally this is in widget
+ coordinates. The exception to this rule is QAbstractScrollArea and
+ its subclasses that map the context menu event to coordinates of the
+ \link QAbstractScrollArea::viewport() viewport() \endlink .
+
+
+ \sa mapToGlobal() QMenu contextMenuPolicy
+*/
+
+
+/*!
+ \property QWidget::contextMenuPolicy
+ \brief how the widget shows a context menu
+
+ The default value of this property is Qt::DefaultContextMenu,
+ which means the contextMenuEvent() handler is called. Other values
+ are Qt::NoContextMenu, Qt::PreventContextMenu,
+ Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
+ Qt::CustomContextMenu, the signal customContextMenuRequested() is
+ emitted.
+
+ \sa contextMenuEvent(), customContextMenuRequested(), actions()
+*/
+
+Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
+{
+ return (Qt::ContextMenuPolicy)data->context_menu_policy;
+}
+
+void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
+{
+ data->context_menu_policy = (uint) policy;
+}
+
+/*!
+ \property QWidget::focusPolicy
+ \brief the way the widget accepts keyboard focus
+
+ The policy is Qt::TabFocus if the widget accepts keyboard
+ focus by tabbing, Qt::ClickFocus if the widget accepts
+ focus by clicking, Qt::StrongFocus if it accepts both, and
+ Qt::NoFocus (the default) if it does not accept focus at
+ all.
+
+ You must enable keyboard focus for a widget if it processes
+ keyboard events. This is normally done from the widget's
+ constructor. For instance, the QLineEdit constructor calls
+ setFocusPolicy(Qt::StrongFocus).
+
+ If the widget has a focus proxy, then the focus policy will
+ be propagated to it.
+
+ \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
+*/
+
+
+Qt::FocusPolicy QWidget::focusPolicy() const
+{
+ return (Qt::FocusPolicy)data->focus_policy;
+}
+
+void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
+{
+ data->focus_policy = (uint) policy;
+ Q_D(QWidget);
+ if (d->extra && d->extra->focus_proxy)
+ d->extra->focus_proxy->setFocusPolicy(policy);
+}
+
+/*!
+ \property QWidget::updatesEnabled
+ \brief whether updates are enabled
+
+ An updates enabled widget receives paint events and has a system
+ background; a disabled widget does not. This also implies that
+ calling update() and repaint() has no effect if updates are
+ disabled.
+
+ By default, this property is true.
+
+ setUpdatesEnabled() is normally used to disable updates for a
+ short period of time, for instance to avoid screen flicker during
+ large changes. In Qt, widgets normally do not generate screen
+ flicker, but on X11 the server might erase regions on the screen
+ when widgets get hidden before they can be replaced by other
+ widgets. Disabling updates solves this.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 13
+
+ Disabling a widget implicitly disables all its children. Enabling a widget
+ enables all child widgets \e except top-level widgets or those that
+ have been explicitly disabled. Re-enabling updates implicitly calls
+ update() on the widget.
+
+ \sa paintEvent()
+*/
+void QWidget::setUpdatesEnabled(bool enable)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
+ d->setUpdatesEnabled_helper(enable);
+}
+
+/*! \fn void QWidget::show()
+
+ Shows the widget and its child widgets. This function is
+ equivalent to setVisible(true).
+
+ \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
+ showNormal(), isVisible()
+*/
+
+
+/*! \internal
+
+ Makes the widget visible in the isVisible() meaning of the word.
+ It is only called for toplevels or widgets with visible parents.
+ */
+void QWidgetPrivate::show_recursive()
+{
+ Q_Q(QWidget);
+ // polish if necessary
+
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ createRecursively();
+ q->ensurePolished();
+
+#ifdef QT3_SUPPORT
+ if(sendChildEvents)
+ QApplication::sendPostedEvents(q, QEvent::ChildInserted);
+#endif
+ if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
+ q->parentWidget()->d_func()->layout->activate();
+ // activate our layout before we and our children become visible
+ if (layout)
+ layout->activate();
+
+ show_helper();
+}
+
+void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
+{
+ Q_Q(QWidget);
+
+ disableUpdates = disableUpdates && q->updatesEnabled();
+ if (disableUpdates)
+ q->setAttribute(Qt::WA_UpdatesDisabled);
+
+ if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
+ QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
+ QApplication::sendEvent(q, &e);
+ q->setAttribute(Qt::WA_PendingMoveEvent, false);
+ }
+
+ if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
+ QResizeEvent e(data.crect.size(), QSize());
+ QApplication::sendEvent(q, &e);
+ q->setAttribute(Qt::WA_PendingResizeEvent, false);
+ }
+
+ if (disableUpdates)
+ q->setAttribute(Qt::WA_UpdatesDisabled, false);
+
+ if (!recursive)
+ return;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
+ }
+}
+
+void QWidgetPrivate::activateChildLayoutsRecursively()
+{
+ sendPendingMoveAndResizeEvents(false, true);
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (!child || child->isHidden() || child->isWindow())
+ continue;
+
+ child->ensurePolished();
+
+ // Activate child's layout
+ QWidgetPrivate *childPrivate = child->d_func();
+ if (childPrivate->layout)
+ childPrivate->layout->activate();
+
+ // Pretend we're visible.
+ const bool wasVisible = child->isVisible();
+ if (!wasVisible)
+ child->setAttribute(Qt::WA_WState_Visible);
+
+ // Do the same for all my children.
+ childPrivate->activateChildLayoutsRecursively();
+
+ // We're not cheating anymore.
+ if (!wasVisible)
+ child->setAttribute(Qt::WA_WState_Visible, false);
+ }
+}
+
+void QWidgetPrivate::show_helper()
+{
+ Q_Q(QWidget);
+ data.in_show = true; // qws optimization
+ // make sure we receive pending move and resize events
+ sendPendingMoveAndResizeEvents();
+
+ // become visible before showing all children
+ q->setAttribute(Qt::WA_WState_Visible);
+
+ // finally show all children recursively
+ showChildren(false);
+
+#ifdef QT3_SUPPORT
+ if (q->parentWidget() && sendChildEvents)
+ QApplication::sendPostedEvents(q->parentWidget(),
+ QEvent::ChildInserted);
+#endif
+
+
+ // popup handling: new popups and tools need to be raised, and
+ // existing popups must be closed. Also propagate the current
+ // windows's KeyboardFocusChange status.
+ if (q->isWindow()) {
+ if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
+ q->raise();
+ if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
+ q->setAttribute(Qt::WA_KeyboardFocusChange);
+ } else {
+ while (QApplication::activePopupWidget()) {
+ if (!QApplication::activePopupWidget()->close())
+ break;
+ }
+ }
+ }
+
+ // Automatic embedding of child windows of widgets already embedded into
+ // QGraphicsProxyWidget when they are shown the first time.
+ bool isEmbedded = false;
+#ifndef QT_NO_GRAPHICSVIEW
+ if (q->isWindow()) {
+ isEmbedded = q->graphicsProxyWidget() ? true : false;
+ if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
+ QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
+ if (ancestorProxy) {
+ isEmbedded = true;
+ ancestorProxy->d_func()->embedSubWindow(q);
+ }
+ }
+ }
+#else
+ Q_UNUSED(isEmbedded);
+#endif
+
+ // On Windows, show the popup now so that our own focus handling
+ // stores the correct old focus widget even if it's stolen in the
+ // showevent
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
+ if (!isEmbedded && q->windowType() == Qt::Popup)
+ qApp->d_func()->openPopup(q);
+#endif
+
+ // send the show event before showing the window
+ QShowEvent showEvent;
+ QApplication::sendEvent(q, &showEvent);
+
+ if (!isEmbedded && q->isModal() && q->isWindow())
+ // QApplicationPrivate::enterModal *before* show, otherwise the initial
+ // stacking might be wrong
+ QApplicationPrivate::enterModal(q);
+
+
+ show_sys();
+
+#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
+ if (!isEmbedded && q->windowType() == Qt::Popup)
+ qApp->d_func()->openPopup(q);
+#endif
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (q->windowType() != Qt::ToolTip) // Tooltips are read aloud twice in MS narrator.
+ QAccessible::updateAccessibility(q, 0, QAccessible::ObjectShow);
+#endif
+
+ if (QApplicationPrivate::hidden_focus_widget == q) {
+ QApplicationPrivate::hidden_focus_widget = 0;
+ q->setFocus(Qt::OtherFocusReason);
+ }
+
+ // Process events when showing a Qt::SplashScreen widget before the event loop
+ // is spinnning; otherwise it might not show up on particular platforms.
+ // This makes QSplashScreen behave the same on all platforms.
+ if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
+ QApplication::processEvents();
+
+ data.in_show = false; // reset qws optimization
+}
+
+/*! \fn void QWidget::hide()
+
+ Hides the widget. This function is equivalent to
+ setVisible(false).
+
+
+ \note If you are working with QDialog or its subclasses and you invoke
+ the show() function after this function, the dialog will be displayed in
+ its original position.
+
+ \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
+*/
+
+/*!\internal
+ */
+void QWidgetPrivate::hide_helper()
+{
+ Q_Q(QWidget);
+
+ bool isEmbedded = false;
+#if !defined QT_NO_GRAPHICSVIEW
+ isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != 0;
+#else
+ Q_UNUSED(isEmbedded);
+#endif
+
+ if (!isEmbedded && (q->windowType() == Qt::Popup))
+ qApp->d_func()->closePopup(q);
+
+ // Move test modal here. Otherwise, a modal dialog could get
+ // destroyed and we lose all access to its parent because we haven't
+ // left modality. (Eg. modal Progress Dialog)
+ if (!isEmbedded && q->isModal() && q->isWindow())
+ QApplicationPrivate::leaveModal(q);
+
+#if defined(Q_WS_WIN)
+ if (q->isWindow() && !(q->windowType() == Qt::Popup) && q->parentWidget()
+ && !q->parentWidget()->isHidden() && q->isActiveWindow())
+ q->parentWidget()->activateWindow(); // Activate parent
+#endif
+
+ q->setAttribute(Qt::WA_Mapped, false);
+ hide_sys();
+
+ bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
+
+ if (wasVisible) {
+ q->setAttribute(Qt::WA_WState_Visible, false);
+
+ }
+
+ QHideEvent hideEvent;
+ QApplication::sendEvent(q, &hideEvent);
+ hideChildren(false);
+
+ // next bit tries to move the focus if the focus widget is now
+ // hidden.
+ if (wasVisible) {
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
+ qApp->d_func()->sendSyntheticEnterLeave(q);
+#endif
+
+ QWidget *fw = QApplication::focusWidget();
+ while (fw && !fw->isWindow()) {
+ if (fw == q) {
+ q->focusNextPrevChild(true);
+ break;
+ }
+ fw = fw->parentWidget();
+ }
+ }
+
+ if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->removeDirtyWidget(q);
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (wasVisible)
+ QAccessible::updateAccessibility(q, 0, QAccessible::ObjectHide);
+#endif
+}
+
+/*!
+ \fn bool QWidget::isHidden() const
+
+ Returns true if the widget is hidden, otherwise returns false.
+
+ A hidden widget will only become visible when show() is called on
+ it. It will not be automatically shown when the parent is shown.
+
+ To check visibility, use !isVisible() instead (notice the exclamation mark).
+
+ isHidden() implies !isVisible(), but a widget can be not visible
+ and not hidden at the same time. This is the case for widgets that are children of
+ widgets that are not visible.
+
+
+ Widgets are hidden if:
+ \list
+ \o they were created as independent windows,
+ \o they were created as children of visible widgets,
+ \o hide() or setVisible(false) was called.
+ \endlist
+*/
+
+
+void QWidget::setVisible(bool visible)
+{
+ if (visible) { // show
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ Q_D(QWidget);
+
+ // Designer uses a trick to make grabWidget work without showing
+ if (!isWindow() && parentWidget() && parentWidget()->isVisible()
+ && !parentWidget()->testAttribute(Qt::WA_WState_Created))
+ parentWidget()->window()->d_func()->createRecursively();
+
+ //we have to at least create toplevels before applyX11SpecificCommandLineArguments
+ //but not children of non-visible parents
+ QWidget *pw = parentWidget();
+ if (!testAttribute(Qt::WA_WState_Created)
+ && (isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
+ create();
+ }
+
+#if defined(Q_WS_X11)
+ if (windowType() == Qt::Window)
+ QApplicationPrivate::applyX11SpecificCommandLineArguments(this);
+#elif defined(Q_WS_QWS)
+ if (windowType() == Qt::Window)
+ QApplicationPrivate::applyQWSSpecificCommandLineArguments(this);
+#endif
+
+ bool wasResized = testAttribute(Qt::WA_Resized);
+ Qt::WindowStates initialWindowState = windowState();
+
+ // polish if necessary
+ ensurePolished();
+
+ // remember that show was called explicitly
+ setAttribute(Qt::WA_WState_ExplicitShowHide);
+ // whether we need to inform the parent widget immediately
+ bool needUpdateGeometry = !isWindow() && testAttribute(Qt::WA_WState_Hidden);
+ // we are no longer hidden
+ setAttribute(Qt::WA_WState_Hidden, false);
+
+ if (needUpdateGeometry)
+ d->updateGeometry_helper(true);
+
+#ifdef QT3_SUPPORT
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+#endif
+ // activate our layout before we and our children become visible
+ if (d->layout)
+ d->layout->activate();
+
+ if (!isWindow()) {
+ QWidget *parent = parentWidget();
+ while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
+ parent->d_func()->layout->activate();
+ if (parent->isWindow())
+ break;
+ parent = parent->parentWidget();
+ }
+ if (parent)
+ parent->d_func()->setDirtyOpaqueRegion();
+ }
+
+ // adjust size if necessary
+ if (!wasResized
+ && (isWindow() || !parentWidget()->d_func()->layout)) {
+ if (isWindow()) {
+ adjustSize();
+ if (windowState() != initialWindowState)
+ setWindowState(initialWindowState);
+ } else {
+ adjustSize();
+ }
+ setAttribute(Qt::WA_Resized, false);
+ }
+
+ setAttribute(Qt::WA_KeyboardFocusChange, false);
+
+ if (isWindow() || parentWidget()->isVisible()) {
+ // remove posted quit events when showing a new window
+ QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
+
+ d->show_helper();
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
+ qApp->d_func()->sendSyntheticEnterLeave(this);
+#endif
+ }
+
+ QEvent showToParentEvent(QEvent::ShowToParent);
+ QApplication::sendEvent(this, &showToParentEvent);
+ } else { // hide
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ return;
+#if defined(Q_WS_WIN)
+ // reset WS_DISABLED style in a Blocked window
+ if(isWindow() && testAttribute(Qt::WA_WState_Created)
+ && QApplicationPrivate::isBlockedByModal(this))
+ {
+ LONG dwStyle = GetWindowLong(winId(), GWL_STYLE);
+ dwStyle &= ~WS_DISABLED;
+ SetWindowLong(winId(), GWL_STYLE, dwStyle);
+ }
+#endif
+ if (QApplicationPrivate::hidden_focus_widget == this)
+ QApplicationPrivate::hidden_focus_widget = 0;
+
+ Q_D(QWidget);
+
+ // hw: The test on getOpaqueRegion() needs to be more intelligent
+ // currently it doesn't work if the widget is hidden (the region will
+ // be clipped). The real check should be testing the cached region
+ // (and dirty flag) directly.
+ if (!isWindow() && parentWidget()) // && !d->getOpaqueRegion().isEmpty())
+ parentWidget()->d_func()->setDirtyOpaqueRegion();
+
+ setAttribute(Qt::WA_WState_Hidden);
+ setAttribute(Qt::WA_WState_ExplicitShowHide);
+ if (testAttribute(Qt::WA_WState_Created))
+ d->hide_helper();
+
+ // invalidate layout similar to updateGeometry()
+ if (!isWindow() && parentWidget()) {
+ if (parentWidget()->d_func()->layout)
+ parentWidget()->d_func()->layout->invalidate();
+ else if (parentWidget()->isVisible())
+ QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest));
+ }
+
+ QEvent hideToParentEvent(QEvent::HideToParent);
+ QApplication::sendEvent(this, &hideToParentEvent);
+ }
+}
+
+/*!\fn void QWidget::setHidden(bool hidden)
+
+ Convenience function, equivalent to setVisible(!\a hidden).
+*/
+
+/*!\fn void QWidget::setShown(bool shown)
+
+ Use setVisible(\a shown) instead.
+*/
+
+
+void QWidgetPrivate::_q_showIfNotHidden()
+{
+ Q_Q(QWidget);
+ if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
+ q->setVisible(true);
+}
+
+void QWidgetPrivate::showChildren(bool spontaneous)
+{
+ QList<QObject*> childList = children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
+ if (!widget
+ || widget->isWindow()
+ || widget->testAttribute(Qt::WA_WState_Hidden))
+ continue;
+ if (spontaneous) {
+ widget->setAttribute(Qt::WA_Mapped);
+ widget->d_func()->showChildren(true);
+ QShowEvent e;
+ QApplication::sendSpontaneousEvent(widget, &e);
+ } else {
+ if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ widget->d_func()->show_recursive();
+ else
+ widget->show();
+ }
+ }
+}
+
+void QWidgetPrivate::hideChildren(bool spontaneous)
+{
+ QList<QObject*> childList = children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
+ if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
+ continue;
+#ifdef QT_MAC_USE_COCOA
+ // Before doing anything we need to make sure that we don't leave anything in a non-consistent state.
+ // When hiding a widget we need to make sure that no mouse_down events are active, because
+ // the mouse_up event will never be received by a hidden widget or one of its descendants.
+ // The solution is simple, before going through with this we check if there are any mouse_down events in
+ // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and
+ // then we continue.
+ // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already
+ // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the
+ // mouse release event. There are two ways to interpret this:
+ // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it
+ // might be waiting for a release event that will never arrive.
+ // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not
+ // supposed to trigger because it is not visible.
+ if(widget == qt_button_down)
+ qt_button_down = 0;
+#endif // QT_MAC_USE_COCOA
+ if (spontaneous)
+ widget->setAttribute(Qt::WA_Mapped, false);
+ else
+ widget->setAttribute(Qt::WA_WState_Visible, false);
+ widget->d_func()->hideChildren(spontaneous);
+ QHideEvent e;
+ if (spontaneous) {
+ QApplication::sendSpontaneousEvent(widget, &e);
+ } else {
+ QApplication::sendEvent(widget, &e);
+ if (widget->internalWinId()
+ && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
+ // hide_sys() on an ancestor won't have any affect on this
+ // widget, so it needs an explicit hide_sys() of its own
+ widget->d_func()->hide_sys();
+ }
+ }
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
+ qApp->d_func()->sendSyntheticEnterLeave(widget);
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ if (!spontaneous)
+ QAccessible::updateAccessibility(widget, 0, QAccessible::ObjectHide);
+#endif
+ }
+}
+
+bool QWidgetPrivate::close_helper(CloseMode mode)
+{
+ if (data.is_closing)
+ return true;
+
+ Q_Q(QWidget);
+ data.is_closing = 1;
+
+ QPointer<QWidget> that = q;
+ QPointer<QWidget> parentWidget = q->parentWidget();
+
+#ifdef QT3_SUPPORT
+ bool isMain = (QApplicationPrivate::main_widget == q);
+#endif
+ bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
+ if (mode != CloseNoEvent) {
+ QCloseEvent e;
+ if (mode == CloseWithSpontaneousEvent)
+ QApplication::sendSpontaneousEvent(q, &e);
+ else
+ QApplication::sendEvent(q, &e);
+ if (!that.isNull() && !e.isAccepted()) {
+ data.is_closing = 0;
+ return false;
+ }
+ }
+
+ if (!that.isNull() && !q->isHidden())
+ q->hide();
+
+#ifdef QT3_SUPPORT
+ if (isMain)
+ QApplication::quit();
+#endif
+ // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
+ quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
+
+ if (quitOnClose) {
+ /* if there is no non-withdrawn primary window left (except
+ the ones without QuitOnClose), we emit the lastWindowClosed
+ signal */
+ QWidgetList list = QApplication::topLevelWidgets();
+ bool lastWindowClosed = true;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
+ continue;
+ lastWindowClosed = false;
+ break;
+ }
+ if (lastWindowClosed)
+ QApplicationPrivate::emitLastWindowClosed();
+ }
+
+ if (!that.isNull()) {
+ data.is_closing = 0;
+ if (q->testAttribute(Qt::WA_DeleteOnClose)) {
+ q->setAttribute(Qt::WA_DeleteOnClose, false);
+ q->deleteLater();
+ }
+ }
+ return true;
+}
+
+
+/*!
+ Closes this widget. Returns true if the widget was closed;
+ otherwise returns false.
+
+ First it sends the widget a QCloseEvent. The widget is \link
+ hide() hidden\endlink if it \link QCloseEvent::accept()
+ accepts\endlink the close event. If it \link QCloseEvent::ignore()
+ ignores\endlink the event, nothing happens. The default
+ implementation of QWidget::closeEvent() accepts the close event.
+
+ If the widget has the Qt::WA_DeleteOnClose flag, the widget
+ is also deleted. A close events is delivered to the widget no
+ matter if the widget is visible or not.
+
+ The \l QApplication::lastWindowClosed() signal is emitted when the
+ last visible primary window (i.e. window with no parent) with the
+ Qt::WA_QuitOnClose attribute set is closed. By default this
+ attribute is set for all widgets except transient windows such as
+ splash screens, tool windows, and popup menus.
+
+*/
+
+bool QWidget::close()
+{
+ return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
+}
+
+/*!
+ \property QWidget::visible
+ \brief whether the widget is visible
+
+ Calling setVisible(true) or show() sets the widget to visible
+ status if all its parent widgets up to the window are visible. If
+ an ancestor is not visible, the widget won't become visible until
+ all its ancestors are shown. If its size or position has changed,
+ Qt guarantees that a widget gets move and resize events just
+ before it is shown. If the widget has not been resized yet, Qt
+ will adjust the widget's size to a useful default using
+ adjustSize().
+
+ Calling setVisible(false) or hide() hides a widget explicitly. An
+ explicitly hidden widget will never become visible, even if all
+ its ancestors become visible, unless you show it.
+
+ A widget receives show and hide events when its visibility status
+ changes. Between a hide and a show event, there is no need to
+ waste CPU cycles preparing or displaying information to the user.
+ A video application, for example, might simply stop generating new
+ frames.
+
+ A widget that happens to be obscured by other windows on the
+ screen is considered to be visible. The same applies to iconified
+ windows and windows that exist on another virtual
+ desktop (on platforms that support this concept). A widget
+ receives spontaneous show and hide events when its mapping status
+ is changed by the window system, e.g. a spontaneous hide event
+ when the user minimizes the window, and a spontaneous show event
+ when the window is restored again.
+
+ You almost never have to reimplement the setVisible() function. If
+ you need to change some settings before a widget is shown, use
+ showEvent() instead. If you need to do some delayed initialization
+ use the Polish event delivered to the event() function.
+
+ \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
+ showEvent(), hideEvent()
+*/
+
+
+/*!
+ Returns true if this widget would become visible if \a ancestor is
+ shown; otherwise returns false.
+
+ The true case occurs if neither the widget itself nor any parent
+ up to but excluding \a ancestor has been explicitly hidden.
+
+ This function will still return true if the widget is obscured by
+ other windows on the screen, but could be physically visible if it
+ or they were to be moved.
+
+ isVisibleTo(0) is identical to isVisible().
+
+ \sa show() hide() isVisible()
+*/
+
+bool QWidget::isVisibleTo(QWidget* ancestor) const
+{
+ if (!ancestor)
+ return isVisible();
+ const QWidget * w = this;
+ while (!w->isHidden()
+ && !w->isWindow()
+ && w->parentWidget()
+ && w->parentWidget() != ancestor)
+ w = w->parentWidget();
+ return !w->isHidden();
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use visibleRegion() instead.
+*/
+QRect QWidget::visibleRect() const
+{
+ return d_func()->clipRect();
+}
+#endif
+
+/*!
+ Returns the unobscured region where paint events can occur.
+
+ For visible widgets, this is an approximation of the area not
+ covered by other widgets; otherwise, this is an empty region.
+
+ The repaint() function calls this function if necessary, so in
+ general you do not need to call it.
+
+*/
+QRegion QWidget::visibleRegion() const
+{
+ Q_D(const QWidget);
+
+ QRect clipRect = d->clipRect();
+ if (clipRect.isEmpty())
+ return QRegion();
+ QRegion r(clipRect);
+ d->subtractOpaqueChildren(r, clipRect);
+ d->subtractOpaqueSiblings(r);
+#ifdef Q_WS_QWS
+ const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(windowSurface());
+ if (surface) {
+ const QPoint offset = mapTo(surface->window(), QPoint());
+ r &= surface->clipRegion().translated(-offset);
+ }
+#endif
+ return r;
+}
+
+
+QSize QWidgetPrivate::adjustedSize() const
+{
+ Q_Q(const QWidget);
+
+ QSize s = q->sizeHint();
+
+ if (q->isWindow()) {
+ Qt::Orientations exp;
+ if (layout) {
+ if (layout->hasHeightForWidth())
+ s.setHeight(layout->totalHeightForWidth(s.width()));
+ exp = layout->expandingDirections();
+ } else
+ {
+ if (q->sizePolicy().hasHeightForWidth())
+ s.setHeight(q->heightForWidth(s.width()));
+ exp = q->sizePolicy().expandingDirections();
+ }
+ if (exp & Qt::Horizontal)
+ s.setWidth(qMax(s.width(), 200));
+ if (exp & Qt::Vertical)
+ s.setHeight(qMax(s.height(), 100));
+#if defined(Q_WS_X11)
+ QRect screen = QApplication::desktop()->screenGeometry(q->x11Info().screen());
+#else // all others
+ QRect screen = QApplication::desktop()->screenGeometry(q->pos());
+#endif
+#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN)
+ s.setWidth(qMin(s.width(), screen.width()));
+ s.setHeight(qMin(s.height(), screen.height()));
+#else
+ s.setWidth(qMin(s.width(), screen.width()*2/3));
+ s.setHeight(qMin(s.height(), screen.height()*2/3));
+#endif
+ if (QTLWExtra *extra = maybeTopData())
+ extra->sizeAdjusted = true;
+ }
+
+ if (!s.isValid()) {
+ QRect r = q->childrenRect(); // get children rectangle
+ if (r.isNull())
+ return s;
+ s = r.size() + QSize(2 * r.x(), 2 * r.y());
+ }
+
+ return s;
+}
+
+/*!
+ Adjusts the size of the widget to fit its contents.
+
+ This function uses sizeHint() if it is valid, i.e., the size hint's width
+ and height are \>= 0. Otherwise, it sets the size to the children
+ rectangle that covers all child widgets (the union of all child widget
+ rectangles).
+
+ For windows, the screen size is also taken into account. If the sizeHint()
+ is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
+ {expanding}, the window will be at least (200, 100). The maximum size of
+ a window is 2/3 of the screen's width and height.
+
+ \sa sizeHint(), childrenRect()
+*/
+
+void QWidget::adjustSize()
+{
+ Q_D(QWidget);
+ ensurePolished();
+ QSize s = d->adjustedSize();
+
+ if (d->layout)
+ d->layout->activate();
+
+ if (s.isValid())
+ resize(s);
+}
+
+
+/*!
+ \property QWidget::sizeHint
+ \brief the recommended size for the widget
+
+ If the value of this property is an invalid size, no size is
+ recommended.
+
+ The default implementation of sizeHint() returns an invalid size
+ if there is no layout for this widget, and returns the layout's
+ preferred size otherwise.
+
+ \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
+ setMinimumSize(), updateGeometry()
+*/
+
+QSize QWidget::sizeHint() const
+{
+ Q_D(const QWidget);
+ if (d->layout)
+ return d->layout->totalSizeHint();
+ return QSize(-1, -1);
+}
+
+/*!
+ \property QWidget::minimumSizeHint
+ \brief the recommended minimum size for the widget
+
+ If the value of this property is an invalid size, no minimum size
+ is recommended.
+
+ The default implementation of minimumSizeHint() returns an invalid
+ size if there is no layout for this widget, and returns the
+ layout's minimum size otherwise. Most built-in widgets reimplement
+ minimumSizeHint().
+
+ \l QLayout will never resize a widget to a size smaller than the
+ minimum size hint unless minimumSize() is set or the size policy is
+ set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
+ size hint will be ignored.
+
+ \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
+*/
+QSize QWidget::minimumSizeHint() const
+{
+ Q_D(const QWidget);
+ if (d->layout)
+ return d->layout->totalMinimumSize();
+ return QSize(-1, -1);
+}
+
+
+/*!
+ \fn QWidget *QWidget::parentWidget() const
+
+ Returns the parent of this widget, or 0 if it does not have any
+ parent widget.
+*/
+
+
+/*!
+ Returns true if this widget is a parent, (or grandparent and so on
+ to any level), of the given \a child, and both widgets are within
+ the same window; otherwise returns false.
+*/
+
+bool QWidget::isAncestorOf(const QWidget *child) const
+{
+ while (child) {
+ if (child == this)
+ return true;
+ if (child->isWindow())
+ return false;
+ child = child->parentWidget();
+ }
+ return false;
+}
+
+#if defined(Q_WS_WIN)
+inline void setDisabledStyle(QWidget *w, bool setStyle)
+{
+ // set/reset WS_DISABLED style.
+ if(w && w->isWindow() && w->isVisible() && w->isEnabled()) {
+ LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE);
+ LONG newStyle = dwStyle;
+ if (setStyle)
+ newStyle |= WS_DISABLED;
+ else
+ newStyle &= ~WS_DISABLED;
+ if (newStyle != dwStyle) {
+ SetWindowLong(w->winId(), GWL_STYLE, newStyle);
+ // we might need to repaint in some situations (eg. menu)
+ w->repaint();
+ }
+ }
+}
+#endif
+
+/*****************************************************************************
+ QWidget event handling
+ *****************************************************************************/
+
+/*!
+ This is the main event handler; it handles event \a event. You can
+ reimplement this function in a subclass, but we recommend using
+ one of the specialized event handlers instead.
+
+ Key press and release events are treated differently from other
+ events. event() checks for Tab and Shift+Tab and tries to move the
+ focus appropriately. If there is no widget to move the focus to
+ (or the key press is not Tab or Shift+Tab), event() calls
+ keyPressEvent().
+
+ Mouse and tablet event handling is also slightly special: only
+ when the widget is \l enabled, event() will call the specialized
+ handlers such as mousePressEvent(); otherwise it will discard the
+ event.
+
+ This function returns true if the event was recognized, otherwise
+ it returns false. If the recognized event was accepted (see \l
+ QEvent::accepted), any further processing such as event
+ propagation to the parent widget stops.
+
+ \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
+ keyPressEvent(), keyReleaseEvent(), leaveEvent(),
+ mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
+ mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
+ QObject::event(), QObject::timerEvent()
+*/
+
+bool QWidget::event(QEvent *event)
+{
+ Q_D(QWidget);
+
+ // ignore mouse events when disabled
+ if (!isEnabled()) {
+ switch(event->type()) {
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ case QEvent::TabletMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ case QEvent::ContextMenu:
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+#endif
+ return false;
+ default:
+ break;
+ }
+ }
+ switch (event->type()) {
+ case QEvent::MouseMove:
+ mouseMoveEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonPress:
+ // Don't reset input context here. Whether reset or not is
+ // a responsibility of input method. reset() will be
+ // called by mouseHandler() of input method if necessary
+ // via mousePressEvent() of text widgets.
+#if 0
+ resetInputContext();
+#endif
+ mousePressEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonDblClick:
+ mouseDoubleClickEvent((QMouseEvent*)event);
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ wheelEvent((QWheelEvent*)event);
+ break;
+#endif
+#ifndef QT_NO_TABLETEVENT
+ case QEvent::TabletMove:
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ tabletEvent((QTabletEvent*)event);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ event->ignore();
+ return false;
+#endif
+ case QEvent::KeyPress: {
+ QKeyEvent *k = (QKeyEvent *)event;
+ bool res = false;
+ if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
+ if (k->key() == Qt::Key_Backtab
+ || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
+ res = focusNextPrevChild(false);
+ else if (k->key() == Qt::Key_Tab)
+ res = focusNextPrevChild(true);
+ if (res)
+ break;
+ }
+ keyPressEvent(k);
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
+ && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
+ if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
+ if (k->key() == Qt::Key_Up)
+ res = focusNextPrevChild(false);
+ else if (k->key() == Qt::Key_Down)
+ res = focusNextPrevChild(true);
+ } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
+ if (k->key() == Qt::Key_Up)
+ res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
+ else if (k->key() == Qt::Key_Right)
+ res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
+ else if (k->key() == Qt::Key_Down)
+ res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
+ else if (k->key() == Qt::Key_Left)
+ res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
+ }
+ if (res) {
+ k->accept();
+ break;
+ }
+ }
+#endif
+#ifndef QT_NO_WHATSTHIS
+ if (!k->isAccepted()
+ && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
+ && d->whatsThis.size()) {
+ QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImMicroFocus).toRect().center()), d->whatsThis, this);
+ k->accept();
+ }
+#endif
+ }
+ break;
+
+ case QEvent::KeyRelease:
+ keyReleaseEvent((QKeyEvent*)event);
+ // fall through
+ case QEvent::ShortcutOverride:
+ break;
+
+ case QEvent::InputMethod:
+ inputMethodEvent((QInputMethodEvent *) event);
+ break;
+
+ case QEvent::PolishRequest:
+ ensurePolished();
+ break;
+
+ case QEvent::Polish: {
+ style()->polish(this);
+ setAttribute(Qt::WA_WState_Polished);
+ if (!QApplication::font(this).isCopyOf(QApplication::font()))
+ d->resolveFont();
+ if (!QApplication::palette(this).isCopyOf(QApplication::palette()))
+ d->resolvePalette();
+#ifdef QT3_SUPPORT
+ if(d->sendChildEvents)
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+#endif
+ }
+ break;
+
+ case QEvent::ApplicationWindowIconChange:
+ if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
+ d->setWindowIcon_sys();
+ d->setWindowIcon_helper();
+ }
+ break;
+ case QEvent::FocusIn:
+#ifdef QT_SOFTKEYS_ENABLED
+ QSoftKeyManager::updateSoftKeys();
+#endif
+ focusInEvent((QFocusEvent*)event);
+ break;
+
+ case QEvent::FocusOut:
+ focusOutEvent((QFocusEvent*)event);
+ break;
+
+ case QEvent::Enter:
+#ifndef QT_NO_STATUSTIP
+ if (d->statusTip.size()) {
+ QStatusTipEvent tip(d->statusTip);
+ QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
+ }
+#endif
+ enterEvent(event);
+ break;
+
+ case QEvent::Leave:
+#ifndef QT_NO_STATUSTIP
+ if (d->statusTip.size()) {
+ QString empty;
+ QStatusTipEvent tip(empty);
+ QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
+ }
+#endif
+ leaveEvent(event);
+ break;
+
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ update();
+ break;
+
+ case QEvent::Paint:
+ // At this point the event has to be delivered, regardless
+ // whether the widget isVisible() or not because it
+ // already went through the filters
+ paintEvent((QPaintEvent*)event);
+ break;
+
+ case QEvent::Move:
+ moveEvent((QMoveEvent*)event);
+ break;
+
+ case QEvent::Resize:
+ resizeEvent((QResizeEvent*)event);
+ break;
+
+ case QEvent::Close:
+ closeEvent((QCloseEvent *)event);
+ break;
+
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ switch (data->context_menu_policy) {
+ case Qt::PreventContextMenu:
+ break;
+ case Qt::DefaultContextMenu:
+ contextMenuEvent(static_cast<QContextMenuEvent *>(event));
+ break;
+ case Qt::CustomContextMenu:
+ emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
+ break;
+#ifndef QT_NO_MENU
+ case Qt::ActionsContextMenu:
+ if (d->actions.count()) {
+ QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
+ 0, this);
+ break;
+ }
+ // fall through
+#endif
+ default:
+ event->ignore();
+ break;
+ }
+ break;
+#endif // QT_NO_CONTEXTMENU
+
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::Drop:
+ dropEvent((QDropEvent*) event);
+ break;
+
+ case QEvent::DragEnter:
+ dragEnterEvent((QDragEnterEvent*) event);
+ break;
+
+ case QEvent::DragMove:
+ dragMoveEvent((QDragMoveEvent*) event);
+ break;
+
+ case QEvent::DragLeave:
+ dragLeaveEvent((QDragLeaveEvent*) event);
+ break;
+#endif
+
+ case QEvent::Show:
+ showEvent((QShowEvent*) event);
+ break;
+
+ case QEvent::Hide:
+ hideEvent((QHideEvent*) event);
+ break;
+
+ case QEvent::ShowWindowRequest:
+ if (!isHidden())
+ d->show_sys();
+ break;
+
+ case QEvent::ApplicationFontChange:
+ d->resolveFont();
+ break;
+ case QEvent::ApplicationPaletteChange:
+ if (!(windowType() == Qt::Desktop))
+ d->resolvePalette();
+ break;
+
+ case QEvent::ToolBarChange:
+ case QEvent::ActivationChange:
+ case QEvent::EnabledChange:
+ case QEvent::FontChange:
+ case QEvent::StyleChange:
+ case QEvent::PaletteChange:
+ case QEvent::WindowTitleChange:
+ case QEvent::IconTextChange:
+ case QEvent::ModifiedChange:
+ case QEvent::MouseTrackingChange:
+ case QEvent::ParentChange:
+ case QEvent::WindowStateChange:
+ case QEvent::LocaleChange:
+ case QEvent::MacSizeChange:
+ case QEvent::ContentsRectChange:
+ changeEvent(event);
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate: {
+#ifdef QT3_SUPPORT
+ windowActivationChange(event->type() != QEvent::WindowActivate);
+#endif
+ if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
+ update();
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(childList.at(i));
+ if (w && w->isVisible() && !w->isWindow())
+ QApplication::sendEvent(w, event);
+ }
+
+#ifdef QT_SOFTKEYS_ENABLED
+ if (isWindow())
+ QSoftKeyManager::updateSoftKeys();
+#endif
+
+ break; }
+
+ case QEvent::LanguageChange:
+#ifdef QT3_SUPPORT
+ languageChange();
+#endif
+ changeEvent(event);
+ {
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ if (o)
+ QApplication::sendEvent(o, event);
+ }
+ }
+ update();
+ break;
+
+ case QEvent::ApplicationLayoutDirectionChange:
+ d->resolveLayoutDirection();
+ break;
+
+ case QEvent::LayoutDirectionChange:
+ if (d->layout)
+ d->layout->invalidate();
+ update();
+ changeEvent(event);
+ break;
+ case QEvent::UpdateRequest:
+ d->syncBackingStore();
+ break;
+ case QEvent::UpdateLater:
+ update(static_cast<QUpdateLaterEvent*>(event)->region());
+ break;
+
+ case QEvent::WindowBlocked:
+ case QEvent::WindowUnblocked:
+ {
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ if (o && o != QApplication::activeModalWidget()) {
+ if (qobject_cast<QWidget *>(o) && static_cast<QWidget *>(o)->isWindow()) {
+ // do not forward the event to child windows,
+ // QApplication does this for us
+ continue;
+ }
+ QApplication::sendEvent(o, event);
+ }
+ }
+#if defined(Q_WS_WIN)
+ setDisabledStyle(this, (event->type() == QEvent::WindowBlocked));
+#endif
+ }
+ break;
+#ifndef QT_NO_TOOLTIP
+ case QEvent::ToolTip:
+ if (!d->toolTip.isEmpty())
+ QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this);
+ else
+ event->ignore();
+ break;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ case QEvent::WhatsThis:
+ if (d->whatsThis.size())
+ QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
+ else
+ event->ignore();
+ break;
+ case QEvent::QueryWhatsThis:
+ if (d->whatsThis.isEmpty())
+ event->ignore();
+ break;
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ case QEvent::AccessibilityDescription:
+ case QEvent::AccessibilityHelp: {
+ QAccessibleEvent *ev = static_cast<QAccessibleEvent *>(event);
+ if (ev->child())
+ return false;
+ switch (ev->type()) {
+#ifndef QT_NO_TOOLTIP
+ case QEvent::AccessibilityDescription:
+ ev->setValue(d->toolTip);
+ break;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ case QEvent::AccessibilityHelp:
+ ev->setValue(d->whatsThis);
+ break;
+#endif
+ default:
+ return false;
+ }
+ break; }
+#endif
+ case QEvent::EmbeddingControl:
+ d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
+ data->fstrut_dirty = false;
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ d->topData()->embedded = 1;
+#endif
+ break;
+#ifndef QT_NO_ACTION
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ case QEvent::ActionChanged:
+#ifdef QT_SOFTKEYS_ENABLED
+ QSoftKeyManager::updateSoftKeys();
+#endif
+ actionEvent((QActionEvent*)event);
+ break;
+#endif
+
+ case QEvent::KeyboardLayoutChange:
+ {
+ changeEvent(event);
+
+ // inform children of the change
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(childList.at(i));
+ if (w && w->isVisible() && !w->isWindow())
+ QApplication::sendEvent(w, event);
+ }
+ break;
+ }
+#ifdef Q_WS_MAC
+ case QEvent::MacGLWindowChange:
+ d->needWindowChange = false;
+ break;
+#endif
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+#ifndef Q_WS_MAC
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first();
+ if (touchPoint.isPrimary() || touchEvent->deviceType() == QTouchEvent::TouchPad)
+ break;
+
+ // fake a mouse event!
+ QEvent::Type eventType = QEvent::None;
+ switch (touchEvent->type()) {
+ case QEvent::TouchBegin:
+ eventType = QEvent::MouseButtonPress;
+ break;
+ case QEvent::TouchUpdate:
+ eventType = QEvent::MouseMove;
+ break;
+ case QEvent::TouchEnd:
+ eventType = QEvent::MouseButtonRelease;
+ break;
+ default:
+ Q_ASSERT(!true);
+ break;
+ }
+ if (eventType == QEvent::None)
+ break;
+
+ QMouseEvent mouseEvent(eventType,
+ touchPoint.pos().toPoint(),
+ touchPoint.screenPos().toPoint(),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ touchEvent->modifiers());
+ (void) QApplication::sendEvent(this, &mouseEvent);
+#endif // Q_WS_MAC
+ break;
+ }
+#ifndef QT_NO_GESTURES
+ case QEvent::Gesture:
+ event->ignore();
+ break;
+#endif
+#ifndef QT_NO_PROPERTIES
+ case QEvent::DynamicPropertyChange: {
+ const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
+ if (!qstrncmp(propName, "_q_customDpi", 12) && propName.length() == 13) {
+ uint value = property(propName.constData()).toUInt();
+ if (!d->extra)
+ d->createExtra();
+ const char axis = propName.at(12);
+ if (axis == 'X')
+ d->extra->customDpiX = value;
+ else if (axis == 'Y')
+ d->extra->customDpiY = value;
+ d->updateFont(d->data.fnt);
+ }
+ // fall through
+ }
+#endif
+ default:
+ return QObject::event(event);
+ }
+ return true;
+}
+
+/*!
+ This event handler can be reimplemented to handle state changes.
+
+ The state being changed in this event can be retrieved through the \a event
+ supplied.
+
+ Change events include: QEvent::ToolBarChange,
+ QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
+ QEvent::StyleChange, QEvent::PaletteChange,
+ QEvent::WindowTitleChange, QEvent::IconTextChange,
+ QEvent::ModifiedChange, QEvent::MouseTrackingChange,
+ QEvent::ParentChange, QEvent::WindowStateChange,
+ QEvent::LanguageChange, QEvent::LocaleChange,
+ QEvent::LayoutDirectionChange.
+
+*/
+void QWidget::changeEvent(QEvent * event)
+{
+ switch(event->type()) {
+ case QEvent::EnabledChange:
+ update();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+#endif
+ break;
+
+ case QEvent::FontChange:
+ case QEvent::StyleChange: {
+ Q_D(QWidget);
+ update();
+ updateGeometry();
+ if (d->layout)
+ d->layout->invalidate();
+#ifdef Q_WS_QWS
+ if (isWindow())
+ d->data.fstrut_dirty = true;
+#endif
+ break;
+ }
+
+ case QEvent::PaletteChange:
+ update();
+ break;
+
+#ifdef Q_WS_MAC
+ case QEvent::MacSizeChange:
+ updateGeometry();
+ break;
+ case QEvent::ToolTipChange:
+ case QEvent::MouseTrackingChange:
+ qt_mac_update_mouseTracking(this);
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse move events for the widget.
+
+ If mouse tracking is switched off, mouse move events only occur if
+ a mouse button is pressed while the mouse is being moved. If mouse
+ tracking is switched on, mouse move events occur even if no mouse
+ button is pressed.
+
+ QMouseEvent::pos() reports the position of the mouse cursor,
+ relative to this widget. For press and release events, the
+ position is usually the same as the position of the last mouse
+ move event, but it might be different if the user's hand shakes.
+ This is a feature of the underlying window system, not Qt.
+
+ If you want to show a tooltip immediately, while the mouse is
+ moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
+ and show them as a tooltip), you must first enable mouse tracking
+ as described above. Then, to ensure that the tooltip is updated
+ immediately, you must call QToolTip::showText() instead of
+ setToolTip() in your implementation of mouseMoveEvent().
+
+ \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
+ mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mouseMoveEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse press events for the widget.
+
+ If you create new widgets in the mousePressEvent() the
+ mouseReleaseEvent() may not end up where you expect, depending on
+ the underlying window system (or X11 window manager), the widgets'
+ location and maybe more.
+
+ The default implementation implements the closing of popup widgets
+ when you click outside the window. For other widget types it does
+ nothing.
+
+ \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
+ mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mousePressEvent(QMouseEvent *event)
+{
+ event->ignore();
+ if ((windowType() == Qt::Popup)) {
+ event->accept();
+ QWidget* w;
+ while ((w = QApplication::activePopupWidget()) && w != this){
+ w->close();
+ if (QApplication::activePopupWidget() == w) // widget does not want to disappear
+ w->hide(); // hide at least
+ }
+ if (!rect().contains(event->pos())){
+ close();
+ }
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse release events for the widget.
+
+ \sa mousePressEvent(), mouseDoubleClickEvent(),
+ mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse double click events for the widget.
+
+ The default implementation generates a normal mouse press event.
+
+ \note The widget will also receive mouse press and mouse release
+ events in addition to the double click event. It is up to the
+ developer to ensure that the application interprets these events
+ correctly.
+
+ \sa mousePressEvent(), mouseReleaseEvent() mouseMoveEvent(),
+ event(), QMouseEvent
+*/
+
+void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ mousePressEvent(event); // try mouse press event
+}
+
+#ifndef QT_NO_WHEELEVENT
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive wheel events for the widget.
+
+ If you reimplement this handler, it is very important that you
+ \link QWheelEvent ignore()\endlink the event if you do not handle
+ it, so that the widget's parent can interpret it.
+
+ The default implementation ignores the event.
+
+ \sa QWheelEvent::ignore(), QWheelEvent::accept(), event(),
+ QWheelEvent
+*/
+
+void QWidget::wheelEvent(QWheelEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_WHEELEVENT
+
+#ifndef QT_NO_TABLETEVENT
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive tablet events for the widget.
+
+ If you reimplement this handler, it is very important that you
+ \link QTabletEvent ignore()\endlink the event if you do not handle
+ it, so that the widget's parent can interpret it.
+
+ The default implementation ignores the event.
+
+ \sa QTabletEvent::ignore(), QTabletEvent::accept(), event(),
+ QTabletEvent
+*/
+
+void QWidget::tabletEvent(QTabletEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_TABLETEVENT
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive key press events for the widget.
+
+ A widget must call setFocusPolicy() to accept focus initially and
+ have focus in order to receive a key press event.
+
+ If you reimplement this handler, it is very important that you
+ call the base class implementation if you do not act upon the key.
+
+ The default implementation closes popup widgets if the user
+ presses Esc. Otherwise the event is ignored, so that the widget's
+ parent can interpret it.
+
+ Note that QKeyEvent starts with isAccepted() == true, so you do not
+ need to call QKeyEvent::accept() - just do not call the base class
+ implementation if you act upon the key.
+
+ \sa keyReleaseEvent(), setFocusPolicy(),
+ focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
+*/
+
+void QWidget::keyPressEvent(QKeyEvent *event)
+{
+ if ((windowType() == Qt::Popup) && event->key() == Qt::Key_Escape) {
+ event->accept();
+ close();
+ } else {
+ event->ignore();
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive key release events for the widget.
+
+ A widget must \link setFocusPolicy() accept focus\endlink
+ initially and \link hasFocus() have focus\endlink in order to
+ receive a key release event.
+
+ If you reimplement this handler, it is very important that you
+ call the base class implementation if you do not act upon the key.
+
+ The default implementation ignores the event, so that the widget's
+ parent can interpret it.
+
+ Note that QKeyEvent starts with isAccepted() == true, so you do not
+ need to call QKeyEvent::accept() - just do not call the base class
+ implementation if you act upon the key.
+
+ \sa keyPressEvent(), QKeyEvent::ignore(), setFocusPolicy(),
+ focusInEvent(), focusOutEvent(), event(), QKeyEvent
+*/
+
+void QWidget::keyReleaseEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ \fn void QWidget::focusInEvent(QFocusEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ keyboard focus events (focus received) for the widget. The event
+ is passed in the \a event parameter
+
+ A widget normally must setFocusPolicy() to something other than
+ Qt::NoFocus in order to receive focus events. (Note that the
+ application programmer can call setFocus() on any widget, even
+ those that do not normally accept focus.)
+
+ The default implementation updates the widget (except for windows
+ that do not specify a focusPolicy()).
+
+ \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
+ keyReleaseEvent(), event(), QFocusEvent
+*/
+
+void QWidget::focusInEvent(QFocusEvent *)
+{
+ if (focusPolicy() != Qt::NoFocus || !isWindow()) {
+ update();
+ }
+}
+
+/*!
+ \fn void QWidget::focusOutEvent(QFocusEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ keyboard focus events (focus lost) for the widget. The events is
+ passed in the \a event parameter.
+
+ A widget normally must setFocusPolicy() to something other than
+ Qt::NoFocus in order to receive focus events. (Note that the
+ application programmer can call setFocus() on any widget, even
+ those that do not normally accept focus.)
+
+ The default implementation updates the widget (except for windows
+ that do not specify a focusPolicy()).
+
+ \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
+ keyReleaseEvent(), event(), QFocusEvent
+*/
+
+void QWidget::focusOutEvent(QFocusEvent *)
+{
+ if (focusPolicy() != Qt::NoFocus || !isWindow())
+ update();
+}
+
+/*!
+ \fn void QWidget::enterEvent(QEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget enter events which are passed in the \a event parameter.
+
+ An event is sent to the widget when the mouse cursor enters the
+ widget.
+
+ \sa leaveEvent(), mouseMoveEvent(), event()
+*/
+
+void QWidget::enterEvent(QEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::leaveEvent(QEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget leave events which are passed in the \a event parameter.
+
+ A leave event is sent to the widget when the mouse cursor leaves
+ the widget.
+
+ \sa enterEvent(), mouseMoveEvent(), event()
+*/
+
+void QWidget::leaveEvent(QEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::paintEvent(QPaintEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive paint
+ events passed in \a event.
+
+ A paint event is a request to repaint all or part of a widget. It can
+ happen for one of the following reasons:
+
+ \list
+ \o repaint() or update() was invoked,
+ \o the widget was obscured and has now been uncovered, or
+ \o many other reasons.
+ \endlist
+
+ Many widgets can simply repaint their entire surface when asked to, but
+ some slow widgets need to optimize by painting only the requested region:
+ QPaintEvent::region(). This speed optimization does not change the result,
+ as painting is clipped to that region during event processing. QListView
+ and QTableView do this, for example.
+
+ Qt also tries to speed up painting by merging multiple paint events into
+ one. When update() is called several times or the window system sends
+ several paint events, Qt merges these events into one event with a larger
+ region (see QRegion::united()). The repaint() function does not permit this
+ optimization, so we suggest using update() whenever possible.
+
+ When the paint event occurs, the update region has normally been erased, so
+ you are painting on the widget's background.
+
+ The background can be set using setBackgroundRole() and setPalette().
+
+ Since Qt 4.0, QWidget automatically double-buffers its painting, so there
+ is no need to write double-buffering code in paintEvent() to avoid flicker.
+
+ \bold{Note for the X11 platform}: It is possible to toggle global double
+ buffering by calling \c qt_x11_set_global_double_buffer(). For example,
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 14
+
+ \note Generally, you should refrain from calling update() or repaint()
+ \bold{inside} a paintEvent(). For example, calling update() or repaint() on
+ children inside a paintevent() results in undefined behavior; the child may
+ or may not get a paint event.
+
+ \warning If you are using a custom paint engine without Qt's backingstore,
+ Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
+ never be called; the backingstore will be used instead.
+
+ \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
+ {Analog Clock Example}
+*/
+
+void QWidget::paintEvent(QPaintEvent *)
+{
+}
+
+
+/*!
+ \fn void QWidget::moveEvent(QMoveEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget move events which are passed in the \a event parameter.
+ When the widget receives this event, it is already at the new
+ position.
+
+ The old position is accessible through QMoveEvent::oldPos().
+
+ \sa resizeEvent(), event(), move(), QMoveEvent
+*/
+
+void QWidget::moveEvent(QMoveEvent *)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ widget resize events which are passed in the \a event parameter.
+ When resizeEvent() is called, the widget already has its new
+ geometry. The old size is accessible through
+ QResizeEvent::oldSize().
+
+ The widget will be erased and receive a paint event immediately
+ after processing the resize event. No drawing need be (or should
+ be) done inside this handler.
+
+
+ \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
+ {Scribble Example}
+*/
+
+void QWidget::resizeEvent(QResizeEvent * /* event */)
+{
+}
+
+#ifndef QT_NO_ACTION
+/*!
+ \fn void QWidget::actionEvent(QActionEvent *event)
+
+ This event handler is called with the given \a event whenever the
+ widget's actions are changed.
+
+ \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
+*/
+void QWidget::actionEvent(QActionEvent *)
+{
+
+}
+#endif
+
+/*!
+ This event handler is called with the given \a event when Qt receives a window
+ close request for a top-level widget from the window system.
+
+ By default, the event is accepted and the widget is closed. You can reimplement
+ this function to change the way the widget responds to window close requests.
+ For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
+ on all events.
+
+ Main window applications typically use reimplementations of this function to check
+ whether the user's work has been saved and ask for permission before closing.
+ For example, the \l{Application Example} uses a helper function to determine whether
+ or not to close the window:
+
+ \snippet mainwindows/application/mainwindow.cpp 3
+ \snippet mainwindows/application/mainwindow.cpp 4
+
+ \sa event(), hide(), close(), QCloseEvent, {Application Example}
+*/
+
+void QWidget::closeEvent(QCloseEvent *event)
+{
+ event->accept();
+}
+
+#ifndef QT_NO_CONTEXTMENU
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive widget context menu events.
+
+ The handler is called when the widget's \l contextMenuPolicy is
+ Qt::DefaultContextMenu.
+
+ The default implementation ignores the context event.
+ See the \l QContextMenuEvent documentation for more details.
+
+ \sa event(), QContextMenuEvent customContextMenuRequested()
+*/
+
+void QWidget::contextMenuEvent(QContextMenuEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_CONTEXTMENU
+
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive Input Method composition events. This handler
+ is called when the state of the input method changes.
+
+ Note that when creating custom text editing widgets, the
+ Qt::WA_InputMethodEnabled window attribute must be set explicitly
+ (using the setAttribute() function) in order to receive input
+ method events.
+
+ The default implementation calls event->ignore(), which rejects the
+ Input Method event. See the \l QInputMethodEvent documentation for more
+ details.
+
+ \sa event(), QInputMethodEvent
+*/
+void QWidget::inputMethodEvent(QInputMethodEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This method is only relevant for input widgets. It is used by the
+ input method to query a set of properties of the widget to be
+ able to support complex input method operations as support for
+ surrounding text and reconversions.
+
+ \a query specifies which property is queried.
+
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext, inputMethodHints
+*/
+QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ switch(query) {
+ case Qt::ImMicroFocus:
+ return QRect(width()/2, 0, 1, height());
+ case Qt::ImFont:
+ return font();
+ case Qt::ImAnchorPosition:
+ // Fallback.
+ return inputMethodQuery(Qt::ImCursorPosition);
+ default:
+ return QVariant();
+ }
+}
+
+/*!
+ \property QWidget::inputMethodHints
+ \brief What input method specific hints the widget has.
+
+ This is only relevant for input widgets. It is used by
+ the input method to retrieve hints as to how the input method
+ should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
+ is set, the input method may change its visual components to reflect
+ that only numbers can be entered.
+
+ \note The flags are only hints, so the particular input method
+ implementation is free to ignore them. If you want to be
+ sure that a certain type of characters are entered,
+ you should also set a QValidator on the widget.
+
+ The default value is Qt::ImhNone.
+
+ \since 4.6
+
+ \sa inputMethodQuery(), QInputContext
+*/
+Qt::InputMethodHints QWidget::inputMethodHints() const
+{
+#ifndef QT_NO_IM
+ const QWidgetPrivate *priv = d_func();
+ while (priv->inheritsInputMethodHints) {
+ priv = priv->q_func()->parentWidget()->d_func();
+ Q_ASSERT(priv);
+ }
+ return priv->imHints;
+#else //QT_NO_IM
+ return 0;
+#endif //QT_NO_IM
+}
+
+void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
+{
+#ifndef QT_NO_IM
+ Q_D(QWidget);
+ d->imHints = hints;
+ // Optimization to update input context only it has already been created.
+ if (d->ic || qApp->d_func()->inputContext) {
+ QInputContext *ic = inputContext();
+ if (ic)
+ ic->update();
+ }
+#endif //QT_NO_IM
+}
+
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*!
+ \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
+
+ This event handler is called when a drag is in progress and the
+ mouse enters this widget. The event is passed in the \a event parameter.
+
+ If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
+ move events}.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragEnterEvent
+*/
+void QWidget::dragEnterEvent(QDragEnterEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
+
+ This event handler is called if a drag is in progress, and when
+ any of the following conditions occur: the cursor enters this widget,
+ the cursor moves within this widget, or a modifier key is pressed on
+ the keyboard while this widget has the focus. The event is passed
+ in the \a event parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragMoveEvent
+*/
+void QWidget::dragMoveEvent(QDragMoveEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
+
+ This event handler is called when a drag is in progress and the
+ mouse leaves this widget. The event is passed in the \a event
+ parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragLeaveEvent
+*/
+void QWidget::dragLeaveEvent(QDragLeaveEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dropEvent(QDropEvent *event)
+
+ This event handler is called when the drag is dropped on this
+ widget. The event is passed in the \a event parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDropEvent
+*/
+void QWidget::dropEvent(QDropEvent *)
+{
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+/*!
+ \fn void QWidget::showEvent(QShowEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget show events which are passed in the \a event parameter.
+
+ Non-spontaneous show events are sent to widgets immediately
+ before they are shown. The spontaneous show events of windows are
+ delivered afterwards.
+
+ Note: A widget receives spontaneous show and hide events when its
+ mapping status is changed by the window system, e.g. a spontaneous
+ hide event when the user minimizes the window, and a spontaneous
+ show event when the window is restored again. After receiving a
+ spontaneous hide event, a widget is still considered visible in
+ the sense of isVisible().
+
+ \sa visible, event(), QShowEvent
+*/
+void QWidget::showEvent(QShowEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::hideEvent(QHideEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget hide events. The event is passed in the \a event parameter.
+
+ Hide events are sent to widgets immediately after they have been
+ hidden.
+
+ Note: A widget receives spontaneous show and hide events when its
+ mapping status is changed by the window system, e.g. a spontaneous
+ hide event when the user minimizes the window, and a spontaneous
+ show event when the window is restored again. After receiving a
+ spontaneous hide event, a widget is still considered visible in
+ the sense of isVisible().
+
+ \sa visible, event(), QHideEvent
+*/
+void QWidget::hideEvent(QHideEvent *)
+{
+}
+
+/*
+ \fn QWidget::x11Event(MSG *)
+
+ This special event handler can be reimplemented in a subclass to receive
+ native X11 events.
+
+ In your reimplementation of this function, if you want to stop Qt from
+ handling the event, return true. If you return false, this native event
+ is passed back to Qt, which translates it into a Qt event and sends it to
+ the widget.
+
+ \note Events are only delivered to this event handler if the widget is
+ native.
+
+ \warning This function is not portable.
+
+ \sa QApplication::x11EventFilter(), QWidget::winId()
+*/
+
+
+#if defined(Q_WS_MAC)
+
+/*!
+ \fn bool QWidget::macEvent(EventHandlerCallRef caller, EventRef event)
+
+ This special event handler can be reimplemented in a subclass to
+ receive native Macintosh events.
+
+ The parameters are a bit different depending if Qt is build against Carbon
+ or Cocoa. In Carbon, \a caller and \a event are the corresponding
+ EventHandlerCallRef and EventRef that correspond to the Carbon event
+ handlers that are installed. In Cocoa, \a caller is always 0 and the
+ EventRef is the EventRef generated from the NSEvent.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \warning This function was not called inside of Qt until Qt 4.4.
+ If you need compatibility with earlier versions of Qt, consider QApplication::macEventFilter() instead.
+
+ \sa QApplication::macEventFilter()
+*/
+
+bool QWidget::macEvent(EventHandlerCallRef, EventRef)
+{
+ return false;
+}
+
+#endif
+#if defined(Q_WS_WIN)
+
+/*!
+ This special event handler can be reimplemented in a subclass to
+ receive native Windows events which are passed in the \a message
+ parameter.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true and set \a result to the value
+ that the window procedure should return. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \sa QApplication::winEventFilter()
+*/
+bool QWidget::winEvent(MSG *message, long *result)
+{
+ Q_UNUSED(message);
+ Q_UNUSED(result);
+ return false;
+}
+
+#endif
+#if defined(Q_WS_X11)
+
+/*!
+ \fn bool QWidget::x11Event(XEvent *event)
+
+ This special event handler can be reimplemented in a subclass to receive
+ native X11 events passed in the \a event parameter.
+
+ In your reimplementation of this function, if you want to stop Qt from
+ handling the event, return true. If you return false, this native event
+ is passed back to Qt, which translates it into a Qt event and sends it to
+ the widget.
+
+ \note Events are only delivered to this event handler if the widget is
+ native.
+
+ \warning This function is not portable.
+
+ \sa QApplication::x11EventFilter(), QWidget::winId()
+*/
+bool QWidget::x11Event(XEvent *)
+{
+ return false;
+}
+
+#endif
+#if defined(Q_WS_QWS)
+
+/*!
+ \fn bool QWidget::qwsEvent(QWSEvent *event)
+
+ This special event handler can be reimplemented in a subclass to
+ receive native Qt for Embedded Linux events which are passed in the
+ \a event parameter.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \sa QApplication::qwsEventFilter()
+*/
+bool QWidget::qwsEvent(QWSEvent *)
+{
+ return false;
+}
+
+#endif
+
+
+/*!
+ Ensures that the widget has been polished by QStyle (i.e., has a
+ proper font and palette).
+
+ QWidget calls this function after it has been fully constructed
+ but before it is shown the very first time. You can call this
+ function if you want to ensure that the widget is polished before
+ doing an operation, e.g., the correct font size might be needed in
+ the widget's sizeHint() reimplementation. Note that this function
+ \e is called from the default implementation of sizeHint().
+
+ Polishing is useful for final initialization that must happen after
+ all constructors (from base classes as well as from subclasses)
+ have been called.
+
+ If you need to change some settings when a widget is polished,
+ reimplement event() and handle the QEvent::Polish event type.
+
+ \bold{Note:} The function is declared const so that it can be called from
+ other const functions (e.g., sizeHint()).
+
+ \sa event()
+*/
+void QWidget::ensurePolished() const
+{
+ Q_D(const QWidget);
+
+ const QMetaObject *m = metaObject();
+ if (m == d->polished)
+ return;
+ d->polished = m;
+
+ QEvent e(QEvent::Polish);
+ QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
+
+ // polish children after 'this'
+ QList<QObject*> children = d->children;
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *o = children.at(i);
+ if(!o->isWidgetType())
+ continue;
+ if (QWidget *w = qobject_cast<QWidget *>(o))
+ w->ensurePolished();
+ }
+
+ if (d->parent && d->sendChildEvents) {
+ QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
+ QCoreApplication::sendEvent(d->parent, &e);
+ }
+}
+
+/*!
+ Returns the mask currently set on a widget. If no mask is set the
+ return value will be an empty region.
+
+ \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
+*/
+QRegion QWidget::mask() const
+{
+ Q_D(const QWidget);
+ return d->extra ? d->extra->mask : QRegion();
+}
+
+/*!
+ Returns the layout manager that is installed on this widget, or 0
+ if no layout manager is installed.
+
+ The layout manager sets the geometry of the widget's children
+ that have been added to the layout.
+
+ \sa setLayout(), sizePolicy(), {Layout Management}
+*/
+QLayout *QWidget::layout() const
+{
+ return d_func()->layout;
+}
+
+
+/*!
+ \fn void QWidget::setLayout(QLayout *layout)
+
+ Sets the layout manager for this widget to \a layout.
+
+ If there already is a layout manager installed on this widget,
+ QWidget won't let you install another. You must first delete the
+ existing layout manager (returned by layout()) before you can
+ call setLayout() with the new layout.
+
+ If \a layout is the layout manger on a different widget, setLayout()
+ will reparent the layout and make it the layout manager for this widget.
+
+ Example:
+
+ \snippet examples/uitools/textfinder/textfinder.cpp 3b
+
+ An alternative to calling this function is to pass this widget to
+ the layout's constructor.
+
+ The QWidget will take ownership of \a layout.
+
+ \sa layout(), {Layout Management}
+*/
+
+void QWidget::setLayout(QLayout *l)
+{
+ if (!l) {
+ qWarning("QWidget::setLayout: Cannot set layout to 0");
+ return;
+ }
+ if (layout()) {
+ if (layout() != l)
+ qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
+ " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
+ objectName().toLocal8Bit().data());
+ return;
+ }
+
+ QObject *oldParent = l->parent();
+ if (oldParent && oldParent != this) {
+ if (oldParent->isWidgetType()) {
+ // Steal the layout off a widget parent. Takes effect when
+ // morphing laid-out container widgets in Designer.
+ QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
+ oldParentWidget->takeLayout();
+ } else {
+ qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
+ l->objectName().toLocal8Bit().data(), metaObject()->className(),
+ objectName().toLocal8Bit().data());
+ return;
+ }
+ }
+
+ Q_D(QWidget);
+ l->d_func()->topLevel = true;
+ d->layout = l;
+ if (oldParent != this) {
+ l->setParent(this);
+ l->d_func()->reparentChildWidgets(this);
+ l->invalidate();
+ }
+
+ if (isWindow() && d->maybeTopData())
+ d->topData()->sizeAdjusted = false;
+}
+
+/*!
+ \fn QLayout *QWidget::takeLayout()
+
+ Remove the layout from the widget.
+ \since 4.5
+*/
+
+QLayout *QWidget::takeLayout()
+{
+ Q_D(QWidget);
+ QLayout *l = layout();
+ if (!l)
+ return 0;
+ d->layout = 0;
+ l->setParent(0);
+ return l;
+}
+
+/*!
+ \property QWidget::sizePolicy
+ \brief the default layout behavior of the widget
+
+ If there is a QLayout that manages this widget's children, the
+ size policy specified by that layout is used. If there is no such
+ QLayout, the result of this function is used.
+
+ The default policy is Preferred/Preferred, which means that the
+ widget can be freely resized, but prefers to be the size
+ sizeHint() returns. Button-like widgets set the size policy to
+ specify that they may stretch horizontally, but are fixed
+ vertically. The same applies to lineedit controls (such as
+ QLineEdit, QSpinBox or an editable QComboBox) and other
+ horizontally orientated widgets (such as QProgressBar).
+ QToolButton's are normally square, so they allow growth in both
+ directions. Widgets that support different directions (such as
+ QSlider, QScrollBar or QHeader) specify stretching in the
+ respective direction only. Widgets that can provide scroll bars
+ (usually subclasses of QScrollArea) tend to specify that they can
+ use additional space, and that they can make do with less than
+ sizeHint().
+
+ \sa sizeHint() QLayout QSizePolicy updateGeometry()
+*/
+QSizePolicy QWidget::sizePolicy() const
+{
+ Q_D(const QWidget);
+ return d->size_policy;
+}
+
+void QWidget::setSizePolicy(QSizePolicy policy)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_WState_OwnSizePolicy);
+ if (policy == d->size_policy)
+ return;
+ d->size_policy = policy;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *extra = d->extra) {
+ if (extra->proxyWidget)
+ extra->proxyWidget->setSizePolicy(policy);
+ }
+#endif
+
+ updateGeometry();
+
+ if (isWindow() && d->maybeTopData())
+ d->topData()->sizeAdjusted = false;
+}
+
+/*!
+ \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
+ \overload
+
+ Sets the size policy of the widget to \a horizontal and \a
+ vertical, with standard stretch and no height-for-width.
+
+ \sa QSizePolicy::QSizePolicy()
+*/
+
+/*!
+ Returns the preferred height for this widget, given the width \a w.
+
+ If this widget has a layout, the default implementation returns
+ the layout's preferred height. if there is no layout, the default
+ implementation returns -1 indicating that the preferred height
+ does not depend on the width.
+*/
+
+int QWidget::heightForWidth(int w) const
+{
+ if (layout() && layout()->hasHeightForWidth())
+ return layout()->totalHeightForWidth(w);
+ return -1;
+}
+
+
+/*!
+ \internal
+
+ *virtual private*
+
+ This is a bit hackish, but ideally we would have created a virtual function
+ in the public API (however, too late...) so that subclasses could reimplement
+ their own function.
+ Instead we add a virtual function to QWidgetPrivate.
+ ### Qt5: move to public class and make virtual
+*/
+bool QWidgetPrivate::hasHeightForWidth() const
+{
+ return layout ? layout->hasHeightForWidth() : size_policy.hasHeightForWidth();
+}
+
+/*!
+ \fn QWidget *QWidget::childAt(int x, int y) const
+
+ Returns the visible child widget at the position (\a{x}, \a{y})
+ in the widget's coordinate system. If there is no visible child
+ widget at the specified position, the function returns 0.
+*/
+
+/*!
+ \overload
+
+ Returns the visible child widget at point \a p in the widget's own
+ coordinate system.
+*/
+
+QWidget *QWidget::childAt(const QPoint &p) const
+{
+ return d_func()->childAt_helper(p, false);
+}
+
+QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
+{
+ if (children.isEmpty())
+ return 0;
+
+#ifdef Q_WS_MAC
+ Q_Q(const QWidget);
+ // Unified tool bars on the Mac require special handling since they live outside
+ // QMainWindow's geometry(). See commit: 35667fd45ada49269a5987c235fdedfc43e92bb8
+ bool includeFrame = q->isWindow() && qobject_cast<const QMainWindow *>(q)
+ && static_cast<const QMainWindow *>(q)->unifiedTitleAndToolBarOnMac();
+ if (includeFrame)
+ return childAtRecursiveHelper(p, ignoreChildrenInDestructor, includeFrame);
+#endif
+
+ if (!pointInsideRectAndMask(p))
+ return 0;
+ return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
+}
+
+QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor, bool includeFrame) const
+{
+#ifndef Q_WS_MAC
+ Q_UNUSED(includeFrame);
+#endif
+ for (int i = children.size() - 1; i >= 0; --i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
+ || (ignoreChildrenInDestructor && child->data->in_destructor)) {
+ continue;
+ }
+
+ // Map the point 'p' from parent coordinates to child coordinates.
+ QPoint childPoint = p;
+#ifdef Q_WS_MAC
+ // 'includeFrame' is true if the child's parent is a top-level QMainWindow with an unified tool bar.
+ // An unified tool bar on the Mac lives outside QMainWindow's geometry(), so a normal
+ // QWidget::mapFromParent won't do the trick.
+ if (includeFrame && qobject_cast<QToolBar *>(child))
+ childPoint = qt_mac_nativeMapFromParent(child, p);
+ else
+#endif
+ childPoint -= child->data->crect.topLeft();
+
+ // Check if the point hits the child.
+ if (!child->d_func()->pointInsideRectAndMask(childPoint))
+ continue;
+
+ // Do the same for the child's descendants.
+ if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
+ return w;
+
+ // We have found our target; namely the child at position 'p'.
+ return child;
+ }
+ return 0;
+}
+
+void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
+{
+ Q_Q(QWidget);
+ if (widgetItem)
+ widgetItem->invalidateSizeCache();
+ QWidget *parent;
+ if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
+ if (!q->isWindow() && !q->isHidden() && (parent = q->parentWidget())) {
+ if (parent->d_func()->layout)
+ parent->d_func()->layout->invalidate();
+ else if (parent->isVisible())
+ QApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
+ }
+ }
+}
+
+/*!
+ Notifies the layout system that this widget has changed and may
+ need to change geometry.
+
+ Call this function if the sizeHint() or sizePolicy() have changed.
+
+ For explicitly hidden widgets, updateGeometry() is a no-op. The
+ layout system will be notified as soon as the widget is shown.
+*/
+
+void QWidget::updateGeometry()
+{
+ Q_D(QWidget);
+ d->updateGeometry_helper(false);
+}
+
+/*! \property QWidget::windowFlags
+
+ Window flags are a combination of a type (e.g. Qt::Dialog) and
+ zero or more hints to the window system (e.g.
+ Qt::FramelessWindowHint).
+
+ If the widget had type Qt::Widget or Qt::SubWindow and becomes a
+ window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
+ 0) on the desktop. If the widget is a window and becomes a
+ Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
+ relative to its parent widget.
+
+ \note This function calls setParent() when changing the flags for
+ a window, causing the widget to be hidden. You must call show() to make
+ the widget visible again..
+
+ \sa windowType(), {Window Flags Example}
+*/
+void QWidget::setWindowFlags(Qt::WindowFlags flags)
+{
+ if (data->window_flags == flags)
+ return;
+
+ Q_D(QWidget);
+
+ if ((data->window_flags | flags) & Qt::Window) {
+ // the old type was a window and/or the new type is a window
+ QPoint oldPos = pos();
+ bool visible = isVisible();
+ setParent(parentWidget(), flags);
+
+ // if both types are windows or neither of them are, we restore
+ // the old position
+ if (!((data->window_flags ^ flags) & Qt::Window)
+ && (visible || testAttribute(Qt::WA_Moved))) {
+ move(oldPos);
+ }
+ // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
+ d->adjustQuitOnCloseAttribute();
+ } else {
+ data->window_flags = flags;
+ }
+}
+
+/*!
+ Sets the window flags for the widget to \a flags,
+ \e without telling the window system.
+
+ \warning Do not call this function unless you really know what
+ you're doing.
+
+ \sa setWindowFlags()
+*/
+void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
+{
+ data->window_flags = flags;
+}
+
+/*!
+ \fn Qt::WindowType QWidget::windowType() const
+
+ Returns the window type of this widget. This is identical to
+ windowFlags() & Qt::WindowType_Mask.
+
+ \sa windowFlags
+*/
+
+/*!
+ Sets the parent of the widget to \a parent, and resets the window
+ flags. The widget is moved to position (0, 0) in its new parent.
+
+ If the new parent widget is in a different window, the
+ reparented widget and its children are appended to the end of the
+ \l{setFocusPolicy()}{tab chain} of the new parent
+ widget, in the same internal order as before. If one of the moved
+ widgets had keyboard focus, setParent() calls clearFocus() for that
+ widget.
+
+ If the new parent widget is in the same window as the
+ old parent, setting the parent doesn't change the tab order or
+ keyboard focus.
+
+ If the "new" parent widget is the old parent widget, this function
+ does nothing.
+
+ \note The widget becomes invisible as part of changing its parent,
+ even if it was previously visible. You must call show() to make the
+ widget visible again.
+
+ \warning It is very unlikely that you will ever need this
+ function. If you have a widget that changes its content
+ dynamically, it is far easier to use \l QStackedWidget.
+
+ \sa setWindowFlags()
+*/
+void QWidget::setParent(QWidget *parent)
+{
+ if (parent == parentWidget())
+ return;
+ setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
+}
+
+/*!
+ \overload
+
+ This function also takes widget flags, \a f as an argument.
+*/
+
+void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_D(QWidget);
+ bool resized = testAttribute(Qt::WA_Resized);
+ bool wasCreated = testAttribute(Qt::WA_WState_Created);
+ QWidget *oldtlw = window();
+
+ QWidget *desktopWidget = 0;
+ if (parent && parent->windowType() == Qt::Desktop)
+ desktopWidget = parent;
+ bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
+
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
+ if (newParent && parent && !desktopWidget) {
+ if (testAttribute(Qt::WA_NativeWindow) && !qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // On Mac, toolbars inside the unified title bar will never overlap with
+ // siblings in the content view. So we skip enforce native siblings in that case
+ && !d->isInUnifiedToolbar && parentWidget() && parentWidget()->isWindow()
+#endif // Q_WS_MAC && QT_MAC_USE_COCOA
+ )
+ parent->d_func()->enforceNativeChildren();
+ else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
+ setAttribute(Qt::WA_NativeWindow);
+ }
+#endif
+
+ if (wasCreated) {
+ if (!testAttribute(Qt::WA_WState_Hidden)) {
+ hide();
+ setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ }
+ if (newParent) {
+ QEvent e(QEvent::ParentAboutToChange);
+ QApplication::sendEvent(this, &e);
+ }
+ }
+ if (newParent && isAncestorOf(focusWidget()))
+ focusWidget()->clearFocus();
+
+ QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData();
+ QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStore : 0;
+
+ d->setParent_sys(parent, f);
+
+ QTLWExtra *topExtra = window()->d_func()->maybeTopData();
+ QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStore : 0;
+ if (oldBsTracker && oldBsTracker != bsTracker)
+ oldBsTracker->unregisterWidgetSubtree(this);
+
+ if (desktopWidget)
+ parent = 0;
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QTLWExtra *extra = d->maybeTopData();
+ QWindowSurface *windowSurface = (extra ? extra->windowSurface : 0);
+ if (newParent && windowSurface) {
+ QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore();
+ if (oldBs)
+ oldBs->subSurfaces.removeAll(windowSurface);
+
+ if (parent) {
+ QWidgetBackingStore *newBs = parent->d_func()->maybeBackingStore();
+ if (newBs)
+ newBs->subSurfaces.append(windowSurface);
+ }
+ }
+#endif
+
+ if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
+ if (newParent)
+ oldBs->removeDirtyWidget(this);
+ // Move the widget and all its static children from
+ // the old backing store to the new one.
+ oldBs->moveStaticWidgets(this);
+ }
+
+ if ((QApplicationPrivate::app_compile_version < 0x040200
+ || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
+ && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ d->reparentFocusWidgets(oldtlw);
+ setAttribute(Qt::WA_Resized, resized);
+ if (!testAttribute(Qt::WA_StyleSheet)
+ && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
+ d->resolveFont();
+ d->resolvePalette();
+ }
+ d->resolveLayoutDirection();
+ d->resolveLocale();
+
+ // Note: GL widgets under WGL or EGL will always need a ParentChange
+ // event to handle recreation/rebinding of the GL context, hence the
+ // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
+ // platforms).
+ if (newParent
+#if defined(Q_WS_WIN) || defined(QT_OPENGL_ES)
+ || (f & Qt::MSWindowsOwnDC)
+#endif
+ ) {
+ // propagate enabled updates enabled state to non-windows
+ if (!isWindow()) {
+ if (!testAttribute(Qt::WA_ForceDisabled))
+ d->setEnabled_helper(parent ? parent->isEnabled() : true);
+ if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
+ d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
+ }
+ d->inheritStyle();
+
+ // send and post remaining QObject events
+ if (parent && d->sendChildEvents) {
+ QChildEvent e(QEvent::ChildAdded, this);
+ QApplication::sendEvent(parent, &e);
+#ifdef QT3_SUPPORT
+ if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
+ QApplication::postEvent(parent,
+ new QEvent(QEvent::ChildInsertedRequest),
+ Qt::HighEventPriority);
+ }
+ parent->d_func()->pendingChildInsertedEvents.append(this);
+#endif
+ }
+
+//### already hidden above ---> must probably do something smart on the mac
+// #ifdef Q_WS_MAC
+// extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
+// if(!qt_mac_is_macdrawer(q)) //special case
+// q->setAttribute(Qt::WA_WState_Hidden);
+// #else
+// q->setAttribute(Qt::WA_WState_Hidden);
+//#endif
+
+ if (parent && d->sendChildEvents && d->polished) {
+ QChildEvent e(QEvent::ChildPolished, this);
+ QCoreApplication::sendEvent(parent, &e);
+ }
+
+ QEvent e(QEvent::ParentChange);
+ QApplication::sendEvent(this, &e);
+ }
+
+ if (!wasCreated) {
+ if (isWindow() || parentWidget()->isVisible())
+ setAttribute(Qt::WA_WState_Hidden, true);
+ else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
+ setAttribute(Qt::WA_WState_Hidden, false);
+ }
+
+ d->updateIsOpaque();
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Embed the widget into a proxy if the parent is embedded.
+ // ### Doesn't handle reparenting out of an embedded widget.
+ if (oldtlw->graphicsProxyWidget()) {
+ if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
+ ancestorProxy->d_func()->unembedSubWindow(this);
+ }
+ if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
+ if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
+ ancestorProxy->d_func()->embedSubWindow(this);
+ }
+#endif
+}
+
+/*!
+ Scrolls the widget including its children \a dx pixels to the
+ right and \a dy downward. Both \a dx and \a dy may be negative.
+
+ After scrolling, the widgets will receive paint events for
+ the areas that need to be repainted. For widgets that Qt knows to
+ be opaque, this is only the newly exposed parts.
+ For example, if an opaque widget is scrolled 8 pixels to the left,
+ only an 8-pixel wide stripe at the right edge needs updating.
+
+ Since widgets propagate the contents of their parents by default,
+ you need to set the \l autoFillBackground property, or use
+ setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
+ a widget opaque.
+
+ For widgets that use contents propagation, a scroll will cause an
+ update of the entire scroll area.
+
+ \sa {Transparency and Double Buffering}
+*/
+
+void QWidget::scroll(int dx, int dy)
+{
+ if ((!updatesEnabled() && children().size() == 0) || !isVisible())
+ return;
+ if (dx == 0 && dy == 0)
+ return;
+ Q_D(QWidget);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
+ // Graphics View maintains its own dirty region as a list of rects;
+ // until we can connect item updates directly to the view, we must
+ // separately add a translated dirty region.
+ if (!d->dirty.isEmpty()) {
+ foreach (const QRect &rect, (d->dirty.translated(dx, dy)).rects())
+ proxy->update(rect);
+ }
+ proxy->scroll(dx, dy, proxy->subWidgetRect(this));
+ return;
+ }
+#endif
+ d->setDirtyOpaqueRegion();
+ d->scroll_sys(dx, dy);
+}
+
+/*!
+ \overload
+
+ This version only scrolls \a r and does not move the children of
+ the widget.
+
+ If \a r is empty or invalid, the result is undefined.
+
+ \sa QScrollArea
+*/
+void QWidget::scroll(int dx, int dy, const QRect &r)
+{
+
+ if ((!updatesEnabled() && children().size() == 0) || !isVisible())
+ return;
+ if (dx == 0 && dy == 0)
+ return;
+ Q_D(QWidget);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
+ // Graphics View maintains its own dirty region as a list of rects;
+ // until we can connect item updates directly to the view, we must
+ // separately add a translated dirty region.
+ if (!d->dirty.isEmpty()) {
+ foreach (const QRect &rect, (d->dirty.translated(dx, dy) & r).rects())
+ proxy->update(rect);
+ }
+ proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
+ return;
+ }
+#endif
+ d->scroll_sys(dx, dy, r);
+}
+
+/*!
+ Repaints the widget directly by calling paintEvent() immediately,
+ unless updates are disabled or the widget is hidden.
+
+ We suggest only using repaint() if you need an immediate repaint,
+ for example during animation. In almost all circumstances update()
+ is better, as it permits Qt to optimize for speed and minimize
+ flicker.
+
+ \warning If you call repaint() in a function which may itself be
+ called from paintEvent(), you may get infinite recursion. The
+ update() function never causes recursion.
+
+ \sa update(), paintEvent(), setUpdatesEnabled()
+*/
+
+void QWidget::repaint()
+{
+ repaint(rect());
+}
+
+/*! \overload
+
+ This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
+ the widget.
+
+ If \a w is negative, it is replaced with \c{width() - x}, and if
+ \a h is negative, it is replaced width \c{height() - y}.
+*/
+void QWidget::repaint(int x, int y, int w, int h)
+{
+ if (x > data->crect.width() || y > data->crect.height())
+ return;
+
+ if (w < 0)
+ w = data->crect.width() - x;
+ if (h < 0)
+ h = data->crect.height() - y;
+
+ repaint(QRect(x, y, w, h));
+}
+
+/*! \overload
+
+ This version repaints a rectangle \a rect inside the widget.
+*/
+void QWidget::repaint(const QRect &rect)
+{
+ Q_D(QWidget);
+
+ if (testAttribute(Qt::WA_WState_ConfigPending)) {
+ update(rect);
+ return;
+ }
+
+ if (!isVisible() || !updatesEnabled() || rect.isEmpty())
+ return;
+
+ if (hasBackingStoreSupport()) {
+#ifdef QT_MAC_USE_COCOA
+ if (qt_widget_private(this)->isInUnifiedToolbar) {
+ qt_widget_private(this)->unifiedSurface->renderToolbar(this, true);
+ return;
+ }
+#endif // QT_MAC_USE_COCOA
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
+ tlwExtra->inRepaint = true;
+ tlwExtra->backingStore->markDirty(rect, this, true);
+ tlwExtra->inRepaint = false;
+ }
+ } else {
+ d->repaint_sys(rect);
+ }
+}
+
+/*!
+ \overload
+
+ This version repaints a region \a rgn inside the widget.
+*/
+void QWidget::repaint(const QRegion &rgn)
+{
+ Q_D(QWidget);
+
+ if (testAttribute(Qt::WA_WState_ConfigPending)) {
+ update(rgn);
+ return;
+ }
+
+ if (!isVisible() || !updatesEnabled() || rgn.isEmpty())
+ return;
+
+ if (hasBackingStoreSupport()) {
+#ifdef QT_MAC_USE_COCOA
+ if (qt_widget_private(this)->isInUnifiedToolbar) {
+ qt_widget_private(this)->unifiedSurface->renderToolbar(this, true);
+ return;
+ }
+#endif // QT_MAC_USE_COCOA
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
+ tlwExtra->inRepaint = true;
+ tlwExtra->backingStore->markDirty(rgn, this, true);
+ tlwExtra->inRepaint = false;
+ }
+ } else {
+ d->repaint_sys(rgn);
+ }
+}
+
+/*!
+ Updates the widget unless updates are disabled or the widget is
+ hidden.
+
+ This function does not cause an immediate repaint; instead it
+ schedules a paint event for processing when Qt returns to the main
+ event loop. This permits Qt to optimize for more speed and less
+ flicker than a call to repaint() does.
+
+ Calling update() several times normally results in just one
+ paintEvent() call.
+
+ Qt normally erases the widget's area before the paintEvent() call.
+ If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
+ responsible for painting all its pixels with an opaque color.
+
+ \sa repaint() paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
+*/
+void QWidget::update()
+{
+ update(rect());
+}
+
+/*! \fn void QWidget::update(int x, int y, int w, int h)
+ \overload
+
+ This version updates a rectangle (\a x, \a y, \a w, \a h) inside
+ the widget.
+*/
+
+/*!
+ \overload
+
+ This version updates a rectangle \a rect inside the widget.
+*/
+void QWidget::update(const QRect &rect)
+{
+ if (!isVisible() || !updatesEnabled() || rect.isEmpty())
+ return;
+
+ if (testAttribute(Qt::WA_WState_InPaintEvent)) {
+ QApplication::postEvent(this, new QUpdateLaterEvent(rect));
+ return;
+ }
+
+ if (hasBackingStoreSupport()) {
+#ifdef QT_MAC_USE_COCOA
+ if (qt_widget_private(this)->isInUnifiedToolbar) {
+ qt_widget_private(this)->unifiedSurface->renderToolbar(this, true);
+ return;
+ }
+#endif // QT_MAC_USE_COCOA
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
+ tlwExtra->backingStore->markDirty(rect, this);
+ } else {
+ d_func()->repaint_sys(rect);
+ }
+}
+
+/*!
+ \overload
+
+ This version repaints a region \a rgn inside the widget.
+*/
+void QWidget::update(const QRegion &rgn)
+{
+ if (!isVisible() || !updatesEnabled() || rgn.isEmpty())
+ return;
+
+ if (testAttribute(Qt::WA_WState_InPaintEvent)) {
+ QApplication::postEvent(this, new QUpdateLaterEvent(rgn));
+ return;
+ }
+
+ if (hasBackingStoreSupport()) {
+#ifdef QT_MAC_USE_COCOA
+ if (qt_widget_private(this)->isInUnifiedToolbar) {
+ qt_widget_private(this)->unifiedSurface->renderToolbar(this, true);
+ return;
+ }
+#endif // QT_MAC_USE_COCOA
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
+ tlwExtra->backingStore->markDirty(rgn, this);
+ } else {
+ d_func()->repaint_sys(rgn);
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Clear the rectangle at point (\a x, \a y) of width \a w and height
+ \a h.
+
+ \warning This is best done in a paintEvent().
+*/
+void QWidget::erase_helper(int x, int y, int w, int h)
+{
+ if (testAttribute(Qt::WA_NoSystemBackground) || testAttribute(Qt::WA_UpdatesDisabled) || !testAttribute(Qt::WA_WState_Visible))
+ return;
+ if (w < 0)
+ w = data->crect.width() - x;
+ if (h < 0)
+ h = data->crect.height() - y;
+ if (w != 0 && h != 0) {
+ QPainter p(this);
+ p.eraseRect(QRect(x, y, w, h));
+ }
+}
+
+/*!
+ \overload
+
+ Clear the given region, \a rgn.
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+void QWidget::erase(const QRegion& rgn)
+{
+ if (testAttribute(Qt::WA_NoSystemBackground) || testAttribute(Qt::WA_UpdatesDisabled) || !testAttribute(Qt::WA_WState_Visible))
+ return;
+
+ QPainter p(this);
+ p.setClipRegion(rgn);
+ p.eraseRect(rgn.boundingRect());
+}
+
+void QWidget::drawText_helper(int x, int y, const QString &str)
+{
+ if(!testAttribute(Qt::WA_WState_Visible))
+ return;
+ QPainter paint(this);
+ paint.drawText(x, y, str);
+}
+
+
+/*!
+ Closes the widget.
+
+ Use the no-argument overload instead.
+*/
+bool QWidget::close(bool alsoDelete)
+{
+ QPointer<QWidget> that = this;
+ bool accepted = close();
+ if (alsoDelete && accepted && that)
+ deleteLater();
+ return accepted;
+}
+
+void QWidget::setIcon(const QPixmap &i)
+{
+ setWindowIcon(i);
+}
+
+/*!
+ Return's the widget's icon.
+
+ Use windowIcon() instead.
+*/
+const QPixmap *QWidget::icon() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->iconPixmap : 0;
+}
+
+#endif // QT3_SUPPORT
+
+ /*!
+ \internal
+
+ This just sets the corresponding attribute bit to 1 or 0
+ */
+static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
+ QWidgetPrivate *d)
+{
+ if (attribute < int(8*sizeof(uint))) {
+ if (on)
+ data->widget_attributes |= (1<<attribute);
+ else
+ data->widget_attributes &= ~(1<<attribute);
+ } else {
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ if (on)
+ d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
+ else
+ d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
+ }
+}
+
+/*!
+ Sets the attribute \a attribute on this widget if \a on is true;
+ otherwise clears the attribute.
+
+ \sa testAttribute()
+*/
+void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
+{
+ if (testAttribute(attribute) == on)
+ return;
+
+ Q_D(QWidget);
+ Q_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
+ "QWidget::setAttribute(WidgetAttribute, bool)",
+ "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
+#ifdef Q_WS_WIN
+ // ### Don't use PaintOnScreen+paintEngine() to do native painting in 5.0
+ if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
+ // see qwidget_win.cpp, ::paintEngine for details
+ paintEngine();
+ if (d->noPaintOnScreen)
+ return;
+ }
+#endif
+
+ setAttribute_internal(attribute, on, data, d);
+
+ switch (attribute) {
+
+#ifndef QT_NO_DRAGANDDROP
+ case Qt::WA_AcceptDrops: {
+ if (on && !testAttribute(Qt::WA_DropSiteRegistered))
+ setAttribute(Qt::WA_DropSiteRegistered, true);
+ else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
+ setAttribute(Qt::WA_DropSiteRegistered, false);
+ QEvent e(QEvent::AcceptDropsChange);
+ QApplication::sendEvent(this, &e);
+ break;
+ }
+ case Qt::WA_DropSiteRegistered: {
+ d->registerDropSite(on);
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
+ w->setAttribute(Qt::WA_DropSiteRegistered, on);
+ }
+ break;
+ }
+#endif
+
+ case Qt::WA_NoChildEventsForParent:
+ d->sendChildEvents = !on;
+ break;
+ case Qt::WA_NoChildEventsFromChildren:
+ d->receiveChildEvents = !on;
+ break;
+ case Qt::WA_MacBrushedMetal:
+#ifdef Q_WS_MAC
+ d->setStyle_helper(style(), false, true); // Make sure things get unpolished/polished correctly.
+ // fall through since changing the metal attribute affects the opaque size grip.
+ case Qt::WA_MacOpaqueSizeGrip:
+ d->macUpdateOpaqueSizeGrip();
+ break;
+ case Qt::WA_MacShowFocusRect:
+ if (hasFocus()) {
+ clearFocus();
+ setFocus();
+ }
+ break;
+ case Qt::WA_Hover:
+ qt_mac_update_mouseTracking(this);
+ break;
+#endif
+ case Qt::WA_MacAlwaysShowToolWindow:
+#ifdef Q_WS_MAC
+ d->macUpdateHideOnSuspend();
+#endif
+ break;
+ case Qt::WA_MacNormalSize:
+ case Qt::WA_MacSmallSize:
+ case Qt::WA_MacMiniSize:
+#ifdef Q_WS_MAC
+ {
+ // We can only have one of these set at a time
+ const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
+ Qt::WA_MacMiniSize };
+ for (int i = 0; i < 3; ++i) {
+ if (MacSizes[i] != attribute)
+ setAttribute_internal(MacSizes[i], false, data, d);
+ }
+ d->macUpdateSizeAttribute();
+ }
+#endif
+ break;
+ case Qt::WA_ShowModal:
+ if (!on) {
+ if (isVisible())
+ QApplicationPrivate::leaveModal(this);
+ // reset modality type to Modeless when clearing WA_ShowModal
+ data->window_modality = Qt::NonModal;
+ } else if (data->window_modality == Qt::NonModal) {
+ // determine the modality type if it hasn't been set prior
+ // to setting WA_ShowModal. set the default to WindowModal
+ // if we are the child of a group leader; otherwise use
+ // ApplicationModal.
+ QWidget *w = parentWidget();
+ if (w)
+ w = w->window();
+ while (w && !w->testAttribute(Qt::WA_GroupLeader)) {
+ w = w->parentWidget();
+ if (w)
+ w = w->window();
+ }
+ data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader))
+ ? Qt::WindowModal
+ : Qt::ApplicationModal;
+ // Some window managers does not allow us to enter modal after the
+ // window is showing. Therefore, to be consistent, we cannot call
+ // QApplicationPrivate::enterModal(this) here. The window must be
+ // hidden before changing modality.
+ }
+ if (testAttribute(Qt::WA_WState_Created)) {
+ // don't call setModal_sys() before create_sys()
+ d->setModal_sys();
+ }
+ break;
+ case Qt::WA_MouseTracking: {
+ QEvent e(QEvent::MouseTrackingChange);
+ QApplication::sendEvent(this, &e);
+ break; }
+ case Qt::WA_NativeWindow: {
+#if defined(Q_WS_QPA)
+ d->createTLExtra();
+#endif
+#ifndef QT_NO_IM
+ QWidget *focusWidget = d->effectiveFocusWidget();
+ QInputContext *ic = 0;
+ if (on && !internalWinId() && hasFocus()
+ && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ ic = focusWidget->d_func()->inputContext();
+ if (ic) {
+ ic->reset();
+ ic->setFocusWidget(0);
+ }
+ }
+ if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // On Mac, toolbars inside the unified title bar will never overlap with
+ // siblings in the content view. So we skip enforce native siblings in that case
+ && !d->isInUnifiedToolbar && parentWidget()->isWindow()
+#endif // Q_WS_MAC && QT_MAC_USE_COCOA
+ )
+ parentWidget()->d_func()->enforceNativeChildren();
+ if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
+ d->createWinId();
+ if (ic && isEnabled() && focusWidget->isEnabled()
+ && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ ic->setFocusWidget(focusWidget);
+ }
+#endif //QT_NO_IM
+ break;
+ }
+ case Qt::WA_PaintOnScreen:
+ d->updateIsOpaque();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
+ // Recreate the widget if it's already created as an alien widget and
+ // WA_PaintOnScreen is enabled. Paint on screen widgets must have win id.
+ // So must their children.
+ if (on) {
+ setAttribute(Qt::WA_NativeWindow);
+ d->enforceNativeChildren();
+ }
+#endif
+ // fall through
+ case Qt::WA_OpaquePaintEvent:
+ d->updateIsOpaque();
+ break;
+ case Qt::WA_NoSystemBackground:
+ d->updateIsOpaque();
+ // fall through...
+ case Qt::WA_UpdatesDisabled:
+ d->updateSystemBackground();
+ break;
+ case Qt::WA_TransparentForMouseEvents:
+#ifdef Q_WS_MAC
+ d->macUpdateIgnoreMouseEvents();
+#endif
+ break;
+ case Qt::WA_InputMethodEnabled: {
+#ifndef QT_NO_IM
+ QWidget *focusWidget = d->effectiveFocusWidget();
+ QInputContext *ic = focusWidget->d_func()->assignedInputContext();
+ if (!ic && (!on || hasFocus()))
+ ic = focusWidget->d_func()->inputContext();
+ if (ic) {
+ if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled()
+ && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ ic->setFocusWidget(focusWidget);
+ } else if (!on && ic->focusWidget() == focusWidget) {
+ ic->reset();
+ ic->setFocusWidget(0);
+ }
+ }
+#endif //QT_NO_IM
+ break;
+ }
+ case Qt::WA_WindowPropagation:
+ d->resolvePalette();
+ d->resolveFont();
+ d->resolveLocale();
+ break;
+#ifdef Q_WS_X11
+ case Qt::WA_NoX11EventCompression:
+ if (!d->extra)
+ d->createExtra();
+ d->extra->compress_events = on;
+ break;
+ case Qt::WA_X11OpenGLOverlay:
+ d->updateIsOpaque();
+ break;
+ case Qt::WA_X11DoNotAcceptFocus:
+ if (testAttribute(Qt::WA_WState_Created))
+ d->updateX11AcceptFocus();
+ break;
+#endif
+ case Qt::WA_DontShowOnScreen: {
+ if (on && isVisible()) {
+ // Make sure we keep the current state and only hide the widget
+ // from the desktop. show_sys will only update platform specific
+ // attributes at this point.
+ d->hide_sys();
+#ifdef Q_WS_QWS
+ // Release the region for this window from qws if the widget has
+ // been shown before the attribute was set.
+ if (QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(windowSurface())) {
+ QWidget::qwsDisplay()->requestRegion(surface->winId(), surface->key(),
+ surface->permanentState(), QRegion());
+ }
+#endif
+ d->show_sys();
+ }
+ break;
+ }
+
+#ifdef Q_WS_X11
+ case Qt::WA_X11NetWmWindowTypeDesktop:
+ case Qt::WA_X11NetWmWindowTypeDock:
+ case Qt::WA_X11NetWmWindowTypeToolBar:
+ case Qt::WA_X11NetWmWindowTypeMenu:
+ case Qt::WA_X11NetWmWindowTypeUtility:
+ case Qt::WA_X11NetWmWindowTypeSplash:
+ case Qt::WA_X11NetWmWindowTypeDialog:
+ case Qt::WA_X11NetWmWindowTypeDropDownMenu:
+ case Qt::WA_X11NetWmWindowTypePopupMenu:
+ case Qt::WA_X11NetWmWindowTypeToolTip:
+ case Qt::WA_X11NetWmWindowTypeNotification:
+ case Qt::WA_X11NetWmWindowTypeCombo:
+ case Qt::WA_X11NetWmWindowTypeDND:
+ if (testAttribute(Qt::WA_WState_Created))
+ d->setNetWmWindowTypes();
+ break;
+#endif
+
+ case Qt::WA_StaticContents:
+ if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ if (on)
+ bs->addStaticWidget(this);
+ else
+ bs->removeStaticWidget(this);
+ }
+ break;
+ case Qt::WA_TranslucentBackground:
+ if (on) {
+ setAttribute(Qt::WA_NoSystemBackground);
+ d->updateIsTranslucent();
+ }
+
+ break;
+ case Qt::WA_AcceptTouchEvents:
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
+ if (on)
+ d->registerTouchWindow();
+#endif
+ break;
+ case Qt::WA_LockPortraitOrientation:
+ case Qt::WA_LockLandscapeOrientation:
+ case Qt::WA_AutoOrientation: {
+ const Qt::WidgetAttribute orientations[3] = {
+ Qt::WA_LockPortraitOrientation,
+ Qt::WA_LockLandscapeOrientation,
+ Qt::WA_AutoOrientation
+ };
+
+ if (on) {
+ // We can only have one of these set at a time
+ for (int i = 0; i < 3; ++i) {
+ if (orientations[i] != attribute)
+ setAttribute_internal(orientations[i], false, data, d);
+ }
+ }
+
+#ifdef Q_WS_S60
+ CAknAppUiBase* appUi = static_cast<CAknAppUiBase*>(CEikonEnv::Static()->EikAppUi());
+ const CAknAppUiBase::TAppUiOrientation s60orientations[] = {
+ CAknAppUiBase::EAppUiOrientationPortrait,
+ CAknAppUiBase::EAppUiOrientationLandscape,
+ CAknAppUiBase::EAppUiOrientationAutomatic
+ };
+ CAknAppUiBase::TAppUiOrientation s60orientation = CAknAppUiBase::EAppUiOrientationUnspecified;
+ for (int i = 0; i < 3; ++i) {
+ if (testAttribute(orientations[i])) {
+ s60orientation = s60orientations[i];
+ break;
+ }
+ }
+ QT_TRAP_THROWING(appUi->SetOrientationL(s60orientation));
+ S60->orientationSet = true;
+ QSymbianControl *window = static_cast<QSymbianControl *>(internalWinId());
+ if (window)
+ window->ensureFixNativeOrientation();
+#endif
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
+
+ Returns true if attribute \a attribute is set on this widget;
+ otherwise returns false.
+
+ \sa setAttribute()
+ */
+bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
+{
+ Q_D(const QWidget);
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
+}
+
+/*!
+ \property QWidget::windowOpacity
+
+ \brief The level of opacity for the window.
+
+ The valid range of opacity is from 1.0 (completely opaque) to
+ 0.0 (completely transparent).
+
+ By default the value of this property is 1.0.
+
+ This feature is available on Embedded Linux, Mac OS X, Windows,
+ and X11 platforms that support the Composite extension.
+
+ This feature is not available on Windows CE.
+
+ Note that under X11 you need to have a composite manager running,
+ and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
+ supported by the window manager you are using.
+
+ \warning Changing this property from opaque to transparent might issue a
+ paint event that needs to be processed before the window is displayed
+ correctly. This affects mainly the use of QPixmap::grabWindow(). Also note
+ that semi-transparent windows update and resize significantly slower than
+ opaque windows.
+
+ \sa setMask()
+*/
+qreal QWidget::windowOpacity() const
+{
+ Q_D(const QWidget);
+ return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
+}
+
+void QWidget::setWindowOpacity(qreal opacity)
+{
+ Q_D(QWidget);
+ if (!isWindow())
+ return;
+
+ opacity = qBound(qreal(0.0), opacity, qreal(1.0));
+ QTLWExtra *extra = d->topData();
+ extra->opacity = uint(opacity * 255);
+ setAttribute(Qt::WA_WState_WindowOpacitySet);
+
+#ifndef Q_WS_QWS
+ if (!testAttribute(Qt::WA_WState_Created))
+ return;
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
+ // Avoid invalidating the cache if set.
+ if (proxy->cacheMode() == QGraphicsItem::NoCache)
+ proxy->update();
+ else if (QGraphicsScene *scene = proxy->scene())
+ scene->update(proxy->sceneBoundingRect());
+ return;
+ }
+#endif
+
+ d->setWindowOpacity_sys(opacity);
+}
+
+/*!
+ \property QWidget::windowModified
+ \brief whether the document shown in the window has unsaved changes
+
+ A modified window is a window whose content has changed but has
+ not been saved to disk. This flag will have different effects
+ varied by the platform. On Mac OS X the close button will have a
+ modified look; on other platforms, the window title will have an
+ '*' (asterisk).
+
+ The window title must contain a "[*]" placeholder, which
+ indicates where the '*' should appear. Normally, it should appear
+ right after the file name (e.g., "document1.txt[*] - Text
+ Editor"). If the window isn't modified, the placeholder is simply
+ removed.
+
+ Note that if a widget is set as modified, all its ancestors will
+ also be set as modified. However, if you call \c
+ {setWindowModified(false)} on a widget, this will not propagate to
+ its parent because other children of the parent might have been
+ modified.
+
+ \sa windowTitle, {Application Example}, {SDI Example}, {MDI Example}
+*/
+bool QWidget::isWindowModified() const
+{
+ return testAttribute(Qt::WA_WindowModified);
+}
+
+void QWidget::setWindowModified(bool mod)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_WindowModified, mod);
+
+#ifndef Q_WS_MAC
+ if (!windowTitle().contains(QLatin1String("[*]")) && mod)
+ qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
+#endif
+ d->setWindowTitle_helper(windowTitle());
+ d->setWindowIconText_helper(windowIconText());
+#ifdef Q_WS_MAC
+ d->setWindowModified_sys(mod);
+#endif
+
+ QEvent e(QEvent::ModifiedChange);
+ QApplication::sendEvent(this, &e);
+}
+
+#ifndef QT_NO_TOOLTIP
+/*!
+ \property QWidget::toolTip
+
+ \brief the widget's tooltip
+
+ Note that by default tooltips are only shown for widgets that are
+ children of the active window. You can change this behavior by
+ setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
+ not on the widget with the tooltip.
+
+ If you want to control a tooltip's behavior, you can intercept the
+ event() function and catch the QEvent::ToolTip event (e.g., if you
+ want to customize the area for which the tooltip should be shown).
+
+ By default, this property contains an empty string.
+
+ \sa QToolTip statusTip whatsThis
+*/
+void QWidget::setToolTip(const QString &s)
+{
+ Q_D(QWidget);
+ d->toolTip = s;
+
+ QEvent event(QEvent::ToolTipChange);
+ QApplication::sendEvent(this, &event);
+}
+
+QString QWidget::toolTip() const
+{
+ Q_D(const QWidget);
+ return d->toolTip;
+}
+#endif // QT_NO_TOOLTIP
+
+
+#ifndef QT_NO_STATUSTIP
+/*!
+ \property QWidget::statusTip
+ \brief the widget's status tip
+
+ By default, this property contains an empty string.
+
+ \sa toolTip whatsThis
+*/
+void QWidget::setStatusTip(const QString &s)
+{
+ Q_D(QWidget);
+ d->statusTip = s;
+}
+
+QString QWidget::statusTip() const
+{
+ Q_D(const QWidget);
+ return d->statusTip;
+}
+#endif // QT_NO_STATUSTIP
+
+#ifndef QT_NO_WHATSTHIS
+/*!
+ \property QWidget::whatsThis
+
+ \brief the widget's What's This help text.
+
+ By default, this property contains an empty string.
+
+ \sa QWhatsThis QWidget::toolTip QWidget::statusTip
+*/
+void QWidget::setWhatsThis(const QString &s)
+{
+ Q_D(QWidget);
+ d->whatsThis = s;
+}
+
+QString QWidget::whatsThis() const
+{
+ Q_D(const QWidget);
+ return d->whatsThis;
+}
+#endif // QT_NO_WHATSTHIS
+
+#ifndef QT_NO_ACCESSIBILITY
+/*!
+ \property QWidget::accessibleName
+
+ \brief the widget's name as seen by assistive technologies
+
+ This property is used by accessible clients to identify, find, or announce
+ the widget for accessible clients.
+
+ By default, this property contains an empty string.
+
+ \sa QAccessibleInterface::text()
+*/
+void QWidget::setAccessibleName(const QString &name)
+{
+ Q_D(QWidget);
+ d->accessibleName = name;
+}
+
+QString QWidget::accessibleName() const
+{
+ Q_D(const QWidget);
+ return d->accessibleName;
+}
+
+/*!
+ \property QWidget::accessibleDescription
+
+ \brief the widget's description as seen by assistive technologies
+
+ By default, this property contains an empty string.
+
+ \sa QAccessibleInterface::text()
+*/
+void QWidget::setAccessibleDescription(const QString &description)
+{
+ Q_D(QWidget);
+ d->accessibleDescription = description;
+}
+
+QString QWidget::accessibleDescription() const
+{
+ Q_D(const QWidget);
+ return d->accessibleDescription;
+}
+#endif // QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_SHORTCUT
+/*!
+ Adds a shortcut to Qt's shortcut system that watches for the given
+ \a key sequence in the given \a context. If the \a context is
+ Qt::ApplicationShortcut, the shortcut applies to the application as a
+ whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
+ or to the window itself, Qt::WindowShortcut.
+
+ If the same \a key sequence has been grabbed by several widgets,
+ when the \a key sequence occurs a QEvent::Shortcut event is sent
+ to all the widgets to which it applies in a non-deterministic
+ order, but with the ``ambiguous'' flag set to true.
+
+ \warning You should not normally need to use this function;
+ instead create \l{QAction}s with the shortcut key sequences you
+ require (if you also want equivalent menu options and toolbar
+ buttons), or create \l{QShortcut}s if you just need key sequences.
+ Both QAction and QShortcut handle all the event filtering for you,
+ and provide signals which are triggered when the user triggers the
+ key sequence, so are much easier to use than this low-level
+ function.
+
+ \sa releaseShortcut() setShortcutEnabled()
+*/
+int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
+{
+ Q_ASSERT(qApp);
+ if (key.isEmpty())
+ return 0;
+ setAttribute(Qt::WA_GrabbedShortcut);
+ return qApp->d_func()->shortcutMap.addShortcut(this, key, context);
+}
+
+/*!
+ Removes the shortcut with the given \a id from Qt's shortcut
+ system. The widget will no longer receive QEvent::Shortcut events
+ for the shortcut's key sequence (unless it has other shortcuts
+ with the same key sequence).
+
+ \warning You should not normally need to use this function since
+ Qt's shortcut system removes shortcuts automatically when their
+ parent widget is destroyed. It is best to use QAction or
+ QShortcut to handle shortcuts, since they are easier to use than
+ this low-level function. Note also that this is an expensive
+ operation.
+
+ \sa grabShortcut() setShortcutEnabled()
+*/
+void QWidget::releaseShortcut(int id)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.removeShortcut(id, this, 0);
+}
+
+/*!
+ If \a enable is true, the shortcut with the given \a id is
+ enabled; otherwise the shortcut is disabled.
+
+ \warning You should not normally need to use this function since
+ Qt's shortcut system enables/disables shortcuts automatically as
+ widgets become hidden/visible and gain or lose focus. It is best
+ to use QAction or QShortcut to handle shortcuts, since they are
+ easier to use than this low-level function.
+
+ \sa grabShortcut() releaseShortcut()
+*/
+void QWidget::setShortcutEnabled(int id, bool enable)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
+}
+
+/*!
+ \since 4.2
+
+ If \a enable is true, auto repeat of the shortcut with the
+ given \a id is enabled; otherwise it is disabled.
+
+ \sa grabShortcut() releaseShortcut()
+*/
+void QWidget::setShortcutAutoRepeat(int id, bool enable)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
+}
+#endif // QT_NO_SHORTCUT
+/*!
+ Updates the widget's micro focus.
+
+ \sa QInputContext
+*/
+void QWidget::updateMicroFocus()
+{
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
+ Q_D(QWidget);
+ // and optimization to update input context only it has already been created.
+ if (d->assignedInputContext() || qApp->d_func()->inputContext) {
+ QInputContext *ic = inputContext();
+ if (ic)
+ ic->update();
+ }
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // ##### is this correct
+ QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+#endif
+}
+
+
+#if defined (Q_WS_WIN)
+/*!
+ Returns the window system handle of the widget, for low-level
+ access. Using this function is not portable.
+
+ An HDC acquired with getDC() has to be released with releaseDC().
+
+ \warning Using this function is not portable.
+*/
+HDC QWidget::getDC() const
+{
+ Q_D(const QWidget);
+ if (d->hd)
+ return (HDC) d->hd;
+ return GetDC(winId());
+}
+
+/*!
+ Releases the HDC \a hdc acquired by a previous call to getDC().
+
+ \warning Using this function is not portable.
+*/
+void QWidget::releaseDC(HDC hdc) const
+{
+ Q_D(const QWidget);
+ // If its the widgets own dc, it will be released elsewhere. If
+ // its a different HDC we release it and issue a warning if it
+ // fails.
+ if (hdc != d->hd && !ReleaseDC(winId(), hdc))
+ qErrnoWarning("QWidget::releaseDC(): failed to release HDC");
+}
+#else
+/*!
+ Returns the window system handle of the widget, for low-level
+ access. Using this function is not portable.
+
+ The HANDLE type varies with platform; see \c qwindowdefs.h for
+ details.
+*/
+Qt::HANDLE QWidget::handle() const
+{
+ Q_D(const QWidget);
+ if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
+ (void)winId(); // enforce native window
+ return d->hd;
+}
+#endif
+
+
+/*!
+ Raises this widget to the top of the parent widget's stack.
+
+ After this call the widget will be visually in front of any
+ overlapping sibling widgets.
+
+ \note When using activateWindow(), you can call this function to
+ ensure that the window is stacked on top.
+
+ \sa lower(), stackUnder()
+*/
+
+void QWidget::raise()
+{
+ Q_D(QWidget);
+ if (!isWindow()) {
+ QWidget *p = parentWidget();
+ const int parentChildCount = p->d_func()->children.size();
+ if (parentChildCount < 2)
+ return;
+ const int from = p->d_func()->children.indexOf(this);
+ Q_ASSERT(from >= 0);
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != parentChildCount -1)
+ p->d_func()->children.move(from, parentChildCount - 1);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == parentChildCount - 1)
+ return;
+
+ QRegion region(rect());
+ d->subtractOpaqueSiblings(region);
+ d->invalidateBuffer(region);
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->raise_sys();
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ Lowers the widget to the bottom of the parent widget's stack.
+
+ After this call the widget will be visually behind (and therefore
+ obscured by) any overlapping sibling widgets.
+
+ \sa raise(), stackUnder()
+*/
+
+void QWidget::lower()
+{
+ Q_D(QWidget);
+ if (!isWindow()) {
+ QWidget *p = parentWidget();
+ const int parentChildCount = p->d_func()->children.size();
+ if (parentChildCount < 2)
+ return;
+ const int from = p->d_func()->children.indexOf(this);
+ Q_ASSERT(from >= 0);
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != 0)
+ p->d_func()->children.move(from, 0);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == 0)
+ return;
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->lower_sys();
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+
+/*!
+ Places the widget under \a w in the parent widget's stack.
+
+ To make this work, the widget itself and \a w must be siblings.
+
+ \sa raise(), lower()
+*/
+void QWidget::stackUnder(QWidget* w)
+{
+ Q_D(QWidget);
+ QWidget *p = parentWidget();
+ if (!w || isWindow() || p != w->parentWidget() || this == w)
+ return;
+ if (p) {
+ int from = p->d_func()->children.indexOf(this);
+ int to = p->d_func()->children.indexOf(w);
+ Q_ASSERT(from >= 0);
+ Q_ASSERT(to >= 0);
+ if (from < to)
+ --to;
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != to)
+ p->d_func()->children.move(from, to);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == to)
+ return;
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->stackUnder_sys(w);
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidget::styleChange(QStyle&) { }
+void QWidget::enabledChange(bool) { } // compat
+void QWidget::paletteChange(const QPalette &) { } // compat
+void QWidget::fontChange(const QFont &) { } // compat
+void QWidget::windowActivationChange(bool) { } // compat
+void QWidget::languageChange() { } // compat
+
+
+/*!
+ \enum QWidget::BackgroundOrigin
+
+ \compat
+
+ \value WidgetOrigin
+ \value ParentOrigin
+ \value WindowOrigin
+ \value AncestorOrigin
+
+*/
+
+/*!
+ \fn bool QWidget::isVisibleToTLW() const
+
+ Use isVisible() instead.
+*/
+
+/*!
+ \fn void QWidget::iconify()
+
+ Use showMinimized() instead.
+*/
+
+/*!
+ \fn void QWidget::constPolish() const
+
+ Use ensurePolished() instead.
+*/
+
+/*!
+ \fn void QWidget::reparent(QWidget *parent, Qt::WindowFlags f, const QPoint &p, bool showIt)
+
+ Use setParent() to change the parent or the widget's widget flags;
+ use move() to move the widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn void QWidget::reparent(QWidget *parent, const QPoint &p, bool showIt)
+
+ Use setParent() to change the parent; use move() to move the
+ widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn void QWidget::recreate(QWidget *parent, Qt::WindowFlags f, const QPoint & p, bool showIt)
+
+ Use setParent() to change the parent or the widget's widget flags;
+ use move() to move the widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn bool QWidget::hasMouse() const
+
+ Use testAttribute(Qt::WA_UnderMouse) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownCursor() const
+
+ Use testAttribute(Qt::WA_SetCursor) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownFont() const
+
+ Use testAttribute(Qt::WA_SetFont) instead.
+*/
+
+/*!
+ \fn void QWidget::unsetFont()
+
+ Use setFont(QFont()) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownPalette() const
+
+ Use testAttribute(Qt::WA_SetPalette) instead.
+*/
+
+/*!
+ \fn void QWidget::unsetPalette()
+
+ Use setPalette(QPalette()) instead.
+*/
+
+/*!
+ \fn void QWidget::setEraseColor(const QColor &color)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setEraseColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setErasePixmap(const QPixmap &pixmap)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setErasePixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteForegroundColor(const QColor &color)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteForegroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->foregroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteBackgroundColor(const QColor &color)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteBackgroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteBackgroundPixmap(const QPixmap &pixmap)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteBackgroundPixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setBackgroundPixmap(const QPixmap &pixmap)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setBackgroundPixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setBackgroundColor(const QColor &color)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setBackgroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+
+/*!
+ \fn QWidget *QWidget::parentWidget(bool sameWindow) const
+
+ Use the no-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setKeyCompression(bool b)
+
+ Use setAttribute(Qt::WA_KeyCompression, b) instead.
+*/
+
+/*!
+ \fn void QWidget::setFont(const QFont &f, bool b)
+
+ Use the single-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setPalette(const QPalette &p, bool b)
+
+ Use the single-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setBackgroundOrigin(BackgroundOrigin background)
+
+ \obsolete
+*/
+
+/*!
+ \fn BackgroundOrigin QWidget::backgroundOrigin() const
+
+ \obsolete
+
+ Always returns \c WindowOrigin.
+*/
+
+/*!
+ \fn QPoint QWidget::backgroundOffset() const
+
+ \obsolete
+
+ Always returns QPoint().
+*/
+
+/*!
+ \fn void QWidget::repaint(bool b)
+
+ The boolean parameter \a b is ignored. Use the no-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(int x, int y, int w, int h, bool b)
+
+ The boolean parameter \a b is ignored. Use the four-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(const QRect &r, bool b)
+
+ The boolean parameter \a b is ignored. Use the single rect-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(const QRegion &rgn, bool b)
+
+ The boolean parameter \a b is ignored. Use the single region-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::erase()
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::erase(int x, int y, int w, int h)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::erase(const QRect &rect)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::drawText(const QPoint &p, const QString &s)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your drawing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::drawText(int x, int y, const QString &s)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your drawing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn QWidget *QWidget::childAt(const QPoint &p, bool includeThis) const
+
+ Use the single point argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setCaption(const QString &c)
+
+ Use setWindowTitle() instead.
+*/
+
+/*!
+ \fn void QWidget::setIcon(const QPixmap &i)
+
+ Use setWindowIcon() instead.
+*/
+
+/*!
+ \fn void QWidget::setIconText(const QString &it)
+
+ Use setWindowIconText() instead.
+*/
+
+/*!
+ \fn QString QWidget::caption() const
+
+ Use windowTitle() instead.
+*/
+
+/*!
+ \fn QString QWidget::iconText() const
+
+ Use windowIconText() instead.
+*/
+
+/*!
+ \fn bool QWidget::isTopLevel() const
+ \obsolete
+
+ Use isWindow() instead.
+*/
+
+/*!
+ \fn bool QWidget::isRightToLeft() const
+ \internal
+*/
+
+/*!
+ \fn bool QWidget::isLeftToRight() const
+ \internal
+*/
+
+/*!
+ \fn void QWidget::setInputMethodEnabled(bool enabled)
+
+ Use setAttribute(Qt::WA_InputMethodEnabled, \a enabled) instead.
+*/
+
+/*!
+ \fn bool QWidget::isInputMethodEnabled() const
+
+ Use testAttribute(Qt::WA_InputMethodEnabled) instead.
+*/
+
+/*!
+ \fn void QWidget::setActiveWindow()
+
+ Use activateWindow() instead.
+*/
+
+/*!
+ \fn bool QWidget::isShown() const
+
+ Use !isHidden() instead (notice the exclamation mark), or use isVisible() to check whether the widget is visible.
+*/
+
+/*!
+ \fn bool QWidget::isDialog() const
+
+ Use windowType() == Qt::Dialog instead.
+*/
+
+/*!
+ \fn bool QWidget::isPopup() const
+
+ Use windowType() == Qt::Popup instead.
+*/
+
+/*!
+ \fn bool QWidget::isDesktop() const
+
+ Use windowType() == Qt::Desktop instead.
+*/
+
+/*!
+ \fn void QWidget::polish()
+
+ Use ensurePolished() instead.
+*/
+
+/*!
+ \fn QWidget *QWidget::childAt(int x, int y, bool includeThis) const
+
+ Use the childAt() overload that doesn't have an \a includeThis parameter.
+
+ \oldcode
+ return widget->childAt(x, y, true);
+ \newcode
+ QWidget *child = widget->childAt(x, y, true);
+ if (child)
+ return child;
+ if (widget->rect().contains(x, y))
+ return widget;
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver, bool hfw)
+ \compat
+
+ Use the \l sizePolicy property and heightForWidth() function instead.
+*/
+
+/*!
+ \fn bool QWidget::isUpdatesEnabled() const
+ \compat
+
+ Use the \l updatesEnabled property instead.
+*/
+
+/*!
+ \macro QWIDGETSIZE_MAX
+ \relates QWidget
+
+ Defines the maximum size for a QWidget object.
+
+ The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
+
+ \sa QWidget::setMaximumSize()
+*/
+
+/*!
+ \fn QWidget::setupUi(QWidget *widget)
+
+ Sets up the user interface for the specified \a widget.
+
+ \note This function is available with widgets that derive from user
+ interface descriptions created using \l{uic}.
+
+ \sa {Using a Designer UI File in Your Application}
+*/
+
+QRect QWidgetPrivate::frameStrut() const
+{
+ Q_Q(const QWidget);
+ if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ // x2 = x1 + w - 1, so w/h = 1
+ return QRect(0, 0, 1, 1);
+ }
+
+ if (data.fstrut_dirty
+#ifndef Q_WS_WIN
+ // ### Fix properly for 4.3
+ && q->isVisible()
+#endif
+ && q->testAttribute(Qt::WA_WState_Created))
+ const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
+
+ return maybeTopData() ? maybeTopData()->frameStrut : QRect();
+}
+
+#ifdef QT_KEYPAD_NAVIGATION
+/*!
+ \internal
+
+ Changes the focus from the current focusWidget to a widget in
+ the \a direction.
+
+ Returns true, if there was a widget in that direction
+*/
+bool QWidgetPrivate::navigateToDirection(Direction direction)
+{
+ QWidget *targetWidget = widgetInNavigationDirection(direction);
+ if (targetWidget)
+ targetWidget->setFocus();
+ return (targetWidget != 0);
+}
+
+/*!
+ \internal
+
+ Searches for a widget that is positioned in the \a direction, starting
+ from the current focusWidget.
+
+ Returns the pointer to a found widget or 0, if there was no widget in
+ that direction.
+*/
+QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
+{
+ const QWidget *sourceWidget = QApplication::focusWidget();
+ if (!sourceWidget)
+ return 0;
+ const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
+ const int sourceX =
+ (direction == DirectionNorth || direction == DirectionSouth) ?
+ (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
+ :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
+ const int sourceY =
+ (direction == DirectionEast || direction == DirectionWest) ?
+ (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
+ :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
+ const QPoint sourcePoint(sourceX, sourceY);
+ const QPoint sourceCenter = sourceRect.center();
+ const QWidget *sourceWindow = sourceWidget->window();
+
+ QWidget *targetWidget = 0;
+ int shortestDistance = INT_MAX;
+ foreach(QWidget *targetCandidate, QApplication::allWidgets()) {
+
+ const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
+
+ // For focus proxies, the child widget handling the focus can have keypad navigation focus,
+ // but the owner of the proxy cannot.
+ // Additionally, empty widgets should be ignored.
+ if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
+ continue;
+
+ // Only navigate to a target widget that...
+ if ( targetCandidate != sourceWidget
+ // ...takes the focus,
+ && targetCandidate->focusPolicy() & Qt::TabFocus
+ // ...is above if DirectionNorth,
+ && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
+ // ...is on the right if DirectionEast,
+ && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
+ // ...is below if DirectionSouth,
+ && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
+ // ...is on the left if DirectionWest,
+ && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
+ // ...is enabled,
+ && targetCandidate->isEnabled()
+ // ...is visible,
+ && targetCandidate->isVisible()
+ // ...is in the same window,
+ && targetCandidate->window() == sourceWindow) {
+ const int targetCandidateDistance = pointToRect(sourcePoint, targetCandidateRect);
+ if (targetCandidateDistance < shortestDistance) {
+ shortestDistance = targetCandidateDistance;
+ targetWidget = targetCandidate;
+ }
+ }
+ }
+ return targetWidget;
+}
+
+/*!
+ \internal
+
+ Tells us if it there is currently a reachable widget by keypad navigation in
+ a certain \a orientation.
+ If no navigation is possible, occurring key events in that \a orientation may
+ be used to interact with the value in the focused widget, even though it
+ currently has not the editFocus.
+
+ \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
+*/
+bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
+{
+ return orientation == Qt::Horizontal?
+ (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
+ || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
+ :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
+ || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
+}
+/*!
+ \internal
+
+ Checks, if the \a widget is inside a QTabWidget. If is is inside
+ one, left/right key events will be used to switch between tabs in keypad
+ navigation. If there is no QTabWidget, the horizontal key events can be used
+to
+ interact with the value in the focused widget, even though it currently has
+ not the editFocus.
+
+ \sa QWidget::hasEditFocus()
+*/
+bool QWidgetPrivate::inTabWidget(QWidget *widget)
+{
+ for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
+ if (qobject_cast<const QTabWidget*>(tabWidget))
+ return true;
+ return false;
+}
+#endif
+
+/*!
+ \preliminary
+ \since 4.2
+ \obsolete
+
+ Sets the window surface to be the \a surface specified.
+ The QWidget takes will ownership of the \a surface.
+ widget itself is deleted.
+*/
+void QWidget::setWindowSurface(QWindowSurface *surface)
+{
+ // ### createWinId() ??
+
+#ifndef Q_BACKINGSTORE_SUBSURFACES
+ if (!isTopLevel())
+ return;
+#endif
+
+ Q_D(QWidget);
+
+ QTLWExtra *topData = d->topData();
+ if (topData->windowSurface == surface)
+ return;
+
+ QWindowSurface *oldSurface = topData->windowSurface;
+ delete topData->windowSurface;
+ topData->windowSurface = surface;
+
+ QWidgetBackingStore *bs = d->maybeBackingStore();
+ if (!bs)
+ return;
+
+ if (isTopLevel()) {
+ if (bs->windowSurface != oldSurface && bs->windowSurface != surface)
+ delete bs->windowSurface;
+ bs->windowSurface = surface;
+ }
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ else {
+ bs->subSurfaces.append(surface);
+ }
+ bs->subSurfaces.removeOne(oldSurface);
+#endif
+}
+
+/*!
+ \preliminary
+ \since 4.2
+
+ Returns the QWindowSurface this widget will be drawn into.
+*/
+QWindowSurface *QWidget::windowSurface() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra && extra->windowSurface)
+ return extra->windowSurface;
+
+ QWidgetBackingStore *bs = d->maybeBackingStore();
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ if (bs && bs->subSurfaces.isEmpty())
+ return bs->windowSurface;
+
+ if (!isTopLevel()) {
+ const QWidget *w = parentWidget();
+ while (w) {
+ QTLWExtra *extra = w->d_func()->maybeTopData();
+ if (extra && extra->windowSurface)
+ return extra->windowSurface;
+ if (w->isTopLevel())
+ break;
+ w = w->parentWidget();
+ }
+ }
+#endif // Q_BACKINGSTORE_SUBSURFACES
+
+ return bs ? bs->windowSurface : 0;
+}
+
+void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
+{
+ if (left)
+ *left = (int)leftLayoutItemMargin;
+ if (top)
+ *top = (int)topLayoutItemMargin;
+ if (right)
+ *right = (int)rightLayoutItemMargin;
+ if (bottom)
+ *bottom = (int)bottomLayoutItemMargin;
+}
+
+void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
+{
+ if (leftLayoutItemMargin == left
+ && topLayoutItemMargin == top
+ && rightLayoutItemMargin == right
+ && bottomLayoutItemMargin == bottom)
+ return;
+
+ Q_Q(QWidget);
+ leftLayoutItemMargin = (signed char)left;
+ topLayoutItemMargin = (signed char)top;
+ rightLayoutItemMargin = (signed char)right;
+ bottomLayoutItemMargin = (signed char)bottom;
+ q->updateGeometry();
+}
+
+void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
+{
+ Q_Q(QWidget);
+ QStyleOption myOpt;
+ if (!opt) {
+ myOpt.initFrom(q);
+ myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
+ opt = &myOpt;
+ }
+
+ QRect liRect = q->style()->subElementRect(element, opt, q);
+ if (liRect.isValid()) {
+ leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
+ topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
+ rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
+ bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
+ } else {
+ leftLayoutItemMargin = 0;
+ topLayoutItemMargin = 0;
+ rightLayoutItemMargin = 0;
+ bottomLayoutItemMargin = 0;
+ }
+}
+// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
+void QWidgetPrivate::adjustQuitOnCloseAttribute()
+{
+ Q_Q(QWidget);
+
+ if (!q->parentWidget()) {
+ Qt::WindowType type = q->windowType();
+ if (type == Qt::Widget || type == Qt::SubWindow)
+ type = Qt::Window;
+ if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
+ q->setAttribute(Qt::WA_QuitOnClose, false);
+ }
+}
+
+
+
+Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
+{
+ return widget->data;
+}
+
+Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
+{
+ return widget->d_func();
+}
+
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ \since 4.5
+
+ Returns the proxy widget for the corresponding embedded widget in a graphics
+ view; otherwise returns 0.
+
+ \sa QGraphicsProxyWidget::createProxyForChildWidget(),
+ QGraphicsScene::addWidget()
+ */
+QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
+{
+ Q_D(const QWidget);
+ if (d->extra) {
+ return d->extra->proxyWidget;
+ }
+ return 0;
+}
+#endif
+
+
+/*!
+ \typedef QWidgetList
+ \relates QWidget
+
+ Synonym for QList<QWidget *>.
+*/
+
+#ifndef QT_NO_GESTURES
+/*!
+ Subscribes the widget to a given \a gesture with specific \a flags.
+
+ \sa ungrabGesture(), QGestureEvent
+ \since 4.6
+*/
+void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
+{
+ Q_D(QWidget);
+ d->gestureContext.insert(gesture, flags);
+ (void)QGestureManager::instance(); // create a gesture manager
+}
+
+/*!
+ Unsubscribes the widget from a given \a gesture type
+
+ \sa grabGesture(), QGestureEvent
+ \since 4.6
+*/
+void QWidget::ungrabGesture(Qt::GestureType gesture)
+{
+ Q_D(QWidget);
+ if (d->gestureContext.remove(gesture)) {
+ if (QGestureManager *manager = QGestureManager::instance())
+ manager->cleanupCachedGestures(this, gesture);
+ }
+}
+#endif // QT_NO_GESTURES
+
+/*!
+ \typedef WId
+ \relates QWidget
+
+ Platform dependent window identifier.
+*/
+
+/*!
+ \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+
+ Frees up window system resources. Destroys the widget window if \a
+ destroyWindow is true.
+
+ destroy() calls itself recursively for all the child widgets,
+ passing \a destroySubWindows for the \a destroyWindow parameter.
+ To have more control over destruction of subwidgets, destroy
+ subwidgets selectively first.
+
+ This function is usually called from the QWidget destructor.
+*/
+
+/*!
+ \fn QPaintEngine *QWidget::paintEngine() const
+
+ Returns the widget's paint engine.
+
+ Note that this function should not be called explicitly by the
+ user, since it's meant for reimplementation purposes only. The
+ function is called by Qt internally, and the default
+ implementation may not always return a valid pointer.
+*/
+
+/*!
+ \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
+
+ Translates the widget coordinate \a pos to global screen
+ coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
+ the global coordinates of the top-left pixel of the widget.
+
+ \sa mapFromGlobal() mapTo() mapToParent()
+*/
+
+/*!
+ \fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+
+ Translates the global screen coordinate \a pos to widget
+ coordinates.
+
+ \sa mapToGlobal() mapFrom() mapFromParent()
+*/
+
+/*!
+ \fn void QWidget::grabMouse()
+
+ Grabs the mouse input.
+
+ This widget receives all mouse events until releaseMouse() is
+ called; other widgets get no mouse events at all. Keyboard
+ events are not affected. Use grabKeyboard() if you want to grab
+ that.
+
+ \warning Bugs in mouse-grabbing applications very often lock the
+ terminal. Use this function with extreme caution, and consider
+ using the \c -nograb command line option while debugging.
+
+ It is almost never necessary to grab the mouse when using Qt, as
+ Qt grabs and releases it sensibly. In particular, Qt grabs the
+ mouse when a mouse button is pressed and keeps it until the last
+ button is released.
+
+ \note Only visible widgets can grab mouse input. If isVisible()
+ returns false for a widget, that widget cannot call grabMouse().
+
+ \note \bold{(Mac OS X developers)} For \e Cocoa, calling
+ grabMouse() on a widget only works when the mouse is inside the
+ frame of that widget. For \e Carbon, it works outside the widget's
+ frame as well, like for Windows and X11.
+
+ \sa releaseMouse() grabKeyboard() releaseKeyboard()
+*/
+
+/*!
+ \fn void QWidget::grabMouse(const QCursor &cursor)
+ \overload grabMouse()
+
+ Grabs the mouse input and changes the cursor shape.
+
+ The cursor will assume shape \a cursor (for as long as the mouse
+ focus is grabbed) and this widget will be the only one to receive
+ mouse events until releaseMouse() is called().
+
+ \warning Grabbing the mouse might lock the terminal.
+
+ \note \bold{(Mac OS X developers)} See the note in QWidget::grabMouse().
+
+ \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
+*/
+
+/*!
+ \fn void QWidget::releaseMouse()
+
+ Releases the mouse grab.
+
+ \sa grabMouse(), grabKeyboard(), releaseKeyboard()
+*/
+
+/*!
+ \fn void QWidget::grabKeyboard()
+
+ Grabs the keyboard input.
+
+ This widget receives all keyboard events until releaseKeyboard()
+ is called; other widgets get no keyboard events at all. Mouse
+ events are not affected. Use grabMouse() if you want to grab that.
+
+ The focus widget is not affected, except that it doesn't receive
+ any keyboard events. setFocus() moves the focus as usual, but the
+ new focus widget receives keyboard events only after
+ releaseKeyboard() is called.
+
+ If a different widget is currently grabbing keyboard input, that
+ widget's grab is released first.
+
+ \sa releaseKeyboard() grabMouse() releaseMouse() focusWidget()
+*/
+
+/*!
+ \fn void QWidget::releaseKeyboard()
+
+ Releases the keyboard grab.
+
+ \sa grabKeyboard(), grabMouse(), releaseMouse()
+*/
+
+/*!
+ \fn QWidget *QWidget::mouseGrabber()
+
+ Returns the widget that is currently grabbing the mouse input.
+
+ If no widget in this application is currently grabbing the mouse,
+ 0 is returned.
+
+ \sa grabMouse(), keyboardGrabber()
+*/
+
+/*!
+ \fn QWidget *QWidget::keyboardGrabber()
+
+ Returns the widget that is currently grabbing the keyboard input.
+
+ If no widget in this application is currently grabbing the
+ keyboard, 0 is returned.
+
+ \sa grabMouse(), mouseGrabber()
+*/
+
+/*!
+ \fn void QWidget::activateWindow()
+
+ Sets the top-level widget containing this widget to be the active
+ window.
+
+ An active window is a visible top-level window that has the
+ keyboard input focus.
+
+ This function performs the same operation as clicking the mouse on
+ the title bar of a top-level window. On X11, the result depends on
+ the Window Manager. If you want to ensure that the window is
+ stacked on top as well you should also call raise(). Note that the
+ window must be visible, otherwise activateWindow() has no effect.
+
+ On Windows, if you are calling this when the application is not
+ currently the active one then it will not make it the active
+ window. It will change the color of the taskbar entry to indicate
+ that the window has changed in some way. This is because Microsoft
+ does not allow an application to interrupt what the user is currently
+ doing in another application.
+
+ \sa isActiveWindow(), window(), show()
+*/
+
+/*!
+ \fn int QWidget::metric(PaintDeviceMetric m) const
+
+ Internal implementation of the virtual QPaintDevice::metric()
+ function.
+
+ \a m is the metric to get.
+*/
+
+void QWidget::init(QPainter *painter) const
+{
+ const QPalette &pal = palette();
+ painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 0);
+ painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
+ QFont f(font(), const_cast<QWidget *>(this));
+ painter->d_func()->state->deviceFont = f;
+ painter->d_func()->state->font = f;
+}
+
+QPaintDevice *QWidget::redirected(QPoint *offset) const
+{
+ return d_func()->redirected(offset);
+}
+
+QPainter *QWidget::sharedPainter() const
+{
+ // Someone sent a paint event directly to the widget
+ if (!d_func()->redirectDev)
+ return 0;
+
+ QPainter *sp = d_func()->sharedPainter();
+ if (!sp || !sp->isActive())
+ return 0;
+
+ if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
+ return 0;
+
+ return sp;
+}
+
+/*!
+ \fn void QWidget::setMask(const QRegion &region)
+ \overload
+
+ Causes only the parts of the widget which overlap \a region to be
+ visible. If the region includes pixels outside the rect() of the
+ widget, window system controls in that area may or may not be
+ visible, depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ \sa windowOpacity
+*/
+void QWidget::setMask(const QRegion &newMask)
+{
+ Q_D(QWidget);
+
+ d->createExtra();
+ if (newMask == d->extra->mask)
+ return;
+
+#ifndef QT_NO_BACKINGSTORE
+ const QRegion oldMask(d->extra->mask);
+#endif
+
+ d->extra->mask = newMask;
+ d->extra->hasMask = !newMask.isEmpty();
+
+#ifndef QT_MAC_USE_COCOA
+ if (!testAttribute(Qt::WA_WState_Created))
+ return;
+#endif
+
+ d->setMask_sys(newMask);
+
+#ifndef QT_NO_BACKINGSTORE
+ if (!isVisible())
+ return;
+
+ if (!d->extra->hasMask) {
+ // Mask was cleared; update newly exposed area.
+ QRegion expose(rect());
+ expose -= oldMask;
+ if (!expose.isEmpty()) {
+ d->setDirtyOpaqueRegion();
+ update(expose);
+ }
+ return;
+ }
+
+ if (!isWindow()) {
+ // Update newly exposed area on the parent widget.
+ QRegion parentExpose(rect());
+ parentExpose -= newMask;
+ if (!parentExpose.isEmpty()) {
+ d->setDirtyOpaqueRegion();
+ parentExpose.translate(data->crect.topLeft());
+ parentWidget()->update(parentExpose);
+ }
+
+ // Update newly exposed area on this widget
+ if (!oldMask.isEmpty())
+ update(newMask - oldMask);
+ }
+#endif
+}
+
+/*!
+ \fn void QWidget::setMask(const QBitmap &bitmap)
+
+ Causes only the pixels of the widget for which \a bitmap has a
+ corresponding 1 bit to be visible. If the region includes pixels
+ outside the rect() of the widget, window system controls in that
+ area may or may not be visible, depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ The following code shows how an image with an alpha channel can be
+ used to generate a mask for a widget:
+
+ \snippet doc/src/snippets/widget-mask/main.cpp 0
+
+ The label shown by this code is masked using the image it contains,
+ giving the appearance that an irregularly-shaped image is being drawn
+ directly onto the screen.
+
+ Masked widgets receive mouse events only on their visible
+ portions.
+
+ \sa clearMask(), windowOpacity(), {Shaped Clock Example}
+*/
+void QWidget::setMask(const QBitmap &bitmap)
+{
+ setMask(QRegion(bitmap));
+}
+
+/*!
+ \fn void QWidget::clearMask()
+
+ Removes any mask set by setMask().
+
+ \sa setMask()
+*/
+void QWidget::clearMask()
+{
+ setMask(QRegion());
+}
+
+/*! \fn const QX11Info &QWidget::x11Info() const
+ Returns information about the configuration of the X display used to display
+ the widget.
+
+ \warning This function is only available on X11.
+*/
+
+/*! \fn Qt::HANDLE QWidget::x11PictureHandle() const
+ Returns the X11 Picture handle of the widget for XRender
+ support. Use of this function is not portable. This function will
+ return 0 if XRender support is not compiled into Qt, if the
+ XRender extension is not supported on the X11 display, or if the
+ handle could not be created.
+*/
+
+#ifdef Q_OS_SYMBIAN
+void QWidgetPrivate::_q_delayedDestroy(WId winId)
+{
+ delete winId;
+}
+#endif
+
+#if QT_MAC_USE_COCOA
+void QWidgetPrivate::syncUnifiedMode() {
+ // The whole purpose of this method is to keep the unifiedToolbar in sync.
+ // That means making sure we either exchange the drawing methods or we let
+ // the toolbar know that it does not require to draw the baseline.
+ Q_Q(QWidget);
+ // This function makes sense only if this is a top level
+ if(!q->isWindow())
+ return;
+ OSWindowRef window = qt_mac_window_for(q);
+ if(changeMethods) {
+ // Ok, we are in documentMode.
+ if(originalDrawMethod)
+ qt_mac_replaceDrawRect(window, this);
+ } else {
+ if(!originalDrawMethod)
+ qt_mac_replaceDrawRectOriginal(window, this);
+ }
+}
+
+#endif // QT_MAC_USE_COCOA
+
+QT_END_NAMESPACE
+
+#include "moc_qwidget.cpp"
+
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
new file mode 100644
index 0000000000..d14e8652be
--- /dev/null
+++ b/src/widgets/kernel/qwidget.h
@@ -0,0 +1,1091 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGET_H
+#define QWIDGET_H
+
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qmargins.h>
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qfont.h>
+#include <QtGui/qfontmetrics.h>
+#include <QtGui/qfontinfo.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qkeysequence.h>
+
+#ifdef Q_WS_QPA //should this go somewhere else?
+#include <QtGui/qwindow.h>
+#include <QtGui/qwindowformat_qpa.h>
+#endif
+
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qevent.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QLayout;
+class QWSRegionManager;
+class QStyle;
+class QAction;
+class QVariant;
+
+class QActionEvent;
+class QMouseEvent;
+class QWheelEvent;
+class QHoverEvent;
+class QKeyEvent;
+class QFocusEvent;
+class QPaintEvent;
+class QMoveEvent;
+class QResizeEvent;
+class QCloseEvent;
+class QContextMenuEvent;
+class QInputMethodEvent;
+class QTabletEvent;
+class QDragEnterEvent;
+class QDragMoveEvent;
+class QDragLeaveEvent;
+class QDropEvent;
+class QShowEvent;
+class QHideEvent;
+class QInputContext;
+class QIcon;
+class QWindowSurface;
+class QPlatformWindow;
+class QLocale;
+class QGraphicsProxyWidget;
+class QGraphicsEffect;
+class QRasterWindowSurface;
+class QUnifiedToolbarSurface;
+#if defined(Q_WS_X11)
+class QX11Info;
+#endif
+
+class QWidgetData
+{
+public:
+ WId winid;
+ uint widget_attributes;
+ Qt::WindowFlags window_flags;
+ uint window_state : 4;
+ uint focus_policy : 4;
+ uint sizehint_forced :1;
+ uint is_closing :1;
+ uint in_show : 1;
+ uint in_set_window_state : 1;
+ mutable uint fstrut_dirty : 1;
+ uint context_menu_policy : 3;
+ uint window_modality : 2;
+ uint in_destructor : 1;
+ uint unused : 13;
+ QRect crect;
+ mutable QPalette pal;
+ QFont fnt;
+#if defined(Q_WS_QWS)
+// QRegion req_region; // Requested region
+// mutable QRegion paintable_region; // Paintable region
+// mutable bool paintable_region_dirty;// needs to be recalculated
+// mutable QRegion alloc_region; // Allocated region
+// mutable bool alloc_region_dirty; // needs to be recalculated
+// mutable int overlapping_children; // Handle overlapping children
+
+ int alloc_region_index;
+// int alloc_region_revision;
+#endif
+ QRect wrect;
+};
+
+class QWidgetPrivate;
+
+class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidget)
+
+ Q_PROPERTY(bool modal READ isModal)
+ Q_PROPERTY(Qt::WindowModality windowModality READ windowModality WRITE setWindowModality)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QRect frameGeometry READ frameGeometry)
+ Q_PROPERTY(QRect normalGeometry READ normalGeometry)
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int y READ y)
+ Q_PROPERTY(QPoint pos READ pos WRITE move DESIGNABLE false STORED false)
+ Q_PROPERTY(QSize frameSize READ frameSize)
+ Q_PROPERTY(QSize size READ size WRITE resize DESIGNABLE false STORED false)
+ Q_PROPERTY(int width READ width)
+ Q_PROPERTY(int height READ height)
+ Q_PROPERTY(QRect rect READ rect)
+ Q_PROPERTY(QRect childrenRect READ childrenRect)
+ Q_PROPERTY(QRegion childrenRegion READ childrenRegion)
+ Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy)
+ Q_PROPERTY(QSize minimumSize READ minimumSize WRITE setMinimumSize)
+ Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize)
+ Q_PROPERTY(int minimumWidth READ minimumWidth WRITE setMinimumWidth STORED false DESIGNABLE false)
+ Q_PROPERTY(int minimumHeight READ minimumHeight WRITE setMinimumHeight STORED false DESIGNABLE false)
+ Q_PROPERTY(int maximumWidth READ maximumWidth WRITE setMaximumWidth STORED false DESIGNABLE false)
+ Q_PROPERTY(int maximumHeight READ maximumHeight WRITE setMaximumHeight STORED false DESIGNABLE false)
+ Q_PROPERTY(QSize sizeIncrement READ sizeIncrement WRITE setSizeIncrement)
+ Q_PROPERTY(QSize baseSize READ baseSize WRITE setBaseSize)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
+ Q_PROPERTY(QFont font READ font WRITE setFont)
+#ifndef QT_NO_CURSOR
+ Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
+#endif
+ Q_PROPERTY(bool mouseTracking READ hasMouseTracking WRITE setMouseTracking)
+ Q_PROPERTY(bool isActiveWindow READ isActiveWindow)
+ Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
+ Q_PROPERTY(bool focus READ hasFocus)
+ Q_PROPERTY(Qt::ContextMenuPolicy contextMenuPolicy READ contextMenuPolicy WRITE setContextMenuPolicy)
+ Q_PROPERTY(bool updatesEnabled READ updatesEnabled WRITE setUpdatesEnabled DESIGNABLE false)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible DESIGNABLE false)
+ Q_PROPERTY(bool minimized READ isMinimized)
+ Q_PROPERTY(bool maximized READ isMaximized)
+ Q_PROPERTY(bool fullScreen READ isFullScreen)
+ Q_PROPERTY(QSize sizeHint READ sizeHint)
+ Q_PROPERTY(QSize minimumSizeHint READ minimumSizeHint)
+ Q_PROPERTY(bool acceptDrops READ acceptDrops WRITE setAcceptDrops)
+ Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle DESIGNABLE isWindow)
+ Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon DESIGNABLE isWindow)
+ Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText DESIGNABLE isWindow)
+ Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow)
+ Q_PROPERTY(bool windowModified READ isWindowModified WRITE setWindowModified DESIGNABLE isWindow)
+#ifndef QT_NO_TOOLTIP
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
+#endif
+#ifndef QT_NO_STATUSTIP
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
+#endif
+#ifndef QT_NO_WHATSTHIS
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ Q_PROPERTY(QString accessibleName READ accessibleName WRITE setAccessibleName)
+ Q_PROPERTY(QString accessibleDescription READ accessibleDescription WRITE setAccessibleDescription)
+#endif
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
+ QDOC_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
+ Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
+#endif
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale)
+ Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+
+public:
+ enum RenderFlag {
+ DrawWindowBackground = 0x1,
+ DrawChildren = 0x2,
+ IgnoreMask = 0x4
+ };
+ Q_DECLARE_FLAGS(RenderFlags, RenderFlag)
+
+ explicit QWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QWidget(QWidget* parent, const char *name, Qt::WindowFlags f = 0);
+#endif
+ ~QWidget();
+
+ int devType() const;
+
+ WId winId() const;
+ void createWinId(); // internal, going away
+ inline WId internalWinId() const { return data->winid; }
+ WId effectiveWinId() const;
+
+ // GUI style setting
+ QStyle *style() const;
+ void setStyle(QStyle *);
+ // Widget types and states
+
+ bool isTopLevel() const;
+ bool isWindow() const;
+
+ bool isModal() const;
+ Qt::WindowModality windowModality() const;
+ void setWindowModality(Qt::WindowModality windowModality);
+
+ bool isEnabled() const;
+ bool isEnabledTo(QWidget*) const;
+ bool isEnabledToTLW() const;
+
+public Q_SLOTS:
+ void setEnabled(bool);
+ void setDisabled(bool);
+ void setWindowModified(bool);
+
+ // Widget coordinates
+
+public:
+ QRect frameGeometry() const;
+ const QRect &geometry() const;
+ QRect normalGeometry() const;
+
+ int x() const;
+ int y() const;
+ QPoint pos() const;
+ QSize frameSize() const;
+ QSize size() const;
+ inline int width() const;
+ inline int height() const;
+ inline QRect rect() const;
+ QRect childrenRect() const;
+ QRegion childrenRegion() const;
+
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ int minimumWidth() const;
+ int minimumHeight() const;
+ int maximumWidth() const;
+ int maximumHeight() const;
+ void setMinimumSize(const QSize &);
+ void setMinimumSize(int minw, int minh);
+ void setMaximumSize(const QSize &);
+ void setMaximumSize(int maxw, int maxh);
+ void setMinimumWidth(int minw);
+ void setMinimumHeight(int minh);
+ void setMaximumWidth(int maxw);
+ void setMaximumHeight(int maxh);
+
+#ifdef Q_QDOC
+ void setupUi(QWidget *widget);
+#endif
+
+ QSize sizeIncrement() const;
+ void setSizeIncrement(const QSize &);
+ void setSizeIncrement(int w, int h);
+ QSize baseSize() const;
+ void setBaseSize(const QSize &);
+ void setBaseSize(int basew, int baseh);
+
+ void setFixedSize(const QSize &);
+ void setFixedSize(int w, int h);
+ void setFixedWidth(int w);
+ void setFixedHeight(int h);
+
+ // Widget coordinate mapping
+
+ QPoint mapToGlobal(const QPoint &) const;
+ QPoint mapFromGlobal(const QPoint &) const;
+ QPoint mapToParent(const QPoint &) const;
+ QPoint mapFromParent(const QPoint &) const;
+ QPoint mapTo(QWidget *, const QPoint &) const;
+ QPoint mapFrom(QWidget *, const QPoint &) const;
+
+ QWidget *window() const;
+ QWidget *nativeParentWidget() const;
+ inline QWidget *topLevelWidget() const { return window(); }
+
+ // Widget appearance functions
+ const QPalette &palette() const;
+ void setPalette(const QPalette &);
+
+ void setBackgroundRole(QPalette::ColorRole);
+ QPalette::ColorRole backgroundRole() const;
+
+ void setForegroundRole(QPalette::ColorRole);
+ QPalette::ColorRole foregroundRole() const;
+
+ const QFont &font() const;
+ void setFont(const QFont &);
+ QFontMetrics fontMetrics() const;
+ QFontInfo fontInfo() const;
+
+#ifndef QT_NO_CURSOR
+ QCursor cursor() const;
+ void setCursor(const QCursor &);
+ void unsetCursor();
+#endif
+
+ void setMouseTracking(bool enable);
+ bool hasMouseTracking() const;
+ bool underMouse() const;
+
+ void setMask(const QBitmap &);
+ void setMask(const QRegion &);
+ QRegion mask() const;
+ void clearMask();
+
+ void render(QPaintDevice *target, const QPoint &targetOffset = QPoint(),
+ const QRegion &sourceRegion = QRegion(),
+ RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+
+ void render(QPainter *painter, const QPoint &targetOffset = QPoint(),
+ const QRegion &sourceRegion = QRegion(),
+ RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ QGraphicsEffect *graphicsEffect() const;
+ void setGraphicsEffect(QGraphicsEffect *effect);
+#endif //QT_NO_GRAPHICSEFFECT
+
+#ifndef QT_NO_GESTURES
+ void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
+ void ungrabGesture(Qt::GestureType type);
+#endif
+
+public Q_SLOTS:
+ void setWindowTitle(const QString &);
+#ifndef QT_NO_STYLE_STYLESHEET
+ void setStyleSheet(const QString& styleSheet);
+#endif
+public:
+#ifndef QT_NO_STYLE_STYLESHEET
+ QString styleSheet() const;
+#endif
+ QString windowTitle() const;
+ void setWindowIcon(const QIcon &icon);
+ QIcon windowIcon() const;
+ void setWindowIconText(const QString &);
+ QString windowIconText() const;
+ void setWindowRole(const QString &);
+ QString windowRole() const;
+ void setWindowFilePath(const QString &filePath);
+ QString windowFilePath() const;
+
+ void setWindowOpacity(qreal level);
+ qreal windowOpacity() const;
+
+ bool isWindowModified() const;
+#ifndef QT_NO_TOOLTIP
+ void setToolTip(const QString &);
+ QString toolTip() const;
+#endif
+#ifndef QT_NO_STATUSTIP
+ void setStatusTip(const QString &);
+ QString statusTip() const;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ void setWhatsThis(const QString &);
+ QString whatsThis() const;
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QString accessibleName() const;
+ void setAccessibleName(const QString &name);
+ QString accessibleDescription() const;
+ void setAccessibleDescription(const QString &description);
+#endif
+
+ void setLayoutDirection(Qt::LayoutDirection direction);
+ Qt::LayoutDirection layoutDirection() const;
+ void unsetLayoutDirection();
+
+ void setLocale(const QLocale &locale);
+ QLocale locale() const;
+ void unsetLocale();
+
+ inline bool isRightToLeft() const { return layoutDirection() == Qt::RightToLeft; }
+ inline bool isLeftToRight() const { return layoutDirection() == Qt::LeftToRight; }
+
+public Q_SLOTS:
+ inline void setFocus() { setFocus(Qt::OtherFocusReason); }
+
+public:
+ bool isActiveWindow() const;
+ void activateWindow();
+ void clearFocus();
+
+ void setFocus(Qt::FocusReason reason);
+ Qt::FocusPolicy focusPolicy() const;
+ void setFocusPolicy(Qt::FocusPolicy policy);
+ bool hasFocus() const;
+ static void setTabOrder(QWidget *, QWidget *);
+ void setFocusProxy(QWidget *);
+ QWidget *focusProxy() const;
+ Qt::ContextMenuPolicy contextMenuPolicy() const;
+ void setContextMenuPolicy(Qt::ContextMenuPolicy policy);
+
+ // Grab functions
+ void grabMouse();
+#ifndef QT_NO_CURSOR
+ void grabMouse(const QCursor &);
+#endif
+ void releaseMouse();
+ void grabKeyboard();
+ void releaseKeyboard();
+#ifndef QT_NO_SHORTCUT
+ int grabShortcut(const QKeySequence &key, Qt::ShortcutContext context = Qt::WindowShortcut);
+ void releaseShortcut(int id);
+ void setShortcutEnabled(int id, bool enable = true);
+ void setShortcutAutoRepeat(int id, bool enable = true);
+#endif
+ static QWidget *mouseGrabber();
+ static QWidget *keyboardGrabber();
+
+ // Update/refresh functions
+ inline bool updatesEnabled() const;
+ void setUpdatesEnabled(bool enable);
+
+#if 0 //def Q_WS_QWS
+ void repaintUnclipped(const QRegion &, bool erase = true);
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *graphicsProxyWidget() const;
+#endif
+
+public Q_SLOTS:
+ void update();
+ void repaint();
+
+public:
+ inline void update(int x, int y, int w, int h);
+ void update(const QRect&);
+ void update(const QRegion&);
+
+ void repaint(int x, int y, int w, int h);
+ void repaint(const QRect &);
+ void repaint(const QRegion &);
+
+public Q_SLOTS:
+ // Widget management functions
+
+ virtual void setVisible(bool visible);
+ inline void setHidden(bool hidden) { setVisible(!hidden); }
+#ifndef Q_WS_WINCE
+ inline void show() { setVisible(true); }
+#else
+ void show();
+#endif
+ inline void hide() { setVisible(false); }
+ inline QT_MOC_COMPAT void setShown(bool shown) { setVisible(shown); }
+
+ void showMinimized();
+ void showMaximized();
+ void showFullScreen();
+ void showNormal();
+
+ bool close();
+ void raise();
+ void lower();
+
+public:
+ void stackUnder(QWidget*);
+ void move(int x, int y);
+ void move(const QPoint &);
+ void resize(int w, int h);
+ void resize(const QSize &);
+ inline void setGeometry(int x, int y, int w, int h);
+ void setGeometry(const QRect &);
+ QByteArray saveGeometry() const;
+ bool restoreGeometry(const QByteArray &geometry);
+ void adjustSize();
+ bool isVisible() const;
+ bool isVisibleTo(QWidget*) const;
+ // ### Qt 5: bool isVisibleTo(_const_ QWidget *) const
+ inline bool isHidden() const;
+
+ bool isMinimized() const;
+ bool isMaximized() const;
+ bool isFullScreen() const;
+
+ Qt::WindowStates windowState() const;
+ void setWindowState(Qt::WindowStates state);
+ void overrideWindowState(Qt::WindowStates state);
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+ QSizePolicy sizePolicy() const;
+ void setSizePolicy(QSizePolicy);
+ inline void setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical);
+ virtual int heightForWidth(int) const;
+
+ QRegion visibleRegion() const;
+
+ void setContentsMargins(int left, int top, int right, int bottom);
+ void setContentsMargins(const QMargins &margins);
+ void getContentsMargins(int *left, int *top, int *right, int *bottom) const;
+ QMargins contentsMargins() const;
+
+ QRect contentsRect() const;
+
+public:
+ QLayout *layout() const;
+ void setLayout(QLayout *);
+ void updateGeometry();
+
+ void setParent(QWidget *parent);
+ void setParent(QWidget *parent, Qt::WindowFlags f);
+
+ void scroll(int dx, int dy);
+ void scroll(int dx, int dy, const QRect&);
+
+ // Misc. functions
+
+ QWidget *focusWidget() const;
+ QWidget *nextInFocusChain() const;
+ QWidget *previousInFocusChain() const;
+
+ // drag and drop
+ bool acceptDrops() const;
+ void setAcceptDrops(bool on);
+
+#ifndef QT_NO_ACTION
+ //actions
+ void addAction(QAction *action);
+ void addActions(QList<QAction*> actions);
+ void insertAction(QAction *before, QAction *action);
+ void insertActions(QAction *before, QList<QAction*> actions);
+ void removeAction(QAction *action);
+ QList<QAction*> actions() const;
+#endif
+
+ QWidget *parentWidget() const;
+
+ void setWindowFlags(Qt::WindowFlags type);
+ inline Qt::WindowFlags windowFlags() const;
+ void overrideWindowFlags(Qt::WindowFlags type);
+
+ inline Qt::WindowType windowType() const;
+
+ static QWidget *find(WId);
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QWidgetMapper *wmapper();
+#endif
+ inline QWidget *childAt(int x, int y) const;
+ QWidget *childAt(const QPoint &p) const;
+
+#if defined(Q_WS_X11)
+ const QX11Info &x11Info() const;
+ Qt::HANDLE x11PictureHandle() const;
+#endif
+
+#if defined(Q_WS_MAC)
+ Qt::HANDLE macQDHandle() const;
+ Qt::HANDLE macCGHandle() const;
+#endif
+
+#if defined(Q_WS_WIN)
+ HDC getDC() const;
+ void releaseDC(HDC) const;
+#else
+ Qt::HANDLE handle() const;
+#endif
+
+ void setAttribute(Qt::WidgetAttribute, bool on = true);
+ inline bool testAttribute(Qt::WidgetAttribute) const;
+
+ QPaintEngine *paintEngine() const;
+
+ void ensurePolished() const;
+
+ QInputContext *inputContext();
+ void setInputContext(QInputContext *);
+
+ bool isAncestorOf(const QWidget *child) const;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ bool hasEditFocus() const;
+ void setEditFocus(bool on);
+#endif
+
+ bool autoFillBackground() const;
+ void setAutoFillBackground(bool enabled);
+
+ void setWindowSurface(QWindowSurface *surface);
+ QWindowSurface *windowSurface() const;
+
+#if defined(Q_WS_QPA)
+ void setWindowHandle(QWindow *window);
+ QWindow *windowHandle() const;
+
+ friend class QDesktopScreenWidget;
+#endif
+
+Q_SIGNALS:
+ void customContextMenuRequested(const QPoint &pos);
+
+protected:
+ // Event handlers
+ bool event(QEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent(QWheelEvent *);
+#endif
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+ virtual void enterEvent(QEvent *);
+ virtual void leaveEvent(QEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ virtual void moveEvent(QMoveEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void closeEvent(QCloseEvent *);
+#ifndef QT_NO_CONTEXTMENU
+ virtual void contextMenuEvent(QContextMenuEvent *);
+#endif
+#ifndef QT_NO_TABLETEVENT
+ virtual void tabletEvent(QTabletEvent *);
+#endif
+#ifndef QT_NO_ACTION
+ virtual void actionEvent(QActionEvent *);
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragMoveEvent(QDragMoveEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void dropEvent(QDropEvent *);
+#endif
+
+ virtual void showEvent(QShowEvent *);
+ virtual void hideEvent(QHideEvent *);
+
+#if defined(Q_WS_MAC)
+ virtual bool macEvent(EventHandlerCallRef, EventRef);
+#endif
+#if defined(Q_WS_WIN)
+ virtual bool winEvent(MSG *message, long *result);
+#endif
+#if defined(Q_WS_X11)
+ virtual bool x11Event(XEvent *);
+#endif
+#if defined(Q_WS_QWS)
+ virtual bool qwsEvent(QWSEvent *);
+#endif
+
+ // Misc. protected functions
+ virtual void changeEvent(QEvent *);
+
+ int metric(PaintDeviceMetric) const;
+ void init(QPainter *painter) const;
+ QPaintDevice *redirected(QPoint *offset) const;
+ QPainter *sharedPainter() const;
+
+ virtual void inputMethodEvent(QInputMethodEvent *);
+public:
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
+protected:
+ void resetInputContext();
+protected Q_SLOTS:
+ void updateMicroFocus();
+protected:
+
+ void create(WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true);
+ void destroy(bool destroyWindow = true,
+ bool destroySubWindows = true);
+
+ virtual bool focusNextPrevChild(bool next);
+ inline bool focusNextChild() { return focusNextPrevChild(true); }
+ inline bool focusPreviousChild() { return focusNextPrevChild(false); }
+
+protected:
+ QWidget(QWidgetPrivate &d, QWidget* parent, Qt::WindowFlags f);
+private:
+
+ bool testAttribute_helper(Qt::WidgetAttribute) const;
+
+ QLayout *takeLayout();
+
+ friend class QBackingStoreDevice;
+ friend class QWidgetBackingStore;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QGuiApplication;
+ friend class QGuiApplicationPrivate;
+ friend class QBaseApplication;
+ friend class QPainter;
+ friend class QPainterPrivate;
+ friend class QPixmap; // for QPixmap::fill()
+ friend class QFontMetrics;
+ friend class QFontInfo;
+ friend class QETWidget;
+ friend class QLayout;
+ friend class QWidgetItem;
+ friend class QWidgetItemV2;
+ friend class QGLContext;
+ friend class QGLWidget;
+ friend class QGLWindowSurface;
+ friend class QX11PaintEngine;
+ friend class QWin32PaintEngine;
+ friend class QShortcutPrivate;
+ friend class QShortcutMap;
+ friend class QWindowSurface;
+ friend class QGraphicsProxyWidget;
+ friend class QGraphicsProxyWidgetPrivate;
+ friend class QStyleSheetStyle;
+ friend struct QWidgetExceptionCleaner;
+ friend class QWidgetWindow;
+#ifndef QT_NO_GESTURES
+ friend class QGestureManager;
+ friend class QWinNativePanGestureRecognizer;
+#endif // QT_NO_GESTURES
+ friend class QWidgetEffectSourcePrivate;
+
+#ifdef Q_WS_MAC
+ friend class QCoreGraphicsPaintEnginePrivate;
+ friend QPoint qt_mac_posInWindow(const QWidget *w);
+ friend OSWindowRef qt_mac_window_for(const QWidget *w);
+ friend bool qt_mac_is_metal(const QWidget *w);
+ friend OSViewRef qt_mac_nativeview_for(const QWidget *w);
+ friend void qt_event_request_window_change(QWidget *widget);
+ friend bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref);
+ friend class QRasterWindowSurface;
+ friend class QUnifiedToolbarSurface;
+#endif
+#ifdef Q_WS_QWS
+ friend class QWSBackingStore;
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+ friend class QWSWindowSurface;
+ friend class QScreen;
+ friend class QVNCScreen;
+ friend bool isWidgetOpaque(const QWidget *);
+ friend class QGLWidgetPrivate;
+#endif
+#ifdef Q_OS_SYMBIAN
+ friend class QSymbianControl;
+ friend class QS60WindowSurface;
+#endif
+#ifdef Q_WS_X11
+ friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
+ friend void qt_net_remove_user_time(QWidget *tlw);
+ friend void qt_set_winid_on_widget(QWidget*, Qt::HANDLE);
+#endif
+
+ friend Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget);
+ friend Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget);
+
+private:
+ Q_DISABLE_COPY(QWidget)
+ Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden())
+#ifdef Q_OS_SYMBIAN
+ Q_PRIVATE_SLOT(d_func(), void _q_delayedDestroy(WId winId))
+#endif
+
+ QWidgetData *data;
+
+#ifdef QT3_SUPPORT
+public:
+ inline QT3_SUPPORT bool isUpdatesEnabled() const { return updatesEnabled(); }
+ QT3_SUPPORT QStyle *setStyle(const QString&);
+ inline QT3_SUPPORT bool isVisibleToTLW() const;
+ QT3_SUPPORT QRect visibleRect() const;
+ inline QT3_SUPPORT void iconify() { showMinimized(); }
+ inline QT3_SUPPORT void constPolish() const { ensurePolished(); }
+ inline QT3_SUPPORT void polish() { ensurePolished(); }
+ inline QT3_SUPPORT void reparent(QWidget *parent, Qt::WindowFlags f, const QPoint &p, bool showIt=false)
+ { setParent(parent, f); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void reparent(QWidget *parent, const QPoint &p, bool showIt=false)
+ { setParent(parent, windowFlags() & ~Qt::WindowType_Mask); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void recreate(QWidget *parent, Qt::WindowFlags f, const QPoint & p, bool showIt=false)
+ { setParent(parent, f); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver, bool hfw)
+ { QSizePolicy sp(hor, ver); sp.setHeightForWidth(hfw); setSizePolicy(sp);}
+ inline QT3_SUPPORT bool hasMouse() const { return testAttribute(Qt::WA_UnderMouse); }
+#ifndef QT_NO_CURSOR
+ inline QT3_SUPPORT bool ownCursor() const { return testAttribute(Qt::WA_SetCursor); }
+#endif
+ inline QT3_SUPPORT bool ownFont() const { return testAttribute(Qt::WA_SetFont); }
+ inline QT3_SUPPORT void unsetFont() { setFont(QFont()); }
+ inline QT3_SUPPORT bool ownPalette() const { return testAttribute(Qt::WA_SetPalette); }
+ inline QT3_SUPPORT void unsetPalette() { setPalette(QPalette()); }
+ Qt::BackgroundMode QT3_SUPPORT backgroundMode() const;
+ void QT3_SUPPORT setBackgroundMode(Qt::BackgroundMode, Qt::BackgroundMode = Qt::PaletteBackground);
+ const QT3_SUPPORT QColor &eraseColor() const;
+ void QT3_SUPPORT setEraseColor(const QColor &);
+ const QT3_SUPPORT QColor &foregroundColor() const;
+ const QT3_SUPPORT QPixmap *erasePixmap() const;
+ void QT3_SUPPORT setErasePixmap(const QPixmap &);
+ const QT3_SUPPORT QColor &paletteForegroundColor() const;
+ void QT3_SUPPORT setPaletteForegroundColor(const QColor &);
+ const QT3_SUPPORT QColor &paletteBackgroundColor() const;
+ void QT3_SUPPORT setPaletteBackgroundColor(const QColor &);
+ const QT3_SUPPORT QPixmap *paletteBackgroundPixmap() const;
+ void QT3_SUPPORT setPaletteBackgroundPixmap(const QPixmap &);
+ const QT3_SUPPORT QBrush& backgroundBrush() const;
+ const QT3_SUPPORT QColor &backgroundColor() const;
+ const QT3_SUPPORT QPixmap *backgroundPixmap() const;
+ void QT3_SUPPORT setBackgroundPixmap(const QPixmap &);
+ QT3_SUPPORT void setBackgroundColor(const QColor &);
+ QT3_SUPPORT QWidget *parentWidget(bool sameWindow) const;
+ inline QT3_SUPPORT void setKeyCompression(bool b) { setAttribute(Qt::WA_KeyCompression, b); }
+ inline QT3_SUPPORT void setFont(const QFont &f, bool) { setFont(f); }
+ inline QT3_SUPPORT void setPalette(const QPalette &p, bool) { setPalette(p); }
+ enum BackgroundOrigin { WidgetOrigin, ParentOrigin, WindowOrigin, AncestorOrigin };
+ inline QT3_SUPPORT void setBackgroundOrigin(BackgroundOrigin) {}
+ inline QT3_SUPPORT BackgroundOrigin backgroundOrigin() const { return WindowOrigin; }
+ inline QT3_SUPPORT QPoint backgroundOffset() const { return QPoint(); }
+ inline QT3_SUPPORT void repaint(bool) { repaint(); }
+ inline QT3_SUPPORT void repaint(int x, int y, int w, int h, bool) { repaint(x,y,w,h); }
+ inline QT3_SUPPORT void repaint(const QRect &r, bool) { repaint(r); }
+ inline QT3_SUPPORT void repaint(const QRegion &rgn, bool) { repaint(rgn); }
+ QT3_SUPPORT void erase();
+ inline QT3_SUPPORT void erase(int x, int y, int w, int h) { erase_helper(x, y, w, h); }
+ QT3_SUPPORT void erase(const QRect &);
+ QT3_SUPPORT void erase(const QRegion &);
+ QT3_SUPPORT void drawText(const QPoint &p, const QString &s)
+ { drawText_helper(p.x(), p.y(), s); }
+ inline QT3_SUPPORT void drawText(int x, int y, const QString &s)
+ { drawText_helper(x, y, s); }
+ QT3_SUPPORT bool close(bool);
+ inline QT3_SUPPORT QWidget *childAt(int x, int y, bool includeThis) const
+ {
+ QWidget *w = childAt(x, y);
+ return w ? w : ((includeThis && rect().contains(x,y))?const_cast<QWidget*>(this):0);
+ }
+ inline QT3_SUPPORT QWidget *childAt(const QPoint &p, bool includeThis) const
+ {
+ QWidget *w = childAt(p);
+ return w ? w : ((includeThis && rect().contains(p))?const_cast<QWidget*>(this):0);
+ }
+ inline QT3_SUPPORT void setCaption(const QString &c) { setWindowTitle(c); }
+ QT3_SUPPORT void setIcon(const QPixmap &i);
+ inline QT3_SUPPORT void setIconText(const QString &it) { setWindowIconText(it); }
+ inline QT3_SUPPORT QString caption() const { return windowTitle(); }
+ QT3_SUPPORT const QPixmap *icon() const;
+ inline QT3_SUPPORT QString iconText() const { return windowIconText(); }
+ inline QT3_SUPPORT void setInputMethodEnabled(bool b) { setAttribute(Qt::WA_InputMethodEnabled, b); }
+ inline QT3_SUPPORT bool isInputMethodEnabled() const { return testAttribute(Qt::WA_InputMethodEnabled); }
+ inline QT3_SUPPORT void setActiveWindow() { activateWindow(); }
+ inline QT3_SUPPORT bool isShown() const { return !isHidden(); }
+ inline QT3_SUPPORT bool isDialog() const { return windowType() == Qt::Dialog; }
+ inline QT3_SUPPORT bool isPopup() const { return windowType() == Qt::Popup; }
+ inline QT3_SUPPORT bool isDesktop() const { return windowType() == Qt::Desktop; }
+
+
+private:
+ void drawText_helper(int x, int y, const QString &);
+ void erase_helper(int x, int y, int w, int h);
+#endif // QT3_SUPPORT
+
+protected:
+ virtual void styleChange(QStyle&); // compat
+ virtual void enabledChange(bool); // compat
+ virtual void paletteChange(const QPalette &); // compat
+ virtual void fontChange(const QFont &); // compat
+ virtual void windowActivationChange(bool); // compat
+ virtual void languageChange(); // compat
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags)
+
+template <> inline QWidget *qobject_cast<QWidget*>(QObject *o)
+{
+ if (!o || !o->isWidgetType()) return 0;
+ return static_cast<QWidget*>(o);
+}
+template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o)
+{
+ if (!o || !o->isWidgetType()) return 0;
+ return static_cast<const QWidget*>(o);
+}
+
+inline QWidget *QWidget::childAt(int ax, int ay) const
+{ return childAt(QPoint(ax, ay)); }
+
+inline Qt::WindowType QWidget::windowType() const
+{ return static_cast<Qt::WindowType>(int(data->window_flags & Qt::WindowType_Mask)); }
+inline Qt::WindowFlags QWidget::windowFlags() const
+{ return data->window_flags; }
+
+inline bool QWidget::isTopLevel() const
+{ return (windowType() & Qt::Window); }
+
+inline bool QWidget::isWindow() const
+{ return (windowType() & Qt::Window); }
+
+inline bool QWidget::isEnabled() const
+{ return !testAttribute(Qt::WA_Disabled); }
+
+inline bool QWidget::isModal() const
+{ return data->window_modality != Qt::NonModal; }
+
+inline bool QWidget::isEnabledToTLW() const
+{ return isEnabled(); }
+
+inline int QWidget::minimumWidth() const
+{ return minimumSize().width(); }
+
+inline int QWidget::minimumHeight() const
+{ return minimumSize().height(); }
+
+inline int QWidget::maximumWidth() const
+{ return maximumSize().width(); }
+
+inline int QWidget::maximumHeight() const
+{ return maximumSize().height(); }
+
+inline void QWidget::setMinimumSize(const QSize &s)
+{ setMinimumSize(s.width(),s.height()); }
+
+inline void QWidget::setMaximumSize(const QSize &s)
+{ setMaximumSize(s.width(),s.height()); }
+
+inline void QWidget::setSizeIncrement(const QSize &s)
+{ setSizeIncrement(s.width(),s.height()); }
+
+inline void QWidget::setBaseSize(const QSize &s)
+{ setBaseSize(s.width(),s.height()); }
+
+inline const QFont &QWidget::font() const
+{ return data->fnt; }
+
+inline QFontMetrics QWidget::fontMetrics() const
+{ return QFontMetrics(data->fnt); }
+
+inline QFontInfo QWidget::fontInfo() const
+{ return QFontInfo(data->fnt); }
+
+inline void QWidget::setMouseTracking(bool enable)
+{ setAttribute(Qt::WA_MouseTracking, enable); }
+
+inline bool QWidget::hasMouseTracking() const
+{ return testAttribute(Qt::WA_MouseTracking); }
+
+inline bool QWidget::underMouse() const
+{ return testAttribute(Qt::WA_UnderMouse); }
+
+inline bool QWidget::updatesEnabled() const
+{ return !testAttribute(Qt::WA_UpdatesDisabled); }
+
+inline void QWidget::update(int ax, int ay, int aw, int ah)
+{ update(QRect(ax, ay, aw, ah)); }
+
+inline bool QWidget::isVisible() const
+{ return testAttribute(Qt::WA_WState_Visible); }
+
+inline bool QWidget::isHidden() const
+{ return testAttribute(Qt::WA_WState_Hidden); }
+
+inline void QWidget::move(int ax, int ay)
+{ move(QPoint(ax, ay)); }
+
+inline void QWidget::resize(int w, int h)
+{ resize(QSize(w, h)); }
+
+inline void QWidget::setGeometry(int ax, int ay, int aw, int ah)
+{ setGeometry(QRect(ax, ay, aw, ah)); }
+
+inline QRect QWidget::rect() const
+{ return QRect(0,0,data->crect.width(),data->crect.height()); }
+
+inline const QRect &QWidget::geometry() const
+{ return data->crect; }
+
+inline QSize QWidget::size() const
+{ return data->crect.size(); }
+
+inline int QWidget::width() const
+{ return data->crect.width(); }
+
+inline int QWidget::height() const
+{ return data->crect.height(); }
+
+inline QWidget *QWidget::parentWidget() const
+{ return static_cast<QWidget *>(QObject::parent()); }
+
+inline void QWidget::setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver)
+{ setSizePolicy(QSizePolicy(hor, ver)); }
+
+inline bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
+{
+ if (attribute < int(8*sizeof(uint)))
+ return data->widget_attributes & (1<<attribute);
+ return testAttribute_helper(attribute);
+}
+
+#ifdef QT3_SUPPORT
+inline bool QWidget::isVisibleToTLW() const
+{ return isVisible(); }
+inline QWidget *QWidget::parentWidget(bool sameWindow) const
+{
+ if (sameWindow && isWindow())
+ return 0;
+ return static_cast<QWidget *>(QObject::parent());
+}
+inline void QWidget::setPaletteForegroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(foregroundRole(), c); setPalette(p); }
+inline const QBrush& QWidget::backgroundBrush() const { return palette().brush(backgroundRole()); }
+inline void QWidget::setBackgroundPixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline const QPixmap *QWidget::backgroundPixmap() const { return 0; }
+inline void QWidget::setBackgroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QColor & QWidget::backgroundColor() const { return palette().color(backgroundRole()); }
+inline const QColor &QWidget::foregroundColor() const { return palette().color(foregroundRole());}
+inline const QColor &QWidget::eraseColor() const { return palette().color(backgroundRole()); }
+inline void QWidget::setEraseColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QPixmap *QWidget::erasePixmap() const { return 0; }
+inline void QWidget::setErasePixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline const QColor &QWidget::paletteForegroundColor() const { return palette().color(foregroundRole());}
+inline const QColor &QWidget::paletteBackgroundColor() const { return palette().color(backgroundRole()); }
+inline void QWidget::setPaletteBackgroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QPixmap *QWidget::paletteBackgroundPixmap() const
+{ return 0; }
+inline void QWidget::setPaletteBackgroundPixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline QT3_SUPPORT void QWidget::erase() { erase_helper(0, 0, data->crect.width(), data->crect.height()); }
+inline QT3_SUPPORT void QWidget::erase(const QRect &r) { erase_helper(r.x(), r.y(), r.width(), r.height()); }
+#endif
+
+#define QWIDGETSIZE_MAX ((1<<24)-1)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWIDGET_H
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
new file mode 100644
index 0000000000..7826cab795
--- /dev/null
+++ b/src/widgets/kernel/qwidget_p.h
@@ -0,0 +1,1034 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGET_P_H
+#define QWIDGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qwidget.h"
+#include "private/qobject_p.h"
+#include "QtCore/qrect.h"
+#include "QtCore/qlocale.h"
+#include "QtCore/qset.h"
+#include "QtGui/qregion.h"
+#include "QtGui/qsizepolicy.h"
+#include "QtGui/qstyle.h"
+#include "QtGui/qapplication.h"
+#include <private/qgraphicseffect_p.h>
+#include "QtGui/qgraphicsproxywidget.h"
+#include "QtGui/qgraphicsscene.h"
+#include "QtGui/qgraphicsview.h"
+#include <private/qgesture_p.h>
+
+#ifdef Q_WS_WIN
+#include "QtCore/qt_windows.h"
+#include <private/qdnd_p.h>
+#endif // Q_WS_WIN
+
+#ifdef Q_WS_X11
+#include "QtGui/qx11info_x11.h"
+#endif
+
+#ifdef Q_WS_MAC
+#include <private/qt_mac_p.h>
+#endif
+
+#if defined(Q_WS_QWS)
+#include "QtGui/qinputcontext.h"
+#include "QtGui/qscreen_qws.h"
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+class RDrawableWindow;
+class CCoeControl;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Extra QWidget data
+// - to minimize memory usage for members that are seldom used.
+// - top-level widgets have extra extra data to reduce cost further
+#if defined(Q_WS_QWS)
+class QWSManager;
+#endif
+#if defined(Q_WS_MAC)
+class QCoreGraphicsPaintEnginePrivate;
+#endif
+#if defined(Q_WS_QPA)
+class QWidgetWindow;
+#endif
+class QPaintEngine;
+class QPixmap;
+class QWidgetBackingStore;
+class QGraphicsProxyWidget;
+class QWidgetItemV2;
+
+class QStyle;
+
+class QUnifiedToolbarSurface;
+
+class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker
+{
+
+public:
+ QWidgetBackingStoreTracker();
+ ~QWidgetBackingStoreTracker();
+
+ void create(QWidget *tlw);
+ void destroy();
+
+ void registerWidget(QWidget *w);
+ void unregisterWidget(QWidget *w);
+ void unregisterWidgetSubtree(QWidget *w);
+
+ inline QWidgetBackingStore* data()
+ {
+ return m_ptr;
+ }
+
+ inline QWidgetBackingStore* operator->()
+ {
+ return m_ptr;
+ }
+
+ inline QWidgetBackingStore& operator*()
+ {
+ return *m_ptr;
+ }
+
+ inline operator bool() const
+ {
+ return (0 != m_ptr);
+ }
+
+private:
+ Q_DISABLE_COPY(QWidgetBackingStoreTracker)
+
+private:
+ QWidgetBackingStore* m_ptr;
+ QSet<QWidget *> m_widgets;
+};
+
+struct QTLWExtra {
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ QIcon *icon; // widget icon
+ QPixmap *iconPixmap;
+ QWidgetBackingStoreTracker backingStore;
+ QWindowSurface *windowSurface;
+ QPainter *sharedPainter;
+
+ // Implicit pointers (shared_null).
+ QString caption; // widget caption
+ QString iconText; // widget icon text
+ QString role; // widget role
+ QString filePath; // widget file path
+
+ // Other variables.
+ short incw, inch; // size increments
+ short basew, baseh; // base sizes
+ // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
+ QRect frameStrut;
+ QRect normalGeometry; // used by showMin/maximized/FullScreen
+ Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
+
+ // *************************** Cross-platform bit fields ****************************
+ uint opacity : 8;
+ uint posFromMove : 1;
+ uint sizeAdjusted : 1;
+ uint inTopLevelResize : 1;
+ uint inRepaint : 1;
+ uint embedded : 1;
+
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
+ uint spont_unmapped: 1; // window was spontaneously unmapped
+ uint dnd : 1; // DND properties installed
+ uint validWMState : 1; // is WM_STATE valid?
+ uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet
+ WId parentWinId; // parent window Id (valid after reparenting)
+ WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom
+ QPoint fullScreenOffset;
+#ifndef QT_NO_XSYNC
+ WId syncUpdateCounter;
+ ulong syncRequestTimestamp;
+ qint32 newCounterValueHi;
+ quint32 newCounterValueLo;
+#endif
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered.
+ HICON winIconBig; // internal big Windows icon
+ HICON winIconSmall; // internal small Windows icon
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ uint resizer : 4;
+ uint isSetGeometry : 1;
+ uint isMove : 1;
+ quint32 wattr;
+ quint32 wclass;
+ WindowGroupRef group;
+ IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
+ quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
+#ifdef QT_MAC_USE_COCOA
+ // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and
+ // manually resized.
+ // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the
+ // starting position as 0,0 instead of the normal starting position.
+ bool wasMaximized;
+#endif // QT_MAC_USE_COCOA
+
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+#ifndef QT_NO_QWS_MANAGER
+ QWSManager *qwsManager;
+#endif
+#elif defined(Q_OS_SYMBIAN)
+ uint inExpose : 1; // Prevents drawing recursion
+ uint nativeWindowTransparencyEnabled : 1; // Tracks native window transparency
+#elif defined(Q_WS_QPA)
+ QWidgetWindow *window;
+ quint32 screenIndex; // index in qplatformscreenlist
+#endif
+};
+
+struct QWExtra {
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ void *glContext; // if the widget is hijacked by QGLWindowSurface
+ QTLWExtra *topextra; // only useful for TLWs
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
+#endif
+#ifndef QT_NO_CURSOR
+ QCursor *curs;
+#endif
+ QPointer<QStyle> style;
+ QPointer<QWidget> focus_proxy;
+
+ // Implicit pointers (shared_empty/shared_null).
+ QRegion mask; // widget mask
+ QString styleSheet;
+
+ // Other variables.
+ qint32 minw;
+ qint32 minh; // minimum size
+ qint32 maxw;
+ qint32 maxh; // maximum size
+ quint16 customDpiX;
+ quint16 customDpiY;
+ QSize staticContentsSize;
+
+ // *************************** Cross-platform bit fields ****************************
+ uint explicitMinSize : 2;
+ uint explicitMaxSize : 2;
+ uint autoFillBackground : 1;
+ uint nativeChildrenForced : 1;
+ uint inRenderWithPainter : 1;
+ uint hasMask : 1;
+
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *dropTarget; // drop target
+ QList<QPointer<QWidget> > oleDropWidgets;
+#endif
+#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11
+ uint compress_events : 1;
+ WId xDndProxy; // XDND forwarding to embedded windows
+#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC
+#ifdef QT_MAC_USE_COCOA
+ // Cocoa Mask stuff
+ QImage maskBits;
+ CGImageRef imageMask;
+#endif
+#elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian
+ uint activated : 1; // RWindowBase::Activated has been called
+
+ /**
+ * If this bit is set, each native widget receives the signals from the
+ * Symbian control immediately before and immediately after draw ops are
+ * sent to the window server for this control:
+ * void beginNativePaintEvent(const QRect &paintRect);
+ * void endNativePaintEvent(const QRect &paintRect);
+ */
+ uint receiveNativePaintEvents : 1;
+
+ /**
+ * Defines the behaviour of QSymbianControl::Draw.
+ */
+ enum NativePaintMode {
+ /**
+ * Normal drawing mode: blits the required region of the backing store
+ * via WSERV.
+ */
+ Blit,
+
+ /**
+ * Disable drawing for this widget.
+ */
+ Disable,
+
+ /**
+ * Paint zeros into the WSERV framebuffer, using BitGDI APIs. For windows
+ * with an EColor16MU display mode, zero is written only into the R, G and B
+ * channels of the pixel.
+ */
+ ZeroFill,
+
+ /**
+ * Blit backing store, propagating alpha channel into the framebuffer.
+ */
+ BlitWriteAlpha,
+
+ Default = Blit
+ };
+
+ NativePaintMode nativePaintMode;
+
+#endif
+};
+
+/*!
+ \internal
+
+ Returns true if \a p or any of its parents enable the
+ Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and
+ QWidget::setParent() to determine whether it's necessary to embed the
+ widget into a QGraphicsProxyWidget or not.
+*/
+static inline bool bypassGraphicsProxyWidget(const QWidget *p)
+{
+ while (p) {
+ if (p->windowFlags() & Qt::BypassGraphicsProxyWidget)
+ return true;
+ p = p->parentWidget();
+ }
+ return false;
+}
+
+class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QWidget)
+
+public:
+ // *************************** Cross-platform ***************************************
+ enum DrawWidgetFlags {
+ DrawAsRoot = 0x01,
+ DrawPaintOnScreen = 0x02,
+ DrawRecursive = 0x04,
+ DrawInvisible = 0x08,
+ DontSubtractOpaqueChildren = 0x10,
+ DontSetCompositionMode = 0x20,
+ DontDrawOpaqueChildren = 0x40,
+ DontDrawNativeChildren = 0x80
+ };
+
+ enum CloseMode {
+ CloseNoEvent,
+ CloseWithEvent,
+ CloseWithSpontaneousEvent
+ };
+
+ enum Direction {
+ DirectionNorth = 0x01,
+ DirectionEast = 0x10,
+ DirectionSouth = 0x02,
+ DirectionWest = 0x20
+ };
+
+ // Functions.
+ explicit QWidgetPrivate(int version = QObjectPrivateVersion);
+ ~QWidgetPrivate();
+
+ QWExtra *extraData() const;
+ QTLWExtra *topData() const;
+ QTLWExtra *maybeTopData() const;
+ QPainter *sharedPainter() const;
+ void setSharedPainter(QPainter *painter);
+ QWidgetBackingStore *maybeBackingStore() const;
+ void init(QWidget *desktopWidget, Qt::WindowFlags f);
+ void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
+ void createRecursively();
+ void createWinId(WId id = 0);
+
+ void createTLExtra();
+ void createExtra();
+ void deleteExtra();
+ void createSysExtra();
+ void deleteSysExtra();
+ void createTLSysExtra();
+ void deleteTLSysExtra();
+ void updateSystemBackground();
+ void propagatePaletteChange();
+
+ void setPalette_helper(const QPalette &);
+ void resolvePalette();
+ QPalette naturalWidgetPalette(uint inheritedMask) const;
+
+ void setMask_sys(const QRegion &);
+#ifdef Q_OS_SYMBIAN
+ void setSoftKeys_sys(const QList<QAction*> &softkeys);
+ void activateSymbianWindow(WId wid = 0);
+ void _q_delayedDestroy(WId winId);
+#endif
+
+ void raise_sys();
+ void lower_sys();
+ void stackUnder_sys(QWidget *);
+
+ void setFocus_sys();
+
+ void updateFont(const QFont &);
+ inline void setFont_helper(const QFont &font) {
+ if (data.fnt == font && data.fnt.resolve() == font.resolve())
+ return;
+ updateFont(font);
+ }
+ void resolveFont();
+ QFont naturalWidgetFont(uint inheritedMask) const;
+
+ void setLayoutDirection_helper(Qt::LayoutDirection);
+ void resolveLayoutDirection();
+
+ void setLocale_helper(const QLocale &l, bool forceUpdate = false);
+ void resolveLocale();
+
+ void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false);
+ void inheritStyle();
+
+ void setUpdatesEnabled_helper(bool );
+
+ void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const;
+ bool isAboutToShow() const;
+ QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
+ void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags);
+ void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags, bool readyToRender);
+ void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
+ QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
+
+
+ void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index,
+ const QRegion &rgn, const QPoint &offset, int flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , const QWindowSurface *currentSurface
+#endif
+ , QPainter *sharedPainter, QWidgetBackingStore *backingStore);
+
+
+ QPainter *beginSharedPainter();
+ bool endSharedPainter();
+#ifndef QT_NO_GRAPHICSVIEW
+ static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin);
+#endif
+ QWindowSurface *createDefaultWindowSurface();
+ QWindowSurface *createDefaultWindowSurface_sys();
+ void repaint_sys(const QRegion &rgn);
+
+ QRect clipRect() const;
+ QRegion clipRegion() const;
+ void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
+ void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
+ bool alsoNonOpaque = false) const;
+ void clipToEffectiveMask(QRegion &region) const;
+ void updateIsOpaque();
+ void setOpaque(bool opaque);
+ void updateIsTranslucent();
+ bool paintOnScreen() const;
+#ifndef QT_NO_GRAPHICSEFFECT
+ void invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ const QRegion &getOpaqueChildren() const;
+ void setDirtyOpaqueRegion();
+
+ bool close_helper(CloseMode mode);
+
+ void setWindowIcon_helper();
+ void setWindowIcon_sys(bool forceReset = false);
+ void setWindowOpacity_sys(qreal opacity);
+ void adjustQuitOnCloseAttribute();
+
+ void scrollChildren(int dx, int dy);
+ void moveRect(const QRect &, int dx, int dy);
+ void scrollRect(const QRect &, int dx, int dy);
+ void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
+ // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+ void invalidateBuffer(const QRegion &);
+ void invalidateBuffer(const QRect &);
+ bool isOverlapped(const QRect&) const;
+ void syncBackingStore();
+ void syncBackingStore(const QRegion &region);
+
+ void reparentFocusWidgets(QWidget *oldtlw);
+
+ static int pointToRect(const QPoint &p, const QRect &r);
+
+ void setWinId(WId);
+ void showChildren(bool spontaneous);
+ void hideChildren(bool spontaneous);
+ void setParent_sys(QWidget *parent, Qt::WindowFlags);
+ void scroll_sys(int dx, int dy);
+ void scroll_sys(int dx, int dy, const QRect &r);
+ void deactivateWidgetCleanup();
+ void setGeometry_sys(int, int, int, int, bool);
+ void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
+ void activateChildLayoutsRecursively();
+ void show_recursive();
+ void show_helper();
+ void show_sys();
+ void hide_sys();
+ void hide_helper();
+ void _q_showIfNotHidden();
+
+ void setEnabled_helper(bool);
+ void registerDropSite(bool);
+ static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0);
+
+ void updateFrameStrut();
+ QRect frameStrut() const;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static bool navigateToDirection(Direction direction);
+ static QWidget *widgetInNavigationDirection(Direction direction);
+ static bool canKeypadNavigate(Qt::Orientation orientation);
+ static bool inTabWidget(QWidget *widget);
+#endif
+
+ void setWindowIconText_sys(const QString &cap);
+ void setWindowIconText_helper(const QString &cap);
+ void setWindowTitle_sys(const QString &cap);
+
+#ifndef QT_NO_CURSOR
+ void setCursor_sys(const QCursor &cursor);
+ void unsetCursor_sys();
+#endif
+
+ void setWindowTitle_helper(const QString &cap);
+ void setWindowFilePath_helper(const QString &filePath);
+
+ bool setMinimumSize_helper(int &minw, int &minh);
+ bool setMaximumSize_helper(int &maxw, int &maxh);
+ virtual bool hasHeightForWidth() const;
+ void setConstraints_sys();
+ bool pointInsideRectAndMask(const QPoint &) const;
+ QWidget *childAt_helper(const QPoint &, bool) const;
+ QWidget *childAtRecursiveHelper(const QPoint &p, bool, bool includeFrame = false) const;
+ void updateGeometry_helper(bool forceUpdate);
+
+ void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const;
+ void setLayoutItemMargins(int left, int top, int right, int bottom);
+ void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
+
+ // aboutToDestroy() is called just before the contents of
+ // QWidget::destroy() is executed. It's used to signal QWidget
+ // sub-classes that their internals are about to be released.
+ virtual void aboutToDestroy() {}
+
+ QInputContext *assignedInputContext() const;
+ QInputContext *inputContext() const;
+ inline QWidget *effectiveFocusWidget() {
+ QWidget *w = q_func();
+ while (w->focusProxy())
+ w = w->focusProxy();
+ return w;
+ }
+
+ void setModal_sys();
+
+ // This is an helper function that return the available geometry for
+ // a widget and takes care is this one is in QGraphicsView.
+ // If the widget is not embed in a scene then the geometry available is
+ // null, we let QDesktopWidget decide for us.
+ static QRect screenGeometry(const QWidget *widget)
+ {
+ QRect screen;
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
+ //It's embedded if it has an ancestor
+ if (ancestorProxy) {
+ if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != 0) {
+ // One view, let be smart and return the viewport rect then the popup is aligned
+ if (ancestorProxy->scene()->views().size() == 1) {
+ QGraphicsView *view = ancestorProxy->scene()->views().at(0);
+ screen = view->mapToScene(view->viewport()->rect()).boundingRect().toRect();
+ } else {
+ screen = ancestorProxy->scene()->sceneRect().toRect();
+ }
+ }
+ }
+#endif
+ return screen;
+ }
+
+ inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
+ {
+ Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
+ redirectDev = replacement;
+ redirectOffset = offset;
+ }
+
+ inline QPaintDevice *redirected(QPoint *offset) const
+ {
+ if (offset)
+ *offset = redirectDev ? redirectOffset : QPoint();
+ return redirectDev;
+ }
+
+ inline void restoreRedirected()
+ { redirectDev = 0; }
+
+ inline void enforceNativeChildren()
+ {
+ if (!extra)
+ createExtra();
+
+ if (extra->nativeChildrenForced)
+ return;
+ extra->nativeChildrenForced = 1;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->setAttribute(Qt::WA_NativeWindow);
+ }
+ }
+
+ inline bool nativeChildrenForced() const
+ {
+ return extra ? extra->nativeChildrenForced : false;
+ }
+
+ inline QRect effectiveRectFor(const QRect &rect) const
+ {
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (graphicsEffect && graphicsEffect->isEnabled())
+ return graphicsEffect->boundingRectFor(rect).toAlignedRect();
+#endif //QT_NO_GRAPHICSEFFECT
+ return rect;
+ }
+
+ QSize adjustedSize() const;
+
+ inline void handleSoftwareInputPanel(Qt::MouseButton button, bool clickCausedFocus)
+ {
+ Q_Q(QWidget);
+ if (button == Qt::LeftButton && qApp->autoSipEnabled()) {
+ QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
+ q->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
+ if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(q, &event);
+ }
+ }
+ }
+
+#ifndef Q_WS_QWS // Almost cross-platform :-)
+ void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+
+ inline QPoint mapToWS(const QPoint &p) const
+ { return p - data.wrect.topLeft(); }
+
+ inline QPoint mapFromWS(const QPoint &p) const
+ { return p + data.wrect.topLeft(); }
+
+ inline QRect mapToWS(const QRect &r) const
+ { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
+
+ inline QRect mapFromWS(const QRect &r) const
+ { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+#endif
+
+ // Variables.
+ // Regular pointers (keep them together to avoid gaps on 64 bit architectures).
+ QWExtra *extra;
+ QWidget *focus_next;
+ QWidget *focus_prev;
+ QWidget *focus_child;
+ QLayout *layout;
+ QRegion *needsFlush;
+ QPaintDevice *redirectDev;
+ QWidgetItemV2 *widgetItem;
+ QPaintEngine *extraPaintEngine;
+ mutable const QMetaObject *polished;
+ QGraphicsEffect *graphicsEffect;
+ // All widgets are added into the allWidgets set. Once
+ // they receive a window id they are also added to the mapper.
+ // This should just ensure that all widgets are deleted by QApplication
+ static QWidgetMapper *mapper;
+ static QWidgetSet *allWidgets;
+#if !defined(QT_NO_IM)
+ QPointer<QInputContext> ic;
+ Qt::InputMethodHints imHints;
+#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ static QPointer<QWidget> editingWidget;
+#endif
+
+ // Implicit pointers (shared_null/shared_empty).
+ QRegion opaqueChildren;
+ QRegion dirty;
+#ifndef QT_NO_TOOLTIP
+ QString toolTip;
+#endif
+#ifndef QT_NO_STATUSTIP
+ QString statusTip;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ QString whatsThis;
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QString accessibleName;
+ QString accessibleDescription;
+#endif
+
+ // Other variables.
+ uint inheritedFontResolveMask;
+ uint inheritedPaletteResolveMask;
+ short leftmargin;
+ short topmargin;
+ short rightmargin;
+ short bottommargin;
+ signed char leftLayoutItemMargin;
+ signed char topLayoutItemMargin;
+ signed char rightLayoutItemMargin;
+ signed char bottomLayoutItemMargin;
+ static int instanceCounter; // Current number of widget instances
+ static int maxInstances; // Maximum number of widget instances
+ Qt::HANDLE hd;
+ QWidgetData data;
+ QSizePolicy size_policy;
+ QLocale locale;
+ QPoint redirectOffset;
+#ifndef QT_NO_ACTION
+ QList<QAction*> actions;
+#endif
+#ifndef QT_NO_GESTURES
+ QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
+#endif
+
+ // Bit fields.
+ uint high_attributes[4]; // the low ones are in QWidget::widget_attributes
+ QPalette::ColorRole fg_role : 8;
+ QPalette::ColorRole bg_role : 8;
+ uint dirtyOpaqueChildren : 1;
+ uint isOpaque : 1;
+ uint inDirtyList : 1;
+ uint isScrolled : 1;
+ uint isMoved : 1;
+ uint isGLWidget : 1;
+ uint usesDoubleBufferedGLContext : 1;
+#ifndef QT_NO_IM
+ uint inheritsInputMethodHints : 1;
+#endif
+
+ // *************************** Platform specific ************************************
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
+ QX11Info xinfo;
+ Qt::HANDLE picture;
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+
+ void setWindowRole();
+ void sendStartupMessage(const char *message) const;
+ void setNetWmWindowTypes();
+ void x11UpdateIsOpaque();
+ bool isBackgroundInherited() const;
+ void updateX11AcceptFocus();
+ QPoint mapToGlobal(const QPoint &pos) const;
+ QPoint mapFromGlobal(const QPoint &pos) const;
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+#ifndef QT_NO_GESTURES
+ uint nativeGesturePanEnabled : 1;
+#endif
+ bool shouldShowMaximizeButton();
+ void winUpdateIsOpaque();
+ void reparentChildren();
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *registerOleDnd(QWidget *widget);
+ void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
+#endif
+ void grabMouseWhileInWindow();
+ void registerTouchWindow();
+ void winSetupGestures();
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ // This is new stuff
+ uint needWindowChange : 1;
+
+ // Each wiget keeps a list of all its child and grandchild OpenGL widgets.
+ // This list is used to update the gl context whenever a parent and a granparent
+ // moves, and also to check for intersections with gl widgets within the window
+ // when a widget moves.
+ struct GlWidgetInfo
+ {
+ GlWidgetInfo(QWidget *widget) : widget(widget), lastUpdateWidget(0) { }
+ bool operator==(const GlWidgetInfo &other) const { return (widget == other.widget); }
+ QWidget * widget;
+ QWidget * lastUpdateWidget;
+ };
+
+ // dirtyOnWidget contains the areas in the widget that needs to be repained,
+ // in the same way as dirtyOnScreen does for the window. Areas are added in
+ // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use
+ // this information repaint invalid areas when widgets are scrolled.
+ QRegion dirtyOnWidget;
+ EventHandlerRef window_event;
+ QList<GlWidgetInfo> glWidgets;
+
+ //these are here just for code compat (HIViews)
+ Qt::HANDLE qd_hd;
+
+ void macUpdateSizeAttribute();
+ void macUpdateHideOnSuspend();
+ void macUpdateOpaqueSizeGrip();
+ void macUpdateIgnoreMouseEvents();
+ void macUpdateMetalAttribute();
+ void macUpdateIsOpaque();
+ void macSetNeedsDisplay(QRegion region);
+ void setEnabled_helper_sys(bool enable);
+ bool isRealWindow() const;
+ void adjustWithinMaxAndMinSize(int &w, int &h);
+ void applyMaxAndMinSizeOnWindow();
+ void update_sys(const QRect &rect);
+ void update_sys(const QRegion &rgn);
+ void setGeometry_sys_helper(int, int, int, int, bool);
+ void setWindowModified_sys(bool b);
+ void updateMaximizeButton_sys();
+ void setWindowFilePath_sys(const QString &filePath);
+ void createWindow_sys();
+ void recreateMacWindow();
+#ifndef QT_MAC_USE_COCOA
+ void initWindowPtr();
+ void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
+#else
+ void setSubWindowStacking(bool set);
+ void setWindowLevel();
+ void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
+ void syncCocoaMask();
+ void finishCocoaMaskSetup();
+ void syncUnifiedMode();
+ // Did we add the drawRectOriginal method?
+ bool drawRectOriginalAdded;
+ // Is the original drawRect method available?
+ bool originalDrawMethod;
+ // Do we need to change the methods?
+ bool changeMethods;
+
+ // Unified toolbar variables
+ bool isInUnifiedToolbar;
+ QUnifiedToolbarSurface *unifiedSurface;
+ QPoint toolbar_offset;
+ QWidget *toolbar_ancestor;
+ bool flushRequested;
+ bool touchEventsEnabled;
+#endif // QT_MAC_USE_COCOA
+ void determineWindowClass();
+ void transferChildren();
+ bool qt_mac_dnd_event(uint, DragRef);
+ void toggleDrawers(bool);
+ //mac event functions
+ static bool qt_create_root_win();
+ static void qt_clean_root_win();
+ static bool qt_mac_update_sizer(QWidget *, int up = 0);
+ static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
+ static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
+ static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
+ void registerTouchWindow(bool enable = true);
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+ void moveSurface(QWindowSurface *surface, const QPoint &offset);
+ QRegion localRequestedRegion() const;
+ QRegion localAllocatedRegion() const;
+
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
+#endif
+ QScreen* getScreen() const;
+#elif defined(Q_WS_QPA) // <--------------------------------------------------------- QPA
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
+#endif
+#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+ int symbianScreenNumber; // only valid for desktop widget and top-levels
+ bool fixNativeOrientationCalled;
+ void s60UpdateIsOpaque();
+ void reparentChildren();
+ void registerTouchWindow();
+#endif
+
+};
+
+struct QWidgetPaintContext
+{
+ inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f,
+ QPainter *p, QWidgetBackingStore *b)
+ : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {}
+
+ QPaintDevice *pdev;
+ QRegion rgn;
+ QPoint offset;
+ int flags;
+ QPainter *sharedPainter;
+ QWidgetBackingStore *backingStore;
+ QPainter *painter;
+};
+
+#ifndef QT_NO_GRAPHICSEFFECT
+class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
+{
+public:
+ QWidgetEffectSourcePrivate(QWidget *widget)
+ : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0), updateDueToGraphicsEffect(false)
+ {}
+
+ inline void detach()
+ { m_widget->d_func()->graphicsEffect = 0; }
+
+ inline const QGraphicsItem *graphicsItem() const
+ { return 0; }
+
+ inline const QWidget *widget() const
+ { return m_widget; }
+
+ inline void update()
+ {
+ updateDueToGraphicsEffect = true;
+ m_widget->update();
+ updateDueToGraphicsEffect = false;
+ }
+
+ inline bool isPixmap() const
+ { return false; }
+
+ inline void effectBoundingRectChanged()
+ {
+ // ### This function should take a rect parameter; then we can avoid
+ // updating too much on the parent widget.
+ if (QWidget *parent = m_widget->parentWidget())
+ parent->update();
+ else
+ update();
+ }
+
+ inline const QStyleOption *styleOption() const
+ { return 0; }
+
+ inline QRect deviceRect() const
+ { return m_widget->window()->rect(); }
+
+ QRectF boundingRect(Qt::CoordinateSystem system) const;
+ void draw(QPainter *p);
+ QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffect::PixmapPadMode mode) const;
+
+ QWidget *m_widget;
+ QWidgetPaintContext *context;
+ QTransform lastEffectTransform;
+ bool updateDueToGraphicsEffect;
+};
+#endif //QT_NO_GRAPHICSEFFECT
+
+inline QWExtra *QWidgetPrivate::extraData() const
+{
+ return extra;
+}
+
+inline QTLWExtra *QWidgetPrivate::topData() const
+{
+ const_cast<QWidgetPrivate *>(this)->createTLExtra();
+ return extra->topextra;
+}
+
+inline QTLWExtra *QWidgetPrivate::maybeTopData() const
+{
+ return extra ? extra->topextra : 0;
+}
+
+inline QPainter *QWidgetPrivate::sharedPainter() const
+{
+ Q_Q(const QWidget);
+ QTLWExtra *x = q->window()->d_func()->maybeTopData();
+ return x ? x->sharedPainter : 0;
+}
+
+inline void QWidgetPrivate::setSharedPainter(QPainter *painter)
+{
+ Q_Q(QWidget);
+ QTLWExtra *x = q->window()->d_func()->topData();
+ x->sharedPainter = painter;
+}
+
+inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const
+{
+ Q_Q(const QWidget);
+ return q->rect().contains(p) && (!extra || !extra->hasMask || q->testAttribute(Qt::WA_MouseNoMask)
+ || extra->mask.contains(p));
+}
+
+inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
+{
+ Q_Q(const QWidget);
+ QTLWExtra *x = q->window()->d_func()->maybeTopData();
+ return x ? x->backingStore.data() : 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QWIDGET_P_H
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
new file mode 100644
index 0000000000..d239e6d652
--- /dev/null
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -0,0 +1,824 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtGui/qwidget.h"
+#include "QtGui/qevent.h"
+#include "QtGui/qapplication.h"
+#include "QtGui/private/qbackingstore_p.h"
+#include "QtGui/private/qwidget_p.h"
+#include "QtGui/private/qwidgetwindow_qpa_p.h"
+#include "QtGui/private/qapplication_p.h"
+#include "QtGui/qdesktopwidget.h"
+#include "QtGui/qplatformwindow_qpa.h"
+#include "QtGui/qplatformglcontext_qpa.h"
+
+#include <QtGui/QPlatformCursor>
+
+QT_BEGIN_NAMESPACE
+
+void q_createNativeChildrenAndSetParent(QWindow *parentWindow, const QWidget *parentWidget)
+{
+ QObjectList children = parentWidget->children();
+ for (int i = 0; i < children.size(); i++) {
+ if (children.at(i)->isWidgetType()) {
+ const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
+ if (childWidget) { // should not be necessary
+ if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
+ if (!childWidget->windowHandle())
+ childWidget->winId();
+ if (childWidget->windowHandle())
+ childWidget->windowHandle()->setParent(parentWindow);
+ } else {
+ q_createNativeChildrenAndSetParent(parentWindow,childWidget);
+ }
+ }
+ }
+ }
+
+}
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+
+ Q_UNUSED(window);
+ Q_UNUSED(initializeWindow);
+ Q_UNUSED(destroyOldWindow);
+
+ Qt::WindowFlags flags = data.window_flags;
+
+ if ((!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) || q->windowType() == Qt::Desktop )
+ return; // we only care about real toplevels
+
+ QWindowSurface *surface = q->windowSurface();
+
+ QWindow *win = topData()->window;
+
+ if (!q->isWindow()) {
+ if (QWidget *nativeParent = q->nativeParentWidget()) {
+ if (nativeParent->windowHandle())
+ win->setParent(nativeParent->windowHandle());
+ }
+ }
+
+ win->setWindowFlags(data.window_flags);
+ win->setGeometry(q->geometry());
+ win->create();
+
+ data.window_flags = win->windowFlags();
+
+ if (!surface ) {
+ if (win) {
+ surface = QGuiApplicationPrivate::platformIntegration()->createWindowSurface(win, win->winId());
+ q->setWindowSurface(surface);
+ } else {
+ q->setAttribute(Qt::WA_PaintOnScreen,true);
+ }
+ }
+
+ setWinId(win->winId());
+
+// first check children. and create them if necessary
+// q_createNativeChildrenAndSetParent(q->windowHandle(),q);
+
+ QGuiApplicationPrivate::platformIntegration()->moveToScreen(win, topData()->screenIndex);
+// qDebug() << "create_sys" << q << q->internalWinId();
+}
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+
+ if ((windowType() == Qt::Popup))
+ qApp->d_func()->closePopup(this);
+
+ //### we don't have proper focus event handling yet
+ if (this == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+
+ if (windowType() != Qt::Desktop) {
+ if (destroySubWindows) {
+ QObjectList childList(children());
+ for (int i = 0; i < childList.size(); i++) {
+ QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
+ if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
+ if (widget->windowHandle()) {
+ widget->destroy();
+ }
+ }
+ }
+ }
+ if (destroyWindow) {
+ d->deleteTLSysExtra();
+ } else {
+ if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
+ d->hide_sys();
+ }
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+
+ Qt::WindowFlags oldFlags = data.window_flags;
+
+ int targetScreen = -1;
+ // Handle a request to move the widget to a particular screen
+ if (newparent && newparent->windowType() == Qt::Desktop) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+
+ // get the desktop's screen number
+ targetScreen = newparent->window()->d_func()->topData()->screenIndex;
+ newparent = 0;
+ }
+
+ if (parent != newparent) {
+ QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
+ if (q->windowHandle() && newparent) {
+ QWidget * parentWithWindow = newparent->windowHandle()? newparent : newparent->nativeParentWidget();
+ if (parentWithWindow && parentWithWindow->windowHandle()) {
+ q->windowHandle()->setParent(parentWithWindow->windowHandle());
+ }
+ }
+
+ }
+
+ if (!newparent) {
+ f |= Qt::Window;
+ if (targetScreen == -1) {
+ if (parent)
+ targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex;
+ }
+ }
+
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ // Reparenting toplevel to child
+ if (!(f&Qt::Window) && (oldFlags&Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
+ //qDebug() << "setParent_sys() change from toplevel";
+ q->destroy();
+ }
+
+ data.window_flags = f;
+ q->setAttribute(Qt::WA_WState_Created, false);
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ q->setAttribute(Qt::WA_WState_Hidden, false);
+
+ if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ // move the window to the selected screen
+ if (!newparent && targetScreen != -1) {
+ if (maybeTopData())
+ maybeTopData()->screenIndex = targetScreen;
+ // only if it is already created
+ if (q->testAttribute(Qt::WA_WState_Created)) {
+ QPlatformIntegration *platform = QGuiApplicationPrivate::platformIntegration();
+ platform->moveToScreen(q->windowHandle(), targetScreen);
+ }
+ }
+}
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x += w->data->crect.x();
+ y += w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x -= w->data->crect.x();
+ y -= w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+void QWidgetPrivate::updateSystemBackground() {}
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ if (q->isVisible())
+ qt_qpa_set_cursor(q, false);
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ if (q->isVisible())
+ qt_qpa_set_cursor(q, false);
+}
+
+void QWidgetPrivate::updateCursor() const
+{
+ // XXX
+}
+
+#endif //QT_NO_CURSOR
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QWindow *window = q->windowHandle())
+ window->setWindowTitle(caption);
+
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/)
+{
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
+QWidget *qt_pressGrab = 0;
+QWidget *qt_mouseGrb = 0;
+static QWidget *keyboardGrb = 0;
+
+void QWidget::grabMouse()
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ // XXX
+ //qwsDisplay()->grabMouse(this,true);
+
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ // XXX
+ //qwsDisplay()->grabMouse(this,true);
+ //qwsDisplay()->selectCursor(this, cursor.handle());
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+#endif
+
+void QWidget::releaseMouse()
+{
+ if (qt_mouseGrb == this) {
+ // XXX
+ //qwsDisplay()->grabMouse(this,false);
+ qt_mouseGrb = 0;
+ }
+}
+
+void QWidget::grabKeyboard()
+{
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ // XXX
+ //qwsDisplay()->grabKeyboard(this, true);
+ keyboardGrb = this;
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (keyboardGrb == this) {
+ // XXX
+ //qwsDisplay()->grabKeyboard(this, false);
+ keyboardGrb = 0;
+ }
+}
+
+QWidget *QWidget::mouseGrabber()
+{
+ if (qt_mouseGrb)
+ return qt_mouseGrb;
+ return qt_pressGrab;
+}
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
+
+void QWidget::activateWindow()
+{
+ if (windowHandle())
+ windowHandle()->requestActivateWindow();
+}
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
+
+ if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
+ return;
+
+ QWindow *window = q->windowHandle();
+ if (window) {
+ QRect geomRect = q->geometry();
+ if (!q->isWindow()) {
+ QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
+ geomRect.moveTopLeft(topLeftOfWindow);
+ }
+ const QRect windowRect = window->geometry();
+ if (windowRect != geomRect) {
+ window->setGeometry(geomRect);
+ }
+ if (QWindowSurface *surface = q->windowSurface()) {
+ if (windowRect.size() != geomRect.size()) {
+ surface->resize(geomRect.size());
+ }
+ }
+ if (window)
+ window->setVisible(true);
+ }
+}
+
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ q->setAttribute(Qt::WA_Mapped, false);
+ if (!q->isWindow()) {
+ QWidget *p = q->parentWidget();
+ if (p &&p->isVisible()) {
+ invalidateBuffer(q->rect());
+ }
+ return;
+ }
+ if (QWindow *window = q->windowHandle()) {
+ window->setVisible(false);
+ }
+
+ //### we don't yet have proper focus event handling
+ if (q == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+
+}
+
+void QWidgetPrivate::setMaxWindowState_helper()
+{
+ setFullScreenSize_helper(); //### decoration size
+}
+
+void QWidgetPrivate::setFullScreenSize_helper()
+{
+ Q_Q(QWidget);
+
+ const uint old_state = data.in_set_window_state;
+ data.in_set_window_state = 1;
+
+ const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q));
+ q->move(screen.topLeft());
+ q->resize(screen.size());
+
+ data.in_set_window_state = old_state;
+}
+
+static Qt::WindowStates effectiveState(Qt::WindowStates state)
+ {
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+ }
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+ if (isWindow() && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ data->window_state = newstate;
+ data->in_set_window_state = 1;
+ bool needShow = false;
+ Qt::WindowStates newEffectiveState = effectiveState(newstate);
+ Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
+ if (isWindow() && newEffectiveState != oldEffectiveState) {
+ d->createTLExtra();
+ if (oldEffectiveState == Qt::WindowNoState) { //normal
+ d->topData()->normalGeometry = geometry();
+ } else if (oldEffectiveState == Qt::WindowFullScreen) {
+ setParent(0, d->topData()->savedFlags);
+ needShow = true;
+ } else if (oldEffectiveState == Qt::WindowMinimized) {
+ needShow = true;
+ }
+
+ if (newEffectiveState == Qt::WindowMinimized) {
+ //### not ideal...
+ hide();
+ needShow = false;
+ } else if (newEffectiveState == Qt::WindowFullScreen) {
+ d->topData()->savedFlags = windowFlags();
+ setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
+ d->setFullScreenSize_helper();
+ raise();
+ needShow = true;
+ } else if (newEffectiveState == Qt::WindowMaximized) {
+ createWinId();
+ d->setMaxWindowState_helper();
+ } else { //normal
+ QRect r = d->topData()->normalGeometry;
+ if (r.width() >= 0) {
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ setGeometry(r);
+ }
+ }
+ }
+ data->in_set_window_state = 0;
+
+ if (needShow)
+ show();
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ q->windowHandle()->raise();
+ }
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ q->windowHandle()->lower();
+ } else if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget*)
+{
+ Q_Q(QWidget);
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
+
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ QPoint oldp = q->geometry().topLeft();
+ QSize olds = q->size();
+ QRect r(x, y, w, h);
+
+ bool isResize = olds != r.size();
+ isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
+
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if (r.size() == olds && oldp == r.topLeft())
+ return;
+
+ if (!data.in_set_window_state) {
+ q->data->window_state &= ~Qt::WindowMaximized;
+ q->data->window_state &= ~Qt::WindowFullScreen;
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ }
+
+ QPoint oldPos = q->pos();
+ data.crect = r;
+
+ if (q->isVisible()) {
+ if (q->windowHandle()) {
+ if (q->isWindow()) {
+ q->windowHandle()->setGeometry(q->geometry());
+ } else {
+ QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
+ q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
+ }
+ const QWidgetBackingStore *bs = maybeBackingStore();
+ if (bs->windowSurface) {
+ if (isResize)
+ bs->windowSurface->resize(r.size());
+ }
+ } else {
+ if (isMove && !isResize)
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, olds);
+ }
+
+ if (isMove) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ QResizeEvent e(r.size(), olds);
+ QApplication::sendEvent(q, &e);
+ if (q->windowHandle())
+ q->update();
+ }
+ } else { // not visible
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+ scrollRect(q->rect(), dx, dy);
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ scrollRect(r, dx, dy);
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+
+ QPlatformScreen *screen = QPlatformScreen::platformScreenForWindow(windowHandle());
+ if (!screen) {
+ if (m == PdmDpiX || m == PdmDpiY)
+ return 72;
+ return QPaintDevice::metric(m);
+ }
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmWidthMM) {
+ val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else if (m == PdmHeightMM) {
+ val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
+ } else if (m == PdmDepth) {
+ return screen->depth();
+ } else if (m == PdmDpiX || m == PdmPhysicalDpiX) {
+ if (d->extra && d->extra->customDpiX)
+ return d->extra->customDpiX;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4));
+ } else if (m == PdmDpiY || m == PdmPhysicalDpiY) {
+ if (d->extra && d->extra->customDpiY)
+ return d->extra->customDpiY;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4));
+ } else {
+ val = QPaintDevice::metric(m);// XXX
+ }
+ return val;
+}
+
+/*!
+ \preliminary
+
+ Returns the QPlatformWindow this widget will be drawn into.
+*/
+QWindow *QWidget::windowHandle() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra && extra->window)
+ return extra->window;
+
+ return 0;
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ Q_Q(QWidget);
+ extra->topextra->screenIndex = 0;
+ extra->topextra->window = new QWidgetWindow(q);
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ if (extra && extra->topextra) {
+ //the toplevel might have a context with a "qglcontext associated with it. We need to
+ //delete the qglcontext before we delete the qplatformglcontext.
+ //One unfortunate thing about this is that we potentially create a glContext just to
+ //delete it straight afterwards.
+ if (extra->topextra->window) {
+ extra->topextra->window->destroy();
+ }
+ setWinId(0);
+ //hmmm. should we delete window..
+ delete extra->topextra->window;
+ extra->topextra->window = 0;
+ }
+}
+
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_UNUSED(region);
+ // XXX
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+ // XXX
+}
+
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+ q->windowHandle()->setOpacity(level);
+}
+
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
+{
+ Q_UNUSED(dontShow);
+ Q_UNUSED(oldRect);
+ // XXX
+}
+
+QPaintEngine *QWidget::paintEngine() const
+{
+ qWarning("QWidget::paintEngine: Should no longer be called");
+ return 0; //##### @@@
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ //This function should not be called.
+ Q_ASSERT(false);
+ return 0;
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+}
+
+#ifndef QT_NO_CURSOR
+void qt_qpa_set_cursor(QWidget * w, bool force)
+{
+ static QCursor arrowCursor(Qt::ArrowCursor);
+ static QPointer<QWidget> lastUnderMouse = 0;
+
+ QCursor * override = QApplication::overrideCursor();
+
+ if (override && w != 0)
+ return;
+
+ QWidget *cursorWidget;
+ QCursor cursorCursor;
+
+ do {
+ if (w == 0) {
+ if (override) {
+ cursorCursor = *override;
+ cursorWidget = QApplication::topLevelAt(QCursor::pos());
+ break;
+ }
+ w = QApplication::widgetAt(QCursor::pos());
+ if (w == 0) // clear the override cursor while over empty space
+ w = QApplication::desktop();
+ } else if (force) {
+ lastUnderMouse = w;
+ } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse
+ && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
+ w = lastUnderMouse;
+ }
+ if (w == QApplication::desktop() && !override) {
+ cursorCursor = arrowCursor;
+ cursorWidget = w;
+ break;
+ }
+
+ QWidget * curWin = QApplication::activeWindow();
+ if (!curWin && w && w->internalWinId())
+ return;
+ QWidget* cW = w && !w->internalWinId() ? w : curWin;
+
+ if (!cW || cW->window() != w->window() ||
+ !cW->isVisible() || !cW->underMouse() || override)
+ return;
+
+ cursorCursor = w->cursor();
+ cursorWidget = w;
+ } while (0);
+ foreach (QWeakPointer<QPlatformCursor> cursor, QPlatformCursorPrivate::getInstances())
+ if (cursor)
+ cursor.data()->changeCursor(&cursorCursor, cursorWidget->windowHandle());
+}
+#endif //QT_NO_CURSOR
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetaction.cpp b/src/widgets/kernel/qwidgetaction.cpp
new file mode 100644
index 0000000000..29586da34b
--- /dev/null
+++ b/src/widgets/kernel/qwidgetaction.cpp
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidgetaction.h"
+#include "qdebug.h"
+
+#ifndef QT_NO_ACTION
+#include "qwidgetaction_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWidgetAction
+ \since 4.2
+ \brief The QWidgetAction class extends QAction by an interface
+ for inserting custom widgets into action based containers, such
+ as toolbars.
+
+ \ingroup mainwindow-classes
+
+ Most actions in an application are represented as items in menus or
+ buttons in toolbars. However sometimes more complex widgets are
+ necessary. For example a zoom action in a word processor may be
+ realized using a QComboBox in a QToolBar, presenting a range
+ of different zoom levels. QToolBar provides QToolBar::insertWidget()
+ as convenience function for inserting a single widget.
+ However if you want to implement an action that uses custom
+ widgets for visualization in multiple containers then you have to
+ subclass QWidgetAction.
+
+ If a QWidgetAction is added for example to a QToolBar then
+ QWidgetAction::createWidget() is called. Reimplementations of that
+ function should create a new custom widget with the specified parent.
+
+ If the action is removed from a container widget then
+ QWidgetAction::deleteWidget() is called with the previously created custom
+ widget as argument. The default implementation hides the widget and deletes
+ it using QObject::deleteLater().
+
+ If you have only one single custom widget then you can set it as default
+ widget using setDefaultWidget(). That widget will then be used if the
+ action is added to a QToolBar, or in general to an action container that
+ supports QWidgetAction. If a QWidgetAction with only a default widget is
+ added to two toolbars at the same time then the default widget is shown
+ only in the first toolbar the action was added to. QWidgetAction takes
+ over ownership of the default widget.
+
+ Note that it is up to the widget to activate the action, for example by
+ reimplementing mouse event handlers and calling QAction::trigger().
+
+ \bold {Mac OS X}: If you add a widget to a menu in the application's menu
+ bar on Mac OS X, the widget will be added and it will function but with some
+ limitations:
+ \list 1
+ \o The widget is reparented away from the QMenu to the native menu
+ view. If you show the menu in some other place (e.g. as a popup menu),
+ the widget will not be there.
+ \o Focus/Keyboard handling of the widget is not possible.
+ \o Due to Apple's design, mouse tracking on the widget currently does
+ not work.
+ \o Connecting the triggered() signal to a slot that opens a modal
+ dialog will cause a crash in Mac OS X 10.4 (known bug acknowledged
+ by Apple), a workaround is to use a QueuedConnection instead of a
+ DirectConnection.
+ \endlist
+
+ \sa QAction, QActionGroup, QWidget
+*/
+
+/*!
+ Constructs an action with \a parent.
+*/
+QWidgetAction::QWidgetAction(QObject *parent)
+ : QAction(*(new QWidgetActionPrivate), parent)
+{
+}
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+QWidgetAction::~QWidgetAction()
+{
+ Q_D(QWidgetAction);
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ disconnect(d->createdWidgets.at(i), SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_widgetDestroyed(QObject*)));
+ QList<QWidget *> widgetsToDelete = d->createdWidgets;
+ d->createdWidgets.clear();
+ qDeleteAll(widgetsToDelete);
+ delete d->defaultWidget;
+}
+
+/*!
+ Sets \a widget to be the default widget. The ownership is
+ transferred to QWidgetAction. Unless createWidget() is
+ reimplemented by a subclass to return a new widget the default
+ widget is used when a container widget requests a widget through
+ requestWidget().
+*/
+void QWidgetAction::setDefaultWidget(QWidget *widget)
+{
+ Q_D(QWidgetAction);
+ if (widget == d->defaultWidget || d->defaultWidgetInUse)
+ return;
+ delete d->defaultWidget;
+ d->defaultWidget = widget;
+ if (!widget)
+ return;
+
+ setVisible(!(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide)));
+ d->defaultWidget->hide();
+ d->defaultWidget->setParent(0);
+ d->defaultWidgetInUse = false;
+ if (!isEnabled())
+ d->defaultWidget->setEnabled(false);
+}
+
+/*!
+ Returns the default widget.
+*/
+QWidget *QWidgetAction::defaultWidget() const
+{
+ Q_D(const QWidgetAction);
+ return d->defaultWidget;
+}
+
+/*!
+ Returns a widget that represents the action, with the given \a
+ parent.
+
+ Container widgets that support actions can call this function to
+ request a widget as visual representation of the action.
+
+ \sa releaseWidget(), createWidget(), defaultWidget()
+*/
+QWidget *QWidgetAction::requestWidget(QWidget *parent)
+{
+ Q_D(QWidgetAction);
+
+ QWidget *w = createWidget(parent);
+ if (!w) {
+ if (d->defaultWidgetInUse || !d->defaultWidget)
+ return 0;
+ d->defaultWidget->setParent(parent);
+ d->defaultWidgetInUse = true;
+ return d->defaultWidget;
+ }
+
+ connect(w, SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_widgetDestroyed(QObject*)));
+ d->createdWidgets.append(w);
+ return w;
+}
+
+/*!
+ Releases the specified \a widget.
+
+ Container widgets that support actions call this function when a widget
+ action is removed.
+
+ \sa requestWidget(), deleteWidget(), defaultWidget()
+*/
+void QWidgetAction::releaseWidget(QWidget *widget)
+{
+ Q_D(QWidgetAction);
+
+ if (widget == d->defaultWidget) {
+ d->defaultWidget->hide();
+ d->defaultWidget->setParent(0);
+ d->defaultWidgetInUse = false;
+ return;
+ }
+
+ if (!d->createdWidgets.contains(widget))
+ return;
+
+ disconnect(widget, SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_widgetDestroyed(QObject*)));
+ d->createdWidgets.removeAll(widget);
+ deleteWidget(widget);
+}
+
+/*!
+ \reimp
+*/
+bool QWidgetAction::event(QEvent *event)
+{
+ Q_D(QWidgetAction);
+ if (event->type() == QEvent::ActionChanged) {
+ if (d->defaultWidget)
+ d->defaultWidget->setEnabled(isEnabled());
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ d->createdWidgets.at(i)->setEnabled(isEnabled());
+ }
+ return QAction::event(event);
+}
+
+/*!
+ \reimp
+ */
+bool QWidgetAction::eventFilter(QObject *obj, QEvent *event)
+{
+ return QAction::eventFilter(obj,event);
+}
+
+/*!
+ This function is called whenever the action is added to a container widget
+ that supports custom widgets. If you don't want a custom widget to be
+ used as representation of the action in the specified \a parent widget then
+ 0 should be returned.
+
+ \sa deleteWidget()
+*/
+QWidget *QWidgetAction::createWidget(QWidget *parent)
+{
+ Q_UNUSED(parent)
+ return 0;
+}
+
+/*!
+ This function is called whenever the action is removed from a
+ container widget that displays the action using a custom \a
+ widget previously created using createWidget(). The default
+ implementation hides the \a widget and schedules it for deletion
+ using QObject::deleteLater().
+
+ \sa createWidget()
+*/
+void QWidgetAction::deleteWidget(QWidget *widget)
+{
+ widget->hide();
+ widget->deleteLater();
+}
+
+/*!
+ Returns the list of widgets that have been using createWidget() and
+ are currently in use by widgets the action has been added to.
+*/
+QList<QWidget *> QWidgetAction::createdWidgets() const
+{
+ Q_D(const QWidgetAction);
+ return d->createdWidgets;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwidgetaction.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qwidgetaction.h b/src/widgets/kernel/qwidgetaction.h
new file mode 100644
index 0000000000..a32b5d60dd
--- /dev/null
+++ b/src/widgets/kernel/qwidgetaction.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGETACTION_H
+#define QWIDGETACTION_H
+
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QWidgetActionPrivate;
+
+class Q_GUI_EXPORT QWidgetAction : public QAction
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidgetAction)
+
+public:
+ explicit QWidgetAction(QObject *parent);
+ virtual ~QWidgetAction();
+
+ void setDefaultWidget(QWidget *w);
+ QWidget *defaultWidget() const;
+
+ QWidget *requestWidget(QWidget *parent);
+ void releaseWidget(QWidget *widget);
+
+protected:
+ virtual bool event(QEvent *);
+ virtual bool eventFilter(QObject *, QEvent *);
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual void deleteWidget(QWidget *widget);
+ QList<QWidget *> createdWidgets() const;
+
+private:
+ Q_DISABLE_COPY(QWidgetAction)
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *))
+ friend class QToolBar;
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWIDGETACTION_H
diff --git a/src/widgets/kernel/qwidgetaction_p.h b/src/widgets/kernel/qwidgetaction_p.h
new file mode 100644
index 0000000000..e4f59a04d2
--- /dev/null
+++ b/src/widgets/kernel/qwidgetaction_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGETACTION_P_H
+#define QWIDGETACTION_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/qaction_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidgetActionPrivate : public QActionPrivate
+{
+ Q_DECLARE_PUBLIC(QWidgetAction)
+public:
+ inline QWidgetActionPrivate() : defaultWidgetInUse(false), autoCreated(false) {}
+ QPointer<QWidget> defaultWidget;
+ QList<QWidget *> createdWidgets;
+ uint defaultWidgetInUse : 1;
+ uint autoCreated : 1; // created by QToolBar::addWidget and the like
+
+ inline void _q_widgetDestroyed(QObject *o) {
+ createdWidgets.removeAll(static_cast<QWidget *>(o));
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
new file mode 100644
index 0000000000..d1ef77d48c
--- /dev/null
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidgetwindow_qpa_p.h"
+
+#include "private/qwidget_p.h"
+#include "private/qapplication_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QWidget *qt_button_down = 0; // widget got last button-down
+
+QWidgetWindow::QWidgetWindow(QWidget *widget)
+ : m_widget(widget)
+{
+}
+
+bool QWidgetWindow::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::Close:
+ handleCloseEvent(static_cast<QCloseEvent *>(event));
+ return true;
+
+ case QEvent::Enter:
+ case QEvent::Leave:
+ handleEnterLeaveEvent(event);
+ return true;
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ handleKeyEvent(static_cast<QKeyEvent *>(event));
+ return true;
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ handleMouseEvent(static_cast<QMouseEvent *>(event));
+ return true;
+
+ case QEvent::Move:
+ handleMoveEvent(static_cast<QMoveEvent *>(event));
+ return true;
+
+ case QEvent::Resize:
+ handleResizeEvent(static_cast<QResizeEvent *>(event));
+ return true;
+
+ case QEvent::Wheel:
+ handleWheelEvent(static_cast<QWheelEvent *>(event));
+ return true;
+
+ default:
+ break;
+ }
+
+ return m_widget->event(event) || QWindow::event(event);
+}
+
+QPointer<QWidget> qt_last_mouse_receiver = 0;
+
+void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
+{
+ if (event->type() == QEvent::Leave) {
+ QApplicationPrivate::dispatchEnterLeave(0, m_widget);
+ qt_last_mouse_receiver = 0;
+ } else {
+ QApplicationPrivate::dispatchEnterLeave(m_widget, 0);
+ qt_last_mouse_receiver = m_widget;
+ }
+}
+
+void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
+{
+ // which child should have it?
+ QWidget *widget = m_implicit_mouse_grabber ? m_implicit_mouse_grabber.data() : m_widget->childAt(event->pos());
+
+ if (qApp->d_func()->inPopupMode()) {
+ widget = qApp->activePopupWidget();
+ m_implicit_mouse_grabber.clear();
+ }
+
+ if (!widget)
+ widget = m_widget;
+
+ if (event->type() == QEvent::MouseButtonPress && !m_implicit_mouse_grabber)
+ m_implicit_mouse_grabber = widget;
+
+ if (event->buttons() == Qt::NoButton)
+ m_implicit_mouse_grabber.clear();
+
+ QPoint mapped = widget->mapFrom(m_widget, event->pos());
+
+ if (widget != qt_last_mouse_receiver) {
+ QApplicationPrivate::dispatchEnterLeave(widget, qt_last_mouse_receiver);
+ qt_last_mouse_receiver = widget;
+ }
+
+ QMouseEvent translated(event->type(), mapped, event->globalPos(), event->button(), event->buttons(), event->modifiers());
+ QGuiApplication::sendSpontaneousEvent(widget, &translated);
+
+ if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::RightButton) {
+ QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
+ QGuiApplication::sendSpontaneousEvent(widget, &e);
+ }
+}
+
+void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
+{
+ QWidget *widget = m_widget->focusWidget();
+
+ if (!widget)
+ widget = m_widget;
+
+ QGuiApplication::sendSpontaneousEvent(widget, event);
+}
+
+void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
+{
+ m_widget->data->crect = geometry();
+ QGuiApplication::sendSpontaneousEvent(m_widget, event);
+}
+
+void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
+{
+ m_widget->data->crect = geometry();
+ QGuiApplication::sendSpontaneousEvent(m_widget, event);
+}
+
+void QWidgetWindow::handleCloseEvent(QCloseEvent *)
+{
+ m_widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
+void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
+{
+ // which child should have it?
+ QWidget *widget = m_widget->childAt(event->pos());
+
+ if (!widget)
+ widget = m_widget;
+
+ QPoint mapped = widget->mapFrom(m_widget, event->pos());
+
+ QWheelEvent translated(mapped, event->globalPos(), event->delta(), event->buttons(), event->modifiers(), event->orientation());
+ QGuiApplication::sendSpontaneousEvent(widget, &translated);
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
new file mode 100644
index 0000000000..9eb1e4f60e
--- /dev/null
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGETWINDOW_QPA_P_H
+#define QWIDGETWINDOW_QPA_P_H
+
+#include <QtGui/qwindow.h>
+
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWidgetWindow : public QWindow
+{
+ Q_OBJECT
+public:
+ QWidgetWindow(QWidget *widget);
+
+ QWidget *widget() const { return m_widget; }
+
+protected:
+ bool event(QEvent *);
+
+ void handleCloseEvent(QCloseEvent *);
+ void handleEnterLeaveEvent(QEvent *);
+ void handleKeyEvent(QKeyEvent *);
+ void handleMouseEvent(QMouseEvent *);
+ void handleMoveEvent(QMoveEvent *);
+ void handleResizeEvent(QResizeEvent *);
+ void handleWheelEvent(QWheelEvent *);
+
+private:
+ QWidget *m_widget;
+ QWeakPointer<QWidget> m_implicit_mouse_grabber;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWIDGETWINDOW_QPA_P_H
diff --git a/src/widgets/kernel/symbian.pri b/src/widgets/kernel/symbian.pri
new file mode 100644
index 0000000000..69422dd02e
--- /dev/null
+++ b/src/widgets/kernel/symbian.pri
@@ -0,0 +1,7 @@
+symbian {
+ contains(QT_CONFIG, s60): LIBS+= $$QMAKE_LIBS_S60
+ RESOURCES += symbian/symbianresources.qrc
+
+ HEADERS += symbian/qsymbianevent.h
+ SOURCES += symbian/qsymbianevent.cpp
+}
diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri
new file mode 100644
index 0000000000..5ecf4dd94a
--- /dev/null
+++ b/src/widgets/kernel/win.pri
@@ -0,0 +1,4 @@
+# Qt/Windows only configuration file
+# --------------------------------------------------------------------
+
+ INCLUDEPATH += ../3rdparty/wintab
diff --git a/src/widgets/kernel/x11.pri b/src/widgets/kernel/x11.pri
new file mode 100644
index 0000000000..82de1b68af
--- /dev/null
+++ b/src/widgets/kernel/x11.pri
@@ -0,0 +1,4 @@
+x11 {
+ contains(QT_CONFIG, nas): LIBS_PRIVATE += -laudio -lXt
+}
+