summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/accessible/accessible.pri21
-rw-r--r--src/widgets/accessible/complexwidgets.cpp469
-rw-r--r--src/widgets/accessible/complexwidgets.h145
-rw-r--r--src/widgets/accessible/itemviews.cpp1220
-rw-r--r--src/widgets/accessible/itemviews.h292
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp377
-rw-r--r--src/widgets/accessible/qaccessiblemenu.h131
-rw-r--r--src/widgets/accessible/qaccessiblewidget.cpp20
-rw-r--r--src/widgets/accessible/qaccessiblewidget.h2
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory.cpp241
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory_p.h53
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp1021
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.h314
-rw-r--r--src/widgets/accessible/rangecontrols.cpp308
-rw-r--r--src/widgets/accessible/rangecontrols.h160
-rw-r--r--src/widgets/accessible/simplewidgets.cpp904
-rw-r--r--src/widgets/accessible/simplewidgets.h216
-rw-r--r--src/widgets/accessible/widgets.pro27
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp77
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp78
-rw-r--r--src/widgets/dialogs/qfiledialog.h4
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h6
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp40
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp40
-rw-r--r--src/widgets/dialogs/qsidebar.cpp3
-rw-r--r--src/widgets/dialogs/qwizard.cpp2
-rw-r--r--src/widgets/doc/qtwidgets.qdocconf1
-rw-r--r--src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp109
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc5
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc20
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp43
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.h3
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h15
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp88
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h5
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp24
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.cpp58
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.h6
-rw-r--r--src/widgets/graphicsview/qgraphicssceneindex.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicsscenelinearindex_p.h45
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp10
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp25
-rw-r--r--src/widgets/itemviews/qfileiconprovider.cpp6
-rw-r--r--src/widgets/itemviews/qtableview.cpp9
-rw-r--r--src/widgets/kernel/kernel.pri9
-rw-r--r--src/widgets/kernel/qapplication.cpp430
-rw-r--r--src/widgets/kernel/qapplication.h1
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp493
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp142
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h (renamed from src/widgets/kernel/qdesktopwidget_qpa_p.h)4
-rw-r--r--src/widgets/kernel/qdesktopwidget_qpa.cpp193
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp2
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp852
-rw-r--r--src/widgets/kernel/qopenglwidget.h (renamed from src/widgets/kernel/qopenglwidget_p.h)73
-rw-r--r--src/widgets/kernel/qshortcut.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp1157
-rw-r--r--src/widgets/kernel/qwidget.h1
-rw-r--r--src/widgets/kernel/qwidget_p.h15
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp1126
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp100
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h17
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h (renamed from src/widgets/kernel/qwidgetwindow_qpa_p.h)6
-rw-r--r--src/widgets/statemachine/qguistatemachine.cpp2
-rw-r--r--src/widgets/styles/qandroidstyle.cpp386
-rw-r--r--src/widgets/styles/qandroidstyle_p.h9
-rw-r--r--src/widgets/styles/qcommonstyle.cpp5
-rw-r--r--src/widgets/styles/qfusionstyle.cpp144
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm65
-rw-r--r--src/widgets/styles/qstyle.cpp3
-rw-r--r--src/widgets/styles/qstyle.h1
-rw-r--r--src/widgets/styles/qstyleanimation.cpp25
-rw-r--r--src/widgets/styles/qstyleanimation_p.h15
-rw-r--r--src/widgets/styles/qstyleoption.cpp2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp21
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp8
-rw-r--r--src/widgets/util/qflickgesture.cpp2
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp68
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h9
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp51
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp72
-rw-r--r--src/widgets/widgets.pro3
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp4
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp2
-rw-r--r--src/widgets/widgets/qcheckbox.h1
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp8
-rw-r--r--src/widgets/widgets/qdockwidget.cpp22
-rw-r--r--src/widgets/widgets/qdockwidget_p.h8
-rw-r--r--src/widgets/widgets/qgroupbox.cpp2
-rw-r--r--src/widgets/widgets/qlineedit.cpp3
-rw-r--r--src/widgets/widgets/qlineedit.h3
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp14
-rw-r--r--src/widgets/widgets/qlineedit_p.h1
-rw-r--r--src/widgets/widgets/qmainwindow.cpp4
-rw-r--r--src/widgets/widgets/qmainwindow.h7
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp68
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h18
-rw-r--r--src/widgets/widgets/qmdiarea.cpp75
-rw-r--r--src/widgets/widgets/qmdiarea_p.h22
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp42
-rw-r--r--src/widgets/widgets/qmdisubwindow_p.h3
-rw-r--r--src/widgets/widgets/qmenu.cpp4
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp2
-rw-r--r--src/widgets/widgets/qradiobutton.h1
-rw-r--r--src/widgets/widgets/qtabbar.cpp40
-rw-r--r--src/widgets/widgets/qtabbar.h4
-rw-r--r--src/widgets/widgets/qtabbar_p.h4
-rw-r--r--src/widgets/widgets/qtabwidget.cpp23
-rw-r--r--src/widgets/widgets/qtabwidget.h4
-rw-r--r--src/widgets/widgets/qtextedit.cpp2
-rw-r--r--src/widgets/widgets/qtoolbar.cpp4
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp5
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp6
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h5
-rw-r--r--src/widgets/widgets/qwidgetresizehandler.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp10
117 files changed, 10057 insertions, 2536 deletions
diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri
index 9fb2f18950..bcdfbd639c 100644
--- a/src/widgets/accessible/accessible.pri
+++ b/src/widgets/accessible/accessible.pri
@@ -1,6 +1,23 @@
# Qt accessibility module
contains(QT_CONFIG, accessibility) {
- HEADERS += accessible/qaccessiblewidget.h
- SOURCES += accessible/qaccessiblewidget.cpp
+ HEADERS += \
+ accessible/qaccessiblewidget.h \
+ accessible/qaccessiblewidgetfactory_p.h \
+ accessible/complexwidgets.h \
+ accessible/itemviews.h \
+ accessible/qaccessiblemenu.h \
+ accessible/qaccessiblewidgets.h \
+ accessible/rangecontrols.h \
+ accessible/simplewidgets.h
+
+ SOURCES += \
+ accessible/qaccessiblewidget.cpp \
+ accessible/qaccessiblewidgetfactory.cpp \
+ accessible/complexwidgets.cpp \
+ accessible/itemviews.cpp \
+ accessible/qaccessiblemenu.cpp \
+ accessible/qaccessiblewidgets.cpp \
+ accessible/rangecontrols.cpp \
+ accessible/simplewidgets.cpp
}
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
new file mode 100644
index 0000000000..f7c2ac0cf1
--- /dev/null
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -0,0 +1,469 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "complexwidgets.h"
+
+#include <qaccessible.h>
+#include <qapplication.h>
+#include <qabstractbutton.h>
+#include <qevent.h>
+#include <qheaderview.h>
+#include <qtabbar.h>
+#include <qcombobox.h>
+#include <qlistview.h>
+#include <qtableview.h>
+#include <qlineedit.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qtreeview.h>
+#include <private/qtabbar_p.h>
+#include <QAbstractScrollArea>
+#include <QScrollArea>
+#include <QScrollBar>
+#include <QDebug>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QString qt_accStripAmp(const QString &text);
+
+#ifndef QT_NO_TABBAR
+/*!
+ \class QAccessibleTabBar
+ \brief The QAccessibleTabBar class implements the QAccessibleInterface for tab bars.
+ \internal
+
+ \ingroup accessibility
+*/
+
+class QAccessibleTabButton: public QAccessibleInterface, public QAccessibleActionInterface
+{
+public:
+ QAccessibleTabButton(QTabBar *parent, int index)
+ : m_parent(parent), m_index(index)
+ {}
+
+ void *interface_cast(QAccessible::InterfaceType t) {
+ if (t == QAccessible::ActionInterface) {
+ return static_cast<QAccessibleActionInterface*>(this);
+ }
+ return 0;
+ }
+
+ QObject *object() const { return 0; }
+ QAccessible::Role role() const { return QAccessible::PageTab; }
+ QAccessible::State state() const {
+ QAccessibleInterface *parentInterface = parent();
+ QAccessible::State state = parentInterface->state();
+ return state;
+ }
+ QRect rect() const {
+ if (!isValid())
+ return QRect();
+
+ QPoint tp = m_parent->mapToGlobal(QPoint(0,0));
+ QRect rec = m_parent->tabRect(m_index);
+ rec = QRect(tp.x() + rec.x(), tp.y() + rec.y(), rec.width(), rec.height());
+ return rec;
+ }
+
+ bool isValid() const { return true; }// (!m_parent.isNull()) && m_parent->count() > m_index; }
+
+ QAccessibleInterface *childAt(int, int) const { return 0; }
+ int childCount() const { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const { return -1; }
+
+ QString text(QAccessible::Text t) const
+ {
+ if (t == QAccessible::Name)
+ return qt_accStripAmp(m_parent->tabText(m_index));
+ else if (t == QAccessible::Description)
+ return m_parent->tabToolTip(m_index);
+ else if (t == QAccessible::Help)
+ return m_parent->tabWhatsThis(m_index);
+ return QString();
+ }
+
+ void setText(QAccessible::Text, const QString &) {}
+
+ QAccessibleInterface *parent() const {
+ return QAccessible::queryAccessibleInterface(m_parent);
+ }
+ QAccessibleInterface *child(int) const { return 0; }
+ // action interface
+ QStringList actionNames() const
+ {
+ return QStringList(pressAction());
+ }
+
+ void doAction(const QString &actionName)
+ {
+ if (actionName == pressAction())
+ m_parent->setCurrentIndex(m_index);
+ }
+
+ QStringList keyBindingsForAction(const QString &) const
+ {
+ return QStringList();
+ }
+
+ int index() const { return m_index; }
+
+private:
+ QPointer<QTabBar> m_parent;
+ int m_index;
+
+};
+
+/*!
+ Constructs a QAccessibleTabBar object for \a w.
+*/
+QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
+: QAccessibleWidget(w, QAccessible::PageTabList)
+{
+ Q_ASSERT(tabBar());
+}
+
+QAccessibleTabBar::~QAccessibleTabBar()
+{
+ foreach (QAccessible::Id id, m_childInterfaces.values())
+ QAccessible::deleteAccessibleInterface(id);
+}
+
+/*! Returns the QTabBar. */
+QTabBar *QAccessibleTabBar::tabBar() const
+{
+ return qobject_cast<QTabBar*>(object());
+}
+
+QAccessibleInterface* QAccessibleTabBar::child(int index) const
+{
+ if (QAccessible::Id id = m_childInterfaces.value(index))
+ return QAccessible::accessibleInterface(id);
+
+ // first the tabs, then 2 buttons
+ if (index < tabBar()->count()) {
+ QAccessibleTabButton *button = new QAccessibleTabButton(tabBar(), index);
+ QAccessible::registerAccessibleInterface(button);
+ m_childInterfaces.insert(index, QAccessible::uniqueId(button));
+ return button;
+ } else if (index >= tabBar()->count()) {
+ // left button
+ if (index - tabBar()->count() == 0) {
+ return QAccessible::queryAccessibleInterface(tabBar()->d_func()->leftB);
+ }
+ // right button
+ if (index - tabBar()->count() == 1) {
+ return QAccessible::queryAccessibleInterface(tabBar()->d_func()->rightB);
+ }
+ }
+ return 0;
+}
+
+int QAccessibleTabBar::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child->object() && child->object() == tabBar()->d_func()->leftB)
+ return tabBar()->count();
+ if (child->object() && child->object() == tabBar()->d_func()->rightB)
+ return tabBar()->count() + 1;
+ if (child->role() == QAccessible::PageTab) {
+ QAccessibleInterface *parent = child->parent();
+ if (parent == this) {
+ const QAccessibleTabButton *tabButton = static_cast<const QAccessibleTabButton *>(child);
+ return tabButton->index();
+ }
+ }
+ return -1;
+}
+
+int QAccessibleTabBar::childCount() const
+{
+ // tabs + scroll buttons
+ return tabBar()->count() + 2;
+}
+
+QString QAccessibleTabBar::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Name) {
+ return qt_accStripAmp(tabBar()->tabText(tabBar()->currentIndex()));
+ }
+ return QString();
+}
+
+#endif // QT_NO_TABBAR
+
+#ifndef QT_NO_COMBOBOX
+/*!
+ \class QAccessibleComboBox
+ \brief The QAccessibleComboBox class implements the QAccessibleInterface for editable and read-only combo boxes.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleComboBox object for \a w.
+*/
+QAccessibleComboBox::QAccessibleComboBox(QWidget *w)
+: QAccessibleWidget(w, QAccessible::ComboBox)
+{
+ Q_ASSERT(comboBox());
+}
+
+/*!
+ Returns the combobox.
+*/
+QComboBox *QAccessibleComboBox::comboBox() const
+{
+ return qobject_cast<QComboBox*>(object());
+}
+
+QAccessibleInterface *QAccessibleComboBox::child(int index) const
+{
+ if (index == 0) {
+ QAbstractItemView *view = comboBox()->view();
+ //QWidget *parent = view ? view->parentWidget() : 0;
+ return QAccessible::queryAccessibleInterface(view);
+ } else if (index == 1 && comboBox()->isEditable()) {
+ return QAccessible::queryAccessibleInterface(comboBox()->lineEdit());
+ }
+ return 0;
+}
+
+int QAccessibleComboBox::childCount() const
+{
+ // list and text edit
+ return comboBox()->isEditable() ? 2 : 1;
+}
+
+QAccessibleInterface *QAccessibleComboBox::childAt(int x, int y) const
+{
+ if (comboBox()->isEditable() && comboBox()->lineEdit()->rect().contains(x, y))
+ return child(1);
+ return 0;
+}
+
+int QAccessibleComboBox::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (comboBox()->view() == child->object())
+ return 0;
+ if (comboBox()->isEditable() && comboBox()->lineEdit() == child->object())
+ return 1;
+ return -1;
+}
+
+/*! \reimp */
+QString QAccessibleComboBox::text(QAccessible::Text t) const
+{
+ QString str;
+
+ switch (t) {
+ case QAccessible::Name:
+#ifndef Q_OS_UNIX // on Linux we use relations for this, name is text (fall through to Value)
+ str = QAccessibleWidget::text(t);
+ break;
+#endif
+ case QAccessible::Value:
+ if (comboBox()->isEditable())
+ str = comboBox()->lineEdit()->text();
+ else
+ str = comboBox()->currentText();
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QAccessible::Accelerator:
+ str = QKeySequence(Qt::Key_Down).toString(QKeySequence::NativeText);
+ break;
+#endif
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return str;
+}
+
+QStringList QAccessibleComboBox::actionNames() const
+{
+ return QStringList() << showMenuAction() << pressAction();
+}
+
+QString QAccessibleComboBox::localizedActionDescription(const QString &actionName) const
+{
+ if (actionName == showMenuAction() || actionName == pressAction())
+ return QComboBox::tr("Open the combo box selection popup");
+ return QString();
+}
+
+void QAccessibleComboBox::doAction(const QString &actionName)
+{
+ if (actionName == showMenuAction() || actionName == pressAction()) {
+ if (comboBox()->view()->isVisible()) {
+ comboBox()->hidePopup();
+ } else {
+ comboBox()->showPopup();
+ }
+ }
+}
+
+QStringList QAccessibleComboBox::keyBindingsForAction(const QString &/*actionName*/) const
+{
+ return QStringList();
+}
+
+#endif // QT_NO_COMBOBOX
+
+#ifndef QT_NO_SCROLLAREA
+// ======================= QAccessibleAbstractScrollArea =======================
+QAccessibleAbstractScrollArea::QAccessibleAbstractScrollArea(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Client)
+{
+ Q_ASSERT(qobject_cast<QAbstractScrollArea *>(widget));
+}
+
+QAccessibleInterface *QAccessibleAbstractScrollArea::child(int index) const
+{
+ return QAccessible::queryAccessibleInterface(accessibleChildren().at(index));
+}
+
+int QAccessibleAbstractScrollArea::childCount() const
+{
+ return accessibleChildren().count();
+}
+
+int QAccessibleAbstractScrollArea::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object())
+ return -1;
+ return accessibleChildren().indexOf(qobject_cast<QWidget *>(child->object()));
+}
+
+bool QAccessibleAbstractScrollArea::isValid() const
+{
+ return (QAccessibleWidget::isValid() && abstractScrollArea() && abstractScrollArea()->viewport());
+}
+
+QAccessibleInterface *QAccessibleAbstractScrollArea::childAt(int x, int y) const
+{
+ if (!abstractScrollArea()->isVisible())
+ return 0;
+
+ for (int i = 0; i < childCount(); ++i) {
+ QPoint wpos = accessibleChildren().at(i)->mapToGlobal(QPoint(0, 0));
+ QRect rect = QRect(wpos, accessibleChildren().at(i)->size());
+ if (rect.contains(x, y))
+ return child(i);
+ }
+ return 0;
+}
+
+QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea() const
+{
+ return static_cast<QAbstractScrollArea *>(object());
+}
+
+QWidgetList QAccessibleAbstractScrollArea::accessibleChildren() const
+{
+ QWidgetList children;
+
+ // Viewport.
+ QWidget * viewport = abstractScrollArea()->viewport();
+ if (viewport)
+ children.append(viewport);
+
+ // Horizontal scrollBar container.
+ QScrollBar *horizontalScrollBar = abstractScrollArea()->horizontalScrollBar();
+ if (horizontalScrollBar && horizontalScrollBar->isVisible()) {
+ children.append(horizontalScrollBar->parentWidget());
+ }
+
+ // Vertical scrollBar container.
+ QScrollBar *verticalScrollBar = abstractScrollArea()->verticalScrollBar();
+ if (verticalScrollBar && verticalScrollBar->isVisible()) {
+ children.append(verticalScrollBar->parentWidget());
+ }
+
+ // CornerWidget.
+ QWidget *cornerWidget = abstractScrollArea()->cornerWidget();
+ if (cornerWidget && cornerWidget->isVisible())
+ children.append(cornerWidget);
+
+ return children;
+}
+
+QAccessibleAbstractScrollArea::AbstractScrollAreaElement
+QAccessibleAbstractScrollArea::elementType(QWidget *widget) const
+{
+ if (!widget)
+ return Undefined;
+
+ if (widget == abstractScrollArea())
+ return Self;
+ if (widget == abstractScrollArea()->viewport())
+ return Viewport;
+ if (widget->objectName() == QLatin1String("qt_scrollarea_hcontainer"))
+ return HorizontalContainer;
+ if (widget->objectName() == QLatin1String("qt_scrollarea_vcontainer"))
+ return VerticalContainer;
+ if (widget == abstractScrollArea()->cornerWidget())
+ return CornerWidget;
+
+ return Undefined;
+}
+
+bool QAccessibleAbstractScrollArea::isLeftToRight() const
+{
+ return abstractScrollArea()->isLeftToRight();
+}
+
+// ======================= QAccessibleScrollArea ===========================
+QAccessibleScrollArea::QAccessibleScrollArea(QWidget *widget)
+ : QAccessibleAbstractScrollArea(widget)
+{
+ Q_ASSERT(qobject_cast<QScrollArea *>(widget));
+}
+#endif // QT_NO_SCROLLAREA
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/complexwidgets.h b/src/widgets/accessible/complexwidgets.h
new file mode 100644
index 0000000000..d3df224d95
--- /dev/null
+++ b/src/widgets/accessible/complexwidgets.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMPLEXWIDGETS_H
+#define COMPLEXWIDGETS_H
+
+#include <QtCore/qpointer.h>
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtWidgets/qabstractitemview.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractButton;
+class QHeaderView;
+class QTabBar;
+class QComboBox;
+class QTitleBar;
+class QAbstractScrollArea;
+class QScrollArea;
+
+#ifndef QT_NO_SCROLLAREA
+class QAccessibleAbstractScrollArea : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleAbstractScrollArea(QWidget *widget);
+
+ enum AbstractScrollAreaElement {
+ Self = 0,
+ Viewport,
+ HorizontalContainer,
+ VerticalContainer,
+ CornerWidget,
+ Undefined
+ };
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+
+//protected:
+ QAbstractScrollArea *abstractScrollArea() const;
+
+private:
+ QWidgetList accessibleChildren() const;
+ AbstractScrollAreaElement elementType(QWidget *widget) const;
+ bool isLeftToRight() const;
+};
+
+class QAccessibleScrollArea : public QAccessibleAbstractScrollArea
+{
+public:
+ explicit QAccessibleScrollArea(QWidget *widget);
+};
+#endif // QT_NO_SCROLLAREA
+
+#ifndef QT_NO_TABBAR
+class QAccessibleTabBar : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleTabBar(QWidget *w);
+ ~QAccessibleTabBar();
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface* child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QTabBar *tabBar() const;
+ mutable QHash<int, QAccessible::Id> m_childInterfaces;
+};
+#endif // QT_NO_TABBAR
+
+#ifndef QT_NO_COMBOBOX
+class QAccessibleComboBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleComboBox(QWidget *w);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface* child(int index) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ QString localizedActionDescription(const QString &actionName) const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+protected:
+ QComboBox *comboBox() const;
+};
+#endif // QT_NO_COMBOBOX
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // COMPLEXWIDGETS_H
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
new file mode 100644
index 0000000000..723a670739
--- /dev/null
+++ b/src/widgets/accessible/itemviews.cpp
@@ -0,0 +1,1220 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemviews.h"
+
+#include <qheaderview.h>
+#include <qtableview.h>
+#include <qlistview.h>
+#include <qtreeview.h>
+#include <private/qtreewidget_p.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ITEMVIEWS
+/*
+Implementation of the IAccessible2 table2 interface. Much simpler than
+the other table interfaces since there is only the main table and cells:
+
+TABLE/LIST/TREE
+ |- HEADER CELL
+ |- CELL
+ |- CELL
+ ...
+*/
+
+
+QAbstractItemView *QAccessibleTable::view() const
+{
+ return qobject_cast<QAbstractItemView*>(object());
+}
+
+int QAccessibleTable::logicalIndex(const QModelIndex &index) const
+{
+ if (!view()->model() || !index.isValid())
+ return -1;
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader);
+}
+
+QAccessibleTable::QAccessibleTable(QWidget *w)
+ : QAccessibleObject(w)
+{
+ Q_ASSERT(view());
+
+ if (qobject_cast<const QTableView*>(view())) {
+ m_role = QAccessible::Table;
+ } else if (qobject_cast<const QTreeView*>(view())) {
+ m_role = QAccessible::Tree;
+ } else if (qobject_cast<const QListView*>(view())) {
+ m_role = QAccessible::List;
+ } else {
+ // is this our best guess?
+ m_role = QAccessible::Table;
+ }
+}
+
+bool QAccessibleTable::isValid() const
+{
+ return (view() && !qobject_cast<QWidget*>(view())->d_func()->data.in_destructor);
+}
+
+QAccessibleTable::~QAccessibleTable()
+{
+ Q_FOREACH (QAccessible::Id id, childToId.values())
+ QAccessible::deleteAccessibleInterface(id);
+}
+
+QHeaderView *QAccessibleTable::horizontalHeader() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
+ header = tv->horizontalHeader();
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view())) {
+ header = tv->header();
+#endif
+ }
+ return header;
+}
+
+QHeaderView *QAccessibleTable::verticalHeader() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
+ header = tv->verticalHeader();
+#endif
+ }
+ return header;
+}
+
+QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const
+{
+ if (!view()->model())
+ return 0;
+ Q_ASSERT(role() != QAccessible::Tree);
+ QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
+ if (!index.isValid()) {
+ qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << view();
+ return 0;
+ }
+ return child(logicalIndex(index));
+}
+
+QAccessibleInterface *QAccessibleTable::caption() const
+{
+ return 0;
+}
+
+QString QAccessibleTable::columnDescription(int column) const
+{
+ if (!view()->model())
+ return QString();
+ return view()->model()->headerData(column, Qt::Horizontal).toString();
+}
+
+int QAccessibleTable::columnCount() const
+{
+ if (!view()->model())
+ return 0;
+ return view()->model()->columnCount();
+}
+
+int QAccessibleTable::rowCount() const
+{
+ if (!view()->model())
+ return 0;
+ return view()->model()->rowCount();
+}
+
+int QAccessibleTable::selectedCellCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedIndexes().count();
+}
+
+int QAccessibleTable::selectedColumnCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedColumns().count();
+}
+
+int QAccessibleTable::selectedRowCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedRows().count();
+}
+
+QString QAccessibleTable::rowDescription(int row) const
+{
+ if (!view()->model())
+ return QString();
+ return view()->model()->headerData(row, Qt::Vertical).toString();
+}
+
+QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const
+{
+ QList<QAccessibleInterface*> cells;
+ if (!view()->selectionModel())
+ return cells;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes())
+ cells.append(child(logicalIndex(index)));
+ return cells;
+}
+
+QList<int> QAccessibleTable::selectedColumns() const
+{
+ if (!view()->selectionModel())
+ return QList<int>();
+ QList<int> columns;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedColumns()) {
+ columns.append(index.column());
+ }
+ return columns;
+}
+
+QList<int> QAccessibleTable::selectedRows() const
+{
+ if (!view()->selectionModel())
+ return QList<int>();
+ QList<int> rows;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedRows()) {
+ rows.append(index.row());
+ }
+ return rows;
+}
+
+QAccessibleInterface *QAccessibleTable::summary() const
+{
+ return 0;
+}
+
+bool QAccessibleTable::isColumnSelected(int column) const
+{
+ if (!view()->selectionModel())
+ return false;
+ return view()->selectionModel()->isColumnSelected(column, QModelIndex());
+}
+
+bool QAccessibleTable::isRowSelected(int row) const
+{
+ if (!view()->selectionModel())
+ return false;
+ return view()->selectionModel()->isRowSelected(row, QModelIndex());
+}
+
+bool QAccessibleTable::selectRow(int row)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+ QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ return true;
+}
+
+bool QAccessibleTable::selectColumn(int column)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+ QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1)
+ return false;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ return true;
+}
+
+bool QAccessibleTable::unselectRow(int row)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+
+ QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
+ if (!index.isValid())
+ return false;
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedRowCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedRowCount() == 1)
+ return false;
+
+ if ((!row || view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) {
+ //If there are rows selected both up the current row and down the current rown,
+ //the ones which are down the current row will be deselected
+ selection = QItemSelection(index, view()->model()->index(rowCount() - 1, 0, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
+ return true;
+}
+
+bool QAccessibleTable::unselectColumn(int column)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+
+ QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
+ if (!index.isValid())
+ return false;
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedColumnCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedColumnCount() == 1)
+ return false;
+
+ if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
+ //If there are columns selected both at the left of the current row and at the right
+ //of the current rown, the ones which are at the right will be deselected
+ selection = QItemSelection(index, view()->model()->index(0, columnCount() - 1, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
+ return true;
+}
+
+QAccessible::Role QAccessibleTable::role() const
+{
+ return m_role;
+}
+
+QAccessible::State QAccessibleTable::state() const
+{
+ return QAccessible::State();
+}
+
+QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const
+{
+ QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
+ QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
+ // FIXME: if indexPosition < 0 in one coordinate, return header
+
+ QModelIndex index = view()->indexAt(indexPosition);
+ if (index.isValid()) {
+ return child(logicalIndex(index));
+ }
+ return 0;
+}
+
+int QAccessibleTable::childCount() const
+{
+ if (!view()->model())
+ return 0;
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (view()->model()->rowCount()+hHeader) * (view()->model()->columnCount()+vHeader);
+}
+
+int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const
+{
+ if (!view()->model())
+ return -1;
+ QAccessibleInterface *parent = iface->parent();
+ if (parent->object() != view())
+ return -1;
+
+ Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface);
+ return logicalIndex(cell->m_index);
+ } else if (iface->role() == QAccessible::ColumnHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return cell->index + (verticalHeader() ? 1 : 0);
+ } else if (iface->role() == QAccessible::RowHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return (cell->index + 1) * (view()->model()->columnCount() + 1);
+ } else if (iface->role() == QAccessible::Pane) {
+ return 0; // corner button
+ } else {
+ qWarning() << "WARNING QAccessibleTable::indexOfChild Fix my children..."
+ << iface->role() << iface->text(QAccessible::Name);
+ }
+ // FIXME: we are in denial of our children. this should stop.
+ return -1;
+}
+
+QString QAccessibleTable::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Description)
+ return view()->accessibleDescription();
+ return view()->accessibleName();
+}
+
+QRect QAccessibleTable::rect() const
+{
+ if (!view()->isVisible())
+ return QRect();
+ QPoint pos = view()->mapToGlobal(QPoint(0, 0));
+ return QRect(pos.x(), pos.y(), view()->width(), view()->height());
+}
+
+QAccessibleInterface *QAccessibleTable::parent() const
+{
+ if (view() && view()->parent()) {
+ if (qstrcmp("QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
+ return QAccessible::queryAccessibleInterface(view()->parent()->parent());
+ }
+ return QAccessible::queryAccessibleInterface(view()->parent());
+ }
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleTable::child(int logicalIndex) const
+{
+ if (!view()->model())
+ return 0;
+
+ if (childToId.contains(logicalIndex)) {
+ QAccessible::Id id = childToId.value(logicalIndex);
+ return QAccessible::accessibleInterface(id);
+ }
+
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+
+ int columns = view()->model()->columnCount() + vHeader;
+
+ int row = logicalIndex / columns;
+ int column = logicalIndex % columns;
+
+ QAccessibleInterface *iface = 0;
+
+ if (vHeader) {
+ if (column == 0) {
+ if (hHeader && row == 0) {
+ iface = new QAccessibleTableCornerButton(view());
+ } else {
+ iface = new QAccessibleTableHeaderCell(view(), row - hHeader, Qt::Vertical);
+ }
+ }
+ --column;
+ }
+ if (!iface && hHeader) {
+ if (row == 0) {
+ iface = new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal);
+ }
+ --row;
+ }
+
+ if (!iface) {
+ QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
+ if (!index.isValid()) {
+ qWarning() << "QAccessibleTable::child: Invalid index at: " << row << column;
+ return 0;
+ }
+ iface = new QAccessibleTableCell(view(), index, cellRole());
+ }
+
+ QAccessible::registerAccessibleInterface(iface);
+ childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
+ return iface;
+}
+
+void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TableInterface)
+ return static_cast<QAccessibleTableInterface*>(this);
+ return 0;
+}
+
+void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
+{
+ // if there is no cache yet, we don't update anything
+ if (childToId.isEmpty())
+ return;
+
+ switch (event->modelChangeType()) {
+ case QAccessibleTableModelChangeEvent::ModelReset:
+ Q_FOREACH (QAccessible::Id id, childToId.values())
+ QAccessible::deleteAccessibleInterface(id);
+ childToId.clear();
+ break;
+
+ // rows are inserted: move every row after that
+ case QAccessibleTableModelChangeEvent::RowsInserted:
+ case QAccessibleTableModelChangeEvent::ColumnsInserted: {
+ int newRows = event->lastRow() - event->firstRow() + 1;
+ int newColumns = event->lastColumn() - event->firstColumn() + 1;
+
+ ChildCache newCache;
+ ChildCache::ConstIterator iter = childToId.constBegin();
+
+ while (iter != childToId.constEnd()) {
+ QAccessible::Id id = iter.value();
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
+ Q_ASSERT(iface);
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ Q_ASSERT(iface->tableCellInterface());
+ QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
+ if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
+ && cell->m_index.row() >= event->firstRow()) {
+ int newRow = cell->m_index.row() + newRows;
+ cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
+ && cell->m_index.column() >= event->firstColumn()) {
+ int newColumn = cell->m_index.column() + newColumns;
+ cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
+ && iface->role() == QAccessible::RowHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index >= event->firstRow()) {
+ cell->index += newRows;
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
+ && iface->role() == QAccessible::ColumnHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index >= event->firstColumn()) {
+ cell->index += newColumns;
+ }
+ }
+ if (indexOfChild(iface) >= 0) {
+ newCache.insert(indexOfChild(iface), id);
+ } else {
+ // ### This should really not happen,
+ // but it might if the view has a root index set.
+ // This needs to be fixed.
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ ++iter;
+ }
+ childToId = newCache;
+ break;
+ }
+
+ case QAccessibleTableModelChangeEvent::ColumnsRemoved:
+ case QAccessibleTableModelChangeEvent::RowsRemoved: {
+ int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
+ int deletedRows = event->lastRow() - event->firstRow() + 1;
+ ChildCache newCache;
+ ChildCache::ConstIterator iter = childToId.constBegin();
+ while (iter != childToId.constEnd()) {
+ QAccessible::Id id = iter.value();
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
+ Q_ASSERT(iface);
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ Q_ASSERT(iface->tableCellInterface());
+ QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
+ if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved) {
+ if (cell->m_index.row() < event->firstRow()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->m_index.row() > event->lastRow()) {
+ int newRow = cell->m_index.row() - deletedRows;
+ cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved) {
+ if (cell->m_index.column() < event->firstColumn()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->m_index.column() > event->lastColumn()) {
+ int newColumn = cell->m_index.column() - deletedColumns;
+ cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
+ && iface->role() == QAccessible::RowHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index < event->firstRow()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->index > event->lastRow()) {
+ cell->index -= deletedRows;
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
+ && iface->role() == QAccessible::ColumnHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index < event->firstColumn()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->index > event->lastColumn()) {
+ cell->index -= deletedColumns;
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ }
+ ++iter;
+ }
+ childToId = newCache;
+ break;
+ }
+
+ case QAccessibleTableModelChangeEvent::DataChanged:
+ // nothing to do in this case
+ break;
+ }
+}
+
+// TREE VIEW
+
+QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const
+{
+ if (!isValid() || !view()->model())
+ return QModelIndex();
+
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ if ((row < 0) || (column < 0) || (treeView->d_func()->viewItems.count() <= row)) {
+ qWarning() << "QAccessibleTree::indexFromLogical: invalid index: " << row << column << " for " << treeView;
+ return QModelIndex();
+ }
+ QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
+
+ if (modelIndex.isValid() && column > 0) {
+ modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
+ }
+ return modelIndex;
+}
+
+QAccessibleInterface *QAccessibleTree::childAt(int x, int y) const
+{
+ if (!view()->model())
+ return 0;
+ QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
+ QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
+
+ QModelIndex index = view()->indexAt(indexPosition);
+ if (!index.isValid())
+ return 0;
+
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
+ int column = index.column();
+
+ int i = row * view()->model()->columnCount() + column;
+ return child(i);
+}
+
+int QAccessibleTree::childCount() const
+{
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ if (!view()->model())
+ return 0;
+
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (treeView->d_func()->viewItems.count() + hHeader)* view()->model()->columnCount();
+}
+
+
+QAccessibleInterface *QAccessibleTree::child(int logicalIndex) const
+{
+ if (logicalIndex < 0 || !view()->model() || !view()->model()->columnCount())
+ return 0;
+
+ QAccessibleInterface *iface = 0;
+ int index = logicalIndex;
+
+ if (horizontalHeader()) {
+ if (index < view()->model()->columnCount()) {
+ iface = new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal);
+ } else {
+ index -= view()->model()->columnCount();
+ }
+ }
+
+ if (!iface) {
+ int row = index / view()->model()->columnCount();
+ int column = index % view()->model()->columnCount();
+ QModelIndex modelIndex = indexFromLogical(row, column);
+ if (!modelIndex.isValid())
+ return 0;
+ iface = new QAccessibleTableCell(view(), modelIndex, cellRole());
+ }
+ QAccessible::registerAccessibleInterface(iface);
+ // ### FIXME: get interfaces from the cache instead of re-creating them
+ return iface;
+}
+
+int QAccessibleTree::rowCount() const
+{
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ return treeView->d_func()->viewItems.count();
+}
+
+int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const
+{
+ if (!view()->model())
+ return -1;
+ QAccessibleInterface *parent = iface->parent();
+ if (parent->object() != view())
+ return -1;
+
+ if (iface->role() == QAccessible::TreeItem) {
+ const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface);
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
+ int column = cell->m_index.column();
+
+ int index = row * view()->model()->columnCount() + column;
+ return index;
+ } else if (iface->role() == QAccessible::ColumnHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return cell->index;
+ } else {
+ qWarning() << "WARNING QAccessibleTable::indexOfChild invalid child"
+ << iface->role() << iface->text(QAccessible::Name);
+ }
+ // FIXME: add scrollbars and don't just ignore them
+ return -1;
+}
+
+QAccessibleInterface *QAccessibleTree::cellAt(int row, int column) const
+{
+ QModelIndex index = indexFromLogical(row, column);
+ if (!index.isValid()) {
+ qWarning() << "Requested invalid tree cell: " << row << column;
+ return 0;
+ }
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ int logicalIndex = treeView->d_func()->accessibleTable2Index(index);
+
+ return child(logicalIndex); // FIXME ### new QAccessibleTableCell(view(), index, cellRole());
+}
+
+QString QAccessibleTree::rowDescription(int) const
+{
+ return QString(); // no headers for rows in trees
+}
+
+bool QAccessibleTree::isRowSelected(int row) const
+{
+ if (!view()->selectionModel())
+ return false;
+ QModelIndex index = indexFromLogical(row);
+ return view()->selectionModel()->isRowSelected(index.row(), index.parent());
+}
+
+bool QAccessibleTree::selectRow(int row)
+{
+ if (!view()->selectionModel())
+ return false;
+ QModelIndex index = indexFromLogical(row);
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ return true;
+}
+
+// TABLE CELL
+
+QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_)
+ : /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_)
+{
+ if (!index_.isValid())
+ qWarning() << "QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_;
+}
+
+void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TableCellInterface)
+ return static_cast<QAccessibleTableCellInterface*>(this);
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
+ return 0;
+}
+
+int QAccessibleTableCell::columnExtent() const { return 1; }
+int QAccessibleTableCell::rowExtent() const { return 1; }
+
+QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells() const
+{
+ QList<QAccessibleInterface*> headerCell;
+ if (verticalHeader()) {
+ // FIXME
+ headerCell.append(new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical));
+ }
+ return headerCell;
+}
+
+QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells() const
+{
+ QList<QAccessibleInterface*> headerCell;
+ if (horizontalHeader()) {
+ // FIXME
+ headerCell.append(new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal));
+ }
+ return headerCell;
+}
+
+QHeaderView *QAccessibleTableCell::horizontalHeader() const
+{
+ QHeaderView *header = 0;
+
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ header = tv->horizontalHeader();
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+
+ return header;
+}
+
+QHeaderView *QAccessibleTableCell::verticalHeader() const
+{
+ QHeaderView *header = 0;
+#ifndef QT_NO_TABLEVIEW
+ if (const QTableView *tv = qobject_cast<const QTableView*>(view))
+ header = tv->verticalHeader();
+#endif
+ return header;
+}
+
+int QAccessibleTableCell::columnIndex() const
+{
+ return m_index.column();
+}
+
+int QAccessibleTableCell::rowIndex() const
+{
+ if (role() == QAccessible::TreeItem) {
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
+ Q_ASSERT(treeView);
+ int row = treeView->d_func()->viewIndex(m_index);
+ return row;
+ }
+ return m_index.row();
+}
+
+bool QAccessibleTableCell::isSelected() const
+{
+ return view->selectionModel()->isSelected(m_index);
+}
+
+QStringList QAccessibleTableCell::actionNames() const
+{
+ QStringList names;
+ names << toggleAction();
+ return names;
+}
+
+void QAccessibleTableCell::doAction(const QString& actionName)
+{
+ if (actionName == toggleAction()) {
+ if (isSelected())
+ unselectCell();
+ else
+ selectCell();
+ }
+}
+
+QStringList QAccessibleTableCell::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+
+void QAccessibleTableCell::selectCell()
+{
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
+ return;
+ Q_ASSERT(table());
+ QAccessibleTableInterface *cellTable = table()->tableInterface();
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable)
+ cellTable->selectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable)
+ cellTable->selectRow(m_index.row());
+ return;
+ }
+
+ if (selectionMode == QAbstractItemView::SingleSelection) {
+ view->clearSelection();
+ }
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Select);
+}
+
+void QAccessibleTableCell::unselectCell()
+{
+
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection))
+ return;
+
+ QAccessibleTableInterface *cellTable = table()->tableInterface();
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable)
+ cellTable->unselectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable)
+ cellTable->unselectRow(m_index.row());
+ return;
+ }
+
+ //If the mode is not MultiSelection or ExtendedSelection and only
+ //one cell is selected it cannot be unselected by the user
+ if ((selectionMode != QAbstractItemView::MultiSelection)
+ && (selectionMode != QAbstractItemView::ExtendedSelection)
+ && (view->selectionModel()->selectedIndexes().count() <= 1))
+ return;
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
+}
+
+QAccessibleInterface *QAccessibleTableCell::table() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessible::Role QAccessibleTableCell::role() const
+{
+ return m_role;
+}
+
+QAccessible::State QAccessibleTableCell::state() const
+{
+ QAccessible::State st;
+ QRect globalRect = view->rect();
+ globalRect.translate(view->mapToGlobal(QPoint(0,0)));
+ if (!globalRect.intersects(rect()))
+ st.invisible = true;
+
+ if (view->selectionModel()->isSelected(m_index))
+ st.selected = true;
+ if (view->selectionModel()->currentIndex() == m_index)
+ st.focused = true;
+ if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked)
+ st.checked = true;
+
+ Qt::ItemFlags flags = m_index.flags();
+ if (flags & Qt::ItemIsSelectable) {
+ st.selectable = true;
+ st.focusable = true;
+ if (view->selectionMode() == QAbstractItemView::MultiSelection)
+ st.multiSelectable = true;
+ if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
+ st.extSelectable = true;
+ }
+ if (m_role == QAccessible::TreeItem) {
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
+ if (treeView->model()->hasChildren(m_index))
+ st.expandable = true;
+ if (treeView->isExpanded(m_index))
+ st.expanded = true;
+ }
+ return st;
+}
+
+
+QRect QAccessibleTableCell::rect() const
+{
+ QRect r;
+ r = view->visualRect(m_index);
+
+ if (!r.isNull()) {
+ r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
+ r.translate(view->mapToGlobal(QPoint(0, 0)));
+ }
+ return r;
+}
+
+QString QAccessibleTableCell::text(QAccessible::Text t) const
+{
+ QAbstractItemModel *model = view->model();
+ QString value;
+ switch (t) {
+ case QAccessible::Name:
+ value = model->data(m_index, Qt::AccessibleTextRole).toString();
+ if (value.isEmpty())
+ value = model->data(m_index, Qt::DisplayRole).toString();
+ break;
+ case QAccessible::Description:
+ value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+void QAccessibleTableCell::setText(QAccessible::Text /*t*/, const QString &text)
+{
+ if (!(m_index.flags() & Qt::ItemIsEditable))
+ return;
+ view->model()->setData(m_index, text);
+}
+
+bool QAccessibleTableCell::isValid() const
+{
+ return view && view->model() && m_index.isValid();
+}
+
+QAccessibleInterface *QAccessibleTableCell::parent() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessibleInterface *QAccessibleTableCell::child(int) const
+{
+ return 0;
+}
+
+QAccessibleTableHeaderCell::QAccessibleTableHeaderCell(QAbstractItemView *view_, int index_, Qt::Orientation orientation_)
+ : view(view_), index(index_), orientation(orientation_)
+{
+ Q_ASSERT(index_ >= 0);
+}
+
+QAccessible::Role QAccessibleTableHeaderCell::role() const
+{
+ if (orientation == Qt::Horizontal)
+ return QAccessible::ColumnHeader;
+ return QAccessible::RowHeader;
+}
+
+QAccessible::State QAccessibleTableHeaderCell::state() const
+{
+ QAccessible::State s;
+ if (QHeaderView *h = headerView()) {
+ s.invisible = !h->testAttribute(Qt::WA_WState_Visible);
+ s.disabled = !h->isEnabled();
+ }
+ return s;
+}
+
+QRect QAccessibleTableHeaderCell::rect() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ if (orientation == Qt::Horizontal) {
+ header = tv->horizontalHeader();
+ } else {
+ header = tv->verticalHeader();
+ }
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+ if (!header)
+ return QRect();
+ QPoint zero = header->mapToGlobal(QPoint(0, 0));
+ int sectionSize = header->sectionSize(index);
+ int sectionPos = header->sectionPosition(index);
+ return orientation == Qt::Horizontal
+ ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
+ : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
+}
+
+QString QAccessibleTableHeaderCell::text(QAccessible::Text t) const
+{
+ QAbstractItemModel *model = view->model();
+ QString value;
+ switch (t) {
+ case QAccessible::Name:
+ value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
+ if (value.isEmpty())
+ value = model->headerData(index, orientation, Qt::DisplayRole).toString();
+ break;
+ case QAccessible::Description:
+ value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+void QAccessibleTableHeaderCell::setText(QAccessible::Text, const QString &)
+{
+ return;
+}
+
+bool QAccessibleTableHeaderCell::isValid() const
+{
+ return view && view->model() && (index >= 0)
+ && ((orientation == Qt::Horizontal) ? (index < view->model()->columnCount()) : (index < view->model()->rowCount()));
+}
+
+QAccessibleInterface *QAccessibleTableHeaderCell::parent() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessibleInterface *QAccessibleTableHeaderCell::child(int) const
+{
+ return 0;
+}
+
+QHeaderView *QAccessibleTableHeaderCell::headerView() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ if (orientation == Qt::Horizontal) {
+ header = tv->horizontalHeader();
+ } else {
+ header = tv->verticalHeader();
+ }
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+ return header;
+}
+
+#endif // QT_NO_ITEMVIEWS
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/itemviews.h b/src/widgets/accessible/itemviews.h
new file mode 100644
index 0000000000..2f9ca6163b
--- /dev/null
+++ b/src/widgets/accessible/itemviews.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACCESSIBLE_ITEMVIEWS_H
+#define ACCESSIBLE_ITEMVIEWS_H
+
+#include "QtCore/qpointer.h"
+#include <QtGui/qaccessible.h>
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtWidgets/qabstractitemview.h>
+#include <QtWidgets/qheaderview.h>
+
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_ITEMVIEWS
+
+class QAccessibleTableCell;
+class QAccessibleTableHeaderCell;
+
+class QAccessibleTable :public QAccessibleTableInterface, public QAccessibleObject
+{
+public:
+ explicit QAccessibleTable(QWidget *w);
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // table interface
+ virtual QAccessibleInterface *cellAt(int row, int column) const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface *caption() const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface *summary() const Q_DECL_OVERRIDE;
+ virtual QString columnDescription(int column) const Q_DECL_OVERRIDE;
+ virtual QString rowDescription(int row) const Q_DECL_OVERRIDE;
+ virtual int columnCount() const Q_DECL_OVERRIDE;
+ virtual int rowCount() const Q_DECL_OVERRIDE;
+
+ // selection
+ virtual int selectedCellCount() const Q_DECL_OVERRIDE;
+ virtual int selectedColumnCount() const Q_DECL_OVERRIDE;
+ virtual int selectedRowCount() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> selectedCells() const Q_DECL_OVERRIDE;
+ virtual QList<int> selectedColumns() const Q_DECL_OVERRIDE;
+ virtual QList<int> selectedRows() const Q_DECL_OVERRIDE;
+ virtual bool isColumnSelected(int column) const Q_DECL_OVERRIDE;
+ virtual bool isRowSelected(int row) const Q_DECL_OVERRIDE;
+ virtual bool selectRow(int row) Q_DECL_OVERRIDE;
+ virtual bool selectColumn(int column) Q_DECL_OVERRIDE;
+ virtual bool unselectRow(int row) Q_DECL_OVERRIDE;
+ virtual bool unselectColumn(int column) Q_DECL_OVERRIDE;
+
+ QAbstractItemView *view() const;
+
+ void modelChange(QAccessibleTableModelChangeEvent *event) Q_DECL_OVERRIDE;
+
+protected:
+ inline QAccessible::Role cellRole() const {
+ switch (m_role) {
+ case QAccessible::List:
+ return QAccessible::ListItem;
+ case QAccessible::Table:
+ return QAccessible::Cell;
+ case QAccessible::Tree:
+ return QAccessible::TreeItem;
+ default:
+ Q_ASSERT(0);
+ }
+ return QAccessible::NoRole;
+ }
+
+ QHeaderView *horizontalHeader() const;
+ QHeaderView *verticalHeader() const;
+
+ // maybe vector
+ typedef QHash<int, QAccessible::Id> ChildCache;
+ mutable ChildCache childToId;
+
+ virtual ~QAccessibleTable();
+
+private:
+ // the child index for a model index
+ inline int logicalIndex(const QModelIndex &index) const;
+ QAccessible::Role m_role;
+};
+
+class QAccessibleTree :public QAccessibleTable
+{
+public:
+ explicit QAccessibleTree(QWidget *w)
+ : QAccessibleTable(w)
+ {}
+
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE;
+
+ int rowCount() const Q_DECL_OVERRIDE;
+
+ // table interface
+ QAccessibleInterface *cellAt(int row, int column) const Q_DECL_OVERRIDE;
+ QString rowDescription(int row) const Q_DECL_OVERRIDE;
+ bool isRowSelected(int row) const Q_DECL_OVERRIDE;
+ bool selectRow(int row) Q_DECL_OVERRIDE;
+
+private:
+ QModelIndex indexFromLogical(int row, int column = 0) const;
+
+ inline int logicalIndex(const QModelIndex &index) const;
+};
+
+class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
+{
+public:
+ QAccessibleTableCell(QAbstractItemView *view, const QModelIndex &m_index, QAccessible::Role role);
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int) const Q_DECL_OVERRIDE;
+
+ // cell interface
+ virtual int columnExtent() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> columnHeaderCells() const Q_DECL_OVERRIDE;
+ virtual int columnIndex() const Q_DECL_OVERRIDE;
+ virtual int rowExtent() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> rowHeaderCells() const Q_DECL_OVERRIDE;
+ virtual int rowIndex() const Q_DECL_OVERRIDE;
+ virtual bool isSelected() const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface* table() const Q_DECL_OVERRIDE;
+
+ //action interface
+ virtual QStringList actionNames() const Q_DECL_OVERRIDE;
+ virtual void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ virtual QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+private:
+ QHeaderView *verticalHeader() const;
+ QHeaderView *horizontalHeader() const;
+ QPointer<QAbstractItemView > view;
+ QModelIndex m_index;
+ QAccessible::Role m_role;
+
+ void selectCell();
+ void unselectCell();
+
+friend class QAccessibleTable;
+friend class QAccessibleTree;
+};
+
+
+class QAccessibleTableHeaderCell: public QAccessibleInterface
+{
+public:
+ // For header cells, pass the header view in addition
+ QAccessibleTableHeaderCell(QAbstractItemView *view, int index, Qt::Orientation orientation);
+
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+private:
+ QHeaderView *headerView() const;
+
+ QPointer<QAbstractItemView> view;
+ int index;
+ Qt::Orientation orientation;
+
+friend class QAccessibleTable;
+friend class QAccessibleTree;
+};
+
+// This is the corner button on the top left of a table.
+// It can be used to select all cells or it is not active at all.
+// For now it is ignored.
+class QAccessibleTableCornerButton: public QAccessibleInterface
+{
+public:
+ QAccessibleTableCornerButton(QAbstractItemView *view_)
+ :view(view_)
+ {}
+
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE { return QAccessible::Pane; }
+ QAccessible::State state() const Q_DECL_OVERRIDE { return QAccessible::State(); }
+ QRect rect() const Q_DECL_OVERRIDE { return QRect(); }
+ bool isValid() const Q_DECL_OVERRIDE { return true; }
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text) const Q_DECL_OVERRIDE { return QString(); }
+ void setText(QAccessible::Text, const QString &) Q_DECL_OVERRIDE {}
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE {
+ return QAccessible::queryAccessibleInterface(view);
+ }
+ QAccessibleInterface *child(int) const Q_DECL_OVERRIDE {
+ return 0;
+ }
+
+private:
+ QPointer<QAbstractItemView> view;
+};
+
+
+#endif
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // ACCESSIBLE_ITEMVIEWS_H
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
new file mode 100644
index 0000000000..f47980d786
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblemenu.h"
+
+#include <qmenu.h>
+#include <qmenubar.h>
+#include <QtWidgets/QAction>
+#include <qstyle.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_MENU
+
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
+
+QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action)
+{
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(action);
+ if (!iface) {
+ iface = new QAccessibleMenuItem(menu, action);
+ QAccessible::registerAccessibleInterface(iface);
+ }
+ return iface;
+}
+
+QAccessibleMenu::QAccessibleMenu(QWidget *w)
+: QAccessibleWidget(w)
+{
+ Q_ASSERT(menu());
+}
+
+QMenu *QAccessibleMenu::menu() const
+{
+ return qobject_cast<QMenu*>(object());
+}
+
+int QAccessibleMenu::childCount() const
+{
+ return menu()->actions().count();
+}
+
+QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const
+{
+ QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y)));
+ if(act && act->isSeparator())
+ act = 0;
+ return act ? getOrCreateMenu(menu(), act) : 0;
+}
+
+QString QAccessibleMenu::text(QAccessible::Text t) const
+{
+ QString tx = QAccessibleWidget::text(t);
+ if (!tx.isEmpty())
+ return tx;
+
+ if (t == QAccessible::Name)
+ return menu()->windowTitle();
+ return tx;
+}
+
+QAccessible::Role QAccessibleMenu::role() const
+{
+ return QAccessible::PopupMenu;
+}
+
+QAccessibleInterface *QAccessibleMenu::child(int index) const
+{
+ if (index < childCount())
+ return getOrCreateMenu(menu(), menu()->actions().at(index));
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleMenu::parent() const
+{
+ if (QAction *menuAction = menu()->menuAction()) {
+ QList<QWidget *> parentCandidates;
+ parentCandidates << menu()->parentWidget();
+ parentCandidates << menuAction->associatedWidgets();
+ foreach (QWidget *w, parentCandidates) {
+ if (qobject_cast<QMenu*>(w) || qobject_cast<QMenuBar*>(w)) {
+ if (w->actions().indexOf(menuAction) != -1)
+ return getOrCreateMenu(w, menuAction);
+ }
+ }
+ }
+ return QAccessibleWidget::parent();
+}
+
+int QAccessibleMenu::indexOfChild( const QAccessibleInterface *child) const
+{
+ QAccessible::Role r = child->role();
+ if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menu()) {
+ return menu()->actions().indexOf(qobject_cast<QAction*>(child->object()));
+ }
+ return -1;
+}
+
+#ifndef QT_NO_MENUBAR
+QAccessibleMenuBar::QAccessibleMenuBar(QWidget *w)
+ : QAccessibleWidget(w, QAccessible::MenuBar)
+{
+ Q_ASSERT(menuBar());
+}
+
+QMenuBar *QAccessibleMenuBar::menuBar() const
+{
+ return qobject_cast<QMenuBar*>(object());
+}
+
+int QAccessibleMenuBar::childCount() const
+{
+ return menuBar()->actions().count();
+}
+
+QAccessibleInterface *QAccessibleMenuBar::child(int index) const
+{
+ if (index < childCount()) {
+ return getOrCreateMenu(menuBar(), menuBar()->actions().at(index));
+ }
+ return 0;
+}
+
+int QAccessibleMenuBar::indexOfChild(const QAccessibleInterface *child) const
+{
+ QAccessible::Role r = child->role();
+ if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menuBar()) {
+ return menuBar()->actions().indexOf(qobject_cast<QAction*>(child->object()));
+ }
+ return -1;
+}
+
+#endif // QT_NO_MENUBAR
+
+QAccessibleMenuItem::QAccessibleMenuItem(QWidget *owner, QAction *action)
+: m_action(action), m_owner(owner)
+{
+}
+
+QAccessibleMenuItem::~QAccessibleMenuItem()
+{}
+
+QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const
+{
+ for (int i = childCount() - 1; i >= 0; --i) {
+ QAccessibleInterface *childInterface = child(i);
+ if (childInterface->rect().contains(x,y)) {
+ return childInterface;
+ }
+ }
+ return 0;
+}
+
+int QAccessibleMenuItem::childCount() const
+{
+ return m_action->menu() ? 1 : 0;
+}
+
+int QAccessibleMenuItem::indexOfChild(const QAccessibleInterface * child) const
+{
+ if (child && child->role() == QAccessible::PopupMenu && child->object() == m_action->menu())
+ return 0;
+ return -1;
+}
+
+bool QAccessibleMenuItem::isValid() const
+{
+ return m_action && m_owner ? true : false;
+}
+
+QAccessibleInterface *QAccessibleMenuItem::parent() const
+{
+ return QAccessible::queryAccessibleInterface(owner());
+}
+
+QAccessibleInterface *QAccessibleMenuItem::child(int index) const
+{
+ if (index == 0 && action()->menu())
+ return QAccessible::queryAccessibleInterface(action()->menu());
+ return 0;
+}
+
+void *QAccessibleMenuItem::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
+ return 0;
+}
+
+QObject *QAccessibleMenuItem::object() const
+{
+ return m_action;
+}
+
+QRect QAccessibleMenuItem::rect() const
+{
+ QRect rect;
+ QWidget *own = owner();
+#ifndef QT_NO_MENUBAR
+ if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) {
+ rect = menuBar->actionGeometry(m_action);
+ QPoint globalPos = menuBar->mapToGlobal(QPoint(0,0));
+ rect = rect.translated(globalPos);
+ } else
+#endif // QT_NO_MENUBAR
+ if (QMenu *menu = qobject_cast<QMenu*>(own)) {
+ rect = menu->actionGeometry(m_action);
+ QPoint globalPos = menu->mapToGlobal(QPoint(0,0));
+ rect = rect.translated(globalPos);
+ }
+ return rect;
+}
+
+QAccessible::Role QAccessibleMenuItem::role() const
+{
+ return m_action->isSeparator() ? QAccessible::Separator : QAccessible::MenuItem;
+}
+
+void QAccessibleMenuItem::setText(QAccessible::Text /*t*/, const QString & /*text */)
+{
+}
+
+QAccessible::State QAccessibleMenuItem::state() const
+{
+ QAccessible::State s;
+ QWidget *own = owner();
+
+ if (own && (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false)) {
+ s.invisible = true;
+ }
+
+ if (QMenu *menu = qobject_cast<QMenu*>(own)) {
+ if (menu->activeAction() == m_action)
+ s.focused = true;
+#ifndef QT_NO_MENUBAR
+ } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) {
+ if (menuBar->activeAction() == m_action)
+ s.focused = true;
+#endif
+ }
+ if (own && own->style()->styleHint(QStyle::SH_Menu_MouseTracking))
+ s.hotTracked = true;
+ if (m_action->isSeparator() || !m_action->isEnabled())
+ s.disabled = true;
+ if (m_action->isChecked())
+ s.checked = true;
+
+ return s;
+}
+
+QString QAccessibleMenuItem::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = m_action->text();
+ str = qt_accStripAmp(str);
+ break;
+ case QAccessible::Accelerator: {
+#ifndef QT_NO_SHORTCUT
+ QKeySequence key = m_action->shortcut();
+ if (!key.isEmpty()) {
+ str = key.toString();
+ } else
+#endif
+ {
+ str = qt_accHotKey(m_action->text());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return str;
+}
+
+QStringList QAccessibleMenuItem::actionNames() const
+{
+ QStringList actions;
+ if (!m_action || m_action->isSeparator())
+ return actions;
+
+ if (m_action->menu()) {
+ actions << showMenuAction();
+ } else {
+ actions << pressAction();
+ }
+ return actions;
+}
+
+void QAccessibleMenuItem::doAction(const QString &actionName)
+{
+ if (!m_action->isEnabled())
+ return;
+
+ if (actionName == pressAction()) {
+ m_action->trigger();
+ } else if (actionName == showMenuAction()) {
+ if (QMenuBar *bar = qobject_cast<QMenuBar*>(owner())) {
+ if (m_action->menu() && m_action->menu()->isVisible()) {
+ m_action->menu()->hide();
+ } else {
+ bar->setActiveAction(m_action);
+ }
+ } else if (QMenu *menu = qobject_cast<QMenu*>(owner())){
+ if (m_action->menu() && m_action->menu()->isVisible()) {
+ m_action->menu()->hide();
+ } else {
+ menu->setActiveAction(m_action);
+ }
+ }
+ }
+}
+
+QStringList QAccessibleMenuItem::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+
+QAction *QAccessibleMenuItem::action() const
+{
+ return m_action;
+}
+
+QWidget *QAccessibleMenuItem::owner() const
+{
+ return m_owner;
+}
+
+#endif // QT_NO_MENU
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
diff --git a/src/widgets/accessible/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu.h
new file mode 100644
index 0000000000..593821e7ff
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblemenu.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEMENU_H
+#define QACCESSIBLEMENU_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_MENU
+class QMenu;
+class QMenuBar;
+class QAction;
+
+class QAccessibleMenu : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMenu(QWidget *w);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ int indexOfChild( const QAccessibleInterface *child ) const Q_DECL_OVERRIDE;
+
+protected:
+ QMenu *menu() const;
+};
+
+#ifndef QT_NO_MENUBAR
+class QAccessibleMenuBar : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMenuBar(QWidget *w);
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QMenuBar *menuBar() const;
+};
+#endif // QT_NO_MENUBAR
+
+
+class QAccessibleMenuItem : public QAccessibleInterface, public QAccessibleActionInterface
+{
+public:
+ explicit QAccessibleMenuItem(QWidget *owner, QAction *w);
+
+ ~QAccessibleMenuItem();
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface * child) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ QObject * object() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString & text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+ QWidget *owner() const;
+protected:
+ QAction *action() const;
+private:
+ QAction *m_action;
+ QPointer<QWidget> m_owner; // can hold either QMenu or the QMenuBar that contains the action
+};
+
+#endif // QT_NO_MENU
+
+QT_END_NAMESPACE
+#endif // QT_NO_ACCESSIBILITY
+#endif // QACCESSIBLEMENU_H
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp
index 4e5fade3f4..48f99f4d35 100644
--- a/src/widgets/accessible/qaccessiblewidget.cpp
+++ b/src/widgets/accessible/qaccessiblewidget.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -134,7 +134,7 @@ static int qt_accAmpIndex(const QString &text)
#endif
}
-QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
+QString qt_accStripAmp(const QString &text)
{
QString newText(text);
int ampIndex = qt_accAmpIndex(newText);
@@ -144,7 +144,7 @@ QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
return newText.replace(QLatin1String("&&"), QLatin1String("&"));
}
-QString Q_WIDGETS_EXPORT qt_accHotKey(const QString &text)
+QString qt_accHotKey(const QString &text)
{
int ampIndex = qt_accAmpIndex(text);
if (ampIndex != -1)
@@ -240,10 +240,10 @@ QWidget *QAccessibleWidget::widget() const
*/
QObject *QAccessibleWidget::parentObject() const
{
- QObject *parent = object()->parent();
- if (!parent)
- parent = qApp;
- return parent;
+ QWidget *w = widget();
+ if (!w || w->isWindow() || !w->parentWidget())
+ return qApp;
+ return w->parent();
}
/*! \reimp */
@@ -353,11 +353,7 @@ QAccessibleWidget::relations(QAccessible::Relation match /*= QAccessible::AllRel
/*! \reimp */
QAccessibleInterface *QAccessibleWidget::parent() const
{
- Q_ASSERT(widget());
- QObject *parentWidget= widget()->parentWidget();
- if (!parentWidget)
- parentWidget = qApp;
- return QAccessible::queryAccessibleInterface(parentWidget);
+ return QAccessible::queryAccessibleInterface(parentObject());
}
/*! \reimp */
diff --git a/src/widgets/accessible/qaccessiblewidget.h b/src/widgets/accessible/qaccessiblewidget.h
index 819bb5b8c4..079e5dbc42 100644
--- a/src/widgets/accessible/qaccessiblewidget.h
+++ b/src/widgets/accessible/qaccessiblewidget.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
new file mode 100644
index 0000000000..3d123cc9ab
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidgets.h"
+#include "qaccessiblemenu.h"
+#include "simplewidgets.h"
+#include "rangecontrols.h"
+#include "complexwidgets.h"
+#include "itemviews.h"
+
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qtreeview.h>
+#include <qvariant.h>
+#include <qaccessible.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object)
+{
+ QAccessibleInterface *iface = 0;
+ if (!object || !object->isWidgetType())
+ return iface;
+ QWidget *widget = static_cast<QWidget*>(object);
+
+ if (false) {
+#ifndef QT_NO_LINEEDIT
+ } else if (classname == QLatin1String("QLineEdit")) {
+ iface = new QAccessibleLineEdit(widget);
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (classname == QLatin1String("QComboBox")) {
+ iface = new QAccessibleComboBox(widget);
+#endif
+#ifndef QT_NO_SPINBOX
+ } else if (classname == QLatin1String("QAbstractSpinBox")) {
+ iface = new QAccessibleAbstractSpinBox(widget);
+ } else if (classname == QLatin1String("QSpinBox")) {
+ iface = new QAccessibleSpinBox(widget);
+ } else if (classname == QLatin1String("QDoubleSpinBox")) {
+ iface = new QAccessibleDoubleSpinBox(widget);
+#endif
+#ifndef QT_NO_SCROLLBAR
+ } else if (classname == QLatin1String("QScrollBar")) {
+ iface = new QAccessibleScrollBar(widget);
+#endif
+ } else if (classname == QLatin1String("QAbstractSlider")) {
+ iface = new QAccessibleAbstractSlider(widget);
+#ifndef QT_NO_SLIDER
+ } else if (classname == QLatin1String("QSlider")) {
+ iface = new QAccessibleSlider(widget);
+#endif
+#ifndef QT_NO_TOOLBUTTON
+ } else if (classname == QLatin1String("QToolButton")) {
+ QAccessible::Role role = QAccessible::NoRole;
+#ifndef QT_NO_MENU
+ QToolButton *tb = qobject_cast<QToolButton*>(widget);
+ if (!tb->menu())
+ role = tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
+ else if (tb->popupMode() == QToolButton::DelayedPopup)
+ role = QAccessible::ButtonDropDown;
+ else
+#endif
+ role = QAccessible::ButtonMenu;
+ iface = new QAccessibleToolButton(widget, role);
+#endif // QT_NO_TOOLBUTTON
+ } else if (classname == QLatin1String("QCheckBox")) {
+ iface = new QAccessibleButton(widget, QAccessible::CheckBox);
+ } else if (classname == QLatin1String("QRadioButton")) {
+ iface = new QAccessibleButton(widget, QAccessible::RadioButton);
+ } else if (classname == QLatin1String("QPushButton")) {
+ QAccessible::Role role = QAccessible::NoRole;
+ QPushButton *pb = qobject_cast<QPushButton*>(widget);
+#ifndef QT_NO_MENU
+ if (pb->menu())
+ role = QAccessible::ButtonMenu;
+ else
+#endif
+ if (pb->isCheckable())
+ role = QAccessible::CheckBox;
+ else
+ role = QAccessible::PushButton;
+ iface = new QAccessibleButton(widget, role);
+ } else if (classname == QLatin1String("QAbstractButton")) {
+ iface = new QAccessibleButton(widget, QAccessible::PushButton);
+ } else if (classname == QLatin1String("QDialog")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Dialog);
+ } else if (classname == QLatin1String("QMessageBox")) {
+ iface = new QAccessibleWidget(widget, QAccessible::AlertMessage);
+#ifndef QT_NO_MAINWINDOW
+ } else if (classname == QLatin1String("QMainWindow")) {
+ iface = new QAccessibleMainWindow(widget);
+#endif
+ } else if (classname == QLatin1String("QLabel") || classname == QLatin1String("QLCDNumber")) {
+ iface = new QAccessibleDisplay(widget);
+#ifndef QT_NO_GROUPBOX
+ } else if (classname == QLatin1String("QGroupBox")) {
+ iface = new QAccessibleGroupBox(widget);
+#endif
+ } else if (classname == QLatin1String("QStatusBar")) {
+ iface = new QAccessibleDisplay(widget);
+#ifndef QT_NO_PROGRESSBAR
+ } else if (classname == QLatin1String("QProgressBar")) {
+ iface = new QAccessibleProgressBar(widget);
+#endif
+ } else if (classname == QLatin1String("QToolBar")) {
+ iface = new QAccessibleWidget(widget, QAccessible::ToolBar, widget->windowTitle());
+#ifndef QT_NO_MENUBAR
+ } else if (classname == QLatin1String("QMenuBar")) {
+ iface = new QAccessibleMenuBar(widget);
+#endif
+#ifndef QT_NO_MENU
+ } else if (classname == QLatin1String("QMenu")) {
+ iface = new QAccessibleMenu(widget);
+#endif
+#ifndef QT_NO_ITEMVIEWS
+ } else if (classname == QLatin1String("QTreeView")) {
+ iface = new QAccessibleTree(widget);
+ } else if (classname == QLatin1String("QTableView") || classname == QLatin1String("QListView")) {
+ iface = new QAccessibleTable(widget);
+ // ### This should be cleaned up. We return the parent for the scrollarea to hide it.
+#endif // QT_NO_ITEMVIEWS
+#ifndef QT_NO_TABBAR
+ } else if (classname == QLatin1String("QTabBar")) {
+ iface = new QAccessibleTabBar(widget);
+#endif
+ } else if (classname == QLatin1String("QSizeGrip")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Grip);
+#ifndef QT_NO_SPLITTER
+ } else if (classname == QLatin1String("QSplitter")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Splitter);
+ } else if (classname == QLatin1String("QSplitterHandle")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Grip);
+#endif
+#if !defined(QT_NO_TEXTEDIT) && !defined(QT_NO_CURSOR)
+ } else if (classname == QLatin1String("QTextEdit")) {
+ iface = new QAccessibleTextEdit(widget);
+ } else if (classname == QLatin1String("QPlainTextEdit")) {
+ iface = new QAccessiblePlainTextEdit(widget);
+#endif
+ } else if (classname == QLatin1String("QTipLabel")) {
+ iface = new QAccessibleDisplay(widget, QAccessible::ToolTip);
+ } else if (classname == QLatin1String("QFrame")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Border);
+#ifndef QT_NO_STACKEDWIDGET
+ } else if (classname == QLatin1String("QStackedWidget")) {
+ iface = new QAccessibleStackedWidget(widget);
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (classname == QLatin1String("QToolBox")) {
+ iface = new QAccessibleToolBox(widget);
+#endif
+#ifndef QT_NO_MDIAREA
+ } else if (classname == QLatin1String("QMdiArea")) {
+ iface = new QAccessibleMdiArea(widget);
+ } else if (classname == QLatin1String("QMdiSubWindow")) {
+ iface = new QAccessibleMdiSubWindow(widget);
+#endif
+ } else if (classname == QLatin1String("QDialogButtonBox")) {
+ iface = new QAccessibleDialogButtonBox(widget);
+#ifndef QT_NO_DIAL
+ } else if (classname == QLatin1String("QDial")) {
+ iface = new QAccessibleDial(widget);
+#endif
+#ifndef QT_NO_RUBBERBAND
+ } else if (classname == QLatin1String("QRubberBand")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Border);
+#endif
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+ } else if (classname == QLatin1String("QTextBrowser")) {
+ iface = new QAccessibleTextBrowser(widget);
+#endif
+#ifndef QT_NO_SCROLLAREA
+ } else if (classname == QLatin1String("QAbstractScrollArea")) {
+ iface = new QAccessibleAbstractScrollArea(widget);
+ } else if (classname == QLatin1String("QScrollArea")) {
+ iface = new QAccessibleScrollArea(widget);
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+ } else if (classname == QLatin1String("QCalendarWidget")) {
+ iface = new QAccessibleCalendarWidget(widget);
+#endif
+#ifndef QT_NO_DOCKWIDGET
+ } else if (classname == QLatin1String("QDockWidget")) {
+ iface = new QAccessibleDockWidget(widget);
+#endif
+
+ } else if (classname == QLatin1String("QDesktopScreenWidget")) {
+ iface = 0;
+ } else if (classname == QLatin1String("QWidget")) {
+ iface = new QAccessibleWidget(widget);
+ } else if (classname == QLatin1String("QWindowContainer")) {
+ iface = new QAccessibleWindowContainer(widget);
+ }
+
+ return iface;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
new file mode 100644
index 0000000000..bf5e2da6bc
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEWIDGETFACTORY_H
+#define QACCESSIBLEWIDGETFACTORY_H
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
new file mode 100644
index 0000000000..cc6310d591
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -0,0 +1,1021 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidgets.h"
+#include "qabstracttextdocumentlayout.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+#include "qtextedit.h"
+#include "private/qtextedit_p.h"
+#include "qtextdocument.h"
+#include "qtextobject.h"
+#include "qplaintextedit.h"
+#include "qtextboundaryfinder.h"
+#include "qscrollbar.h"
+#include "qdebug.h"
+#include <QApplication>
+#include <QStackedWidget>
+#include <QToolBox>
+#include <QMdiArea>
+#include <QMdiSubWindow>
+#include <QDialogButtonBox>
+#include <limits.h>
+#include <QRubberBand>
+#include <QTextBrowser>
+#include <QCalendarWidget>
+#include <QAbstractItemView>
+#include <QDockWidget>
+#include <QMainWindow>
+#include <QAbstractButton>
+#include <private/qdockwidget_p.h>
+#include <QFocusFrame>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QString qt_accStripAmp(const QString &text);
+
+QList<QWidget*> childWidgets(const QWidget *widget)
+{
+ if (widget == 0)
+ return QList<QWidget*>();
+ QList<QObject*> list = widget->children();
+ QList<QWidget*> widgets;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(list.at(i));
+ if (!w)
+ continue;
+ QString objectName = w->objectName();
+ if (!w->isWindow()
+ && !qobject_cast<QFocusFrame*>(w)
+ && !qobject_cast<QMenu*>(w)
+ && objectName != QLatin1String("qt_rubberband")
+ && objectName != QLatin1String("qt_qmainwindow_extended_splitter")) {
+ widgets.append(w);
+ }
+ }
+ return widgets;
+}
+
+#if !defined(QT_NO_TEXTEDIT) && !defined(QT_NO_CURSOR)
+
+QAccessiblePlainTextEdit::QAccessiblePlainTextEdit(QWidget* o)
+ :QAccessibleTextWidget(o)
+{
+ Q_ASSERT(widget()->inherits("QPlainTextEdit"));
+}
+
+QPlainTextEdit* QAccessiblePlainTextEdit::plainTextEdit() const
+{
+ return static_cast<QPlainTextEdit *>(widget());
+}
+
+QString QAccessiblePlainTextEdit::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return plainTextEdit()->toPlainText();
+
+ return QAccessibleWidget::text(t);
+}
+
+void QAccessiblePlainTextEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+ if (plainTextEdit()->isReadOnly())
+ return;
+
+ plainTextEdit()->setPlainText(text);
+}
+
+QAccessible::State QAccessiblePlainTextEdit::state() const
+{
+ QAccessible::State st = QAccessibleTextWidget::state();
+ if (plainTextEdit()->isReadOnly())
+ st.readOnly = true;
+ else
+ st.editable = true;
+ return st;
+}
+
+void *QAccessiblePlainTextEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ else if (t == QAccessible::EditableTextInterface)
+ return static_cast<QAccessibleEditableTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QPoint QAccessiblePlainTextEdit::scrollBarPosition() const
+{
+ QPoint result;
+ result.setX(plainTextEdit()->horizontalScrollBar() ? plainTextEdit()->horizontalScrollBar()->sliderPosition() : 0);
+ result.setY(plainTextEdit()->verticalScrollBar() ? plainTextEdit()->verticalScrollBar()->sliderPosition() : 0);
+ return result;
+}
+
+QTextCursor QAccessiblePlainTextEdit::textCursor() const
+{
+ return plainTextEdit()->textCursor();
+}
+
+void QAccessiblePlainTextEdit::setTextCursor(const QTextCursor &textCursor)
+{
+ plainTextEdit()->setTextCursor(textCursor);
+}
+
+QTextDocument* QAccessiblePlainTextEdit::textDocument() const
+{
+ return plainTextEdit()->document();
+}
+
+QWidget* QAccessiblePlainTextEdit::viewport() const
+{
+ return plainTextEdit()->viewport();
+}
+
+void QAccessiblePlainTextEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ //TODO: Not implemented
+ Q_UNUSED(startIndex);
+ Q_UNUSED(endIndex);
+}
+
+
+/*!
+ \class QAccessibleTextEdit
+ \brief The QAccessibleTextEdit class implements the QAccessibleInterface for richtext editors.
+ \internal
+*/
+
+/*!
+ \fn QAccessibleTextEdit::QAccessibleTextEdit(QWidget *widget)
+
+ Constructs a QAccessibleTextEdit object for a \a widget.
+*/
+QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
+: QAccessibleTextWidget(o, QAccessible::EditableText)
+{
+ Q_ASSERT(widget()->inherits("QTextEdit"));
+}
+
+/*! Returns the text edit. */
+QTextEdit *QAccessibleTextEdit::textEdit() const
+{
+ return static_cast<QTextEdit *>(widget());
+}
+
+QTextCursor QAccessibleTextEdit::textCursor() const
+{
+ return textEdit()->textCursor();
+}
+
+QTextDocument *QAccessibleTextEdit::textDocument() const
+{
+ return textEdit()->document();
+}
+
+void QAccessibleTextEdit::setTextCursor(const QTextCursor &textCursor)
+{
+ textEdit()->setTextCursor(textCursor);
+}
+
+QWidget *QAccessibleTextEdit::viewport() const
+{
+ return textEdit()->viewport();
+}
+
+QPoint QAccessibleTextEdit::scrollBarPosition() const
+{
+ QPoint result;
+ result.setX(textEdit()->horizontalScrollBar() ? textEdit()->horizontalScrollBar()->sliderPosition() : 0);
+ result.setY(textEdit()->verticalScrollBar() ? textEdit()->verticalScrollBar()->sliderPosition() : 0);
+ return result;
+}
+
+QString QAccessibleTextEdit::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return textEdit()->toPlainText();
+
+ return QAccessibleWidget::text(t);
+}
+
+void QAccessibleTextEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+ if (textEdit()->isReadOnly())
+ return;
+
+ textEdit()->setText(text);
+}
+
+QAccessible::State QAccessibleTextEdit::state() const
+{
+ QAccessible::State st = QAccessibleTextWidget::state();
+ if (textEdit()->isReadOnly())
+ st.readOnly = true;
+ else
+ st.editable = true;
+ return st;
+}
+
+void *QAccessibleTextEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ else if (t == QAccessible::EditableTextInterface)
+ return static_cast<QAccessibleEditableTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ QTextEdit *edit = textEdit();
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(startIndex);
+ QRect r = edit->cursorRect(cursor);
+
+ cursor.setPosition(endIndex);
+ r.setBottomRight(edit->cursorRect(cursor).bottomRight());
+
+ r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
+ r.y() + edit->verticalScrollBar()->value());
+
+ // E V I L, but ensureVisible is not public
+ if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
+ qWarning("AccessibleTextEdit::scrollToSubstring failed!");
+}
+
+#endif // QT_NO_TEXTEDIT && QT_NO_CURSOR
+
+#ifndef QT_NO_STACKEDWIDGET
+// ======================= QAccessibleStackedWidget ======================
+QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
+}
+
+QAccessibleInterface *QAccessibleStackedWidget::childAt(int x, int y) const
+{
+ if (!stackedWidget()->isVisible())
+ return 0;
+ QWidget *currentWidget = stackedWidget()->currentWidget();
+ if (!currentWidget)
+ return 0;
+ QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
+ if (currentWidget->rect().contains(position))
+ return child(stackedWidget()->currentIndex());
+ return 0;
+}
+
+int QAccessibleStackedWidget::childCount() const
+{
+ return stackedWidget()->count();
+}
+
+int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child)
+ return -1;
+
+ QWidget *widget = qobject_cast<QWidget*>(child->object());
+ return stackedWidget()->indexOf(widget);
+}
+
+QAccessibleInterface *QAccessibleStackedWidget::child(int index) const
+{
+ if (index < 0 || index >= stackedWidget()->count())
+ return 0;
+ return QAccessible::queryAccessibleInterface(stackedWidget()->widget(index));
+}
+
+QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
+{
+ return static_cast<QStackedWidget *>(object());
+}
+#endif // QT_NO_STACKEDWIDGET
+
+#ifndef QT_NO_TOOLBOX
+// ======================= QAccessibleToolBox ======================
+QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QToolBox *>(widget));
+}
+
+QToolBox * QAccessibleToolBox::toolBox() const
+{
+ return static_cast<QToolBox *>(object());
+}
+#endif // QT_NO_TOOLBOX
+
+// ======================= QAccessibleMdiArea ======================
+#ifndef QT_NO_MDIAREA
+QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QMdiArea *>(widget));
+}
+
+int QAccessibleMdiArea::childCount() const
+{
+ return mdiArea()->subWindowList().count();
+}
+
+QAccessibleInterface *QAccessibleMdiArea::child(int index) const
+{
+ QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
+ QWidget *targetObject = subWindows.value(index);
+ if (!targetObject)
+ return 0;
+ return QAccessible::queryAccessibleInterface(targetObject);
+}
+
+
+int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
+ return -1;
+ if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
+ return mdiArea()->subWindowList().indexOf(window);
+ }
+ return -1;
+}
+
+QMdiArea *QAccessibleMdiArea::mdiArea() const
+{
+ return static_cast<QMdiArea *>(object());
+}
+
+// ======================= QAccessibleMdiSubWindow ======================
+QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window)
+{
+ Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
+}
+
+QString QAccessibleMdiSubWindow::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Name) {
+ QString title = mdiSubWindow()->windowTitle();
+ title.replace(QLatin1String("[*]"), QLatin1String(""));
+ return title;
+ }
+ return QAccessibleWidget::text(textType);
+}
+
+void QAccessibleMdiSubWindow::setText(QAccessible::Text textType, const QString &text)
+{
+ if (textType == QAccessible::Name)
+ mdiSubWindow()->setWindowTitle(text);
+ else
+ QAccessibleWidget::setText(textType, text);
+}
+
+QAccessible::State QAccessibleMdiSubWindow::state() const
+{
+ QAccessible::State state;
+ state.focusable = true;
+ if (!mdiSubWindow()->isMaximized()) {
+ state.movable = true;
+ state.sizeable = true;
+ }
+ if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
+ || QApplication::focusWidget() == mdiSubWindow())
+ state.focused = true;
+ if (!mdiSubWindow()->isVisible())
+ state.invisible = true;
+ if (const QWidget *parent = mdiSubWindow()->parentWidget())
+ if (!parent->contentsRect().contains(mdiSubWindow()->geometry()))
+ state.offscreen = true;
+ if (!mdiSubWindow()->isEnabled())
+ state.disabled = true;
+ return state;
+}
+
+int QAccessibleMdiSubWindow::childCount() const
+{
+ if (mdiSubWindow()->widget())
+ return 1;
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleMdiSubWindow::child(int index) const
+{
+ QMdiSubWindow *source = mdiSubWindow();
+ if (index != 0 || !source->widget())
+ return 0;
+
+ return QAccessible::queryAccessibleInterface(source->widget());
+}
+
+int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child && child->object() && child->object() == mdiSubWindow()->widget())
+ return 0;
+ return -1;
+}
+
+QRect QAccessibleMdiSubWindow::rect() const
+{
+ if (mdiSubWindow()->isHidden())
+ return QRect();
+ if (!mdiSubWindow()->parent())
+ return QAccessibleWidget::rect();
+ const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
+ return QRect(pos, mdiSubWindow()->size());
+}
+
+QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
+{
+ return static_cast<QMdiSubWindow *>(object());
+}
+#endif // QT_NO_MDIAREA
+
+#ifndef QT_NO_DIALOGBUTTONBOX
+// ======================= QAccessibleDialogButtonBox ======================
+QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Grouping)
+{
+ Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
+}
+
+#endif // QT_NO_DIALOGBUTTONBOX
+
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
+ : QAccessibleTextEdit(widget)
+{
+ Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
+}
+
+QAccessible::Role QAccessibleTextBrowser::role() const
+{
+ return QAccessible::StaticText;
+}
+#endif // QT_NO_TEXTBROWSER && QT_NO_CURSOR
+
+#ifndef QT_NO_CALENDARWIDGET
+// ===================== QAccessibleCalendarWidget ========================
+QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Table)
+{
+ Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
+}
+
+int QAccessibleCalendarWidget::childCount() const
+{
+ return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
+}
+
+int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || childCount() <= 0)
+ return -1;
+ if (qobject_cast<QAbstractItemView *>(child->object()))
+ return childCount() - 1; // FIXME
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleCalendarWidget::child(int index) const
+{
+ if (index < 0 || index >= childCount())
+ return 0;
+
+ if (childCount() > 1 && index == 0)
+ return QAccessible::queryAccessibleInterface(navigationBar());
+
+ return QAccessible::queryAccessibleInterface(calendarView());
+}
+
+QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
+{
+ return static_cast<QCalendarWidget *>(object());
+}
+
+QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
+{
+ foreach (QObject *child, calendarWidget()->children()) {
+ if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
+ return static_cast<QAbstractItemView *>(child);
+ }
+ return 0;
+}
+
+QWidget *QAccessibleCalendarWidget::navigationBar() const
+{
+ foreach (QObject *child, calendarWidget()->children()) {
+ if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
+ return static_cast<QWidget *>(child);
+ }
+ return 0;
+}
+#endif // QT_NO_CALENDARWIDGET
+
+#ifndef QT_NO_DOCKWIDGET
+
+// Dock Widget - order of children:
+// - Content widget
+// - Float button
+// - Close button
+// If there is a custom title bar widget, that one becomes child 1, after the content 0
+// (in that case the buttons are ignored)
+QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window)
+{
+}
+
+QDockWidgetLayout *QAccessibleDockWidget::dockWidgetLayout() const
+{
+ return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
+}
+
+int QAccessibleDockWidget::childCount() const
+{
+ if (dockWidget()->titleBarWidget()) {
+ return dockWidget()->widget() ? 2 : 1;
+ }
+ return dockWidgetLayout()->count();
+}
+
+QAccessibleInterface *QAccessibleDockWidget::child(int index) const
+{
+ if (dockWidget()->titleBarWidget()) {
+ if ((!dockWidget()->widget() && index == 0) || (index == 1))
+ return QAccessible::queryAccessibleInterface(dockWidget()->titleBarWidget());
+ if (index == 0)
+ return QAccessible::queryAccessibleInterface(dockWidget()->widget());
+ } else {
+ QLayoutItem *item = dockWidgetLayout()->itemAt(index);
+ if (item)
+ return QAccessible::queryAccessibleInterface(item->widget());
+ }
+ return 0;
+}
+
+int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || child->object()->parent() != object())
+ return -1;
+
+ if (dockWidget()->titleBarWidget() == child->object()) {
+ return dockWidget()->widget() ? 1 : 0;
+ }
+
+ return dockWidgetLayout()->indexOf(qobject_cast<QWidget*>(child->object()));
+}
+
+QRect QAccessibleDockWidget::rect() const
+{
+ QRect rect;
+
+ if (dockWidget()->isFloating()) {
+ rect = dockWidget()->frameGeometry();
+ } else {
+ rect = dockWidget()->rect();
+ rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
+ }
+
+ return rect;
+}
+
+QDockWidget *QAccessibleDockWidget::dockWidget() const
+{
+ return static_cast<QDockWidget *>(object());
+}
+
+QString QAccessibleDockWidget::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Name) {
+ return qt_accStripAmp(dockWidget()->windowTitle());
+ }
+ return QString();
+}
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_CURSOR
+
+QAccessibleTextWidget::QAccessibleTextWidget(QWidget *o, QAccessible::Role r, const QString &name):
+ QAccessibleWidget(o, r, name)
+{
+
+}
+
+QAccessible::State QAccessibleTextWidget::state() const
+{
+ QAccessible::State s = QAccessibleWidget::state();
+ s.selectableText = true;
+ s.multiLine = true;
+ return s;
+}
+
+QRect QAccessibleTextWidget::characterRect(int offset) const
+{
+ QTextBlock block = textDocument()->findBlock(offset);
+ if (!block.isValid())
+ return QRect();
+
+ QTextLayout *layout = block.layout();
+ QPointF layoutPosition = layout->position();
+ int relativeOffset = offset - block.position();
+ QTextLine line = layout->lineForTextPosition(relativeOffset);
+
+ QRect r;
+
+ if (line.isValid()) {
+ qreal x = line.cursorToX(relativeOffset);
+ QFontMetrics fm(textCursor().charFormat().font());
+ const QString ch = text(offset, offset + 1);
+ if (!ch.isEmpty()) {
+ int w = fm.width(ch);
+ int h = fm.height();
+ r = QRect(layoutPosition.x() + x, layoutPosition.y() + line.y(),
+ w, h);
+ r.moveTo(viewport()->mapToGlobal(r.topLeft()));
+ }
+ r.translate(-scrollBarPosition());
+ }
+
+ return r;
+}
+
+int QAccessibleTextWidget::offsetAtPoint(const QPoint &point) const
+{
+ QPoint p = viewport()->mapFromGlobal(point);
+ // convert to document coordinates
+ p += scrollBarPosition();
+ return textDocument()->documentLayout()->hitTest(p, Qt::ExactHit);
+}
+
+int QAccessibleTextWidget::selectionCount() const
+{
+ return textCursor().hasSelection() ? 1 : 0;
+}
+
+QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *endOffset) const
+{
+ /* The list of attributes can be found at:
+ http://linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes
+ */
+
+ // IAccessible2 defines -1 as length and -2 as cursor position
+ if (offset == -2)
+ offset = cursorPosition();
+
+ const int charCount = characterCount();
+
+ // -1 doesn't make much sense here, but it's better to return something
+ // screen readers may ask for text attributes at the cursor pos which may be equal to length
+ if (offset == -1 || offset == charCount)
+ offset = charCount - 1;
+
+ if (offset < 0 || offset > charCount) {
+ *startOffset = -1;
+ *endOffset = -1;
+ return QString();
+ }
+
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QTextBlock block = cursor.block();
+
+ int blockStart = block.position();
+ int blockEnd = blockStart + block.length();
+
+ QTextBlock::iterator iter = block.begin();
+ while (!iter.fragment().contains(offset))
+ ++iter;
+
+ QTextFragment fragment = iter.fragment();
+ int pos = fragment.position();
+
+ // text block and fragment may overlap, use the smallest common range
+ *startOffset = qMax(pos, blockStart);
+ Q_ASSERT(*startOffset <= offset);
+ *endOffset = qMin(pos + fragment.length(), blockEnd);
+ Q_ASSERT(*endOffset >= offset);
+
+ QTextCharFormat charFormat = fragment.charFormat();
+ QTextBlockFormat blockFormat = cursor.blockFormat();
+
+ QMap<QByteArray, QString> attrs;
+ QString family = charFormat.fontFamily();
+ if (!family.isEmpty()) {
+ family = family.replace('\\',QStringLiteral("\\\\"));
+ family = family.replace(':',QStringLiteral("\\:"));
+ family = family.replace(',',QStringLiteral("\\,"));
+ family = family.replace('=',QStringLiteral("\\="));
+ family = family.replace(';',QStringLiteral("\\;"));
+ family = family.replace('\"',QStringLiteral("\\\""));
+ attrs["font-family"] = QString::fromLatin1("\"%1\"").arg(family);
+ }
+
+ int fontSize = int(charFormat.fontPointSize());
+ if (fontSize)
+ attrs["font-size"] = QString::fromLatin1("%1pt").arg(fontSize);
+
+ //Different weight values are not handled
+ attrs["font-weight"] = QString::fromLatin1(charFormat.fontWeight() > QFont::Normal ? "bold" : "normal");
+
+ QFont::Style style = charFormat.font().style();
+ attrs["font-style"] = QString::fromLatin1((style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal"));
+
+ attrs["text-underline-style"] = QString::fromLatin1(charFormat.font().underline() ? "solid" : "none");
+
+ QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
+ attrs["text-position"] = QString::fromLatin1((alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" ));
+
+ QBrush background = charFormat.background();
+ if (background.style() == Qt::SolidPattern) {
+ attrs["background-color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
+ }
+
+ QBrush foreground = charFormat.foreground();
+ if (foreground.style() == Qt::SolidPattern) {
+ attrs["color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
+ }
+
+ switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
+ case Qt::AlignLeft:
+ attrs["text-align"] = QStringLiteral("left");
+ break;
+ case Qt::AlignRight:
+ attrs["text-align"] = QStringLiteral("right");
+ break;
+ case Qt::AlignHCenter:
+ attrs["text-align"] = QStringLiteral("center");
+ break;
+ case Qt::AlignJustify:
+ attrs["text-align"] = QStringLiteral("left");
+ break;
+ }
+
+ QString result;
+ foreach (const QByteArray &attributeName, attrs.keys()) {
+ result.append(QString::fromLatin1(attributeName)).append(':').append(attrs[attributeName]).append(';');
+ }
+
+ return result;
+}
+
+int QAccessibleTextWidget::cursorPosition() const
+{
+ return textCursor().position();
+}
+
+void QAccessibleTextWidget::selection(int selectionIndex, int *startOffset, int *endOffset) const
+{
+ *startOffset = *endOffset = 0;
+ QTextCursor cursor = textCursor();
+
+ if (selectionIndex != 0 || !cursor.hasSelection())
+ return;
+
+ *startOffset = cursor.selectionStart();
+ *endOffset = cursor.selectionEnd();
+}
+
+QString QAccessibleTextWidget::text(int startOffset, int endOffset) const
+{
+ QTextCursor cursor(textCursor());
+
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+
+ return cursor.selectedText().replace(QChar(QChar::ParagraphSeparator), QLatin1Char('\n'));
+}
+
+QPoint QAccessibleTextWidget::scrollBarPosition() const
+{
+ return QPoint(0, 0);
+}
+
+
+QString QAccessibleTextWidget::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ cursor.setPosition(boundaries.first - 1);
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+ }
+
+
+QString QAccessibleTextWidget::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ cursor.setPosition(boundaries.second);
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+}
+
+QString QAccessibleTextWidget::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+}
+
+void QAccessibleTextWidget::setCursorPosition(int position)
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(position);
+ setTextCursor(cursor);
+}
+
+void QAccessibleTextWidget::addSelection(int startOffset, int endOffset)
+{
+ setSelection(0, startOffset, endOffset);
+}
+
+void QAccessibleTextWidget::removeSelection(int selectionIndex)
+{
+ if (selectionIndex != 0)
+ return;
+
+ QTextCursor cursor = textCursor();
+ cursor.clearSelection();
+ setTextCursor(cursor);
+}
+
+void QAccessibleTextWidget::setSelection(int selectionIndex, int startOffset, int endOffset)
+{
+ if (selectionIndex != 0)
+ return;
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+ setTextCursor(cursor);
+}
+
+int QAccessibleTextWidget::characterCount() const
+{
+ QTextCursor cursor = textCursor();
+ cursor.movePosition(QTextCursor::End);
+ return cursor.position();
+}
+
+QTextCursor QAccessibleTextWidget::textCursorForRange(int startOffset, int endOffset) const
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+
+ return cursor;
+}
+
+void QAccessibleTextWidget::deleteText(int startOffset, int endOffset)
+{
+ QTextCursor cursor = textCursorForRange(startOffset, endOffset);
+ cursor.removeSelectedText();
+}
+
+void QAccessibleTextWidget::insertText(int offset, const QString &text)
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ cursor.insertText(text);
+}
+
+void QAccessibleTextWidget::replaceText(int startOffset, int endOffset, const QString &text)
+{
+ QTextCursor cursor = textCursorForRange(startOffset, endOffset);
+ cursor.removeSelectedText();
+ cursor.insertText(text);
+}
+#endif // QT_NO_CURSOR
+
+
+#ifndef QT_NO_MAINWINDOW
+QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window) { }
+
+QAccessibleInterface *QAccessibleMainWindow::child(int index) const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow());
+ if (index >= 0 && index < kids.count()) {
+ return QAccessible::queryAccessibleInterface(kids.at(index));
+ }
+ return 0;
+}
+
+int QAccessibleMainWindow::childCount() const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow());
+ return kids.count();
+}
+
+int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow());
+ return kids.indexOf(static_cast<QWidget*>(iface->object()));
+}
+
+QAccessibleInterface *QAccessibleMainWindow::childAt(int x, int y) const
+{
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return 0;
+ QPoint gp = w->mapToGlobal(QPoint(0, 0));
+ if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
+ return 0;
+
+ QWidgetList kids = childWidgets(mainWindow());
+ QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y));
+ for (int i = 0; i < kids.size(); ++i) {
+ QWidget *child = kids.at(i);
+ if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
+ return QAccessible::queryAccessibleInterface(child);
+ }
+ }
+ return 0;
+}
+
+QMainWindow *QAccessibleMainWindow::mainWindow() const
+{
+ return qobject_cast<QMainWindow *>(object());
+}
+
+#endif //QT_NO_MAINWINDOW
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets.h
new file mode 100644
index 0000000000..27764cb0ac
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgets.h
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEWIDGETS_H
+#define QACCESSIBLEWIDGETS_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include <QtCore/QPointer>
+#include <QtCore/QPair>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+class QStackedWidget;
+class QToolBox;
+class QMdiArea;
+class QMdiSubWindow;
+class QRubberBand;
+class QTextBrowser;
+class QCalendarWidget;
+class QAbstractItemView;
+class QDockWidget;
+class QDockWidgetLayout;
+class QMainWindow;
+class QPlainTextEdit;
+class QTextCursor;
+class QTextDocument;
+
+#ifndef QT_NO_CURSOR
+class QAccessibleTextWidget : public QAccessibleWidget,
+ public QAccessibleTextInterface,
+ public QAccessibleEditableTextInterface
+{
+public:
+ QAccessibleTextWidget(QWidget *o, QAccessible::Role r = QAccessible::EditableText, const QString &name = QString());
+
+ QAccessible::State state() const;
+
+ // QAccessibleTextInterface
+ // selection
+ void selection(int selectionIndex, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int selectionCount() const Q_DECL_OVERRIDE;
+ void addSelection(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void removeSelection(int selectionIndex) Q_DECL_OVERRIDE;
+ void setSelection(int selectionIndex, int startOffset, int endOffset) Q_DECL_OVERRIDE;
+
+ // cursor
+ int cursorPosition() const Q_DECL_OVERRIDE;
+ void setCursorPosition(int position) Q_DECL_OVERRIDE;
+
+ // text
+ QString text(int startOffset, int endOffset) const Q_DECL_OVERRIDE;
+ QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int characterCount() const;
+
+ // character <-> geometry
+ QRect characterRect(int offset) const Q_DECL_OVERRIDE;
+ int offsetAtPoint(const QPoint &point) const Q_DECL_OVERRIDE;
+
+ QString attributes(int offset, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+
+ // QAccessibleEditableTextInterface
+ void deleteText(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void insertText(int offset, const QString &text) Q_DECL_OVERRIDE;
+ void replaceText(int startOffset, int endOffset, const QString &text) Q_DECL_OVERRIDE;
+
+ using QAccessibleWidget::text;
+
+protected:
+ QTextCursor textCursorForRange(int startOffset, int endOffset) const;
+ virtual QPoint scrollBarPosition() const;
+ // return the current text cursor at the caret position including a potential selection
+ virtual QTextCursor textCursor() const = 0;
+ virtual void setTextCursor(const QTextCursor &) = 0;
+ virtual QTextDocument *textDocument() const = 0;
+ virtual QWidget *viewport() const = 0;
+};
+
+#ifndef QT_NO_TEXTEDIT
+class QAccessiblePlainTextEdit : public QAccessibleTextWidget
+{
+public:
+ explicit QAccessiblePlainTextEdit(QWidget *o);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ using QAccessibleTextWidget::text;
+
+protected:
+ QPlainTextEdit *plainTextEdit() const;
+
+ QPoint scrollBarPosition() const Q_DECL_OVERRIDE;
+ QTextCursor textCursor() const Q_DECL_OVERRIDE;
+ void setTextCursor(const QTextCursor &textCursor) Q_DECL_OVERRIDE;
+ QTextDocument *textDocument() const Q_DECL_OVERRIDE;
+ QWidget *viewport() const Q_DECL_OVERRIDE;
+};
+
+class QAccessibleTextEdit : public QAccessibleTextWidget
+{
+public:
+ explicit QAccessibleTextEdit(QWidget *o);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ using QAccessibleTextWidget::text;
+
+protected:
+ QTextEdit *textEdit() const;
+
+ QPoint scrollBarPosition() const Q_DECL_OVERRIDE;
+ QTextCursor textCursor() const Q_DECL_OVERRIDE;
+ void setTextCursor(const QTextCursor &textCursor) Q_DECL_OVERRIDE;
+ QTextDocument *textDocument() const Q_DECL_OVERRIDE;
+ QWidget *viewport() const Q_DECL_OVERRIDE;
+};
+#endif // QT_NO_TEXTEDIT
+#endif //QT_NO_CURSOR
+
+class QAccessibleStackedWidget : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleStackedWidget(QWidget *widget);
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+protected:
+ QStackedWidget *stackedWidget() const;
+};
+
+class QAccessibleToolBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleToolBox(QWidget *widget);
+
+// FIXME we currently expose the toolbox but it is not keyboard navigatable
+// and the accessible hierarchy is not exactly beautiful.
+// int childCount() const;
+// QAccessibleInterface *child(int index) const;
+// int indexOfChild(const QAccessibleInterface *child) const;
+
+protected:
+ QToolBox *toolBox() const;
+};
+
+#ifndef QT_NO_MDIAREA
+class QAccessibleMdiArea : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMdiArea(QWidget *widget);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QMdiArea *mdiArea() const;
+};
+
+class QAccessibleMdiSubWindow : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMdiSubWindow(QWidget *widget);
+
+ QString text(QAccessible::Text textType) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text textType, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+
+protected:
+ QMdiSubWindow *mdiSubWindow() const;
+};
+#endif // QT_NO_MDIAREA
+
+class QAccessibleDialogButtonBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleDialogButtonBox(QWidget *widget);
+};
+
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+class QAccessibleTextBrowser : public QAccessibleTextEdit
+{
+public:
+ explicit QAccessibleTextBrowser(QWidget *widget);
+
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+};
+#endif // QT_NO_TEXTBROWSER && QT_NO_CURSOR
+
+#ifndef QT_NO_CALENDARWIDGET
+class QAccessibleCalendarWidget : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleCalendarWidget(QWidget *widget);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+protected:
+ QCalendarWidget *calendarWidget() const;
+
+private:
+ QAbstractItemView *calendarView() const;
+ QWidget *navigationBar() const;
+};
+#endif // QT_NO_CALENDARWIDGET
+
+#ifndef QT_NO_DOCKWIDGET
+class QAccessibleDockWidget: public QAccessibleWidget
+{
+public:
+ explicit QAccessibleDockWidget(QWidget *widget);
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QRect rect () const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QDockWidget *dockWidget() const;
+protected:
+ QDockWidgetLayout *dockWidgetLayout() const;
+};
+
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_MAINWINDOW
+class QAccessibleMainWindow : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMainWindow(QWidget *widget);
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *iface) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ QMainWindow *mainWindow() const;
+
+};
+#endif //QT_NO_MAINWINDOW
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // QACESSIBLEWIDGETS_H
diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
new file mode 100644
index 0000000000..d4dc74ea69
--- /dev/null
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rangecontrols.h"
+
+#include <qslider.h>
+#include <qdial.h>
+#include <qspinbox.h>
+#include <qscrollbar.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qdebug.h>
+#include <qglobal.h>
+#include <QDoubleSpinBox>
+#include <QDial>
+#include <qmath.h>
+#include <private/qmath_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_SPINBOX
+QAccessibleAbstractSpinBox::QAccessibleAbstractSpinBox(QWidget *w)
+: QAccessibleWidget(w, QAccessible::SpinBox)
+{
+ Q_ASSERT(abstractSpinBox());
+}
+
+/*!
+ Returns the underlying QAbstractSpinBox.
+*/
+QAbstractSpinBox *QAccessibleAbstractSpinBox::abstractSpinBox() const
+{
+ return qobject_cast<QAbstractSpinBox*>(object());
+}
+
+QString QAccessibleAbstractSpinBox::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return abstractSpinBox()->text();
+ return QAccessibleWidget::text(t);
+}
+
+void *QAccessibleAbstractSpinBox::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QVariant QAccessibleAbstractSpinBox::currentValue() const
+{
+ return abstractSpinBox()->property("value");
+}
+
+void QAccessibleAbstractSpinBox::setCurrentValue(const QVariant &value)
+{
+ abstractSpinBox()->setProperty("value", value);
+}
+
+QVariant QAccessibleAbstractSpinBox::maximumValue() const
+{
+ return abstractSpinBox()->property("maximum");
+}
+
+QVariant QAccessibleAbstractSpinBox::minimumValue() const
+{
+ return abstractSpinBox()->property("minimum");
+}
+
+QVariant QAccessibleAbstractSpinBox::minimumStepSize() const
+{
+ return abstractSpinBox()->property("stepSize");
+}
+
+/*!
+ \class QAccessibleSpinBox
+ \brief The QAccessibleSpinBox class implements the QAccessibleInterface for spinbox widgets.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleSpinWidget object for \a w.
+*/
+QAccessibleSpinBox::QAccessibleSpinBox(QWidget *w)
+: QAccessibleAbstractSpinBox(w)
+{
+ Q_ASSERT(spinBox());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+ addControllingSignal(QLatin1String("valueChanged(QString)"));
+}
+
+/*!
+ Returns the underlying QSpinBox.
+*/
+QSpinBox *QAccessibleSpinBox::spinBox() const
+{
+ return qobject_cast<QSpinBox*>(object());
+}
+
+
+// ================================== QAccessibleDoubleSpinBox ==================================
+QAccessibleDoubleSpinBox::QAccessibleDoubleSpinBox(QWidget *widget)
+ : QAccessibleAbstractSpinBox(widget)
+{
+ Q_ASSERT(qobject_cast<QDoubleSpinBox *>(widget));
+ addControllingSignal(QLatin1String("valueChanged(double)"));
+ addControllingSignal(QLatin1String("valueChanged(QString)"));
+}
+
+/*!
+ Returns the underlying QDoubleSpinBox.
+*/
+QDoubleSpinBox *QAccessibleDoubleSpinBox::doubleSpinBox() const
+{
+ return static_cast<QDoubleSpinBox*>(object());
+}
+
+QString QAccessibleDoubleSpinBox::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Value)
+ return doubleSpinBox()->textFromValue(doubleSpinBox()->value());
+ return QAccessibleWidget::text(textType);
+}
+
+#endif // QT_NO_SPINBOX
+
+#ifndef QT_NO_SCROLLBAR
+/*!
+ \class QAccessibleScrollBar
+ \brief The QAccessibleScrollBar class implements the QAccessibleInterface for scroll bars.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleScrollBar object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleScrollBar::QAccessibleScrollBar(QWidget *w)
+: QAccessibleAbstractSlider(w, QAccessible::ScrollBar)
+{
+ Q_ASSERT(scrollBar());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+/*! Returns the scroll bar. */
+QScrollBar *QAccessibleScrollBar::scrollBar() const
+{
+ return qobject_cast<QScrollBar*>(object());
+}
+
+QString QAccessibleScrollBar::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return QString::number(scrollBar()->value());
+ return QAccessibleAbstractSlider::text(t);
+}
+
+#endif // QT_NO_SCROLLBAR
+
+#ifndef QT_NO_SLIDER
+/*!
+ \class QAccessibleSlider
+ \brief The QAccessibleSlider class implements the QAccessibleInterface for sliders.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleScrollBar object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleSlider::QAccessibleSlider(QWidget *w)
+: QAccessibleAbstractSlider(w)
+{
+ Q_ASSERT(slider());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+/*! Returns the slider. */
+QSlider *QAccessibleSlider::slider() const
+{
+ return qobject_cast<QSlider*>(object());
+}
+
+QString QAccessibleSlider::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return QString::number(slider()->value());
+
+ return QAccessibleAbstractSlider::text(t);
+}
+
+QAccessibleAbstractSlider::QAccessibleAbstractSlider(QWidget *w, QAccessible::Role r)
+ : QAccessibleWidget(w, r)
+{
+ Q_ASSERT(qobject_cast<QAbstractSlider *>(w));
+}
+
+void *QAccessibleAbstractSlider::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QVariant QAccessibleAbstractSlider::currentValue() const
+{
+ return abstractSlider()->value();
+}
+
+void QAccessibleAbstractSlider::setCurrentValue(const QVariant &value)
+{
+ abstractSlider()->setValue(value.toInt());
+}
+
+QVariant QAccessibleAbstractSlider::maximumValue() const
+{
+ return abstractSlider()->maximum();
+}
+
+QVariant QAccessibleAbstractSlider::minimumValue() const
+{
+ return abstractSlider()->minimum();
+}
+
+QVariant QAccessibleAbstractSlider::minimumStepSize() const
+{
+ return abstractSlider()->singleStep();
+}
+
+QAbstractSlider *QAccessibleAbstractSlider::abstractSlider() const
+{
+ return static_cast<QAbstractSlider *>(object());
+}
+
+#endif // QT_NO_SLIDER
+
+#ifndef QT_NO_DIAL
+// ======================================= QAccessibleDial ======================================
+QAccessibleDial::QAccessibleDial(QWidget *widget)
+ : QAccessibleAbstractSlider(widget, QAccessible::Dial)
+{
+ Q_ASSERT(qobject_cast<QDial *>(widget));
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+QString QAccessibleDial::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Value)
+ return QString::number(dial()->value());
+
+ return QAccessibleAbstractSlider::text(textType);
+}
+
+QDial *QAccessibleDial::dial() const
+{
+ return static_cast<QDial*>(object());
+}
+#endif // QT_NO_DIAL
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
diff --git a/src/widgets/accessible/rangecontrols.h b/src/widgets/accessible/rangecontrols.h
new file mode 100644
index 0000000000..98cef46c5c
--- /dev/null
+++ b/src/widgets/accessible/rangecontrols.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RANGECONTROLS_H
+#define RANGECONTROLS_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractSpinBox;
+class QAbstractSlider;
+class QScrollBar;
+class QSlider;
+class QSpinBox;
+class QDoubleSpinBox;
+class QDial;
+
+#ifndef QT_NO_SPINBOX
+class QAccessibleAbstractSpinBox: public QAccessibleWidget, public QAccessibleValueInterface // TODO, public QAccessibleActionInterface
+{
+public:
+ explicit QAccessibleAbstractSpinBox(QWidget *w);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &value) Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+
+ // FIXME Action interface
+
+protected:
+ QAbstractSpinBox *abstractSpinBox() const;
+};
+
+class QAccessibleSpinBox : public QAccessibleAbstractSpinBox
+{
+public:
+ explicit QAccessibleSpinBox(QWidget *w);
+
+protected:
+ QSpinBox *spinBox() const;
+};
+
+class QAccessibleDoubleSpinBox : public QAccessibleAbstractSpinBox
+{
+public:
+ explicit QAccessibleDoubleSpinBox(QWidget *widget);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QDoubleSpinBox *doubleSpinBox() const;
+};
+#endif // QT_NO_SPINBOX
+
+class QAccessibleAbstractSlider: public QAccessibleWidget, public QAccessibleValueInterface
+{
+public:
+ explicit QAccessibleAbstractSlider(QWidget *w, QAccessible::Role r = QAccessible::Slider);
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &value) Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+
+protected:
+ QAbstractSlider *abstractSlider() const;
+};
+
+#ifndef QT_NO_SCROLLBAR
+class QAccessibleScrollBar : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleScrollBar(QWidget *w);
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QScrollBar *scrollBar() const;
+};
+#endif // QT_NO_SCROLLBAR
+
+#ifndef QT_NO_SLIDER
+class QAccessibleSlider : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleSlider(QWidget *w);
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QSlider *slider() const;
+};
+#endif // QT_NO_SLIDER
+
+#ifndef QT_NO_DIAL
+class QAccessibleDial : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleDial(QWidget *w);
+
+ QString text(QAccessible::Text textType) const Q_DECL_OVERRIDE;
+
+protected:
+ QDial *dial() const;
+};
+#endif // QT_NO_DIAL
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // RANGECONTROLS_H
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
new file mode 100644
index 0000000000..88d3981391
--- /dev/null
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -0,0 +1,904 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "simplewidgets.h"
+
+#include <qabstractbutton.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qprogressbar.h>
+#include <qstatusbar.h>
+#include <qradiobutton.h>
+#include <qtoolbutton.h>
+#include <qmenu.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qlcdnumber.h>
+#include <qlineedit.h>
+#include <private/qlineedit_p.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qtextdocument.h>
+#include <qwindow.h>
+#include <private/qwindowcontainer_p.h>
+#include <QtCore/qvarlengtharray.h>
+
+#ifdef Q_OS_MAC
+#include <qfocusframe.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+extern QList<QWidget*> childWidgets(const QWidget *widget);
+
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
+
+/*!
+ \class QAccessibleButton
+ \brief The QAccessibleButton class implements the QAccessibleInterface for button type widgets.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Creates a QAccessibleButton object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleButton::QAccessibleButton(QWidget *w, QAccessible::Role role)
+: QAccessibleWidget(w, role)
+{
+ Q_ASSERT(button());
+ if (button()->isCheckable())
+ addControllingSignal(QLatin1String("toggled(bool)"));
+ else
+ addControllingSignal(QLatin1String("clicked()"));
+}
+
+/*! Returns the button. */
+QAbstractButton *QAccessibleButton::button() const
+{
+ return qobject_cast<QAbstractButton*>(object());
+}
+
+/*! \reimp */
+QString QAccessibleButton::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Accelerator:
+ {
+#ifndef QT_NO_SHORTCUT
+ QPushButton *pb = qobject_cast<QPushButton*>(object());
+ if (pb && pb->isDefault())
+ str = QKeySequence(Qt::Key_Enter).toString(QKeySequence::NativeText);
+#endif
+ if (str.isEmpty())
+ str = qt_accHotKey(button()->text());
+ }
+ break;
+ case QAccessible::Name:
+ str = widget()->accessibleName();
+ if (str.isEmpty())
+ str = button()->text();
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+QAccessible::State QAccessibleButton::state() const
+{
+ QAccessible::State state = QAccessibleWidget::state();
+
+ QAbstractButton *b = button();
+ QCheckBox *cb = qobject_cast<QCheckBox *>(b);
+ if (b->isCheckable())
+ state.checkable = true;
+ if (b->isChecked())
+ state.checked = true;
+ else if (cb && cb->checkState() == Qt::PartiallyChecked)
+ state.checkStateMixed = true;
+ if (b->isDown())
+ state.pressed = true;
+ QPushButton *pb = qobject_cast<QPushButton*>(b);
+ if (pb) {
+ if (pb->isDefault())
+ state.defaultButton = true;
+#ifndef QT_NO_MENU
+ if (pb->menu())
+ state.hasPopup = true;
+#endif
+ }
+
+ return state;
+}
+
+QRect QAccessibleButton::rect() const
+{
+ QAbstractButton *ab = button();
+ if (!ab->isVisible())
+ return QRect();
+
+ if (QCheckBox *cb = qobject_cast<QCheckBox *>(ab)) {
+ QPoint wpos = cb->mapToGlobal(QPoint(0, 0));
+ QStyleOptionButton opt;
+ cb->initStyleOption(&opt);
+ return cb->style()->subElementRect(QStyle::SE_CheckBoxClickRect, &opt, cb).translated(wpos);
+ } else if (QRadioButton *rb = qobject_cast<QRadioButton *>(ab)) {
+ QPoint wpos = rb->mapToGlobal(QPoint(0, 0));
+ QStyleOptionButton opt;
+ rb->initStyleOption(&opt);
+ return rb->style()->subElementRect(QStyle::SE_RadioButtonClickRect, &opt, rb).translated(wpos);
+ }
+ return QAccessibleWidget::rect();
+}
+
+QStringList QAccessibleButton::actionNames() const
+{
+ QStringList names;
+ if (widget()->isEnabled()) {
+ switch (role()) {
+ case QAccessible::ButtonMenu:
+ names << showMenuAction();
+ break;
+ case QAccessible::RadioButton:
+ names << toggleAction();
+ break;
+ default:
+ if (button()->isCheckable()) {
+ names << toggleAction();
+ } else {
+ names << pressAction();
+ }
+ break;
+ }
+ }
+ names << QAccessibleWidget::actionNames();
+ return names;
+}
+
+void QAccessibleButton::doAction(const QString &actionName)
+{
+ if (!widget()->isEnabled())
+ return;
+ if (actionName == pressAction() ||
+ actionName == showMenuAction()) {
+#ifndef QT_NO_MENU
+ QPushButton *pb = qobject_cast<QPushButton*>(object());
+ if (pb && pb->menu())
+ pb->showMenu();
+ else
+#endif
+ button()->animateClick();
+ } else if (actionName == toggleAction()) {
+ button()->toggle();
+ } else {
+ QAccessibleWidget::doAction(actionName);
+ }
+}
+
+QStringList QAccessibleButton::keyBindingsForAction(const QString &actionName) const
+{
+ if (actionName == pressAction()) {
+#ifndef QT_NO_SHORTCUT
+ return QStringList() << button()->shortcut().toString();
+#endif
+ }
+ return QStringList();
+}
+
+
+#ifndef QT_NO_TOOLBUTTON
+/*!
+ \class QAccessibleToolButton
+ \brief The QAccessibleToolButton class implements the QAccessibleInterface for tool buttons.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Creates a QAccessibleToolButton object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleToolButton::QAccessibleToolButton(QWidget *w, QAccessible::Role role)
+: QAccessibleButton(w, role)
+{
+ Q_ASSERT(toolButton());
+}
+
+/*! Returns the button. */
+QToolButton *QAccessibleToolButton::toolButton() const
+{
+ return qobject_cast<QToolButton*>(object());
+}
+
+/*!
+ Returns \c true if this tool button is a split button.
+*/
+bool QAccessibleToolButton::isSplitButton() const
+{
+#ifndef QT_NO_MENU
+ return toolButton()->menu() && toolButton()->popupMode() == QToolButton::MenuButtonPopup;
+#else
+ return false;
+#endif
+}
+
+QAccessible::State QAccessibleToolButton::state() const
+{
+ QAccessible::State st = QAccessibleButton::state();
+ if (toolButton()->autoRaise())
+ st.hotTracked = true;
+#ifndef QT_NO_MENU
+ if (toolButton()->menu())
+ st.hasPopup = true;
+#endif
+ return st;
+}
+
+int QAccessibleToolButton::childCount() const
+{
+ return isSplitButton() ? 1 : 0;
+}
+
+QAccessibleInterface *QAccessibleToolButton::child(int index) const
+{
+#ifndef QT_NO_MENU
+ if (index == 0 && toolButton()->menu())
+ {
+ return QAccessible::queryAccessibleInterface(toolButton()->menu());
+ }
+#endif
+ return 0;
+}
+
+/*!
+ \internal
+
+ Returns the button's text label, depending on the text \a t, and
+ the \a child.
+*/
+QString QAccessibleToolButton::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = toolButton()->accessibleName();
+ if (str.isEmpty())
+ str = toolButton()->text();
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleButton::text(t);
+ return qt_accStripAmp(str);
+}
+
+/*
+ The three different tool button types can have the following actions:
+| DelayedPopup | ShowMenuAction + (PressedAction || CheckedAction) |
+| MenuButtonPopup | ShowMenuAction + (PressedAction || CheckedAction) |
+| InstantPopup | ShowMenuAction |
+*/
+QStringList QAccessibleToolButton::actionNames() const
+{
+ QStringList names;
+ if (widget()->isEnabled()) {
+ if (toolButton()->menu())
+ names << showMenuAction();
+ if (toolButton()->popupMode() != QToolButton::InstantPopup)
+ names << QAccessibleButton::actionNames();
+ }
+ return names;
+}
+
+void QAccessibleToolButton::doAction(const QString &actionName)
+{
+ if (!widget()->isEnabled())
+ return;
+
+ if (actionName == pressAction()) {
+ button()->click();
+ } else if (actionName == showMenuAction()) {
+ if (toolButton()->popupMode() != QToolButton::InstantPopup) {
+ toolButton()->setDown(true);
+#ifndef QT_NO_MENU
+ toolButton()->showMenu();
+#endif
+ }
+ } else {
+ QAccessibleButton::doAction(actionName);
+ }
+
+}
+
+#endif // QT_NO_TOOLBUTTON
+
+/*!
+ \class QAccessibleDisplay
+ \brief The QAccessibleDisplay class implements the QAccessibleInterface for widgets that display information.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleDisplay object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleDisplay::QAccessibleDisplay(QWidget *w, QAccessible::Role role)
+: QAccessibleWidget(w, role)
+{
+}
+
+QAccessible::Role QAccessibleDisplay::role() const
+{
+ QLabel *l = qobject_cast<QLabel*>(object());
+ if (l) {
+ if (l->pixmap())
+ return QAccessible::Graphic;
+#ifndef QT_NO_PICTURE
+ if (l->picture())
+ return QAccessible::Graphic;
+#endif
+#ifndef QT_NO_MOVIE
+ if (l->movie())
+ return QAccessible::Animation;
+#endif
+#ifndef QT_NO_PROGRESSBAR
+ } else if (qobject_cast<QProgressBar*>(object())) {
+ return QAccessible::ProgressBar;
+#endif
+ } else if (qobject_cast<QStatusBar*>(object())) {
+ return QAccessible::StatusBar;
+ }
+ return QAccessibleWidget::role();
+}
+
+QString QAccessibleDisplay::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = widget()->accessibleName();
+ if (str.isEmpty()) {
+ if (qobject_cast<QLabel*>(object())) {
+ QLabel *label = qobject_cast<QLabel*>(object());
+ str = label->text();
+ if (label->textFormat() == Qt::RichText
+ || (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) {
+ QTextDocument doc;
+ doc.setHtml(str);
+ str = doc.toPlainText();
+ }
+#ifndef QT_NO_LCDNUMBER
+ } else if (qobject_cast<QLCDNumber*>(object())) {
+ QLCDNumber *l = qobject_cast<QLCDNumber*>(object());
+ if (l->digitCount())
+ str = QString::number(l->value());
+ else
+ str = QString::number(l->intValue());
+#endif
+ } else if (qobject_cast<QStatusBar*>(object())) {
+ return qobject_cast<QStatusBar*>(object())->currentMessage();
+ }
+ }
+ break;
+ case QAccessible::Value:
+#ifndef QT_NO_PROGRESSBAR
+ if (qobject_cast<QProgressBar*>(object()))
+ str = QString::number(qobject_cast<QProgressBar*>(object())->value());
+#endif
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+/*! \reimp */
+QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
+QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
+{
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
+ if (match & QAccessible::Labelled) {
+ QVarLengthArray<QObject *, 4> relatedObjects;
+
+#ifndef QT_NO_SHORTCUT
+ if (QLabel *label = qobject_cast<QLabel*>(object())) {
+ relatedObjects.append(label->buddy());
+ }
+#endif
+ for (int i = 0; i < relatedObjects.count(); ++i) {
+ const QAccessible::Relation rel = QAccessible::Labelled;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i));
+ if (iface)
+ rels.append(qMakePair(iface, rel));
+ }
+ }
+ return rels;
+}
+
+void *QAccessibleDisplay::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ImageInterface)
+ return static_cast<QAccessibleImageInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+/*! \internal */
+QString QAccessibleDisplay::imageDescription() const
+{
+#ifndef QT_NO_TOOLTIP
+ return widget()->toolTip();
+#else
+ return QString::null;
+#endif
+}
+
+/*! \internal */
+QSize QAccessibleDisplay::imageSize() const
+{
+ QLabel *label = qobject_cast<QLabel *>(widget());
+ if (!label)
+ return QSize();
+ const QPixmap *pixmap = label->pixmap();
+ if (!pixmap)
+ return QSize();
+ return pixmap->size();
+}
+
+/*! \internal */
+QPoint QAccessibleDisplay::imagePosition() const
+{
+ QLabel *label = qobject_cast<QLabel *>(widget());
+ if (!label)
+ return QPoint();
+ const QPixmap *pixmap = label->pixmap();
+ if (!pixmap)
+ return QPoint();
+
+ return QPoint(label->mapToGlobal(label->pos()));
+}
+
+#ifndef QT_NO_GROUPBOX
+QAccessibleGroupBox::QAccessibleGroupBox(QWidget *w)
+: QAccessibleWidget(w)
+{
+}
+
+QGroupBox* QAccessibleGroupBox::groupBox() const
+{
+ return static_cast<QGroupBox *>(widget());
+}
+
+QString QAccessibleGroupBox::text(QAccessible::Text t) const
+{
+ QString txt = QAccessibleWidget::text(t);
+
+ if (txt.isEmpty()) {
+ switch (t) {
+ case QAccessible::Name:
+ txt = qt_accStripAmp(groupBox()->title());
+ break;
+ case QAccessible::Description:
+ txt = qt_accStripAmp(groupBox()->toolTip());
+ break;
+ default:
+ break;
+ }
+ }
+
+ return txt;
+}
+
+QAccessible::State QAccessibleGroupBox::state() const
+{
+ QAccessible::State st = QAccessibleWidget::state();
+ st.checkable = groupBox()->isCheckable();
+ st.checked = groupBox()->isChecked();
+ return st;
+}
+
+QAccessible::Role QAccessibleGroupBox::role() const
+{
+ return groupBox()->isCheckable() ? QAccessible::CheckBox : QAccessible::Grouping;
+}
+
+QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
+QAccessibleGroupBox::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
+{
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
+
+ if ((match & QAccessible::Labelled) && (!groupBox()->title().isEmpty())) {
+ const QList<QWidget*> kids = childWidgets(widget());
+ for (int i = 0; i < kids.count(); ++i) {
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(kids.at(i));
+ if (iface)
+ rels.append(qMakePair(iface, QAccessible::Relation(QAccessible::Labelled)));
+ }
+ }
+ return rels;
+}
+
+QStringList QAccessibleGroupBox::actionNames() const
+{
+ QStringList actions = QAccessibleWidget::actionNames();
+
+ if (groupBox()->isCheckable()) {
+ actions.prepend(QAccessibleActionInterface::toggleAction());
+ }
+ return actions;
+}
+
+void QAccessibleGroupBox::doAction(const QString &actionName)
+{
+ if (actionName == QAccessibleActionInterface::toggleAction())
+ groupBox()->setChecked(!groupBox()->isChecked());
+}
+
+QStringList QAccessibleGroupBox::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+#endif
+
+#ifndef QT_NO_LINEEDIT
+/*!
+ \class QAccessibleLineEdit
+ \brief The QAccessibleLineEdit class implements the QAccessibleInterface for widgets with editable text
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleLineEdit object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleLineEdit::QAccessibleLineEdit(QWidget *w, const QString &name)
+: QAccessibleWidget(w, QAccessible::EditableText, name)
+{
+ addControllingSignal(QLatin1String("textChanged(const QString&)"));
+ addControllingSignal(QLatin1String("returnPressed()"));
+}
+
+/*! Returns the line edit. */
+QLineEdit *QAccessibleLineEdit::lineEdit() const
+{
+ return qobject_cast<QLineEdit*>(object());
+}
+
+QString QAccessibleLineEdit::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Value:
+ if (lineEdit()->echoMode() == QLineEdit::Normal)
+ str = lineEdit()->text();
+ else if (lineEdit()->echoMode() != QLineEdit::NoEcho)
+ str = QString(lineEdit()->text().length(), QChar::fromLatin1('*'));
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+void QAccessibleLineEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+
+ QString newText = text;
+ if (lineEdit()->validator()) {
+ int pos = 0;
+ if (lineEdit()->validator()->validate(newText, pos) != QValidator::Acceptable)
+ return;
+ }
+ lineEdit()->setText(newText);
+}
+
+QAccessible::State QAccessibleLineEdit::state() const
+{
+ QAccessible::State state = QAccessibleWidget::state();
+
+ QLineEdit *l = lineEdit();
+ if (l->isReadOnly())
+ state.readOnly = true;
+ else
+ state.editable = true;
+
+ if (l->echoMode() != QLineEdit::Normal)
+ state.passwordEdit = true;
+
+ state.selectableText = true;
+ return state;
+}
+
+void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ if (t == QAccessible::EditableTextInterface)
+ return static_cast<QAccessibleEditableTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+void QAccessibleLineEdit::addSelection(int startOffset, int endOffset)
+{
+ setSelection(0, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::attributes(int offset, int *startOffset, int *endOffset) const
+{
+ // QLineEdit doesn't have text attributes
+ *startOffset = *endOffset = offset;
+ return QString();
+}
+
+int QAccessibleLineEdit::cursorPosition() const
+{
+ return lineEdit()->cursorPosition();
+}
+
+QRect QAccessibleLineEdit::characterRect(int offset) const
+{
+ int x = lineEdit()->d_func()->control->cursorToX(offset);
+ int y;
+ lineEdit()->getTextMargins(0, &y, 0, 0);
+ QFontMetrics fm(lineEdit()->font());
+ const QString ch = text(offset, offset + 1);
+ if (ch.isEmpty())
+ return QRect();
+ int w = fm.width(ch);
+ int h = fm.height();
+ QRect r(x, y, w, h);
+ r.moveTo(lineEdit()->mapToGlobal(r.topLeft()));
+ return r;
+}
+
+int QAccessibleLineEdit::selectionCount() const
+{
+ return lineEdit()->hasSelectedText() ? 1 : 0;
+}
+
+int QAccessibleLineEdit::offsetAtPoint(const QPoint &point) const
+{
+ QPoint p = lineEdit()->mapFromGlobal(point);
+
+ return lineEdit()->cursorPositionAt(p);
+}
+
+void QAccessibleLineEdit::selection(int selectionIndex, int *startOffset, int *endOffset) const
+{
+ *startOffset = *endOffset = 0;
+ if (selectionIndex != 0)
+ return;
+
+ *startOffset = lineEdit()->selectionStart();
+ *endOffset = *startOffset + lineEdit()->selectedText().count();
+}
+
+QString QAccessibleLineEdit::text(int startOffset, int endOffset) const
+{
+ if (startOffset > endOffset)
+ return QString();
+
+ if (lineEdit()->echoMode() != QLineEdit::Normal)
+ return QString();
+
+ return lineEdit()->text().mid(startOffset, endOffset - startOffset);
+}
+
+QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+void QAccessibleLineEdit::removeSelection(int selectionIndex)
+{
+ if (selectionIndex != 0)
+ return;
+
+ lineEdit()->deselect();
+}
+
+void QAccessibleLineEdit::setCursorPosition(int position)
+{
+ lineEdit()->setCursorPosition(position);
+}
+
+void QAccessibleLineEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
+{
+ if (selectionIndex != 0)
+ return;
+
+ lineEdit()->setSelection(startOffset, endOffset - startOffset);
+}
+
+int QAccessibleLineEdit::characterCount() const
+{
+ return lineEdit()->text().count();
+}
+
+void QAccessibleLineEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ lineEdit()->setCursorPosition(endIndex);
+ lineEdit()->setCursorPosition(startIndex);
+}
+
+void QAccessibleLineEdit::deleteText(int startOffset, int endOffset)
+{
+ lineEdit()->setText(lineEdit()->text().remove(startOffset, endOffset - startOffset));
+}
+
+void QAccessibleLineEdit::insertText(int offset, const QString &text)
+{
+ lineEdit()->setText(lineEdit()->text().insert(offset, text));
+}
+
+void QAccessibleLineEdit::replaceText(int startOffset, int endOffset, const QString &text)
+{
+ lineEdit()->setText(lineEdit()->text().replace(startOffset, endOffset - startOffset, text));
+}
+
+#endif // QT_NO_LINEEDIT
+
+#ifndef QT_NO_PROGRESSBAR
+QAccessibleProgressBar::QAccessibleProgressBar(QWidget *o)
+ : QAccessibleDisplay(o)
+{
+ Q_ASSERT(progressBar());
+}
+
+void *QAccessibleProgressBar::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleDisplay::interface_cast(t);
+}
+
+QVariant QAccessibleProgressBar::currentValue() const
+{
+ return progressBar()->value();
+}
+
+QVariant QAccessibleProgressBar::maximumValue() const
+{
+ return progressBar()->maximum();
+}
+
+QVariant QAccessibleProgressBar::minimumValue() const
+{
+ return progressBar()->minimum();
+}
+
+QVariant QAccessibleProgressBar::minimumStepSize() const
+{
+ // This is arbitrary since any value between min and max is valid.
+ // Some screen readers (orca use it to calculate how many digits to display though,
+ // so it makes sense to return a "sensible" value. Providing 100 increments seems ok.
+ return (progressBar()->maximum() - progressBar()->minimum()) / 100.0;
+}
+
+QProgressBar *QAccessibleProgressBar::progressBar() const
+{
+ return qobject_cast<QProgressBar *>(object());
+}
+#endif
+
+
+QAccessibleWindowContainer::QAccessibleWindowContainer(QWidget *w)
+ : QAccessibleWidget(w)
+{
+}
+
+int QAccessibleWindowContainer::childCount() const
+{
+ if (container()->containedWindow())
+ return 1;
+ return 0;
+}
+
+int QAccessibleWindowContainer::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child->object() == container()->containedWindow())
+ return 0;
+ return -1;
+}
+
+QAccessibleInterface *QAccessibleWindowContainer::child(int i) const
+{
+ if (i == 0)
+ return QAccessible::queryAccessibleInterface(container()->containedWindow());
+ return 0;
+}
+
+QWindowContainer *QAccessibleWindowContainer::container() const
+{
+ return static_cast<QWindowContainer *>(widget());
+}
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
diff --git a/src/widgets/accessible/simplewidgets.h b/src/widgets/accessible/simplewidgets.h
new file mode 100644
index 0000000000..e4ce6150e2
--- /dev/null
+++ b/src/widgets/accessible/simplewidgets.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIMPLEWIDGETS_H
+#define SIMPLEWIDGETS_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtWidgets/qaccessiblewidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractButton;
+class QLineEdit;
+class QToolButton;
+class QGroupBox;
+class QProgressBar;
+
+class QAccessibleButton : public QAccessibleWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(QAccessibleButton)
+public:
+ QAccessibleButton(QWidget *w, QAccessible::Role r);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+protected:
+ QAbstractButton *button() const;
+};
+
+#ifndef QT_NO_TOOLBUTTON
+class QAccessibleToolButton : public QAccessibleButton
+{
+public:
+ QAccessibleToolButton(QWidget *w, QAccessible::Role role);
+
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+
+protected:
+ QToolButton *toolButton() const;
+
+ bool isSplitButton() const;
+};
+#endif // QT_NO_TOOLBUTTON
+
+class QAccessibleDisplay : public QAccessibleWidget, public QAccessibleImageInterface
+{
+public:
+ explicit QAccessibleDisplay(QWidget *w, QAccessible::Role role = QAccessible::StaticText);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >relations(QAccessible::Relation match = QAccessible::AllRelations) const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleImageInterface
+ QString imageDescription() const Q_DECL_OVERRIDE;
+ QSize imageSize() const Q_DECL_OVERRIDE;
+ QPoint imagePosition() const Q_DECL_OVERRIDE;
+};
+
+#ifndef QT_NO_GROUPBOX
+class QAccessibleGroupBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleGroupBox(QWidget *w);
+
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >relations(QAccessible::Relation match = QAccessible::AllRelations) const Q_DECL_OVERRIDE;
+
+ //QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &) const Q_DECL_OVERRIDE;
+
+private:
+ QGroupBox *groupBox() const;
+};
+#endif
+
+#ifndef QT_NO_LINEEDIT
+class QAccessibleLineEdit : public QAccessibleWidget, public QAccessibleTextInterface, public QAccessibleEditableTextInterface
+{
+public:
+ explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString());
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void addSelection(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ QString attributes(int offset, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int cursorPosition() const Q_DECL_OVERRIDE;
+ QRect characterRect(int offset) const Q_DECL_OVERRIDE;
+ int selectionCount() const Q_DECL_OVERRIDE;
+ int offsetAtPoint(const QPoint &point) const Q_DECL_OVERRIDE;
+ void selection(int selectionIndex, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString text(int startOffset, int endOffset) const Q_DECL_OVERRIDE;
+ QString textBeforeOffset (int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ void removeSelection(int selectionIndex) Q_DECL_OVERRIDE;
+ void setCursorPosition(int position) Q_DECL_OVERRIDE;
+ void setSelection(int selectionIndex, int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ int characterCount() const Q_DECL_OVERRIDE;
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ // QAccessibleEditableTextInterface
+ void deleteText(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void insertText(int offset, const QString &text) Q_DECL_OVERRIDE;
+ void replaceText(int startOffset, int endOffset, const QString &text) Q_DECL_OVERRIDE;
+protected:
+ QLineEdit *lineEdit() const;
+};
+#endif // QT_NO_LINEEDIT
+
+#ifndef QT_NO_PROGRESSBAR
+class QAccessibleProgressBar : public QAccessibleDisplay, public QAccessibleValueInterface
+{
+public:
+ explicit QAccessibleProgressBar(QWidget *o);
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &) Q_DECL_OVERRIDE {}
+
+protected:
+ QProgressBar *progressBar() const;
+};
+#endif
+
+class QWindowContainer;
+class QAccessibleWindowContainer : public QAccessibleWidget
+{
+public:
+ QAccessibleWindowContainer(QWidget *w);
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int i) const Q_DECL_OVERRIDE;
+
+private:
+ QWindowContainer *container() const;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // SIMPLEWIDGETS_H
diff --git a/src/widgets/accessible/widgets.pro b/src/widgets/accessible/widgets.pro
new file mode 100644
index 0000000000..c6af6d3f71
--- /dev/null
+++ b/src/widgets/accessible/widgets.pro
@@ -0,0 +1,27 @@
+TARGET = qtaccessiblewidgets
+
+PLUGIN_TYPE = accessible
+PLUGIN_EXTENDS = widgets
+PLUGIN_CLASS_NAME = AccessibleFactory
+load(qt_plugin)
+
+QT += core-private gui-private widgets-private
+
+QTDIR_build:REQUIRES += "contains(QT_CONFIG, accessibility)"
+
+SOURCES += main.cpp \
+ simplewidgets.cpp \
+ rangecontrols.cpp \
+ complexwidgets.cpp \
+ qaccessiblewidgets.cpp \
+ qaccessiblemenu.cpp \
+ itemviews.cpp
+
+HEADERS += qaccessiblewidgets.h \
+ simplewidgets.h \
+ rangecontrols.h \
+ complexwidgets.h \
+ qaccessiblemenu.h \
+ itemviews.h
+
+
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 3889a589c7..14c1ce081f 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -1262,9 +1262,17 @@ QColorShower::QColorShower(QColorDialog *parent)
lblHtml->setBuddy(htEd);
#endif
+#if !defined(QT_NO_REGULAREXPRESSION)
QRegularExpression regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
htEd->setValidator(validator);
+#elif !defined(QT_NO_REGEXP)
+ QRegExp regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
+ QRegExpValidator *validator = new QRegExpValidator(regExp, this);
+ htEd->setValidator(validator);
+#else
+ htEd->setReadOnly(true);
+#endif
lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
gl->addWidget(lblHtml, 5, 1);
@@ -1460,38 +1468,46 @@ void QColorDialogPrivate::setCurrentQColor(const QColor &color)
}
}
+// size of standard and custom color selector
+enum {
+ colorColumns = 8,
+ standardColorRows = 6,
+ customColorRows = 2
+};
+
bool QColorDialogPrivate::selectColor(const QColor &col)
{
QRgb color = col.rgb();
- int i = 0, j = 0;
// Check standard colors
if (standard) {
const QRgb *standardColors = QColorDialogOptions::standardColors();
- for (i = 0; i < 6; i++) {
- for (j = 0; j < 8; j++) {
- if (color == standardColors[i + j*6]) {
- _q_newStandard(i, j);
- standard->setCurrent(i, j);
- standard->setSelected(i, j);
- standard->setFocus();
- return true;
- }
- }
+ const QRgb *standardColorsEnd = standardColors + standardColorRows * colorColumns;
+ const QRgb *match = std::find(standardColors, standardColorsEnd, color);
+ if (match != standardColorsEnd) {
+ const int index = int(match - standardColors);
+ const int row = index / standardColorRows;
+ const int column = index % standardColorRows;
+ _q_newStandard(row, column);
+ standard->setCurrent(row, column);
+ standard->setSelected(row, column);
+ standard->setFocus();
+ return true;
}
}
// Check custom colors
if (custom) {
const QRgb *customColors = QColorDialogOptions::customColors();
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 8; j++) {
- if (color == customColors[i + j*2]) {
- _q_newCustom(i, j);
- custom->setCurrent(i, j);
- custom->setSelected(i, j);
- custom->setFocus();
- return true;
- }
- }
+ const QRgb *customColorsEnd = customColors + customColorRows * colorColumns;
+ const QRgb *match = std::find(customColors, customColorsEnd, color);
+ if (match != customColorsEnd) {
+ const int index = int(match - customColors);
+ const int row = index / customColorRows;
+ const int column = index % customColorRows;
+ _q_newCustom(row, column);
+ custom->setCurrent(row, column);
+ custom->setSelected(row, column);
+ custom->setFocus();
+ return true;
}
}
return false;
@@ -1519,12 +1535,12 @@ void QColorDialogPrivate::_q_newColorTypedIn(QRgb rgb)
void QColorDialogPrivate::_q_nextCustom(int r, int c)
{
- nextCust = r + 2 * c;
+ nextCust = r + customColorRows * c;
}
void QColorDialogPrivate::_q_newCustom(int r, int c)
{
- const int i = r + 2 * c;
+ const int i = r + customColorRows * c;
setCurrentRgbColor(QColorDialogOptions::customColor(i));
if (standard)
standard->setSelected(-1,-1);
@@ -1545,12 +1561,10 @@ void QColorDialogPrivate::_q_pickScreenColor()
q->installEventFilter(colorPickingEventFilter);
// If user pushes Escape, the last color before picking will be restored.
beforeScreenColorPicking = cs->currentColor();
- /*For some reason, q->grabMouse(Qt::CrossCursor) doesn't change
- * the cursor, and therefore I have to change it manually.
- */
- q->grabMouse();
#ifndef QT_NO_CURSOR
- q->setCursor(Qt::CrossCursor);
+ q->grabMouse(Qt::CrossCursor);
+#else
+ q->grabMouse();
#endif
q->grabKeyboard();
/* With setMouseTracking(true) the desired color can be more precisedly picked up,
@@ -1575,9 +1589,6 @@ void QColorDialogPrivate::releaseColorPicking()
q->removeEventFilter(colorPickingEventFilter);
q->releaseMouse();
q->releaseKeyboard();
-#ifndef QT_NO_CURSOR
- q->setCursor(Qt::ArrowCursor);
-#endif
q->setMouseTracking(false);
lblScreenColorInfo->setText(QLatin1String("\n"));
addCusBt->setDisabled(false);
@@ -1635,7 +1646,7 @@ void QColorDialogPrivate::initWidgets()
}
if (!smallDisplay) {
- standard = new QColorWell(q, 6, 8, QColorDialogOptions::standardColors());
+ standard = new QColorWell(q, standardColorRows, colorColumns, QColorDialogOptions::standardColors());
lblBasicColors = new QLabel(q);
#ifndef QT_NO_SHORTCUT
lblBasicColors->setBuddy(standard);
@@ -1657,7 +1668,7 @@ void QColorDialogPrivate::initWidgets()
leftLay->addStretch();
#endif
- custom = new QColorWell(q, 2, 8, QColorDialogOptions::customColors());
+ custom = new QColorWell(q, customColorRows, colorColumns, QColorDialogOptions::customColors());
custom->setAcceptDrops(true);
q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int)));
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 6349bdc301..605d430edf 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#define QT_NO_URL_CAST_FROM_STRING
+
#include <qvariant.h>
#include <private/qwidgetitemdata_p.h>
#include "qfiledialog.h"
@@ -579,8 +581,8 @@ QFileDialogPrivate::~QFileDialogPrivate()
void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
{
QFileDialog *d = q_func();
- QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_nativeFileSelected(QUrl)));
- QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_nativeFilesSelected(QList<QUrl>)));
+ QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_emitUrlSelected(QUrl)));
+ QObject::connect(h, SIGNAL(filesSelected(QList<QUrl>)), d, SLOT(_q_emitUrlsSelected(QList<QUrl>)));
QObject::connect(h, SIGNAL(currentChanged(QUrl)), d, SLOT(_q_nativeCurrentChanged(QUrl)));
QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl)));
QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
@@ -2028,26 +2030,6 @@ QString QFileDialog::labelText(DialogLabel label) const
return QString();
}
-/*
- For the native file dialogs
-*/
-
-#if defined(Q_WS_WIN)
-extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
- QString *initialDirectory,
- QString *selectedFilter);
-
-extern QString qt_win_get_existing_directory(const QFileDialogArgs &args);
-#endif
-
/*!
This is a convenience static function that returns an existing file
selected by the user. If the user presses Cancel, it returns a null string.
@@ -2110,13 +2092,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent,
args.filter = filter;
args.mode = ExistingFile;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_open_file_name(args, &(args.directory), selectedFilter);
- }
-#endif
- // create a qt dialog
QFileDialog dialog(args);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
@@ -2239,13 +2215,6 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent,
args.mode = ExistingFiles;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_open_file_names(args, &(args.directory), selectedFilter);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
@@ -2371,13 +2340,6 @@ QString QFileDialog::getSaveFileName(QWidget *parent,
args.mode = AnyFile;
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
- return qt_win_get_save_file_name(args, &(args.directory), selectedFilter);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
dialog.setAcceptMode(AcceptSave);
if (selectedFilter && !selectedFilter->isEmpty())
@@ -2483,17 +2445,6 @@ QString QFileDialog::getExistingDirectory(QWidget *parent,
args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
args.options = options;
-#if defined(Q_WS_WIN)
- if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
-#if defined(Q_OS_WINCE)
- && qt_priv_ptr_valid
-#endif
- ) {
- return qt_win_get_existing_directory(args);
- }
-#endif
-
- // create a qt dialog
QFileDialog dialog(args);
if (dialog.exec() == QDialog::Accepted) {
return dialog.selectedFiles().value(0);
@@ -2609,15 +2560,20 @@ void QFileDialog::done(int result)
void QFileDialog::accept()
{
Q_D(QFileDialog);
- QStringList files = selectedFiles();
- if (files.isEmpty())
- return;
if (!d->usingWidgets()) {
- d->emitFilesSelected(files);
+ const QList<QUrl> urls = selectedUrls();
+ if (urls.isEmpty())
+ return;
+ d->_q_emitUrlsSelected(urls);
+ if (urls.count() == 1)
+ d->_q_emitUrlSelected(urls.first());
QDialog::accept();
return;
}
+ QStringList files = selectedFiles();
+ if (files.isEmpty())
+ return;
QString lineEditText = d->lineEdit()->text();
// "hidden feature" type .. and then enter, and it will move up a dir
// special case for ".."
@@ -2780,7 +2736,7 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->setupUi(q);
QList<QUrl> initialBookmarks;
- initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
+ initialBookmarks << QUrl(QLatin1String("file:"))
<< QUrl::fromLocalFile(QDir::homePath());
qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(QUrl)),
@@ -3648,7 +3604,7 @@ void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldNa
}
}
-void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file)
+void QFileDialogPrivate::_q_emitUrlSelected(const QUrl &file)
{
Q_Q(QFileDialog);
emit q->urlSelected(file);
@@ -3656,7 +3612,7 @@ void QFileDialogPrivate::_q_nativeFileSelected(const QUrl &file)
emit q->fileSelected(file.toLocalFile());
}
-void QFileDialogPrivate::_q_nativeFilesSelected(const QList<QUrl> &files)
+void QFileDialogPrivate::_q_emitUrlsSelected(const QList<QUrl> &files)
{
Q_Q(QFileDialog);
emit q->urlsSelected(files);
@@ -3757,7 +3713,7 @@ void QFileDialogComboBox::showPopup()
idx = idx.parent();
}
// add "my computer"
- list.append(QUrl::fromLocalFile(QLatin1String("")));
+ list.append(QUrl(QLatin1String("file:")));
urlModel->addUrls(list, 0);
idx = model()->index(model()->rowCount() - 1, 0);
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index 404e16cde1..184e07261a 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -287,8 +287,8 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_updateOkButton())
Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex &index))
Q_PRIVATE_SLOT(d_func(), void _q_enterDirectory(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_nativeFileSelected(const QUrl &))
- Q_PRIVATE_SLOT(d_func(), void _q_nativeFilesSelected(const QList<QUrl> &))
+ Q_PRIVATE_SLOT(d_func(), void _q_emitUrlSelected(const QUrl &))
+ Q_PRIVATE_SLOT(d_func(), void _q_emitUrlsSelected(const QList<QUrl> &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeCurrentChanged(const QUrl &))
Q_PRIVATE_SLOT(d_func(), void _q_nativeEnterDirectory(const QUrl&))
Q_PRIVATE_SLOT(d_func(), void _q_goToDirectory(const QString &path))
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 632bbca5a4..24969b1179 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -210,8 +210,8 @@ public:
void _q_updateOkButton();
void _q_currentChanged(const QModelIndex &index);
void _q_enterDirectory(const QModelIndex &index);
- void _q_nativeFileSelected(const QUrl &file);
- void _q_nativeFilesSelected(const QList<QUrl> &files);
+ void _q_emitUrlSelected(const QUrl &file);
+ void _q_emitUrlsSelected(const QList<QUrl> &files);
void _q_nativeCurrentChanged(const QUrl &file);
void _q_nativeEnterDirectory(const QUrl &directory);
void _q_goToDirectory(const QString &);
@@ -369,7 +369,7 @@ inline QUrl QFileDialogPrivate::directory_sys() const
{
if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
return helper->directory();
- return QString();
+ return QUrl();
}
inline void QFileDialogPrivate::selectFile_sys(const QUrl &filename)
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 10d693b4a3..99344b3dd8 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -60,25 +60,37 @@
QT_USE_NAMESPACE
-static const char *signalForMember(const char *member)
+enum CandidateSignal {
+ TextValueSelectedSignal,
+ IntValueSelectedSignal,
+ DoubleValueSelectedSignal,
+
+ NumCandidateSignals
+};
+
+static const char *candidateSignal(int which)
{
- static const int NumCandidates = 4;
- static const char * const candidateSignals[NumCandidates] = {
- SIGNAL(textValueSelected(QString)),
- SIGNAL(intValueSelected(int)),
- SIGNAL(doubleValueSelected(double)),
- SIGNAL(accepted())
+ switch (CandidateSignal(which)) {
+ case TextValueSelectedSignal: return SIGNAL(textValueSelected(QString));
+ case IntValueSelectedSignal: return SIGNAL(intValueSelected(int));
+ case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double));
+
+ case NumCandidateSignals: ; // fall through
};
+ Q_UNREACHABLE();
+ return Q_NULLPTR;
+}
+static const char *signalForMember(const char *member)
+{
QByteArray normalizedMember(QMetaObject::normalizedSignature(member));
- int i = 0;
- while (i < NumCandidates - 1) { // sic
- if (QMetaObject::checkConnectArgs(candidateSignals[i], normalizedMember))
- break;
- ++i;
- }
- return candidateSignals[i];
+ for (int i = 0; i < NumCandidateSignals; ++i)
+ if (QMetaObject::checkConnectArgs(candidateSignal(i), normalizedMember))
+ return candidateSignal(i);
+
+ // otherwise, use fit-all accepted signal:
+ return SIGNAL(accepted());
}
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index 662504fc25..35a75adea2 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -84,6 +84,7 @@ public:
void init(const QString &labelText, const QString &cancelText, int min, int max);
void layout();
void retranslateStrings();
+ void setCancelButtonText(const QString &cancelButtonText);
void _q_disconnectOnClose();
QLabel *label;
@@ -178,9 +179,8 @@ void QProgressDialogPrivate::layout()
void QProgressDialogPrivate::retranslateStrings()
{
- Q_Q(QProgressDialog);
if (useDefaultCancelText)
- q->setCancelButtonText(QProgressDialog::tr("Cancel"));
+ setCancelButtonText(QProgressDialog::tr("Cancel"));
}
void QProgressDialogPrivate::_q_disconnectOnClose()
@@ -354,6 +354,11 @@ QProgressDialog::~QProgressDialog()
void QProgressDialog::setLabel(QLabel *label)
{
Q_D(QProgressDialog);
+ if (label == d->label) {
+ if (label)
+ qWarning("QProgressDialog::setLabel: Attempt to set the same label again");
+ return;
+ }
delete d->label;
d->label = label;
if (label) {
@@ -411,6 +416,11 @@ void QProgressDialog::setLabelText(const QString &text)
void QProgressDialog::setCancelButton(QPushButton *cancelButton)
{
Q_D(QProgressDialog);
+ if (d->cancel == cancelButton) {
+ if (cancelButton)
+ qWarning("QProgressDialog::setCancelButton: Attempt to set the same button again");
+ return;
+ }
delete d->cancel;
d->cancel = cancelButton;
if (cancelButton) {
@@ -448,19 +458,25 @@ void QProgressDialog::setCancelButtonText(const QString &cancelButtonText)
{
Q_D(QProgressDialog);
d->useDefaultCancelText = false;
+ d->setCancelButtonText(cancelButtonText);
+}
+
+void QProgressDialogPrivate::setCancelButtonText(const QString &cancelButtonText)
+{
+ Q_Q(QProgressDialog);
if (!cancelButtonText.isNull()) {
- if (d->cancel) {
- d->cancel->setText(cancelButtonText);
+ if (cancel) {
+ cancel->setText(cancelButtonText);
} else {
- setCancelButton(new QPushButton(cancelButtonText, this));
+ q->setCancelButton(new QPushButton(cancelButtonText, q));
}
} else {
- setCancelButton(0);
+ q->setCancelButton(0);
}
- int w = qMax(isVisible() ? width() : 0, sizeHint().width());
- int h = qMax(isVisible() ? height() : 0, sizeHint().height());
- resize(w, h);
+ int w = qMax(q->isVisible() ? q->width() : 0, q->sizeHint().width());
+ int h = qMax(q->isVisible() ? q->height() : 0, q->sizeHint().height());
+ q->resize(w, h);
}
@@ -483,6 +499,10 @@ void QProgressDialog::setBar(QProgressBar *bar)
qWarning("QProgressDialog::setBar: Cannot set a new progress bar "
"while the old one is active");
#endif
+ if (bar == d->bar) {
+ qWarning("QProgressDialog::setBar: Attempt to set the same progress bar again");
+ return;
+ }
delete d->bar;
d->bar = bar;
int w = qMax(isVisible() ? width() : 0, sizeHint().width());
@@ -507,7 +527,7 @@ bool QProgressDialog::wasCanceled() const
\property QProgressDialog::maximum
\brief the highest value represented by the progress bar
- The default is 0.
+ The default is 100.
\sa minimum, setRange()
*/
diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp
index 3d22992e3a..7b691dc609 100644
--- a/src/widgets/dialogs/qsidebar.cpp
+++ b/src/widgets/dialogs/qsidebar.cpp
@@ -249,7 +249,8 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
continue;
//this makes sure the url is clean
const QString cleanUrl = QDir::cleanPath(url.toLocalFile());
- url = QUrl::fromLocalFile(cleanUrl);
+ if (!cleanUrl.isEmpty())
+ url = QUrl::fromLocalFile(cleanUrl);
for (int j = 0; move && j < rowCount(); ++j) {
QString local = index(j, 0).data(UrlRole).toUrl().toLocalFile();
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index b294e98c30..15f922a5b8 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -1475,7 +1475,7 @@ void QWizardPrivate::updateButtonTexts()
void QWizardPrivate::updateButtonLayout()
{
if (buttonsHaveCustomLayout) {
- QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
+ QVarLengthArray<QWizard::WizardButton, QWizard::NButtons> array(buttonsCustomLayout.count());
for (int i = 0; i < buttonsCustomLayout.count(); ++i)
array[i] = buttonsCustomLayout.at(i);
setButtonLayout(array.constData(), array.count());
diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf
index 508a257fa5..4b19702208 100644
--- a/src/widgets/doc/qtwidgets.qdocconf
+++ b/src/widgets/doc/qtwidgets.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtWidgets
description = Qt Widgets Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = widgets
diff --git a/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp b/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp
new file mode 100644
index 0000000000..bc279e4406
--- /dev/null
+++ b/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+class MyGLWidget : public QOpenGLWidget
+{
+public:
+ MyGLWidget(QWidget *parent) : QOpenGLWidget(parent) { }
+
+protected:
+ void initializeGL()
+ {
+ // Set up the rendering context, load shaders and other resources, etc.:
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ ...
+ }
+
+ void resizeGL(int w, int h)
+ {
+ // Update projection matrix and other size related settings:
+ m_projection.setToIdentity();
+ m_projection.perspective(45.0f, w / float(h), 0.01f, 100.0f);
+ ...
+ }
+
+ void paintGL()
+ {
+ // Draw the scene:
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glClear(GL_COLOR_BUFFER_BIT);
+ ...
+ }
+
+};
+//! [0]
+
+//! [1]
+class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
+{
+ ...
+ void initializeGL()
+ {
+ initializeOpenGLFunctions();
+ glClearColor(...);
+ ...
+ }
+ ...
+};
+//! [1]
+
+//! [2]
+QOpenGLWidget *widget = new QOpenGLWidget(parent);
+QSurfaceFormat format;
+format.setDepthBufferSize(24);
+format.setStencilBufferSize(8);
+format.setVersion(3, 2);
+format.setProfile(QSurfaceFormat::CoreProfile);
+widget->setFormat(format); // must be called before the widget or its parent window gets shown
+//! [2]
+
+//! [3]
+ ...
+ void paintGL()
+ {
+ QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ ...
+ f->glDrawArraysInstanced(...);
+ ...
+ }
+ ...
+//! [3]
diff --git a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
index 36d3dc6af4..702c17bc26 100644
--- a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
+++ b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
@@ -1864,3 +1864,8 @@ QTabBar::close-button:hover {
}
//! [159]
+
+//! [160]
+* { lineedit-password-mask-delay: 1000 }
+//! [160]
+
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index e8c1be4c46..32fe384c75 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -862,6 +862,9 @@
\l{#lineedit-password-character-prop}{lineedit-password-character}
property.
+ The password mask delay can be changed using the
+ \l{#lineedit-password-mask-delay-prop}{lineedit-password-mask-delay}
+
See \l{Qt Style Sheets Examples#Customizing QLineEdit}{Customizing QLineEdit}
for an example.
@@ -2009,6 +2012,23 @@
\snippet code/doc_src_stylesheet.qdoc 61
\row
+ \li \b{\c lineedit-password-mask-delay*} \target lineedit-password-mask-delay-prop
+ \li \l{#Number}{Number}
+ \li The QLineEdit password mask delay in milliseconds before
+ \l{#lineedit-password-character-prop}{lineedit-password-character} is applied to visible character.
+
+ If this property is not specified, it defaults to the
+ value specified by the current style for the
+ \l{QStyle::}{SH_LineEdit_PasswordMaskDelay} style hint.
+
+ \b{This property was added in Qt 5.4.}
+
+ Example:
+
+ \snippet code/doc_src_stylesheet.qdoc 160
+
+
+ \row
\li \b{\c margin} \target margin-prop
\li \l {Box Lengths}
\li The widget's margins. Equivalent to specifying \c
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index e327a8737a..551f229611 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -332,6 +332,8 @@
this flag is disabled; children can draw anywhere. This behavior is
enforced by QGraphicsView::drawItems() or
QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
+ \note This flag is similar to ItemContainsChildrenInShape but in addition
+ enforces the containment by clipping the children.
\value ItemIgnoresTransformations The item ignores inherited
transformations (i.e., its position is still anchored to its parent, but
@@ -423,6 +425,19 @@
ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
allows you to completely take over focus handling.
This flag was introduced in Qt 4.7. \endomit
+
+ \value ItemContainsChildrenInShape This flag indicates that all of the
+ item's direct or indirect children only draw within the item's shape.
+ Unlike ItemClipsChildrenToShape, this restriction is not enforced. Set
+ ItemContainsChildrenInShape when you manually assure that drawing
+ is bound to the item's shape and want to avoid the cost associated with
+ enforcing the clip. Setting this flag enables more efficient drawing and
+ collision detection. The flag is disabled by default.
+ \note If both this flag and ItemClipsChildrenToShape are set, the clip
+ will be enforced. This is equivalent to just setting
+ ItemClipsChildrenToShape.
+ .
+ This flag was introduced in Qt 5.4.
*/
/*!
@@ -836,6 +851,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
flag = AncestorIgnoresTransformations;
enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ flag = AncestorContainsChildren;
+ enabled = flags & QGraphicsItem::ItemContainsChildrenInShape;
+ break;
default:
return;
}
@@ -895,6 +914,8 @@ void QGraphicsItemPrivate::updateAncestorFlags()
flags |= AncestorClipsChildren;
if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
flags |= AncestorIgnoresTransformations;
+ if (pd->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ flags |= AncestorContainsChildren;
}
if (ancestorFlags == flags)
@@ -1831,6 +1852,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->markParentDirty(true);
}
+ if ((flags & ItemContainsChildrenInShape) != (oldFlags & ItemContainsChildrenInShape)) {
+ // Item children containtment changes. Propagate the ancestor flag to all children.
+ d_ptr->updateAncestorFlag(ItemContainsChildrenInShape);
+ }
+
if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
// Item children clipping changes. Propagate the ancestor flag to
// all children.
@@ -2322,7 +2348,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
}
// Update children with explicitly = false.
- const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape)
+ const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
+ || flags & QGraphicsItem::ItemContainsChildrenInShape)
&& !(flags & QGraphicsItem::ItemHasNoContents));
foreach (QGraphicsItem *child, children) {
if (!newVisible || !child->d_ptr->explicitlyHidden)
@@ -2835,7 +2862,9 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
#ifndef QT_NO_GRAPHICSEFFECT
Q_Q(const QGraphicsItem);
QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
- if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
+ if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
+ || topMostEffectItem == q)
return brect;
const QGraphicsItem *effectParent = parent;
@@ -2847,6 +2876,7 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
}
if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
|| topMostEffectItem == effectParent) {
return brect;
}
@@ -7442,7 +7472,8 @@ QVariant QGraphicsItem::extension(const QVariant &variant) const
*/
void QGraphicsItem::addToIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### add to child index only if applicable
return;
}
@@ -7459,7 +7490,8 @@ void QGraphicsItem::addToIndex()
*/
void QGraphicsItem::removeFromIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### remove from child index only if applicable
return;
}
@@ -11451,6 +11483,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStopsFocusHandling:
str = "ItemStopsFocusHandling";
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ str = "ItemContainsChildrenInShape";
+ break;
}
debug << str;
return debug;
diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h
index 4283deb5b8..dfc06fdaea 100644
--- a/src/widgets/graphicsview/qgraphicsitem.h
+++ b/src/widgets/graphicsview/qgraphicsitem.h
@@ -105,7 +105,8 @@ public:
ItemIsFocusScope = 0x8000, // internal
ItemSendsScenePositionChanges = 0x10000,
ItemStopsClickFocusPropagation = 0x20000,
- ItemStopsFocusHandling = 0x40000
+ ItemStopsFocusHandling = 0x40000,
+ ItemContainsChildrenInShape = 0x80000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 3968d89a13..4d1835f178 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -172,7 +172,8 @@ public:
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
AncestorIgnoresTransformations = 0x4,
- AncestorFiltersChildEvents = 0x8
+ AncestorFiltersChildEvents = 0x8,
+ AncestorContainsChildren = 0x10
};
inline QGraphicsItemPrivate()
@@ -213,7 +214,6 @@ public:
needSortChildren(0),
allChildrenDirty(0),
fullUpdatePending(0),
- dirtyChildrenBoundingRect(1),
flags(0),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -239,6 +239,7 @@ public:
mayHaveChildWithGraphicsEffect(0),
isDeclarativeItem(0),
sendParentChangeNotification(0),
+ dirtyChildrenBoundingRect(1),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -544,7 +545,7 @@ public:
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 4;
+ quint32 ancestorFlags : 5;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
@@ -555,10 +556,9 @@ public:
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
quint32 fullUpdatePending : 1;
- quint32 dirtyChildrenBoundingRect : 1;
// Packed 32 bits
- quint32 flags : 19;
+ quint32 flags : 20;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
@@ -571,9 +571,9 @@ public:
quint32 filtersDescendantEvents : 1;
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
- quint32 notifyInvalidated : 1;
// New 32 bits
+ quint32 notifyInvalidated : 1;
quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
@@ -585,7 +585,8 @@ public:
quint32 mayHaveChildWithGraphicsEffect : 1;
quint32 isDeclarativeItem : 1;
quint32 sendParentChangeNotification : 1;
- quint32 padding : 21;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 padding : 19;
// Optional stacking order
int globalStackingOrder;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index bccdb1fbaa..1cd162e6bb 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -299,6 +299,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
painterStateProtection(true),
sortCacheEnabled(false),
allItemsIgnoreTouchEvents(true),
+ minimumRenderSize(0.0),
selectionChanging(0),
rectAdjust(2),
focusItem(0),
@@ -4716,19 +4717,40 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
wasDirtyParentSceneTransform = true;
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool drawItem = itemHasContents && !itemIsFullyTransparent;
- if (drawItem) {
+ if (drawItem || minimumRenderSize > 0.0) {
const QRectF brect = adjustedItemEffectiveBoundingRect(item);
ENSURE_TRANSFORM_PTR
- QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
- : transformPtr->mapRect(brect).toAlignedRect();
- viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
- if (widget)
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
- drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
- : !viewBoundingRect.normalized().isEmpty();
- if (!drawItem) {
+ QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
+ : transformPtr->mapRect(brect);
+
+ bool itemIsTooSmallToRender = false;
+ if (minimumRenderSize > 0.0
+ && (preciseViewBoundingRect.width() < minimumRenderSize
+ || preciseViewBoundingRect.height() < minimumRenderSize)) {
+ itemIsTooSmallToRender = true;
+ drawItem = false;
+ }
+
+ bool itemIsOutsideVisibleRect = false;
+ if (drawItem) {
+ QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
+ viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
+ if (widget)
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
+ : !viewBoundingRect.normalized().isEmpty();
+ itemIsOutsideVisibleRect = !drawItem;
+ }
+
+ if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
+ // We cannot simply use !drawItem here. If we did it is possible
+ // to enter the outter if statement with drawItem == false and minimumRenderSize > 0
+ // and finally end up inside this inner if, even though none of the above two
+ // conditions are met. In that case we should not return from this function
+ // but call draw() instead.
if (!itemHasChildren)
return;
if (itemClipsChildrenToShape) {
@@ -5200,7 +5222,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
// Process children.
if (itemHasChildren && item->d_ptr->dirtyChildren) {
- const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
// Items with no content are threated as 'dummy' items which means they are never drawn and
// 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
// such an item changes geometry, its children have to take care of the update regardless
@@ -5729,6 +5752,49 @@ bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
return d->sendEvent(item, event);
}
+/*!
+ \property QGraphicsScene::minimumRenderSize
+ \since 5.4
+ \brief the minimal view-transformed size an item must have to be drawn
+
+ When the scene is rendered, any item whose width or height, transformed
+ to the target view, is smaller that minimumRenderSize(), will not be
+ rendered. If an item is not rendered and it clips its children items
+ they will also not be rendered. Set this value to speed up rendering
+ of scenes with many objects rendered on a zoomed out view.
+
+ The default value is 0. If unset, or if set to 0 or a negative value,
+ all items will always be rendered.
+
+ For example, setting this property can be especially useful if a scene
+ is rendered by multiple views, one of which serves as an overview which
+ always displays all items. In scenes with many items, such a view will
+ use a high scaling factor so that all items can be shown. Due to the
+ scaling, smaller items will only make an insignificant contribution to
+ the final rendered scene. To avoid drawing these items and reduce the
+ time necessary to render the scene, you can call setMinimumRenderSize()
+ with a non-negative value.
+
+ \note Items that are not drawn as a result of being too small, are still
+ returned by methods such as items() and itemAt(), and participate in
+ collision detection and interactions. It is recommended that you set
+ minimumRenderSize() to a value less than or equal to 1 in order to
+ avoid large unrendered items that are interactive.
+
+ \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform()
+*/
+qreal QGraphicsScene::minimumRenderSize() const
+{
+ Q_D(const QGraphicsScene);
+ return d->minimumRenderSize;
+}
+void QGraphicsScene::setMinimumRenderSize(qreal minSize)
+{
+ Q_D(QGraphicsScene);
+ d->minimumRenderSize = minSize;
+ update();
+}
+
void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
views << view;
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index cde0eda125..d95237baef 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -107,6 +107,7 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
+ Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
public:
enum ItemIndexMethod {
@@ -249,6 +250,9 @@ public:
bool sendEvent(QGraphicsItem *item, QEvent *event);
+ qreal minimumRenderSize() const;
+ void setMinimumRenderSize(qreal minSize);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
@@ -309,6 +313,7 @@ private:
friend class QGraphicsEffect;
friend class QGraphicsSceneIndex;
friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneLinearIndex;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index 9e5bcec488..9f50dcfea7 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -117,6 +117,8 @@ public:
quint32 allItemsIgnoreTouchEvents : 1;
quint32 padding : 15;
+ qreal minimumRenderSize;
+
QRectF growingItemsBoundingRect;
void _q_emitUpdated();
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
index 7598163f2d..50f17ab73f 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -169,7 +169,8 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
untransformableItems << item;
continue;
}
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)
continue;
bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect());
@@ -351,7 +352,8 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec
// Avoid virtual function calls from the destructor.
purgePending = true;
removedItems << item;
- } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect());
}
} else {
@@ -510,7 +512,8 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *
return;
if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
- || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
return; // Item is not in BSP tree; nothing to do.
}
@@ -641,8 +644,10 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value);
bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations;
- bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
- bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
+ bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape
+ || newFlags & QGraphicsItem::ItemContainsChildrenInShape;
if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
@@ -663,10 +668,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
bool ignoredTransform = item->d_ptr->itemIsUntransformable();
bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations)
|| (newParent && newParent->d_ptr->itemIsUntransformable());
- bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren;
+ bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren;
bool ancestorWillClipChildren = newParent
- && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
+ && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || newParent->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren));
if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp
index 631aa7bf19..be91c63fad 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp
@@ -348,7 +348,7 @@ class QGraphicsSceneMouseEventPrivate : public QGraphicsSceneEventPrivate
public:
inline QGraphicsSceneMouseEventPrivate()
: button(Qt::NoButton),
- buttons(0), modifiers(0)
+ buttons(0), modifiers(0), source(Qt::MouseEventNotSynthesized), flags(0)
{ }
QPointF pos;
@@ -363,6 +363,8 @@ public:
Qt::MouseButton button;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers modifiers;
+ Qt::MouseEventSource source;
+ Qt::MouseEventFlags flags;
};
/*!
@@ -626,6 +628,60 @@ Qt::KeyboardModifiers QGraphicsSceneMouseEvent::modifiers() const
}
/*!
+ \since 5.4
+
+ Returns information about the mouse event source.
+
+ The mouse event source can be used to distinguish between genuine
+ and artificial mouse events. The latter are events that are
+ synthesized from touch events by the operating system or Qt itself.
+
+ \sa Qt::MouseEventSource
+ \sa QMouseEvent::source()
+ */
+Qt::MouseEventSource QGraphicsSceneMouseEvent::source() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->source;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setSource(Qt::MouseEventSource source)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->source = source;
+}
+
+/*!
+ \since 5.4
+
+ Returns the mouse event flags.
+
+ The mouse event flags provide additional information about a mouse event.
+
+ \sa Qt::MouseEventFlag
+ \sa QMouseEvent::flags()
+ */
+Qt::MouseEventFlags QGraphicsSceneMouseEvent::flags() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->flags;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setFlags(Qt::MouseEventFlags flags)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->flags = flags;
+}
+
+/*!
\internal
*/
void QGraphicsSceneMouseEvent::setModifiers(Qt::KeyboardModifiers modifiers)
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h
index e744d08edf..2c9c1f3f50 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.h
+++ b/src/widgets/graphicsview/qgraphicssceneevent.h
@@ -121,6 +121,12 @@ public:
Qt::KeyboardModifiers modifiers() const;
void setModifiers(Qt::KeyboardModifiers modifiers);
+ Qt::MouseEventSource source() const;
+ void setSource(Qt::MouseEventSource source);
+
+ Qt::MouseEventFlags flags() const;
+ void setFlags(Qt::MouseEventFlags);
+
private:
Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent)
Q_DISABLE_COPY(QGraphicsSceneMouseEvent)
diff --git a/src/widgets/graphicsview/qgraphicssceneindex.cpp b/src/widgets/graphicsview/qgraphicssceneindex.cpp
index 40f63937f4..d06c5523ca 100644
--- a/src/widgets/graphicsview/qgraphicssceneindex.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneindex.cpp
@@ -278,7 +278,8 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
Q_ASSERT(!item->d_ptr->dirtySceneTransform);
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool processItem = !itemIsFullyTransparent;
if (processItem) {
processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
index 7debcfb501..baf3de3755 100644
--- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
@@ -70,31 +70,62 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
Q_OBJECT
public:
- QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene)
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_itemsIsValid(true)
{ }
QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const
- { Q_UNUSED(order); return m_items; }
+ {
+ Q_UNUSED(order);
+ return validList();
+ }
virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const
{
Q_UNUSED(rect);
Q_UNUSED(order);
- return m_items;
+ return validList();
}
protected :
virtual void clear()
- { m_items.clear(); }
+ {
+ m_items.clear();
+ m_itemsIsValid = true;
+ }
virtual void addItem(QGraphicsItem *item)
- { m_items << item; }
+ {
+ if (m_itemsIsValid)
+ m_items << item;
+ }
virtual void removeItem(QGraphicsItem *item)
- { m_items.removeOne(item); }
+ {
+ Q_UNUSED(item);
+ m_itemsIsValid = false;
+ }
private:
- QList<QGraphicsItem*> m_items;
+ mutable QList<QGraphicsItem*> m_items;
+ mutable bool m_itemsIsValid;
+
+ QList<QGraphicsItem*>& validList() const
+ {
+ if (!m_itemsIsValid)
+ {
+ m_items.clear();
+
+ QList<QGraphicsItem*> stack = scene()->d_func()->topLevelItems;
+ m_items << stack;
+ while (!stack.isEmpty())
+ {
+ m_items << stack.last()->childItems();
+ stack << stack.takeLast()->childItems();
+ }
+ m_itemsIsValid = true;
+ }
+ return m_items;
+ }
};
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index 5bcf52b6a3..7bdfae5fec 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -655,6 +655,8 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
lastMouseMoveScenePoint = mouseEvent.scenePos();
lastMouseMoveScreenPoint = mouseEvent.screenPos();
mouseEvent.setAccepted(false);
@@ -2760,7 +2762,7 @@ void QGraphicsView::setupViewport(QWidget *widget)
return;
}
- const bool isGLWidget = widget->inherits("QGLWidget");
+ const bool isGLWidget = widget->inherits("QGLWidget") || widget->inherits("QOpenGLWidget");
d->accelerateScrolling = !(isGLWidget);
@@ -3217,6 +3219,8 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
mouseEvent.setAccepted(false);
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
else
@@ -3265,6 +3269,8 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
@@ -3392,6 +3398,8 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index b2dc614b2b..4b59e72545 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1949,7 +1949,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case AboveItem:
if (d->isIndexDropEnabled(index.parent())) {
d->dropIndicatorRect = QRect(rect.left(), rect.top(), rect.width(), 0);
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1957,7 +1957,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case BelowItem:
if (d->isIndexDropEnabled(index.parent())) {
d->dropIndicatorRect = QRect(rect.left(), rect.bottom(), rect.width(), 0);
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1965,7 +1965,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case OnItem:
if (d->isIndexDropEnabled(index)) {
d->dropIndicatorRect = rect;
- event->accept();
+ event->acceptProposedAction();
} else {
d->dropIndicatorRect = QRect();
}
@@ -1973,7 +1973,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
case OnViewport:
d->dropIndicatorRect = QRect();
if (d->isIndexDropEnabled(rootIndex())) {
- event->accept(); // allow dropping in empty areas
+ event->acceptProposedAction(); // allow dropping in empty areas
}
break;
}
@@ -1981,7 +1981,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
d->dropIndicatorRect = QRect();
d->dropIndicatorPosition = OnViewport;
if (d->isIndexDropEnabled(rootIndex())) {
- event->accept(); // allow dropping in empty areas
+ event->acceptProposedAction(); // allow dropping in empty areas
}
}
d->viewport->update();
@@ -2050,11 +2050,14 @@ void QAbstractItemView::dropEvent(QDropEvent *event)
int col = -1;
int row = -1;
if (d->dropOn(event, &row, &col, &index)) {
- if (d->model->dropMimeData(event->mimeData(),
- dragDropMode() == InternalMove ? Qt::MoveAction : event->dropAction(), row, col, index)) {
- if (dragDropMode() == InternalMove)
- event->setDropAction(Qt::MoveAction);
+ const Qt::DropAction action = dragDropMode() == InternalMove ? Qt::MoveAction : event->dropAction();
+ if (d->model->dropMimeData(event->mimeData(), action, row, col, index)) {
+ if (action != event->dropAction()) {
+ event->setDropAction(action);
event->accept();
+ } else {
+ event->acceptProposedAction();
+ }
}
}
stopAutoScroll();
@@ -3126,6 +3129,8 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
Q_D(QAbstractItemView);
if (!d->isIndexValid(index))
return;
+ if (indexWidget(index) == widget)
+ return;
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index b12ab736f4..b6b5c63f84 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -368,8 +368,10 @@ QString QFileIconProvider::type(const QFileInfo &info) const
if (info.isRoot())
return QApplication::translate("QFileDialog", "Drive");
if (info.isFile()) {
- if (!info.suffix().isEmpty())
- return info.suffix() + QLatin1Char(' ') + QApplication::translate("QFileDialog", "File");
+ if (!info.suffix().isEmpty()) {
+ //: %1 is a file name suffix, for example txt
+ return QApplication::translate("QFileDialog", "%1 File").arg(info.suffix());
+ }
return QApplication::translate("QFileDialog", "File");
}
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index a252428a81..2bf4c62593 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -1821,8 +1821,15 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
return QModelIndex();
QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
- if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result))
+ if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) {
+ if (d->hasSpans()) {
+ QSpanCollection::Span span = d->span(result.row(), result.column());
+ if (span.width() > 1 || span.height() > 1) {
+ result = d->model->sibling(span.top(), span.left(), result);
+ }
+ }
return result;
+ }
return QModelIndex();
}
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 857fe4ac91..88c1e2595b 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -33,8 +33,8 @@ HEADERS += \
kernel/qstandardgestures_p.h \
kernel/qgesturerecognizer.h \
kernel/qgesturemanager_p.h \
- kernel/qdesktopwidget_qpa_p.h \
- kernel/qwidgetwindow_qpa_p.h \
+ kernel/qdesktopwidget_p.h \
+ kernel/qwidgetwindow_p.h \
kernel/qwindowcontainer_p.h
SOURCES += \
@@ -60,9 +60,6 @@ SOURCES += \
kernel/qgesturemanager.cpp \
kernel/qdesktopwidget.cpp \
kernel/qwidgetsvariant.cpp \
- kernel/qapplication_qpa.cpp \
- kernel/qdesktopwidget_qpa.cpp \
- kernel/qwidget_qpa.cpp \
kernel/qwidgetwindow.cpp \
kernel/qwindowcontainer.cpp
@@ -81,6 +78,6 @@ wince*: {
}
contains(QT_CONFIG, opengl) {
- HEADERS += kernel/qopenglwidget_p.h
+ HEADERS += kernel/qopenglwidget.h
SOURCES += kernel/qopenglwidget.cpp
}
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 04d398206b..2b90971398 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -57,6 +57,7 @@
#include "qstyleoption.h"
#include "qstylefactory.h"
#include "qtextcodec.h"
+#include "qtooltip.h"
#include "qtranslator.h"
#include "qvariant.h"
#include "qwidget.h"
@@ -67,7 +68,7 @@
#include "private/qstylesheetstyle_p.h"
#include "private/qstyle_p.h"
#include "qmessagebox.h"
-#include "qwidgetwindow_qpa_p.h"
+#include "qwidgetwindow_p.h"
#include <QtWidgets/qgraphicsproxywidget.h>
#include <QtGui/qstylehints.h>
#include <QtGui/qinputmethod.h>
@@ -77,6 +78,7 @@
#endif
#include "private/qkeymapper_p.h"
+#include "private/qaccessiblewidgetfactory_p.h"
#include <qthread.h>
#include <private/qthread_p.h>
@@ -93,6 +95,10 @@
#include "private/qgesturemanager_p.h"
#include <qpa/qplatformfontdatabase.h>
+#ifdef Q_OS_WIN
+#include <QtCore/qt_windows.h> // for qt_win_display_dc()
+#endif
+
#include "qdatetime.h"
#ifdef Q_OS_WINCE
@@ -184,6 +190,11 @@ QApplicationPrivate::~QApplicationPrivate()
self = 0;
}
+void QApplicationPrivate::createEventDispatcher()
+{
+ QGuiApplicationPrivate::createEventDispatcher();
+}
+
/*!
\class QApplication
\brief The QApplication class manages the GUI application's control
@@ -361,6 +372,14 @@ QApplicationPrivate::~QApplicationPrivate()
Returns the top-level widget at the given \a point; returns 0 if
there is no such widget.
*/
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ if (const QWindow *window = QGuiApplication::topLevelAt(pos)) {
+ if (const QWidgetWindow *widgetWindow = qobject_cast<const QWidgetWindow *>(window))
+ return widgetWindow->widget();
+ }
+ return 0;
+}
/*!
\fn QWidget *QApplication::topLevelAt(int x, int y)
@@ -371,12 +390,6 @@ QApplicationPrivate::~QApplicationPrivate()
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
);
void qt_init_tooltip_palette();
@@ -576,6 +589,31 @@ void QApplicationPrivate::construct()
extern void qt_gui_eval_init(QCoreApplicationPrivate::Type);
qt_gui_eval_init(application_type);
#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // factory for accessible interfaces for widgets shipped with Qt
+ QAccessible::installFactory(&qAccessibleFactory);
+#endif
+
+}
+
+void qt_init(QApplicationPrivate *priv, int type)
+{
+ Q_UNUSED(priv);
+ Q_UNUSED(type);
+
+ QColormap::initialize();
+
+ qt_init_tooltip_palette();
+
+ QApplicationPrivate::initializeWidgetFontHash();
+}
+
+void qt_init_tooltip_palette()
+{
+#ifndef QT_NO_TOOLTIP
+ if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
+ QToolTip::setPalette(*toolTipPalette);
+#endif
}
#ifndef QT_NO_STATEMACHINE
@@ -634,6 +672,91 @@ void QApplicationPrivate::initialize()
is_app_running = true; // no longer starting up
}
+static void setPossiblePalette(const QPalette *palette, const char *className)
+{
+ if (palette == 0)
+ return;
+ QApplicationPrivate::setPalette_helper(*palette, className, false);
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
+ if (!platformTheme)
+ return;
+ qt_app_palettes_hash()->clear();
+
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
+}
+
+void QApplicationPrivate::initializeWidgetFontHash()
+{
+ const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+ if (!theme)
+ return;
+ FontHash *fontHash = qt_app_fonts_hash();
+ fontHash->clear();
+
+ if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
+ fontHash->insert(QByteArrayLiteral("QMenu"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
+ fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
+ fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
+ fontHash->insert(QByteArrayLiteral("QLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
+ fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
+ fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
+ fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont))
+ fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
+ fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
+ fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::CheckBoxFont))
+ fontHash->insert(QByteArrayLiteral("QCheckBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::RadioButtonFont))
+ fontHash->insert(QByteArrayLiteral("QRadioButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
+ fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
+ fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
+ fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont))
+ fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
+ fontHash->insert(QByteArrayLiteral("QListBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
+ fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
+ fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
+ fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
+}
+
/*****************************************************************************
Functions returning the active popup and modal widgets.
*****************************************************************************/
@@ -757,6 +880,32 @@ QApplication::~QApplication()
#endif
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+// #fixme: Remove.
+static HDC displayDC = 0; // display device context
+
+Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC
+{
+ Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
+ if (!displayDC)
+ displayDC = GetDC(0);
+ return displayDC;
+}
+#endif
+
+void qt_cleanup()
+{
+ QPixmapCache::clear();
+ QColormap::cleanup();
+
+ QApplicationPrivate::active_window = 0; //### this should not be necessary
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ if (displayDC) {
+ ReleaseDC(0, displayDC);
+ displayDC = 0;
+ }
+#endif
+}
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
@@ -2063,6 +2212,39 @@ void QApplication::setActiveWindow(QWidget* act)
}
}
+QWidget *qt_tlw_for_window(QWindow *wnd)
+{
+ // QTBUG-32177, wnd might be a QQuickView embedded via window container.
+ while (wnd && !wnd->isTopLevel()) {
+ QWindow *parent = wnd->parent();
+ // Don't end up in windows not belonging to this application
+ if (parent && parent->type() != Qt::ForeignWindow)
+ wnd = wnd->parent();
+ else
+ break;
+ }
+ if (wnd)
+ foreach (QWidget *tlw, qApp->topLevelWidgets())
+ if (tlw->windowHandle() == wnd)
+ return tlw;
+ return 0;
+}
+
+void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
+{
+ Q_UNUSED(previous);
+ QWindow *wnd = QGuiApplicationPrivate::focus_window;
+ if (inPopupMode()) // some delayed focus event to ignore
+ return;
+ QWidget *tlw = qt_tlw_for_window(wnd);
+ QApplication::setActiveWindow(tlw);
+ // QTBUG-37126, Active X controls may set the focus on native child widgets.
+ if (wnd && tlw && wnd != tlw->windowHandle()) {
+ if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd))
+ widgetWindow->widget()->setFocus(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.
@@ -2431,6 +2613,44 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
return !isBlockedByModal(widget->window());
}
+bool qt_try_modal(QWidget *widget, QEvent::Type type)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ bool block_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 && top && top->parentWidget() == 0)
+ top->raise();
+
+ return !block_event;
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return !self->modalWindowList.isEmpty();
+}
+
/*
\internal
*/
@@ -3168,7 +3388,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->device(), tablet->pointerType(),
tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
- tablet->modifiers(), tablet->uniqueId());
+ tablet->modifiers(), tablet->uniqueId(), tablet->button(), tablet->buttons());
te.spont = e->spontaneous();
res = d->notify_helper(w, w == receiver ? tablet : &te);
eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
@@ -3497,7 +3717,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
// deliver the event
bool consumed = receiver->event(e);
- e->spont = false;
+ QCoreApplicationPrivate::setEventSpontaneous(e, false);
return consumed;
}
@@ -3506,6 +3726,123 @@ bool QApplicationPrivate::inPopupMode()
return QApplicationPrivate::popupWidgets != 0;
}
+static void ungrabKeyboardForPopup(QWidget *popup)
+{
+ if (QWidget::keyboardGrabber())
+ qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
+ else
+ qt_widget_private(popup)->stealKeyboardGrab(false);
+}
+
+static void ungrabMouseForPopup(QWidget *popup)
+{
+ if (QWidget::mouseGrabber())
+ qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
+ else
+ qt_widget_private(popup)->stealMouseGrab(false);
+}
+
+static bool popupGrabOk;
+
+static void grabForPopup(QWidget *popup)
+{
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
+ if (popupGrabOk) {
+ popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
+ if (!popupGrabOk) {
+ // transfer grab back to the keyboard grabber if any
+ ungrabKeyboardForPopup(popup);
+ }
+ }
+}
+
+extern QWidget *qt_button_down;
+extern QWidget *qt_popup_down;
+extern bool qt_replay_popup_mouse_event;
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ 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;
+
+ if (popupGrabOk) {
+ popupGrabOk = false;
+
+ if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
+ QGuiApplicationPrivate::mousePressY))
+ || popup->testAttribute(Qt::WA_NoMouseReplay)) {
+ // mouse release event or inside
+ qt_replay_popup_mouse_event = false;
+ } else { // mouse press event
+ qt_replay_popup_mouse_event = true;
+ }
+
+ // transfer grab back to mouse grabber if any, otherwise release the grab
+ ungrabMouseForPopup(popup);
+
+ // transfer grab back to keyboard grabber if any, otherwise release the grab
+ ungrabKeyboardForPopup(popup);
+ }
+
+ if (active_window) {
+ if (QWidget *fw = active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ QCoreApplication::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);
+
+ if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ grabForPopup(aw);
+ }
+
+}
+
+int openPopupCount = 0;
+
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ openPopupCount++;
+ if (!popupWidgets) // create list
+ popupWidgets = new QWidgetList;
+ popupWidgets->append(popup); // add to end of list
+
+ if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ grabForPopup(popup);
+
+ // 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);
+ }
+ }
+}
+
#ifdef QT_KEYPAD_NAVIGATION
/*!
Sets the kind of focus navigation Qt should use to \a mode.
@@ -3610,6 +3947,18 @@ bool QApplication::keypadNavigationEnabled()
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.
*/
+void QApplication::alert(QWidget *widget, int duration)
+{
+ if (widget) {
+ if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
+ return;
+ if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
+ window->alert(duration);
+ } else {
+ foreach (QWidget *topLevel, topLevelWidgets())
+ QApplication::alert(topLevel, duration);
+ }
+}
/*!
\property QApplication::cursorFlashTime
@@ -3700,6 +4049,38 @@ int QApplication::keyboardInputInterval()
By default, this property has a value of 3.
*/
+#ifndef QT_NO_WHEELEVENT
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setWheelScrollLines(int lines)
+{
+ QApplicationPrivate::wheel_scroll_lines = lines;
+}
+#endif
+
+static inline int uiEffectToFlag(Qt::UIEffect effect)
+{
+ switch (effect) {
+ case Qt::UI_General:
+ return QPlatformTheme::GeneralUiEffect;
+ case Qt::UI_AnimateMenu:
+ return QPlatformTheme::AnimateMenuUiEffect;
+ case Qt::UI_FadeMenu:
+ return QPlatformTheme::FadeMenuUiEffect;
+ case Qt::UI_AnimateCombo:
+ return QPlatformTheme::AnimateComboUiEffect;
+ case Qt::UI_AnimateTooltip:
+ return QPlatformTheme::AnimateTooltipUiEffect;
+ case Qt::UI_FadeTooltip:
+ return QPlatformTheme::FadeTooltipUiEffect;
+ case Qt::UI_AnimateToolBox:
+ return QPlatformTheme::AnimateToolBoxUiEffect;
+ }
+ return 0;
+}
/*!
\fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
@@ -3712,6 +4093,19 @@ int QApplication::keyboardInputInterval()
\sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
*/
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ int effectFlags = uiEffectToFlag(effect);
+ if (enable) {
+ if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
+ effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
+ if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
+ effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
+ QApplicationPrivate::enabledAnimations |= effectFlags;
+ } else {
+ QApplicationPrivate::enabledAnimations &= ~effectFlags;
+ }
+}
/*!
\fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
@@ -3726,6 +4120,12 @@ int QApplication::keyboardInputInterval()
\sa setEffectEnabled(), Qt::UIEffect
*/
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ return QColormap::instance().depth() >= 16
+ && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
+ && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
+}
/*!
\fn void QApplication::beep()
@@ -3733,6 +4133,10 @@ int QApplication::keyboardInputInterval()
Sounds the bell, using the default volume and sound. The function is \e not
available in Qt for Embedded Linux.
*/
+void QApplication::beep()
+{
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "beep");
+}
/*!
\macro qApp
@@ -3845,11 +4249,19 @@ void QApplicationPrivate::initializeMultitouch()
initializeMultitouch_sys();
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+}
+
void QApplicationPrivate::cleanupMultitouch()
{
cleanupMultitouch_sys();
}
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+}
+
QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos)
{
int closestTouchPointId = -1;
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index e72fe29bdb..08a450ab32 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -228,7 +228,6 @@ private:
friend class QWidget;
friend class QWidgetPrivate;
friend class QWidgetWindow;
- friend class QETWidget;
friend class QTranslator;
friend class QWidgetAnimator;
#ifndef QT_NO_SHORTCUT
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
deleted file mode 100644
index 5893c52e1b..0000000000
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qapplication_p.h"
-#include "qcolormap.h"
-#include "qpalette.h"
-#include "qpixmapcache.h"
-#ifndef QT_NO_CURSOR
-#include "private/qcursor_p.h"
-#endif
-#include "qscreen.h"
-
-#include "private/qwidget_p.h"
-#include "private/qevent_p.h"
-
-#include <qpa/qplatformintegrationfactory_p.h>
-#include <qdesktopwidget.h>
-#include <qpa/qplatformcursor.h>
-#include <qpa/qplatformtheme.h>
-#include <qpa/qplatformwindow.h>
-
-#include <qdebug.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <qpa/qwindowsysteminterface_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include "qdesktopwidget_qpa_p.h"
-#include "qwidgetwindow_qpa_p.h"
-#include "qtooltip.h"
-
-#ifdef Q_OS_WIN
-# include <QtCore/qt_windows.h> // for qt_win_display_dc()
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static QString appFont;
-static bool popupGrabOk;
-extern QWidget *qt_button_down;
-extern QWidget *qt_popup_down;
-extern bool qt_replay_popup_mouse_event;
-int openPopupCount = 0;
-extern QPointer<QWidget> qt_last_mouse_receiver;
-
-void QApplicationPrivate::createEventDispatcher()
-{
- QGuiApplicationPrivate::createEventDispatcher();
-}
-
-bool qt_try_modal(QWidget *widget, QEvent::Type type)
-{
- QWidget * top = 0;
-
- if (QApplicationPrivate::tryModalHelper(widget, &top))
- return true;
-
- bool block_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 && top && top->parentWidget() == 0)
- top->raise();
-
- return !block_event;
-}
-
-bool QApplicationPrivate::modalState()
-{
- return !self->modalWindowList.isEmpty();
-}
-
-QWidget *qt_tlw_for_window(QWindow *wnd)
-{
- // QTBUG-32177, wnd might be a QQuickView embedded via window container.
- while (wnd && !wnd->isTopLevel()) {
- QWindow *parent = wnd->parent();
- // Don't end up in windows not belonging to this application
- if (parent && parent->type() != Qt::ForeignWindow)
- wnd = wnd->parent();
- else
- break;
- }
- if (wnd)
- foreach (QWidget *tlw, qApp->topLevelWidgets())
- if (tlw->windowHandle() == wnd)
- return tlw;
- return 0;
-}
-
-void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
-{
- Q_UNUSED(previous);
- QWindow *wnd = QGuiApplicationPrivate::focus_window;
- if (inPopupMode()) // some delayed focus event to ignore
- return;
- QWidget *tlw = qt_tlw_for_window(wnd);
- QApplication::setActiveWindow(tlw);
-}
-
-static void ungrabKeyboardForPopup(QWidget *popup)
-{
- if (QWidget::keyboardGrabber())
- qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
- else
- qt_widget_private(popup)->stealKeyboardGrab(false);
-}
-
-static void ungrabMouseForPopup(QWidget *popup)
-{
- if (QWidget::mouseGrabber())
- qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
- else
- qt_widget_private(popup)->stealMouseGrab(false);
-}
-
-static void grabForPopup(QWidget *popup)
-{
- Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
- popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
- if (popupGrabOk) {
- popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
- if (!popupGrabOk) {
- // transfer grab back to the keyboard grabber if any
- ungrabKeyboardForPopup(popup);
- }
- }
-}
-
-void QApplicationPrivate::closePopup(QWidget *popup)
-{
- 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;
-
- if (popupGrabOk) {
- popupGrabOk = false;
-
- if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
- QGuiApplicationPrivate::mousePressY))
- || popup->testAttribute(Qt::WA_NoMouseReplay)) {
- // mouse release event or inside
- qt_replay_popup_mouse_event = false;
- } else { // mouse press event
- qt_replay_popup_mouse_event = true;
- }
-
- // transfer grab back to mouse grabber if any, otherwise release the grab
- ungrabMouseForPopup(popup);
-
- // transfer grab back to keyboard grabber if any, otherwise release the grab
- ungrabKeyboardForPopup(popup);
- }
-
- if (active_window) {
- if (QWidget *fw = active_window->focusWidget()) {
- if (fw != QApplication::focusWidget()) {
- fw->setFocus(Qt::PopupFocusReason);
- } else {
- QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
- QCoreApplication::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);
-
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
- grabForPopup(aw);
- }
-
-}
-
-void QApplicationPrivate::openPopup(QWidget *popup)
-{
- openPopupCount++;
- if (!popupWidgets) // create list
- popupWidgets = new QWidgetList;
- popupWidgets->append(popup); // add to end of list
-
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
- grabForPopup(popup);
-
- // 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()
-{
-}
-
-static void setPossiblePalette(const QPalette *palette, const char *className)
-{
- if (palette == 0)
- return;
- QApplicationPrivate::setPalette_helper(*palette, className, false);
-}
-
-
-void QApplicationPrivate::initializeWidgetPaletteHash()
-{
- QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
- if (!platformTheme)
- return;
- qt_app_palettes_hash()->clear();
-
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
- setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
-}
-
-void QApplicationPrivate::initializeWidgetFontHash()
-{
- const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
- if (!theme)
- return;
- FontHash *fontHash = qt_app_fonts_hash();
- fontHash->clear();
-
- if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
- fontHash->insert(QByteArrayLiteral("QMenu"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
- fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
- fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
- fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
- fontHash->insert(QByteArrayLiteral("QLabel"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
- fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
- fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
- fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont))
- fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
- fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
- fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::CheckBoxFont))
- fontHash->insert(QByteArrayLiteral("QCheckBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::RadioButtonFont))
- fontHash->insert(QByteArrayLiteral("QRadioButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
- fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
- fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
- fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont))
- fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
- fontHash->insert(QByteArrayLiteral("QListBox"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
- fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
- fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
- fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
- if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
- fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
-}
-
-#ifndef QT_NO_WHEELEVENT
-void QApplication::setWheelScrollLines(int lines)
-{
- QApplicationPrivate::wheel_scroll_lines = lines;
-}
-
-int QApplication::wheelScrollLines()
-{
- return QApplicationPrivate::wheel_scroll_lines;
-}
-#endif
-
-static inline int uiEffectToFlag(Qt::UIEffect effect)
-{
- switch (effect) {
- case Qt::UI_General:
- return QPlatformTheme::GeneralUiEffect;
- case Qt::UI_AnimateMenu:
- return QPlatformTheme::AnimateMenuUiEffect;
- case Qt::UI_FadeMenu:
- return QPlatformTheme::FadeMenuUiEffect;
- case Qt::UI_AnimateCombo:
- return QPlatformTheme::AnimateComboUiEffect;
- case Qt::UI_AnimateTooltip:
- return QPlatformTheme::AnimateTooltipUiEffect;
- case Qt::UI_FadeTooltip:
- return QPlatformTheme::FadeTooltipUiEffect;
- case Qt::UI_AnimateToolBox:
- return QPlatformTheme::AnimateToolBoxUiEffect;
- }
- return 0;
-}
-
-void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
-{
- int effectFlags = uiEffectToFlag(effect);
- if (enable) {
- if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
- effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
- if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
- effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
- QApplicationPrivate::enabledAnimations |= effectFlags;
- } else {
- QApplicationPrivate::enabledAnimations &= ~effectFlags;
- }
-}
-
-bool QApplication::isEffectEnabled(Qt::UIEffect effect)
-{
- return QColormap::instance().depth() >= 16
- && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
- && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
-}
-
-QWidget *QApplication::topLevelAt(const QPoint &pos)
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- QList<QScreen *>::const_iterator screen = screens.constBegin();
- QList<QScreen *>::const_iterator end = screens.constEnd();
-
- while (screen != end) {
- if ((*screen)->geometry().contains(pos)) {
- QWidgetWindow *w = qobject_cast<QWidgetWindow *>((*screen)->handle()->topLevelAt(pos));
- return w ? w->widget() : 0;
- }
- ++screen;
- }
- return 0;
-}
-
-void QApplication::beep()
-{
- QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "beep");
-}
-
-void QApplication::alert(QWidget *widget, int duration)
-{
- if (widget) {
- if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
- return;
- if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
- window->alert(duration);
- } else {
- foreach (QWidget *topLevel, topLevelWidgets())
- QApplication::alert(topLevel, duration);
- }
-}
-
-void qt_init_tooltip_palette()
-{
-#ifndef QT_NO_TOOLTIP
- if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
- QToolTip::setPalette(*toolTipPalette);
-#endif
-}
-
-void qt_init(QApplicationPrivate *priv, int type)
-{
- Q_UNUSED(priv);
- Q_UNUSED(type);
-
- QColormap::initialize();
-
- qt_init_tooltip_palette();
-
- QApplicationPrivate::initializeWidgetFontHash();
-}
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-// #fixme: Remove.
-static HDC displayDC = 0; // display device context
-
-Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC
-{
- Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
- if (!displayDC)
- displayDC = GetDC(0);
- return displayDC;
-}
-#endif
-
-void qt_cleanup()
-{
- QPixmapCache::clear();
- QColormap::cleanup();
-
- QApplicationPrivate::active_window = 0; //### this should not be necessary
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- if (displayDC) {
- ReleaseDC(0, displayDC);
- displayDC = 0;
- }
-#endif
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 649978a912..3975e423a0 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -41,6 +41,8 @@
#include "qglobal.h"
#include "qdesktopwidget.h"
+#include "qdesktopwidget_p.h"
+#include "qscreen.h"
#include "qwidget_p.h"
QT_BEGIN_NAMESPACE
@@ -72,5 +74,145 @@ const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
return rect;
}
+void QDesktopWidgetPrivate::_q_updateScreens()
+{
+ Q_Q(QDesktopWidget);
+ const QList<QScreen *> screenList = QGuiApplication::screens();
+ const int targetLength = screenList.length();
+ const int oldLength = screens.length();
+ int currentLength = oldLength;
+
+ // Add or remove screen widgets as necessary
+ if(currentLength > targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength-- > targetLength) {
+ screen = screens.takeLast();
+ delete screen;
+ }
+ }
+ else if (currentLength < targetLength) {
+ while (currentLength < targetLength) {
+ QScreen *qScreen = screenList.at(currentLength);
+ QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget(currentLength++);
+ screenWidget->setGeometry(qScreen->geometry());
+ QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ QObject::connect(qScreen, SIGNAL(destroyed()),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ screens.append(screenWidget);
+ }
+ }
+
+ QRegion virtualGeometry;
+
+ // update the geometry of each screen widget, determine virtual geometry
+ // and emit change signals afterwards.
+ QList<int> changedScreens;
+ for (int i = 0; i < screens.length(); i++) {
+ const QRect screenGeometry = screenList.at(i)->geometry();
+ if (screenGeometry != screens.at(i)->geometry()) {
+ screens.at(i)->setGeometry(screenGeometry);
+ changedScreens.push_back(i);
+ }
+ virtualGeometry += screenGeometry;
+ }
+
+ q->setGeometry(virtualGeometry.boundingRect());
+
+ if (oldLength != targetLength)
+ emit q->screenCountChanged(targetLength);
+
+ foreach (int changedScreen, changedScreens) {
+ emit q->resized(changedScreen);
+ emit q->workAreaResized(changedScreen);
+ }
+}
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ Q_D(QDesktopWidget);
+ setObjectName(QLatin1String("desktop"));
+ d->_q_updateScreens();
+ connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens()));
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return QGuiApplication::primaryScreen()->virtualSiblings().size() > 1;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return 0;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ return qMax(QGuiApplication::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
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens.at(screenNo)->availableGeometry();
+}
+
+const QRect QDesktopWidget::screenGeometry(int screenNo) const
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens.at(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
+{
+ QList<QScreen *> screens = QGuiApplication::screens();
+
+ for (int i = 0; i < screens.size(); ++i)
+ if (screens.at(i)->geometry().contains(p))
+ return i;
+
+ return primaryScreen(); //even better would be closest screen
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+}
+
QT_END_NAMESPACE
+#include "moc_qdesktopwidget.cpp"
diff --git a/src/widgets/kernel/qdesktopwidget_qpa_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index f461869f1b..160807cf23 100644
--- a/src/widgets/kernel/qdesktopwidget_qpa_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -50,8 +50,8 @@
// We mean it.
//
-#ifndef QDESKTOPWIDGET_QPA_P_H
-#define QDESKTOPWIDGET_QPA_P_H
+#ifndef QDESKTOPWIDGET_P_H
+#define QDESKTOPWIDGET_P_H
#include "QDesktopWidget"
#include "private/qwidget_p.h"
diff --git a/src/widgets/kernel/qdesktopwidget_qpa.cpp b/src/widgets/kernel/qdesktopwidget_qpa.cpp
deleted file mode 100644
index 015573dfbe..0000000000
--- a/src/widgets/kernel/qdesktopwidget_qpa.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdesktopwidget.h"
-#include "qscreen.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::_q_updateScreens()
-{
- Q_Q(QDesktopWidget);
- const QList<QScreen *> screenList = QGuiApplication::screens();
- const int targetLength = screenList.length();
- const int oldLength = screens.length();
- int currentLength = oldLength;
-
- // Add or remove screen widgets as necessary
- if(currentLength > targetLength) {
- QDesktopScreenWidget *screen;
- while (currentLength-- > targetLength) {
- screen = screens.takeLast();
- delete screen;
- }
- }
- else if (currentLength < targetLength) {
- while (currentLength < targetLength) {
- QScreen *qScreen = screenList.at(currentLength);
- QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget(currentLength++);
- screenWidget->setGeometry(qScreen->geometry());
- QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- QObject::connect(qScreen, SIGNAL(destroyed()),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- screens.append(screenWidget);
- }
- }
-
- QRegion virtualGeometry;
-
- // update the geometry of each screen widget, determine virtual geometry
- // and emit change signals afterwards.
- QList<int> changedScreens;
- for (int i = 0; i < screens.length(); i++) {
- const QRect screenGeometry = screenList.at(i)->geometry();
- if (screenGeometry != screens.at(i)->geometry()) {
- screens.at(i)->setGeometry(screenGeometry);
- changedScreens.push_back(i);
- }
- virtualGeometry += screenGeometry;
- }
-
- q->setGeometry(virtualGeometry.boundingRect());
-
- if (oldLength != targetLength)
- emit q->screenCountChanged(targetLength);
-
- foreach (int changedScreen, changedScreens) {
- emit q->resized(changedScreen);
- emit q->workAreaResized(changedScreen);
- }
-}
-
-QDesktopWidget::QDesktopWidget()
- : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
-{
- Q_D(QDesktopWidget);
- setObjectName(QLatin1String("desktop"));
- d->_q_updateScreens();
- connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens()));
-}
-
-QDesktopWidget::~QDesktopWidget()
-{
-}
-
-bool QDesktopWidget::isVirtualDesktop() const
-{
- return QGuiApplication::primaryScreen()->virtualSiblings().size() > 1;
-}
-
-int QDesktopWidget::primaryScreen() const
-{
- return 0;
-}
-
-int QDesktopWidget::numScreens() const
-{
- return qMax(QGuiApplication::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
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- if (screenNo == -1)
- screenNo = 0;
- if (screenNo < 0 || screenNo >= screens.size())
- return QRect();
- else
- return screens.at(screenNo)->availableGeometry();
-}
-
-const QRect QDesktopWidget::screenGeometry(int screenNo) const
-{
- QList<QScreen *> screens = QGuiApplication::screens();
- if (screenNo == -1)
- screenNo = 0;
- if (screenNo < 0 || screenNo >= screens.size())
- return QRect();
- else
- return screens.at(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
-{
- QList<QScreen *> screens = QGuiApplication::screens();
-
- for (int i = 0; i < screens.size(); ++i)
- if (screens.at(i)->geometry().contains(p))
- return i;
-
- return primaryScreen(); //even better would be closest screen
-}
-
-void QDesktopWidget::resizeEvent(QResizeEvent *)
-{
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qdesktopwidget.cpp"
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 929e5e2fcf..532cea1f67 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -46,7 +46,7 @@
#include "private/qgraphicsitem_p.h"
#include "private/qevent_p.h"
#include "private/qapplication_p.h"
-#include "private/qwidgetwindow_qpa_p.h"
+#include "private/qwidgetwindow_p.h"
#include "qgesture.h"
#include "qevent.h"
#include "qgraphicsitem.h"
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 307d0bb909..907f69dfbd 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -39,146 +39,892 @@
**
****************************************************************************/
-#include "qopenglwidget_p.h"
-#include <QOpenGLContext>
-#include <QtWidgets/private/qwidget_p.h>
-
-#include <QOpenGLFramebufferObject>
-#include <QOpenGLFunctions>
-#include <QWindow>
-#include <qpa/qplatformwindow.h>
-#include <QDebug>
+#include "qopenglwidget.h"
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QWindow>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <QtGui/QOpenGLPaintDevice>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qopenglextensions_p.h>
+#include <QtGui/private/qfont_p.h>
+#include <QtWidgets/private/qwidget_p.h>
QT_BEGIN_NAMESPACE
+/*!
+ \class QOpenGLWidget
+ \inmodule QtWidgets
+ \since 5.4
+
+ \brief The QOpenGLWidget class is a widget for rendering OpenGL graphics.
+
+ QOpenGLWidget provides functionality for displaying OpenGL graphics
+ integrated into a Qt application. It is very simple to use: Make
+ your class inherit from it and use the subclass like any other
+ QWidget, except that you have the choice between using QPainter and
+ standard OpenGL rendering commands.
+
+ QOpenGLWidget provides three convenient virtual functions that you
+ can reimplement in your subclass to perform the typical OpenGL
+ tasks:
+
+ \list
+ \li paintGL() - Renders the OpenGL scene. Gets called whenever the widget
+ needs to be updated.
+ \li resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
+ called whenever the widget has been resized (and also when it
+ is shown for the first time because all newly created widgets get a
+ resize event automatically).
+ \li initializeGL() - Sets up the OpenGL resources and state. Gets called
+ once before the first time resizeGL() or paintGL() is called.
+ \endlist
+
+ If you need to trigger a repaint from places other than paintGL() (a
+ typical example is when using \l{QTimer}{timers} to animate scenes),
+ you should call the widget's update() function to schedule an update.
+
+ Your widget's OpenGL rendering context is made current when
+ paintGL(), resizeGL(), or initializeGL() is called. If you need to
+ call the standard OpenGL API functions from other places (e.g. in
+ your widget's constructor or in your own paint functions), you
+ must call makeCurrent() first.
+
+ All rendering happens into an OpenGL framebuffer
+ object. makeCurrent() ensure that it is bound in the context. Keep
+ this in mind when creating and binding additional framebuffer
+ objects in the rendering code in paintGL(). Never re-bind the
+ framebuffer with ID 0. Instead, call defaultFramebufferObject() to
+ get the ID that should be bound.
+
+ QOpenGLWidget allows using different OpenGL versions and profiles
+ when the platform supports it. Just set the requested format via
+ setFormat(). Keep in mind however that having multiple QOpenGLWidget
+ instances in the same window requires that they all use the same
+ format, or at least formats that do not make the contexts
+ non-sharable.
+
+ \section1 Painting Techniques
+
+ As described above, subclass QOpenGLWidget to render pure 3D content in the
+ following way:
+
+ \list
+
+ \li Reimplement the initializeGL() and resizeGL() functions to
+ set up the OpenGL state and provide a perspective transformation.
+
+ \li Reimplement paintGL() to paint the 3D scene, calling only
+ OpenGL functions.
+
+ \endlist
+
+ It is also possible to draw 2D graphics onto a QOpenGLWidget subclass using QPainter:
+
+ \list
+
+ \li In paintGL(), instead of issuing OpenGL commands, construct a QPainter
+ object for use on the widget.
+
+ \li Draw primitives using QPainter's member functions.
+
+ \li Direct OpenGL commands can still be issued. However, you must make sure
+ these are enclosed by a call to the painter's beginNativePainting() and
+ endNativePainting().
+
+ \endlist
+
+ When performing drawing using QPainter only, it is also possible to perform
+ the painting like it is done for ordinary widgets: by reimplementing paintEvent().
+
+ \list
+
+ \li Reimplement the paintEvent() function.
+
+ \li Construct a QPainter object targeting the widget. Either pass the widget to the
+ constructor or the QPainter::begin() function.
+
+ \li Draw primitives using QPainter's member functions.
+
+ \li Painting finishes then the QPainter instance is destroyed. Alternatively,
+ call QPainter::end() explicitly.
+
+ \endlist
+
+ \section1 OpenGL function calls, headers and QOpenGLFunctions
+
+ When making OpenGL function calls, it is strongly recommended to avoid calling
+ the functions directly. Instead, prefer using QOpenGLFunctions (when making
+ portable applications) or the versioned variants (for example,
+ QOpenGLFunctions_3_2_Core and similar, when targeting modern, desktop-only
+ OpenGL). This way the application will work correctly in all Qt build
+ configurations, including the ones that perform dynamic OpenGL implementation
+ loading which means applications are not directly linking to an GL
+ implementation and thus direct function calls are not feasible.
+
+ In paintGL() the current context is always accessible by caling
+ QOpenGLContext::currentContext(). From this context an already initialized,
+ ready-to-be-used QOpenGLFunctions instance is retrievable by calling
+ QOpenGLContext::functions(). An alternative to prefixing every GL call is to
+ inherit from QOpenGLFunctions and call
+ QOpenGLFunctions::initializeOpenGLFunctions() in initializeGL().
+
+ As for the OpenGL headers, note that in most cases there will be no need to
+ directly include any headers like GL.h. The OpenGL-related Qt headers will
+ include qopengl.h which will in turn include an appropriate header for the
+ system. This might be an OpenGL ES 3.x or 2.0 header, the highest version that
+ is available, or a system-provided gl.h. In addition, a copy of the extension
+ headers (called glext.h on some systems) is provided as part of Qt both for
+ OpenGL and OpenGL ES. These will get included automatically on platforms where
+ feasible. This means that constants and function pointer typedefs from ARB,
+ EXT, OES extensions are automatically available.
+
+ \section1 Code examples
+
+ To get started, the simplest QOpenGLWidget subclass could like like the following:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 0
+
+ Alternatively, the prefixing of each and every OpenGL call can be avoidided by deriving
+ from QOpenGLFunctions instead:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 1
+
+ To get a context compatible with a given OpenGL version or profile, or to
+ request depth and stencil buffers, call setFormat():
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 2
+
+ With OpenGL 3.0+ contexts, when portability is not important, the versioned
+ QOpenGLFunctions variants give easy access to all the modern OpenGL functions
+ available in a given version:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 3
+
+ \section1 Relation to QGLWidget
+
+ The legacy QtOpenGL module (classes prefixed with QGL) provides a widget
+ called QGLWidget. QOpenGLWidget is intended to be a modern replacement for
+ it. Therefore, especially in new applications, the general recommendation is
+ to use QOpenGLWidget.
+
+ While the API is very similar, there is an important difference between the
+ two: QOpenGLWidget always renders offscreen, using framebuffer
+ objects. QGLWidget on the other hand uses a native window and surface. The
+ latter causes issues when using it in complex user interfaces since, depending
+ on the platform, such native child widgets may have various limitations,
+ regarding stacking orders for example. QOpenGLWidget avoids this by not
+ creating a separate native window.
+
+ \section1 Threading
+
+ Performing offscreen rendering on worker threads, for example to generate
+ textures that are then used in the GUI/main thread in paintGL(), are supported
+ by exposing the widget's QOpenGLContext so that additional contexts sharing
+ with it can be created on each thread.
+
+ Drawing directly to the QOpenGLWidget's framebuffer outside the GUI/main
+ thread is possible by reimplementing paintEvent() to do nothing. The context's
+ thread affinity has to be changed via QObject::moveToThread(). After that,
+ makeCurrent() and doneCurrent() are usable on the worker thread. Be careful to
+ move the context back to the GUI/main thread afterwards.
+
+ Unlike QGLWidget, triggering a buffer swap just for the QOpenGLWidget is not
+ possible since there is no real, onscreen native surface for it. Instead, it
+ is up to the widget stack to manage composition and buffer swaps on the gui
+ thread. When a thread is done updating the framebuffer, call update() \b{on
+ the GUI/main thread} to schedule composition.
+
+ Extra care has to be taken to avoid using the framebuffer when the GUI/main
+ thread is performing compositing. The signals aboutToCompose() and
+ frameSwapped() will be emitted when the composition is starting and
+ ending. They are emitted on the GUI/main thread. This means that by using a
+ direct connection aboutToCompose() can block the GUI/main thread until the
+ worker thread has finished its rendering. After that, the worker thread must
+ perform no further rendering until the frameSwapped() signal is emitted. If
+ this is not acceptable, the worker thread has to implement a double buffering
+ mechanism. This involves drawing using an alternative render target, that is
+ fully controlled by the thread, e.g. an additional framebuffer object, and
+ blitting to the QOpenGLWidget's framebuffer at a suitable time.
+
+ \section1 Context sharing
+
+ When multiple QOpenGLWidgets are added as children to the same top-level
+ widget, their contexts will share with each other. This does not apply for
+ QOpenGLWidget instances that belong to different windows.
+
+ This means that all QOpenGLWidgets in the same window can access each other's
+ sharable resources, like textures, and there is no need for an extra "global
+ share" context, as was the case with QGLWidget.
+
+ Note that QOpenGLWidget expects a standard conformant implementation of
+ resource sharing when it comes to the underlying graphics drivers. For
+ example, some drivers, in particular for mobile and embedded hardware, have
+ issues with setting up sharing between an existing context and others that are
+ created later. Some other drivers may behave in unexpected ways when trying to
+ utilize shared resources between different threads.
+
+ \section1 Limitations
+
+ Putting other widgets underneath and making the QOpenGLWidget transparent will
+ not lead to the expected results: The widgets underneath will not be
+ visible. This is because in practice the QOpenGLWidget is drawn before all
+ other regular, non-OpenGL widgets, and so see-through type of solutions are
+ not feasible. Other type of layouts, like having widgets on top of the
+ QOpenGLWidget, will function as expected.
+
+ When absolutely necessary, this limitation can be overcome by setting the
+ Qt::WA_AlwaysStackOnTop attribute on the QOpenGLWidget. Be aware however that
+ this breaks stacking order, for example it will not be possible to have other
+ widgets on top of the QOpenGLWidget, so it should only be used in situations
+ where a semi-transparent QOpenGLWidget with other widgets visible underneath
+ is required.
+
+ \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
+ countries.}
+
+ \sa QOpenGLFunctions
+*/
+
+/*!
+ \fn void QOpenGLWidget::aboutToCompose()
+
+ This signal is emitted when the widget's top-level window is about to begin
+ composing the textures of its QOpenGLWidget children and the other widgets.
+*/
+
+/*!
+ \fn void QOpenGLWidget::frameSwapped()
+
+ This signal is emitted after the widget's top-level window has finished
+ composition and returned from its potentially blocking
+ QOpenGLContext::swapBuffers() call.
+*/
+
+/*!
+ \fn void QOpenGLWidget::aboutToResize()
+
+ This signal is emitted when the widget's size is changed and therefore the
+ framebuffer object is going to be recreated.
+*/
+
+/*!
+ \fn void QOpenGLWidget::resized()
+
+ This signal is emitted right after the framebuffer object has been recreated
+ due to resizing the widget.
+*/
+
+class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) : w(widget) { }
+ void ensureActiveTarget() Q_DECL_OVERRIDE;
+
+private:
+ QOpenGLWidget *w;
+};
+
class QOpenGLWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QOpenGLWidget)
public:
QOpenGLWidgetPrivate()
- : fbo(0), uninitialized(true)
+ : context(0),
+ fbo(0),
+ resolvedFbo(0),
+ surface(0),
+ initialized(false),
+ fakeHidden(false),
+ paintDevice(0),
+ inBackingStorePaint(false)
+ {
+ }
+
+ ~QOpenGLWidgetPrivate()
{
+ reset();
}
- GLuint textureId() const { return fbo ? fbo->texture() : 0; }
- const QSurface *surface() const { return q_func()->window()->windowHandle(); }
- QSurface *surface() { return q_func()->window()->windowHandle(); }
+ void reset();
+ void recreateFbo();
+
+ GLuint textureId() const Q_DECL_OVERRIDE;
+
void initialize();
+ void invokeUserPaint();
+ void render();
- QOpenGLContext context;
- QOpenGLFramebufferObject *fbo;
- bool uninitialized;
+ QImage grabFramebuffer() Q_DECL_OVERRIDE;
+ void beginBackingStorePainting() Q_DECL_OVERRIDE { inBackingStorePaint = true; }
+ void endBackingStorePainting() Q_DECL_OVERRIDE { inBackingStorePaint = false; }
+ void beginCompose() Q_DECL_OVERRIDE;
+ void endCompose() Q_DECL_OVERRIDE;
+ void resizeViewportFramebuffer() Q_DECL_OVERRIDE;
- int w,h;
+ QOpenGLContext *context;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLFramebufferObject *resolvedFbo;
+ QOffscreenSurface *surface;
+ bool initialized;
+ bool fakeHidden;
+ QOpenGLPaintDevice *paintDevice;
+ bool inBackingStorePaint;
+ QSurfaceFormat requestedFormat;
};
+void QOpenGLWidgetPaintDevice::ensureActiveTarget()
+{
+ QOpenGLWidgetPrivate *d = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(w));
+ if (!d->initialized)
+ return;
+
+ if (QOpenGLContext::currentContext() != d->context)
+ w->makeCurrent();
+ else
+ d->fbo->bind();
+}
+
+GLuint QOpenGLWidgetPrivate::textureId() const
+{
+ return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
+}
+
+void QOpenGLWidgetPrivate::reset()
+{
+ delete paintDevice;
+ paintDevice = 0;
+ delete fbo;
+ fbo = 0;
+ delete resolvedFbo;
+ resolvedFbo = 0;
+ delete context;
+ context = 0;
+ delete surface;
+ surface = 0;
+ initialized = fakeHidden = inBackingStorePaint = false;
+}
+
+void QOpenGLWidgetPrivate::recreateFbo()
+{
+ Q_Q(QOpenGLWidget);
+
+ emit q->aboutToResize();
+
+ context->makeCurrent(surface);
+
+ delete fbo;
+ delete resolvedFbo;
+
+ int samples = get(q->window())->shareContext()->format().samples();
+ QOpenGLExtensions *extfuncs = static_cast<QOpenGLExtensions *>(context->functions());
+ if (!extfuncs->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
+ samples = 0;
+
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(samples);
+
+ const QSize deviceSize = q->size() * q->devicePixelRatio();
+ fbo = new QOpenGLFramebufferObject(deviceSize, format);
+ if (samples > 0)
+ resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
+
+ fbo->bind();
+
+ paintDevice->setSize(deviceSize);
+
+ emit q->resized();
+}
+
+void QOpenGLWidgetPrivate::beginCompose()
+{
+ Q_Q(QOpenGLWidget);
+ emit q->aboutToCompose();
+}
+
+void QOpenGLWidgetPrivate::endCompose()
+{
+ Q_Q(QOpenGLWidget);
+ emit q->frameSwapped();
+}
+
void QOpenGLWidgetPrivate::initialize()
{
Q_Q(QOpenGLWidget);
- if (!uninitialized)
+ if (initialized)
+ return;
+
+ // Get our toplevel's context with which we will share in order to make the
+ // texture usable by the underlying window's backingstore.
+ QOpenGLContext *shareContext = get(q->window())->shareContext();
+ if (!shareContext) {
+ qWarning("QOpenGLWidget: Cannot be used without a context shared with the toplevel.");
return;
- context.setShareContext(get(q->window())->shareContext());
- context.setFormat(surface()->format());
- context.create();
- context.makeCurrent(surface());
+ }
+
+ QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
+ ctx->setShareContext(shareContext);
+ ctx->setFormat(requestedFormat);
+ if (!ctx->create()) {
+ qWarning("QOpenGLWidget: Failed to create context");
+ return;
+ }
+
+ // The top-level window's surface is not good enough since it causes way too
+ // much trouble with regards to the QSurfaceFormat for example. So just like
+ // in QQuickWidget, use a dedicated QOffscreenSurface.
+ surface = new QOffscreenSurface;
+ surface->setFormat(ctx->format());
+ surface->create();
+
+ if (!ctx->makeCurrent(surface)) {
+ qWarning("QOpenGLWidget: Failed to make context current");
+ return;
+ }
+
+ paintDevice = new QOpenGLWidgetPaintDevice(q);
+ paintDevice->setSize(q->size() * q->devicePixelRatio());
+ paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+
+ context = ctx.take();
+ initialized = true;
+
q->initializeGL();
- uninitialized = false;
}
+void QOpenGLWidgetPrivate::invokeUserPaint()
+{
+ Q_Q(QOpenGLWidget);
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
+
+ q->paintGL();
+
+ if (resolvedFbo) {
+ QRect rect(QPoint(0, 0), fbo->size());
+ QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
+ }
+}
+
+void QOpenGLWidgetPrivate::render()
+{
+ Q_Q(QOpenGLWidget);
+
+ if (fakeHidden || !initialized)
+ return;
+
+ q->makeCurrent();
+ invokeUserPaint();
+ context->functions()->glFlush();
+}
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+QImage QOpenGLWidgetPrivate::grabFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+ if (!initialized)
+ return QImage();
+
+ render();
+ q->makeCurrent();
+ QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), false, false);
+
+ return res;
+}
+
+void QOpenGLWidgetPrivate::resizeViewportFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+ if (!initialized)
+ return;
+
+ if (!fbo || q->size() != fbo->size())
+ recreateFbo();
+}
+
+/*!
+ Constructs a widget which is a child of \a parent, with widget flags set to \a f.
+ */
QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
: QWidget(*(new QOpenGLWidgetPrivate), parent, f)
{
Q_D(QOpenGLWidget);
- d->setRenderToTexture();
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface))
+ d->setRenderToTexture();
+ else
+ qWarning("QOpenGLWidget is not supported on this platform.");
}
+/*!
+ Destroys the widget
+ */
QOpenGLWidget::~QOpenGLWidget()
{
}
+/*!
+ Sets the requested surface \a format.
+
+ \note Requesting an alpha buffer via this function will not lead to the desired results
+ and should be avoided. Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent
+ QOpenGLWidget instances with other widgets visible underneath. Keep in mind however that
+ this breaks the stacking order, so it will no longer be possible to have other widgets
+ on top of the QOpenGLWidget.
+
+ \sa format(), Qt::WA_AlwaysStackOnTop
+ */
+void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
+{
+ Q_UNUSED(format);
+ Q_D(QOpenGLWidget);
+ if (d->initialized) {
+ qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
+ return;
+ }
+
+ d->requestedFormat = format;
+}
+
+/*!
+ Returns the context and surface format used by this widget and its toplevel
+ window.
+
+ After the widget and its toplevel have both been created, resized and shown,
+ this function will return the actual format of the context. This may differ
+ from the requested format if the request could not be fulfilled by the
+ platform. It is also possible to get larger color buffer sizes than
+ requested.
+
+ When the widget's window and the related OpenGL resources are not yet
+ initialized, the return value is the format that has been set via
+ setFormat().
+
+ \sa setFormat(), context()
+ */
+QSurfaceFormat QOpenGLWidget::format() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->initialized ? d->context->format() : d->requestedFormat;
+}
+
+/*!
+ \return \e true if the widget and OpenGL resources, like the context, have
+ been successfully initialized. Note that the return value is always false
+ until the widget is shown.
+*/
bool QOpenGLWidget::isValid() const
{
Q_D(const QOpenGLWidget);
- return d->context.isValid();
+ return d->initialized && d->context->isValid();
}
+/*!
+ Prepares for rendering OpenGL content for this widget by making the
+ corresponding context current and binding the framebuffer object in that
+ context.
+
+ It is not necessary to call this function in most cases, because it
+ is called automatically before invoking paintGL().
+
+ \sa context(), paintGL(), doneCurrent()
+ */
void QOpenGLWidget::makeCurrent()
{
Q_D(QOpenGLWidget);
- d->context.makeCurrent(d->surface());
+ if (!d->initialized) {
+ qWarning("QOpenGLWidget: Cannot make uninitialized widget current");
+ return;
+ }
+
+ d->context->makeCurrent(d->surface);
d->fbo->bind();
}
+/*!
+ Releases the context.
+
+ It is not necessary to call this function in most cases, since the
+ widget will make sure the context is bound and released properly
+ when invoking paintGL().
+ */
void QOpenGLWidget::doneCurrent()
{
Q_D(QOpenGLWidget);
- d->context.doneCurrent();
+ if (!d->initialized)
+ return;
+
+ d->context->doneCurrent();
}
-QSurfaceFormat QOpenGLWidget::format() const
+/*!
+ \return The QOpenGLContext used by this widget or \c 0 if not yet initialized.
+
+ \note The context and the framebuffer object used by the widget changes when
+ reparenting the widget via setParent().
+
+ \sa QOpenGLContext::setShareContext(), defaultFramebufferObject()
+ */
+QOpenGLContext *QOpenGLWidget::context() const
{
Q_D(const QOpenGLWidget);
- return d->surface()->format();
+ return d->context;
}
+/*!
+ \return The framebuffer object handle or \c 0 if not yet initialized.
+
+ \note The framebuffer object belongs to the context returned by context()
+ and may not be accessible from other contexts.
+
+ \note The context and the framebuffer object used by the widget changes when
+ reparenting the widget via setParent(). In addition, the framebuffer object
+ changes on each resize.
+
+ \sa context()
+ */
GLuint QOpenGLWidget::defaultFramebufferObject() const
{
Q_D(const QOpenGLWidget);
return d->fbo ? d->fbo->handle() : 0;
}
+/*!
+ This virtual function is called once before the first call to
+ paintGL() or resizeGL(). Reimplement it in a subclass.
+
+ This function should set up any required OpenGL resources and state.
+
+ There is no need to call makeCurrent() because this has already been
+ done when this function is called. Note however that the framebuffer
+ is not yet available at this stage, so avoid issuing draw calls from
+ here. Defer such calls to paintGL() instead.
+
+ \sa paintGL(), resizeGL()
+*/
void QOpenGLWidget::initializeGL()
{
-
}
+/*!
+ This virtual function is called whenever the widget has been
+ resized. Reimplement it in a subclass. The new size is passed in
+ \a w and \a h.
+
+ There is no need to call makeCurrent() because this has already been
+ done when this function is called. Additionally, the framebuffer is
+ also bound.
+
+ \sa initializeGL(), paintGL()
+*/
void QOpenGLWidget::resizeGL(int w, int h)
{
Q_UNUSED(w);
Q_UNUSED(h);
}
+/*!
+ This virtual function is called whenever the widget needs to be
+ painted. Reimplement it in a subclass.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+
+ Before invoking this function, the context and the framebuffer are
+ bound, and the viewport is set up by a call to glViewport(). No
+ other state is set and no clearing or drawing is performed by the
+ framework.
+
+ \sa initializeGL(), resizeGL()
+*/
void QOpenGLWidget::paintGL()
{
}
-void QOpenGLWidget::updateGL()
+/*!
+ \internal
+
+ Handles resize events that are passed in the \a event parameter.
+ Calls the virtual function resizeGL().
+*/
+void QOpenGLWidget::resizeEvent(QResizeEvent *e)
{
Q_D(QOpenGLWidget);
- if (d->uninitialized || !d->surface())
+
+ if (e->size().isEmpty()) {
+ d->fakeHidden = true;
+ return;
+ }
+ d->fakeHidden = false;
+
+ d->initialize();
+ if (!d->initialized)
return;
- makeCurrent();
- paintGL();
- d->context.functions()->glFlush();
- doneCurrent();
- update();
+ d->recreateFbo();
+ resizeGL(width(), height());
+ d->invokeUserPaint();
+ d->context->functions()->glFlush();
}
+/*!
+ Handles paint events.
-void QOpenGLWidget::resizeEvent(QResizeEvent *)
+ Calling QWidget::update() will lead to sending a paint event \a e,
+ and thus invoking this function. (NB this is asynchronous and will
+ happen at some point after returning from update()). This function
+ will then, after some preparation, call the virtual paintGL() to
+ update the contents of the QOpenGLWidget's framebuffer. The widget's
+ top-level window will then composite the framebuffer's texture with
+ the rest of the window.
+*/
+void QOpenGLWidget::paintEvent(QPaintEvent *e)
{
+ Q_UNUSED(e);
Q_D(QOpenGLWidget);
- d->w = width();
- d->h = height();
- d->initialize();
+ if (!d->initialized)
+ return;
- d->context.makeCurrent(d->surface());
- delete d->fbo; // recreate when resized
- d->fbo = new QOpenGLFramebufferObject(size() * devicePixelRatio(), QOpenGLFramebufferObject::CombinedDepthStencil);
- d->fbo->bind();
- QOpenGLFunctions *funcs = d->context.functions();
- resizeGL(width(), height());
- paintGL();
- funcs->glFlush();
+ if (updatesEnabled())
+ d->render();
+}
+
+/*!
+ Renders and returns a 32-bit RGB image of the framebuffer.
+
+ \note This is a potentially expensive operation because it relies on glReadPixels()
+ to read back the pixels. This may be slow and can stall the GPU pipeline.
+*/
+QImage QOpenGLWidget::grabFramebuffer()
+{
+ Q_D(QOpenGLWidget);
+ return d->grabFramebuffer();
+}
+
+/*!
+ \internal
+*/
+int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ Q_D(const QOpenGLWidget);
+ if (d->inBackingStorePaint)
+ return QWidget::metric(metric);
+
+ QScreen *screen = window()->windowHandle()->screen();
+ if (!screen && QGuiApplication::primaryScreen())
+ screen = QGuiApplication::primaryScreen();
+
+ const float dpmx = qt_defaultDpiX() * 100. / 2.54;
+ const float dpmy = qt_defaultDpiY() * 100. / 2.54;
+
+ switch (metric) {
+ case PdmWidth:
+ return width();
+ case PdmHeight:
+ return height();
+ case PdmDepth:
+ return 32;
+ case PdmWidthMM:
+ if (screen)
+ return width() * screen->physicalSize().width() / screen->geometry().width();
+ else
+ return width() * 1000 / dpmx;
+ case PdmHeightMM:
+ if (screen)
+ return height() * screen->physicalSize().height() / screen->geometry().height();
+ else
+ return height() * 1000 / dpmy;
+ case PdmNumColors:
+ return 0;
+ case PdmDpiX:
+ if (screen)
+ return qRound(screen->logicalDotsPerInchX());
+ else
+ return qRound(dpmx * 0.0254);
+ case PdmDpiY:
+ if (screen)
+ return qRound(screen->logicalDotsPerInchY());
+ else
+ return qRound(dpmy * 0.0254);
+ case PdmPhysicalDpiX:
+ if (screen)
+ return qRound(screen->physicalDotsPerInchX());
+ else
+ return qRound(dpmx * 0.0254);
+ case PdmPhysicalDpiY:
+ if (screen)
+ return qRound(screen->physicalDotsPerInchY());
+ else
+ return qRound(dpmy * 0.0254);
+ case PdmDevicePixelRatio:
+ if (screen)
+ return screen->devicePixelRatio();
+ else
+ return 1.0;
+ default:
+ qWarning("QOpenGLWidget::metric(): unknown metric %d", metric);
+ return 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QPaintDevice *QOpenGLWidget::redirected(QPoint *p) const
+{
+ Q_D(const QOpenGLWidget);
+ if (d->inBackingStorePaint)
+ return QWidget::redirected(p);
+
+ return d->paintDevice;
+}
+
+/*!
+ \internal
+*/
+QPaintEngine *QOpenGLWidget::paintEngine() const
+{
+ Q_D(const QOpenGLWidget);
+ // QWidget needs to "punch a hole" into the backingstore. This needs the
+ // normal paint engine and device, not the GL one. So in this mode, behave
+ // like a normal widget.
+ if (d->inBackingStorePaint)
+ return QWidget::paintEngine();
+
+ if (!d->initialized)
+ return 0;
+
+ return d->paintDevice->paintEngine();
}
-void QOpenGLWidget::paintEvent(QPaintEvent *)
+/*!
+ \internal
+*/
+bool QOpenGLWidget::event(QEvent *e)
{
- qWarning("QOpenGLWidget does not support paintEvent() yet.");
- return;
+ Q_D(QOpenGLWidget);
+ switch (e->type()) {
+ case QEvent::WindowChangeInternal:
+ if (d->initialized)
+ d->reset();
+ // FALLTHROUGH
+ case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
+ if (!d->initialized && !size().isEmpty() && window() && window()->windowHandle()) {
+ d->initialize();
+ if (d->initialized)
+ d->recreateFbo();
+ }
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(e);
}
QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qopenglwidget_p.h b/src/widgets/kernel/qopenglwidget.h
index 1c7f0bfeec..28d802e1f4 100644
--- a/src/widgets/kernel/qopenglwidget_p.h
+++ b/src/widgets/kernel/qopenglwidget.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -39,21 +39,11 @@
**
****************************************************************************/
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It may change from version to version
-// without notice, or even be removed.
-//
-// We mean it.
-//
#ifndef QOPENGLWIDGET_H
#define QOPENGLWIDGET_H
-#include <QWidget>
-#include <QSurfaceFormat>
-
+#include <QtWidgets/QWidget>
+#include <QtGui/QSurfaceFormat>
#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
@@ -66,68 +56,43 @@ class Q_WIDGETS_EXPORT QOpenGLWidget : public QWidget
Q_DECLARE_PRIVATE(QOpenGLWidget)
public:
- explicit QOpenGLWidget(QWidget* parent=0,
- Qt::WindowFlags f=0);
-
-// This API is not finalized yet. The commented-out functions below are
-// QGLWidget functions that have not been implemented for QOpenGLWidget.
-// Some of them may not end up in the final version (which is planned for a
-// future release of Qt).
-
-// explicit QOpenGLWidget(const QSurfaceFormat& format, QWidget* parent=0,
-// Qt::WindowFlags f=0);
+ explicit QOpenGLWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
~QOpenGLWidget();
-// void qglClearColor(const QColor& c) const;
+ void setFormat(const QSurfaceFormat &format);
+ QSurfaceFormat format() const;
bool isValid() const;
-// bool isSharing() const;
void makeCurrent();
void doneCurrent();
-// void swapBuffers();
-
- QSurfaceFormat format() const;
+ QOpenGLContext *context() const;
GLuint defaultFramebufferObject() const;
-// QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
- QImage grabFrameBuffer(bool withAlpha = false);
+ QImage grabFramebuffer();
-// static QImage convertToGLFormat(const QImage& img);
-
-// QPaintEngine *paintEngine() const;
-
-// void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-// void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-
-public Q_SLOTS:
- void updateGL();
+Q_SIGNALS:
+ void aboutToCompose();
+ void frameSwapped();
+ void aboutToResize();
+ void resized();
protected:
-// bool event(QEvent *);
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
-// void setAutoBufferSwap(bool on);
-// bool autoBufferSwap() const;
+ void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;
+ void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
- void paintEvent(QPaintEvent*);
- void resizeEvent(QResizeEvent*);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ QPaintDevice *redirected(QPoint *p) const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
-// virtual void glInit();
-// virtual void glDraw();
-
-// QOpenGLWidget(QOpenGLWidgetPrivate &dd,
-// const QGLFormat &format = QGLFormat(),
-// QWidget *parent = 0,
-// const QOpenGLWidget* shareWidget = 0,
-// Qt::WindowFlags f = 0);
private:
Q_DISABLE_COPY(QOpenGLWidget)
-
-
};
QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp
index dcf6aed591..217f0386cb 100644
--- a/src/widgets/kernel/qshortcut.cpp
+++ b/src/widgets/kernel/qshortcut.cpp
@@ -51,7 +51,7 @@
#include <private/qapplication_p.h>
#include <private/qshortcutmap_p.h>
#include <private/qaction_p.h>
-#include <private/qwidgetwindow_qpa_p.h>
+#include <private/qwidgetwindow_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7396808442..43ce9a82f7 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -69,7 +69,7 @@
# include <private/qmainwindowlayout_p.h>
#endif
#include <qpa/qplatformwindow.h>
-#include "private/qwidgetwindow_qpa_p.h"
+#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#include "qtooltip.h"
#include "qwhatsthis.h"
@@ -357,6 +357,13 @@ void QWidgetPrivate::scrollChildren(int dx, int dy)
}
}
+void QWidgetPrivate::setWSGeometry()
+{
+ Q_Q(QWidget);
+ if (QWindow *window = q->windowHandle())
+ window->setGeometry(data.crect);
+}
+
void QWidgetPrivate::updateWidgetTransform(QEvent *event)
{
Q_Q(QWidget);
@@ -1065,7 +1072,11 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
// 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)) {
+ if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
+# ifdef Q_OS_WIN
+ && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
+# endif
+ ) {
flags |= Qt::WindowSystemMenuHint;
#else
if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
@@ -1348,6 +1359,155 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
d->updateFrameStrut();
}
+void q_createNativeChildrenAndSetParent(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->internalWinId())
+ childWidget->winId();
+ if (childWidget->windowHandle()) {
+ QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle();
+ if (childWidget->isWindow())
+ childWidget->windowHandle()->setTransientParent(parentWindow);
+ else
+ childWidget->windowHandle()->setParent(parentWindow);
+ }
+ } else {
+ q_createNativeChildrenAndSetParent(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())
+ return; // we only care about real toplevels
+
+ QWindow *win = topData()->window;
+ // topData() ensures the extra is created but does not ensure 'window' is non-null
+ // in case the extra was already valid.
+ if (!win) {
+ createTLSysExtra();
+ win = topData()->window;
+ }
+
+ foreach (const QByteArray &propertyName, q->dynamicPropertyNames()) {
+ if (!qstrncmp(propertyName, "_q_platform_", 12))
+ win->setProperty(propertyName, q->property(propertyName));
+ }
+
+#ifdef Q_OS_OSX
+ if (q->testAttribute(Qt::WA_ShowWithoutActivating))
+ win->setProperty("_q_showWithoutActivating", QVariant(true));
+#endif
+ win->setFlags(data.window_flags);
+ fixPosIncludesFrame();
+ if (q->testAttribute(Qt::WA_Moved)
+ || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
+ win->setGeometry(q->geometry());
+ else
+ win->resize(q->size());
+ if (win->isTopLevel())
+ win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
+
+ QSurfaceFormat format = win->requestedFormat();
+ if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
+ && q->testAttribute(Qt::WA_TranslucentBackground)) {
+ format.setAlphaBufferSize(8);
+ }
+ win->setFormat(format);
+
+ if (QWidget *nativeParent = q->nativeParentWidget()) {
+ if (nativeParent->windowHandle()) {
+ if (flags & Qt::Window) {
+ win->setTransientParent(nativeParent->window()->windowHandle());
+ win->setParent(0);
+ } else {
+ win->setTransientParent(0);
+ win->setParent(nativeParent->windowHandle());
+ }
+ }
+ }
+
+ qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
+ QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
+ win->create();
+ // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
+ if ((flags & Qt::Desktop) == Qt::Window)
+ win->handle()->setFrameStrutEventsEnabled(true);
+
+ data.window_flags = win->flags();
+
+ QBackingStore *store = q->backingStore();
+
+ if (!store) {
+ if (win && q->windowType() != Qt::Desktop) {
+ if (q->isTopLevel())
+ q->setBackingStore(new QBackingStore(win));
+ } else {
+ q->setAttribute(Qt::WA_PaintOnScreen, true);
+ }
+ }
+
+ setWindowModified_helper();
+ WId id = win->winId();
+ // See the QPlatformWindow::winId() documentation
+ Q_ASSERT(id != WId(0));
+ setWinId(id);
+
+ // Check children and create windows for them if necessary
+ q_createNativeChildrenAndSetParent(q);
+
+ if (extra && !extra->mask.isEmpty())
+ setMask_sys(extra->mask);
+
+ // If widget is already shown, set window visible, too
+ if (q->isVisible())
+ win->setVisible(true);
+}
+
+#ifdef Q_OS_WIN
+static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
+#endif
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ Q_Q(QWidget);
+ if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
+ extra->topextra->window = new QWidgetWindow(q);
+ if (extra->minw || extra->minh)
+ extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
+ if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
+ extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
+ if (extra->topextra->opacity != 255 && q->isWindow())
+ extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
+#ifdef Q_OS_WIN
+ // Pass on native parent handle for Widget embedded into Active X.
+ const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
+ if (activeXNativeParentHandle.isValid())
+ extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
+ if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
+ extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
+#endif
+ }
+
+}
+
/*!
Destroys the widget.
@@ -1612,6 +1772,9 @@ void QWidgetPrivate::createExtra()
}
}
+void QWidgetPrivate::createSysExtra()
+{
+}
/*!
\internal
@@ -1642,6 +1805,46 @@ void QWidgetPrivate::deleteExtra()
}
}
+void QWidgetPrivate::deleteSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ if (extra && extra->topextra) {
+ //the qplatformbackingstore may hold a reference to the window, so the backingstore
+ //needs to be deleted first. If the backingstore holds GL resources, we need to
+ // make the context current here, since the platform bs does not have a reference
+ // to the widget.
+
+#ifndef QT_NO_OPENGL
+ if (textureChildSeen && extra->topextra->shareContext)
+ extra->topextra->shareContext->makeCurrent(extra->topextra->window);
+#endif
+ extra->topextra->backingStoreTracker.destroy();
+ delete extra->topextra->backingStore;
+ extra->topextra->backingStore = 0;
+#ifndef QT_NO_OPENGL
+ if (textureChildSeen && extra->topextra->shareContext)
+ extra->topextra->shareContext->doneCurrent();
+ delete extra->topextra->shareContext;
+ extra->topextra->shareContext = 0;
+#endif
+
+ //the toplevel might have a context with a "qglcontext associated with it. We need to
+ //delete the qglcontext before we delete the qplatformopenglcontext.
+ //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);
+ delete extra->topextra->window;
+ extra->topextra->window = 0;
+
+ }
+}
+
/*
Returns \c true if there are widgets above this which overlap with
\a rect, which is in parent's coordinate system (same as crect).
@@ -2364,6 +2567,27 @@ WId QWidget::effectiveWinId() const
return 0;
}
+/*!
+ If this is a native widget, return the associated QWindow.
+ Otherwise return null.
+
+ Native widgets include toplevel widgets, QGLWidget, and child widgets
+ on which winId() was called.
+
+ \since 5.0
+
+ \sa winId()
+*/
+QWindow *QWidget::windowHandle() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra)
+ return extra->window;
+
+ return 0;
+}
+
#ifndef QT_NO_STYLE_STYLESHEET
/*!
@@ -2654,6 +2878,13 @@ void QWidget::setWindowModality(Qt::WindowModality windowModality)
setAttribute(Qt::WA_SetWindowModality, true);
}
+void QWidgetPrivate::setModal_sys()
+{
+ Q_Q(QWidget);
+ if (q->windowHandle())
+ q->windowHandle()->setModality(q->windowModality());
+}
+
/*!
\fn bool QWidget::underMouse() const
@@ -2747,6 +2978,17 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
+Qt::WindowState 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;
+}
+
/*!
\fn void QWidget::setWindowState(Qt::WindowStates windowState)
@@ -2777,6 +3019,39 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
\sa Qt::WindowState, windowState()
*/
+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;
+ Qt::WindowState newEffectiveState = effectiveState(newstate);
+ Qt::WindowState oldEffectiveState = effectiveState(oldstate);
+ if (isWindow() && newEffectiveState != oldEffectiveState) {
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ adjustSize();
+
+ d->createTLExtra();
+ if (oldEffectiveState == Qt::WindowNoState)
+ d->topData()->normalGeometry = geometry();
+
+ Q_ASSERT(windowHandle());
+ windowHandle()->setWindowState(newEffectiveState);
+ }
+ data->in_set_window_state = 0;
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
/*!
\property QWidget::fullScreen
@@ -3169,6 +3444,10 @@ void QWidget::setAcceptDrops(bool on)
}
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
/*!
Disables widget input events if \a disable is true; otherwise
@@ -3643,6 +3922,28 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
return true;
}
+void QWidgetPrivate::setConstraints_sys()
+{
+ Q_Q(QWidget);
+ if (extra && q->windowHandle()) {
+ QWindow *win = q->windowHandle();
+ QWindowPrivate *winp = qt_window_private(win);
+
+ winp->minimumSize = QSize(extra->minw, extra->minh);
+ winp->maximumSize = QSize(extra->maxw, extra->maxh);
+
+ if (extra->topextra) {
+ winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
+ winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
+ }
+
+ if (winp->platformWindow) {
+ fixPosIncludesFrame();
+ winp->platformWindow->propagateSizeHints();
+ }
+ }
+}
+
/*!
\overload
@@ -4293,6 +4594,10 @@ void QWidgetPrivate::setPalette_helper(const QPalette &palette)
updateIsOpaque();
}
+void QWidgetPrivate::updateSystemBackground()
+{
+}
+
/*!
\property QWidget::font
\brief the font currently set for the widget
@@ -4629,6 +4934,13 @@ void QWidget::setCursor(const QCursor &cursor)
QApplication::sendEvent(this, &event);
}
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ qt_qpa_set_cursor(q, false);
+}
+
void QWidget::unsetCursor()
{
Q_D(QWidget);
@@ -4644,6 +4956,62 @@ void QWidget::unsetCursor()
QApplication::sendEvent(this, &event);
}
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ qt_qpa_set_cursor(q, false);
+}
+
+static inline void applyCursor(QWidget *w, QCursor c)
+{
+ if (QWindow *window = w->windowHandle())
+ window->setCursor(c);
+}
+
+static inline void unsetCursor(QWidget *w)
+{
+ if (QWindow *window = w->windowHandle())
+ window->unsetCursor();
+}
+
+void qt_qpa_set_cursor(QWidget *w, bool force)
+{
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ static QPointer<QWidget> lastUnderMouse = 0;
+ if (force) {
+ lastUnderMouse = w;
+ } else if (lastUnderMouse) {
+ const WId lastWinId = lastUnderMouse->effectiveWinId();
+ const WId winId = w->effectiveWinId();
+ if (lastWinId && lastWinId == winId)
+ w = lastUnderMouse;
+ } else if (!w->internalWinId()) {
+ return; // The mouse is not under this widget, and it's not native, so don't change it.
+ }
+
+ while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
+ && !w->testAttribute(Qt::WA_SetCursor))
+ w = w->parentWidget();
+
+ QWidget *nativeParent = w;
+ if (!w->internalWinId())
+ nativeParent = w->nativeParentWidget();
+ if (!nativeParent || !nativeParent->internalWinId())
+ return;
+
+ if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
+ if (w->isEnabled())
+ applyCursor(nativeParent, w->cursor());
+ else
+ // Enforce the windows behavior of clearing the cursor on
+ // disabled widgets.
+ unsetCursor(nativeParent);
+ } else {
+ unsetCursor(nativeParent);
+ }
+}
#endif
/*!
@@ -5124,18 +5492,22 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//paint the background
if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
&& !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+ beginBackingStorePainting();
QPainter p(q);
paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0);
+ endBackingStorePainting();
}
if (!sharedPainter)
setSystemClip(pdev, toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
+ beginBackingStorePainting();
QPainter p(q);
QColor tint = q->palette().window().color();
tint.setAlphaF(qreal(.6));
p.fillRect(toBePainted.boundingRect(), tint);
+ endBackingStorePainting();
}
}
@@ -5145,16 +5517,30 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
#endif
+ bool grabbed = false;
+#ifndef QT_NO_OPENGL
if (renderToTexture) {
// This widget renders into a texture which is composed later. We just need to
// punch a hole in the backingstore, so the texture will be visible.
- QPainter p(q);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.fillRect(q->rect(), Qt::transparent);
- } else {
+ if (!q->testAttribute(Qt::WA_AlwaysStackOnTop)) {
+ beginBackingStorePainting();
+ QPainter p(q);
+ if (backingStore) {
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(q->rect(), Qt::transparent);
+ } else {
+ // We are not drawing to a backingstore: fall back to QImage
+ p.drawImage(q->rect(), grabFramebuffer());
+ grabbed = true;
+ }
+ endBackingStorePainting();
+ }
+ }
+#endif // QT_NO_OPENGL
+
+ if (!grabbed) {
//actually send the paint event
- QPaintEvent e(toBePainted);
- QCoreApplication::sendSpontaneousEvent(q, &e);
+ sendPaintEvent(toBePainted);
}
// Native widgets need to be marked dirty on screen so painting will be done in correct context
@@ -5210,6 +5596,13 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
}
+void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
+{
+ Q_Q(QWidget);
+ QPaintEvent e(toBePainted);
+ QCoreApplication::sendSpontaneousEvent(q, &e);
+}
+
void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
{
@@ -5604,6 +5997,17 @@ void QWidgetPrivate::setWindowTitle_helper(const QString &title)
setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
}
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QWindow *window = q->windowHandle())
+ window->setTitle(caption);
+
+}
+
void QWidgetPrivate::setWindowIconText_helper(const QString &title)
{
Q_Q(QWidget);
@@ -5611,6 +6015,11 @@ void QWidgetPrivate::setWindowIconText_helper(const QString &title)
setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
}
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
/*!
\fn void QWidget::windowIconTextChanged(const QString &iconText)
@@ -5719,6 +6128,12 @@ void QWidget::setWindowIcon(const QIcon &icon)
emit windowIconChanged(icon);
}
+void QWidgetPrivate::setWindowIcon_sys()
+{
+ Q_Q(QWidget);
+ if (QWindow *window = q->windowHandle())
+ window->setIcon(q->windowIcon());
+}
/*!
\property QWidget::windowIconText
@@ -5794,6 +6209,16 @@ void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
#endif
}
+void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QWindow *window = q->windowHandle())
+ window->setFilePath(filePath);
+}
+
/*!
Returns the window's role, or an empty string.
@@ -6053,6 +6478,21 @@ void QWidget::setFocus(Qt::FocusReason reason)
}
}
+void QWidgetPrivate::setFocus_sys()
+{
+ Q_Q(QWidget);
+ // Embedded native widget may have taken the focus; get it back to toplevel if that is the case
+ const QWidget *topLevel = q->window();
+ if (topLevel->windowType() != Qt::Popup) {
+ if (QWindow *nativeWindow = q->window()->windowHandle()) {
+ if (nativeWindow != QGuiApplication::focusWindow()
+ && q->testAttribute(Qt::WA_WState_Created)) {
+ nativeWindow->requestActivate();
+ }
+ }
+ }
+}
+
// updates focus_child on parent widgets to point into this widget
void QWidgetPrivate::updateFocusChild()
{
@@ -6554,6 +6994,31 @@ void QWidget::move(const QPoint &p)
QWindowContainer::parentWasMoved(this);
}
+// move() was invoked with Qt::WA_WState_Created not set (frame geometry
+// unknown), that is, crect has a position including the frame.
+// If we can determine the frame strut, fix that and clear the flag.
+void QWidgetPrivate::fixPosIncludesFrame()
+{
+ Q_Q(QWidget);
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->posIncludesFrame) {
+ // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
+ // example, in QGraphicsProxyWidget).
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ te->posIncludesFrame = 0;
+ } else {
+ if (q->windowHandle()) {
+ updateFrameStrut();
+ if (!q->data->fstrut_dirty) {
+ data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
+ te->posIncludesFrame = 0;
+ }
+ } // windowHandle()
+ } // !WA_DontShowOnScreen
+ } // posIncludesFrame
+ } // QTLWExtra
+}
+
/*! \fn void QWidget::resize(int w, int h)
\overload
@@ -6595,6 +7060,110 @@ void QWidget::setGeometry(const QRect &r)
QWindowContainer::parentWasMoved(this);
}
+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);
+ }
+
+ if (q->isWindow() && q->windowHandle()) {
+ QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
+ x = 0;
+ y = 0;
+ w = q->windowHandle()->width();
+ h = q->windowHandle()->height();
+ }
+ }
+
+ 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;
+
+ bool needsShow = false;
+
+ if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+ needsShow = true;
+ }
+
+ if (q->isVisible()) {
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
+ 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()));
+ }
+
+ if (needsShow)
+ show_sys();
+ }
+
+ if (!q->isWindow()) {
+ if (renderToTexture) {
+ QRegion updateRegion(q->geometry());
+ updateRegion += QRect(oldPos, olds);
+ q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
+ } else if (isMove && !isResize) {
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ } else {
+ invalidateBuffer_resizeHelper(oldPos, olds);
+ }
+ }
+ }
+
+ // generate a move event for QWidgets without window handles. QWidgets with native
+ // window handles already receive a move event from
+ // QGuiApplicationPrivate::processGeometryChangeEvent.
+ if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
+ 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);
+ }
+
+}
+
/*!
\since 4.2
Saves the current geometry and state for top-level widgets.
@@ -7208,6 +7777,62 @@ void QWidgetPrivate::show_helper()
data.in_show = false; // reset qws optimization
}
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+
+ QWindow *window = q->windowHandle();
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
+ // add our window to the modal window list
+ QGuiApplicationPrivate::showModalWindow(window);
+ }
+ return;
+ }
+
+ if (renderToTexture && !q->isWindow())
+ QApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
+ else
+ QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
+
+ if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
+ return;
+
+ if (window) {
+ if (q->isWindow())
+ fixPosIncludesFrame();
+ 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) {
+ if (q->testAttribute(Qt::WA_Moved)
+ || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
+ window->setGeometry(geomRect);
+ else
+ window->resize(geomRect.size());
+ }
+
+#ifndef QT_NO_CURSOR
+ qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
+#endif
+ invalidateBuffer(q->rect());
+ window->setVisible(true);
+ // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
+ if (window->isTopLevel()) {
+ const QPoint crectTopLeft = q->data->crect.topLeft();
+ const QPoint windowTopLeft = window->geometry().topLeft();
+ if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
+ q->data->crect.moveTopLeft(windowTopLeft);
+ }
+ }
+}
+
/*!
Hides the widget. This function is equivalent to
setVisible(false).
@@ -7285,6 +7910,39 @@ void QWidgetPrivate::hide_helper()
#endif
}
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+
+ QWindow *window = q->windowHandle();
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ q->setAttribute(Qt::WA_Mapped, false);
+ if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
+ // remove our window from the modal window list
+ QGuiApplicationPrivate::hideModalWindow(window);
+ }
+ // do not return here, if window non-zero, we must hide it
+ }
+
+ deactivateWidgetCleanup();
+
+ if (!q->isWindow()) {
+ QWidget *p = q->parentWidget();
+ if (p &&p->isVisible()) {
+ if (renderToTexture)
+ p->d_func()->invalidateBuffer(q->geometry());
+ else
+ invalidateBuffer(q->rect());
+ }
+ } else {
+ invalidateBuffer(q->rect());
+ }
+
+ if (window)
+ window->setVisible(false);
+}
+
/*!
\fn bool QWidget::isHidden() const
@@ -8213,6 +8871,7 @@ bool QWidget::event(QEvent *event)
case QEvent::MacSizeChange:
case QEvent::ContentsRectChange:
case QEvent::ThemeChange:
+ case QEvent::ReadOnlyChange:
changeEvent(event);
break;
@@ -8386,7 +9045,7 @@ bool QWidget::event(QEvent *event)
QEvent::ModifiedChange, QEvent::MouseTrackingChange,
QEvent::ParentChange, QEvent::WindowStateChange,
QEvent::LanguageChange, QEvent::LocaleChange,
- QEvent::LayoutDirectionChange.
+ QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
*/
void QWidget::changeEvent(QEvent * event)
@@ -9767,6 +10426,88 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
QWindowContainer::parentWasChanged(this);
}
+void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+
+ Qt::WindowFlags oldFlags = data.window_flags;
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+
+ 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;
+ }
+
+ setWinId(0);
+
+ if (parent != newparent) {
+ QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
+ if (q->windowHandle()) {
+ q->windowHandle()->setFlags(f);
+ QWidget *parentWithWindow =
+ newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
+ if (parentWithWindow) {
+ if (f & Qt::Window) {
+ q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
+ q->windowHandle()->setParent(0);
+ } else {
+ q->windowHandle()->setTransientParent(0);
+ q->windowHandle()->setParent(parentWithWindow->windowHandle());
+ }
+ } else {
+ q->windowHandle()->setTransientParent(0);
+ q->windowHandle()->setParent(0);
+ }
+ }
+ }
+
+ 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 (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
+ if (extra && extra->hasWindowContainer)
+ QWindowContainer::toplevelAboutToBeDestroyed(q);
+ q->destroy();
+ }
+
+ adjustFlags(f, q);
+ 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 (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
+ q->createWinId();
+
+ 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)) {
+ q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
+ }
+ }
+}
+
/*!
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.
@@ -9812,6 +10553,13 @@ void QWidget::scroll(int dx, int dy)
d->scroll_sys(dx, dy);
}
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+ scrollRect(q->rect(), dx, dy);
+}
+
/*!
\overload
@@ -9846,6 +10594,11 @@ void QWidget::scroll(int dx, int dy, const QRect &r)
d->scroll_sys(dx, dy, r);
}
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ scrollRect(r, dx, dy);
+}
+
/*!
Repaints the widget directly by calling paintEvent() immediately,
unless updates are disabled or the widget is hidden.
@@ -10093,7 +10846,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#ifdef Q_OS_WIN
// ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
- // see qwidget_qpa.cpp, ::paintEngine for details
+ // see ::paintEngine for details
paintEngine();
if (d->noPaintOnScreen)
return;
@@ -10417,6 +11170,13 @@ void QWidget::setWindowOpacity(qreal opacity)
#endif
}
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+ if (q->windowHandle())
+ q->windowHandle()->setOpacity(level);
+}
+
/*!
\property QWidget::windowModified
\brief whether the document shown in the window has unsaved changes
@@ -10586,12 +11346,21 @@ QString QWidget::whatsThis() const
\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.
+ This is the primary name by which assistive technology such as screen readers
+ announce this widget. For most widgets setting this property is not required.
+ For example for QPushButton the button's text will be used.
+
+ It is important to set this property when the widget does not provide any
+ text. For example a button that only contains an icon needs to set this
+ property to work with screen readers.
+ The name should be short and equivalent to the visual information conveyed
+ by the widget.
+
+ This property has to be \l{Internationalization with Qt}{localized}.
By default, this property contains an empty string.
- \sa QAccessibleInterface::text()
+ \sa QWidget::accessibleDescription, QAccessibleInterface::text()
*/
void QWidget::setAccessibleName(const QString &name)
{
@@ -10612,9 +11381,16 @@ QString QWidget::accessibleName() const
\brief the widget's description as seen by assistive technologies
- By default, this property contains an empty string.
+ The accessible description of a widget should convey what a widget does.
+ While the \l accessibleName should be a short and consise string (e.g. \gui{Save}),
+ the description should give more context, such as \gui{Saves the current document}.
- \sa QAccessibleInterface::text()
+ This property has to be \l{Internationalization with Qt}{localized}.
+
+ By default, this property contains an empty string and Qt falls back
+ to using the tool tip to provide this information.
+
+ \sa QWidget::accessibleName, QAccessibleInterface::text()
*/
void QWidget::setAccessibleDescription(const QString &description)
{
@@ -10774,6 +11550,19 @@ void QWidget::raise()
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
+ q->windowHandle()->raise();
+ } else if (renderToTexture) {
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+ }
+}
+
/*!
Lowers the widget to the bottom of the parent widget's stack.
@@ -10811,6 +11600,17 @@ void QWidget::lower()
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
+ 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()));
+ }
+}
/*!
Places the widget under \a w in the parent widget's stack.
@@ -10847,6 +11647,14 @@ void QWidget::stackUnder(QWidget* w)
QApplication::sendEvent(this, &e);
}
+void QWidgetPrivate::stackUnder_sys(QWidget*)
+{
+ Q_Q(QWidget);
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
/*!
\fn bool QWidget::isTopLevel() const
@@ -10907,6 +11715,24 @@ QRect QWidgetPrivate::frameStrut() const
return maybeTopData() ? maybeTopData()->frameStrut : QRect();
}
+void QWidgetPrivate::updateFrameStrut()
+{
+ Q_Q(QWidget);
+ if (q->data->fstrut_dirty) {
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->window) {
+ if (const QPlatformWindow *pw = te->window->handle()) {
+ const QMargins margins = pw->frameMargins();
+ if (!margins.isNull()) {
+ te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+ q->data->fstrut_dirty = false;
+ }
+ }
+ }
+ }
+ }
+}
+
#ifdef QT_KEYPAD_NAVIGATION
/*!
\internal
@@ -11159,7 +11985,7 @@ QOpenGLContext *QWidgetPrivate::shareContext() const
}
QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
if (!extra->topextra->shareContext) {
- QOpenGLContext *ctx = new QOpenGLContext();
+ QOpenGLContext *ctx = new QOpenGLContext;
ctx->setShareContext(QOpenGLContextPrivate::globalShareContext());
ctx->setFormat(extra->topextra->window->format());
ctx->create();
@@ -11169,6 +11995,24 @@ QOpenGLContext *QWidgetPrivate::shareContext() const
#endif // QT_NO_OPENGL
}
+#ifndef QT_NO_OPENGL
+void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
+{
+ QWidgetPrivate *wd = QWidgetPrivate::get(w);
+ if (!wd->textureChildSeen)
+ return;
+ if (end)
+ wd->endCompose();
+ else
+ wd->beginCompose();
+ for (int i = 0; i < wd->children.size(); ++i) {
+ w = qobject_cast<QWidget *>(wd->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
+ sendComposeStatus(w, end);
+ }
+}
+#endif // QT_NO_OPENGL
+
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
{
return widget->data;
@@ -11243,6 +12087,50 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
This function is usually called from the QWidget destructor.
*/
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+
+ d->aboutToDestroy();
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
+ d->deactivateWidgetCleanup();
+
+ if ((windowType() == Qt::Popup) && qApp)
+ qApp->d_func()->closePopup(this);
+
+ if (this == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+ if (QWidget::mouseGrabber() == this)
+ releaseMouse();
+ if (QWidget::keyboardGrabber() == this)
+ releaseKeyboard();
+
+ setAttribute(Qt::WA_WState_Created, false);
+
+ 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();
+ }
+ }
+
+ d->setWinId(0);
+ }
+}
/*!
\fn QPaintEngine *QWidget::paintEngine() const
@@ -11254,6 +12142,30 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
function is called by Qt internally, and the default
implementation may not always return a valid pointer.
*/
+QPaintEngine *QWidget::paintEngine() const
+{
+ qWarning("QWidget::paintEngine: Should no longer be called");
+
+#ifdef Q_OS_WIN
+ // We set this bit which is checked in setAttribute for
+ // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
+ //
+ // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
+ // Windows which would mean suddenly their widgets stop working.
+ //
+ // 2. Users set paint on screen and subclass paintEngine() to
+ // return 0, in which case we have a "hole" in the backingstore
+ // allowing use of GDI or DirectX directly.
+ //
+ // 1 is WRONG, but to minimize silent failures, we have set this
+ // bit to ignore the setAttribute call. 2. needs to be
+ // supported because its our only means of embedding native
+ // graphics stuff.
+ const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
+#endif
+
+ return 0; //##### @@@
+}
/*!
\fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
@@ -11264,6 +12176,21 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa mapFromGlobal(), mapTo(), mapToParent()
*/
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ int x = pos.x(), y = pos.y();
+ const QWidget *w = this;
+ while (w) {
+ QWindow *window = w->windowHandle();
+ if (window && window->handle())
+ return window->mapToGlobal(QPoint(x, y));
+
+ x += w->data->crect.x();
+ y += w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
/*!
\fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
@@ -11273,6 +12200,75 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa mapToGlobal(), mapFrom(), mapFromParent()
*/
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ int x = pos.x(), y = pos.y();
+ const QWidget *w = this;
+ while (w) {
+ QWindow *window = w->windowHandle();
+ if (window && window->handle())
+ return window->mapFromGlobal(QPoint(x, y));
+
+ x -= w->data->crect.x();
+ y -= w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+QWidget *qt_pressGrab = 0;
+QWidget *qt_mouseGrb = 0;
+static bool mouseGrabWithCursor = false;
+static QWidget *keyboardGrb = 0;
+
+static inline QWindow *grabberWindow(const QWidget *w)
+{
+ QWindow *window = w->windowHandle();
+ if (!window)
+ if (const QWidget *nativeParent = w->nativeParentWidget())
+ window = nativeParent->windowHandle();
+ return window;
+}
+
+#ifndef QT_NO_CURSOR
+static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = 0)
+#else
+static void grabMouseForWidget(QWidget *widget)
+#endif
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ mouseGrabWithCursor = false;
+ if (QWindow *window = grabberWindow(widget)) {
+#ifndef QT_NO_CURSOR
+ if (cursor) {
+ mouseGrabWithCursor = true;
+ QGuiApplication::setOverrideCursor(*cursor);
+ }
+#endif // !QT_NO_CURSOR
+ window->setMouseGrabEnabled(true);
+ }
+
+ qt_mouseGrb = widget;
+ qt_pressGrab = 0;
+}
+
+static void releaseMouseGrabOfWidget(QWidget *widget)
+{
+ if (qt_mouseGrb == widget) {
+ if (QWindow *window = grabberWindow(widget)) {
+#ifndef QT_NO_CURSOR
+ if (mouseGrabWithCursor) {
+ QGuiApplication::restoreOverrideCursor();
+ mouseGrabWithCursor = false;
+ }
+#endif // !QT_NO_CURSOR
+ window->setMouseGrabEnabled(false);
+ }
+ }
+ qt_mouseGrb = 0;
+}
/*!
\fn void QWidget::grabMouse()
@@ -11303,6 +12299,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseMouse(), grabKeyboard(), releaseKeyboard()
*/
+void QWidget::grabMouse()
+{
+ grabMouseForWidget(this);
+}
/*!
\fn void QWidget::grabMouse(const QCursor &cursor)
@@ -11320,6 +12320,21 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
*/
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ grabMouseForWidget(this, &cursor);
+}
+#endif
+
+bool QWidgetPrivate::stealMouseGrab(bool grab)
+{
+ // This is like a combination of grab/releaseMouse() but with error checking
+ // and it has no effect on the result of mouseGrabber().
+ Q_Q(QWidget);
+ QWindow *window = grabberWindow(q);
+ return window ? window->setMouseGrabEnabled(grab) : false;
+}
/*!
\fn void QWidget::releaseMouse()
@@ -11328,6 +12343,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), grabKeyboard(), releaseKeyboard()
*/
+void QWidget::releaseMouse()
+{
+ releaseMouseGrabOfWidget(this);
+}
/*!
\fn void QWidget::grabKeyboard()
@@ -11348,6 +12367,23 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
*/
+void QWidget::grabKeyboard()
+{
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ if (QWindow *window = grabberWindow(this))
+ window->setKeyboardGrabEnabled(true);
+ keyboardGrb = this;
+}
+
+bool QWidgetPrivate::stealKeyboardGrab(bool grab)
+{
+ // This is like a combination of grab/releaseKeyboard() but with error
+ // checking and it has no effect on the result of keyboardGrabber().
+ Q_Q(QWidget);
+ QWindow *window = grabberWindow(q);
+ return window ? window->setKeyboardGrabEnabled(grab) : false;
+}
/*!
\fn void QWidget::releaseKeyboard()
@@ -11356,6 +12392,14 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabKeyboard(), grabMouse(), releaseMouse()
*/
+void QWidget::releaseKeyboard()
+{
+ if (keyboardGrb == this) {
+ if (QWindow *window = grabberWindow(this))
+ window->setKeyboardGrabEnabled(false);
+ keyboardGrb = 0;
+ }
+}
/*!
\fn QWidget *QWidget::mouseGrabber()
@@ -11367,6 +12411,12 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), keyboardGrabber()
*/
+QWidget *QWidget::mouseGrabber()
+{
+ if (qt_mouseGrb)
+ return qt_mouseGrb;
+ return qt_pressGrab;
+}
/*!
\fn QWidget *QWidget::keyboardGrabber()
@@ -11378,6 +12428,10 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa grabMouse(), mouseGrabber()
*/
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
/*!
\fn void QWidget::activateWindow()
@@ -11403,6 +12457,13 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\sa isActiveWindow(), window(), show()
*/
+void QWidget::activateWindow()
+{
+ QWindow *const wnd = window()->windowHandle();
+
+ if (wnd)
+ wnd->requestActivate();
+}
/*!
\fn int QWidget::metric(PaintDeviceMetric m) const
@@ -11412,6 +12473,62 @@ void QWidget::ungrabGesture(Qt::GestureType gesture)
\a m is the metric to get.
*/
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+
+ QWindow *topLevelWindow = 0;
+ QScreen *screen = 0;
+ if (QWidget *topLevel = window())
+ topLevelWindow = topLevel->windowHandle();
+
+ if (topLevelWindow) {
+ QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
+ if (platformScreen)
+ screen = platformScreen->screen();
+ }
+ if (!screen && QGuiApplication::primaryScreen())
+ screen = QGuiApplication::primaryScreen();
+
+ 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) {
+ 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->logicalDotsPerInchX());
+ } else if (m == PdmDpiY) {
+ 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->logicalDotsPerInchY());
+ } else if (m == PdmPhysicalDpiX) {
+ return qRound(screen->physicalDotsPerInchX());
+ } else if (m == PdmPhysicalDpiY) {
+ return qRound(screen->physicalDotsPerInchY());
+ } else if (m == PdmDevicePixelRatio) {
+ return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
+ } else {
+ val = QPaintDevice::metric(m);// XXX
+ }
+ return val;
+}
/*!
Initializes the \a painter pen, background and font to the same as
@@ -11517,6 +12634,14 @@ void QWidget::setMask(const QRegion &newMask)
#endif
}
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_Q(QWidget);
+ if (const QWindow *window = q->windowHandle())
+ if (QPlatformWindow *platformWindow = window->handle())
+ platformWindow->setMask(region);
+}
+
/*!
\fn void QWidget::setMask(const QBitmap &bitmap)
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 159011b824..9c22ad7c3d 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -694,7 +694,6 @@ private:
friend class QPixmap; // for QPixmap::fill()
friend class QFontMetrics;
friend class QFontInfo;
- friend class QETWidget;
friend class QLayout;
friend class QWidgetItem;
friend class QWidgetItemV2;
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 9586d1a8c9..011d456a39 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -61,6 +61,7 @@
#include "QtGui/qregion.h"
#include "QtGui/qinputmethod.h"
#include "QtGui/qopengl.h"
+#include "QtGui/qsurfaceformat.h"
#include "QtWidgets/qsizepolicy.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qapplication.h"
@@ -392,6 +393,7 @@ public:
QWidget::RenderFlags renderFlags);
void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
+ void sendPaintEvent(const QRegion &toBePainted);
void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index,
@@ -627,7 +629,11 @@ public:
#ifndef QT_NO_OPENGL
virtual GLuint textureId() const { return 0; }
-
+ virtual QImage grabFramebuffer() { return QImage(); }
+ virtual void beginBackingStorePainting() { }
+ virtual void endBackingStorePainting() { }
+ virtual void beginCompose() { }
+ virtual void endCompose() { }
void setRenderToTexture() { renderToTexture = true; setTextureChildSeen(); }
void setTextureChildSeen()
{
@@ -642,6 +648,11 @@ public:
get(parent)->setTextureChildSeen();
}
}
+ static void sendComposeStatus(QWidget *w, bool end);
+ // When using a QOpenGLWidget as viewport with QAbstractScrollArea, resize events are
+ // filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget
+ // since the fbo must be resized. We need an alternative way to notify.
+ virtual void resizeViewportFramebuffer() { }
#endif
// Variables.
@@ -732,7 +743,7 @@ public:
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)
- uint noPaintOnScreen : 1; // see qwidget_qpa.cpp ::paintEngine()
+ uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine()
#endif
#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
Qt::HANDLE picture;
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
deleted file mode 100644
index 5a4bd33672..0000000000
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ /dev/null
@@ -1,1126 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "QtWidgets/qwidget.h"
-#include "QtGui/qevent.h"
-#include "QtWidgets/qapplication.h"
-#include "private/qwidgetbackingstore_p.h"
-#include "private/qwidget_p.h"
-#include "private/qwidgetwindow_qpa_p.h"
-#include "private/qapplication_p.h"
-#include "QtWidgets/qdesktopwidget.h"
-#include <qpa/qplatformwindow.h>
-#include "QtGui/qsurfaceformat.h"
-#include <QtGui/qopenglcontext.h>
-#include <qpa/qplatformopenglcontext.h>
-#include <qpa/qplatformintegration.h>
-#include "QtGui/private/qwindow_p.h"
-#include "QtGui/private/qguiapplication_p.h"
-#include <private/qwindowcontainer_p.h>
-
-#include <qpa/qplatformcursor.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QScreen>
-#include <QtCore/QMargins>
-
-QT_BEGIN_NAMESPACE
-
-void q_createNativeChildrenAndSetParent(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->internalWinId())
- childWidget->winId();
- if (childWidget->windowHandle()) {
- QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle();
- if (childWidget->isWindow())
- childWidget->windowHandle()->setTransientParent(parentWindow);
- else
- childWidget->windowHandle()->setParent(parentWindow);
- }
- } else {
- q_createNativeChildrenAndSetParent(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())
- return; // we only care about real toplevels
-
- QWindow *win = topData()->window;
- // topData() ensures the extra is created but does not ensure 'window' is non-null
- // in case the extra was already valid.
- if (!win) {
- createTLSysExtra();
- win = topData()->window;
- }
-
- foreach (const QByteArray &propertyName, q->dynamicPropertyNames()) {
- if (!qstrncmp(propertyName, "_q_platform_", 12))
- win->setProperty(propertyName, q->property(propertyName));
- }
-
-#ifdef Q_OS_OSX
- if (q->testAttribute(Qt::WA_ShowWithoutActivating))
- win->setProperty("_q_showWithoutActivating", QVariant(true));
-#endif
- win->setFlags(data.window_flags);
- fixPosIncludesFrame();
- if (q->testAttribute(Qt::WA_Moved)
- || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
- win->setGeometry(q->geometry());
- else
- win->resize(q->size());
- win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
-
- QSurfaceFormat format = win->requestedFormat();
- if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
- && q->testAttribute(Qt::WA_TranslucentBackground)) {
- format.setAlphaBufferSize(8);
- }
- win->setFormat(format);
-
- if (QWidget *nativeParent = q->nativeParentWidget()) {
- if (nativeParent->windowHandle()) {
- if (flags & Qt::Window) {
- win->setTransientParent(nativeParent->window()->windowHandle());
- win->setParent(0);
- } else {
- win->setTransientParent(0);
- win->setParent(nativeParent->windowHandle());
- }
- }
- }
-
- qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
- QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
- win->create();
- // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
- if ((flags & Qt::Desktop) == Qt::Window)
- win->handle()->setFrameStrutEventsEnabled(true);
-
- data.window_flags = win->flags();
-
- QBackingStore *store = q->backingStore();
-
- if (!store) {
- if (win && q->windowType() != Qt::Desktop) {
- if (q->isTopLevel())
- q->setBackingStore(new QBackingStore(win));
- } else {
- q->setAttribute(Qt::WA_PaintOnScreen, true);
- }
- }
-
- setWindowModified_helper();
- WId id = win->winId();
- // See the QPlatformWindow::winId() documentation
- Q_ASSERT(id != WId(0));
- setWinId(id);
-
- // Check children and create windows for them if necessary
- q_createNativeChildrenAndSetParent(q);
-
- if (extra && !extra->mask.isEmpty())
- setMask_sys(extra->mask);
-
- // If widget is already shown, set window visible, too
- if (q->isVisible())
- win->setVisible(true);
-}
-
-void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
-{
- Q_D(QWidget);
-
- d->aboutToDestroy();
- if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
- d->deactivateWidgetCleanup();
-
- if ((windowType() == Qt::Popup) && qApp)
- qApp->d_func()->closePopup(this);
-
- if (this == QApplicationPrivate::active_window)
- QApplication::setActiveWindow(0);
- if (QWidget::mouseGrabber() == this)
- releaseMouse();
- if (QWidget::keyboardGrabber() == this)
- releaseKeyboard();
-
- setAttribute(Qt::WA_WState_Created, false);
-
- 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();
- }
- }
-
- d->setWinId(0);
- }
-}
-
-void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
-{
- Q_Q(QWidget);
-
- Qt::WindowFlags oldFlags = data.window_flags;
- bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
-
- 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;
- }
-
- setWinId(0);
-
- if (parent != newparent) {
- QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
- if (q->windowHandle()) {
- q->windowHandle()->setFlags(f);
- QWidget *parentWithWindow =
- newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
- if (parentWithWindow) {
- if (f & Qt::Window) {
- q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
- q->windowHandle()->setParent(0);
- } else {
- q->windowHandle()->setTransientParent(0);
- q->windowHandle()->setParent(parentWithWindow->windowHandle());
- }
- } else {
- q->windowHandle()->setTransientParent(0);
- q->windowHandle()->setParent(0);
- }
- }
- }
-
- 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 (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
- if (extra && extra->hasWindowContainer)
- QWindowContainer::toplevelAboutToBeDestroyed(q);
- q->destroy();
- }
-
- adjustFlags(f, q);
- 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 (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
- q->createWinId();
-
- 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)) {
- q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
- }
- }
-}
-
-QPoint QWidget::mapToGlobal(const QPoint &pos) const
-{
- int x = pos.x(), y = pos.y();
- const QWidget *w = this;
- while (w) {
- QWindow *window = w->windowHandle();
- if (window && window->handle())
- return window->mapToGlobal(QPoint(x, y));
-
- 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) {
- QWindow *window = w->windowHandle();
- if (window && window->handle())
- return window->mapFromGlobal(QPoint(x, y));
-
- 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);
- qt_qpa_set_cursor(q, false);
-}
-
-void QWidgetPrivate::unsetCursor_sys()
-{
- Q_Q(QWidget);
- qt_qpa_set_cursor(q, false);
-}
-
-#endif //QT_NO_CURSOR
-
-void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
-{
- Q_Q(QWidget);
- if (!q->isWindow())
- return;
-
- if (QWindow *window = q->windowHandle())
- window->setTitle(caption);
-
-}
-
-void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
-{
- Q_Q(QWidget);
- if (!q->isWindow())
- return;
-
- if (QWindow *window = q->windowHandle())
- window->setFilePath(filePath);
-}
-
-void QWidgetPrivate::setWindowIcon_sys()
-{
- Q_Q(QWidget);
- if (QWindow *window = q->windowHandle())
- window->setIcon(q->windowIcon());
-}
-
-void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
-{
- Q_UNUSED(iconText);
-}
-
-QWidget *qt_pressGrab = 0;
-QWidget *qt_mouseGrb = 0;
-static QWidget *keyboardGrb = 0;
-
-static inline QWindow *grabberWindow(const QWidget *w)
-{
- QWindow *window = w->windowHandle();
- if (!window)
- if (const QWidget *nativeParent = w->nativeParentWidget())
- window = nativeParent->windowHandle();
- return window;
-}
-
-void QWidget::grabMouse()
-{
- if (qt_mouseGrb)
- qt_mouseGrb->releaseMouse();
-
- if (QWindow *window = grabberWindow(this))
- window->setMouseGrabEnabled(true);
-
- qt_mouseGrb = this;
- qt_pressGrab = 0;
-}
-
-#ifndef QT_NO_CURSOR
-void QWidget::grabMouse(const QCursor &cursor)
-{
- Q_UNUSED(cursor);
- grabMouse();
-}
-#endif
-
-bool QWidgetPrivate::stealMouseGrab(bool grab)
-{
- // This is like a combination of grab/releaseMouse() but with error checking
- // and it has no effect on the result of mouseGrabber().
- Q_Q(QWidget);
- QWindow *window = grabberWindow(q);
- return window ? window->setMouseGrabEnabled(grab) : false;
-}
-
-void QWidget::releaseMouse()
-{
- if (qt_mouseGrb == this) {
- if (QWindow *window = grabberWindow(this))
- window->setMouseGrabEnabled(false);
- qt_mouseGrb = 0;
- }
-}
-
-void QWidget::grabKeyboard()
-{
- if (keyboardGrb)
- keyboardGrb->releaseKeyboard();
- if (QWindow *window = grabberWindow(this))
- window->setKeyboardGrabEnabled(true);
- keyboardGrb = this;
-}
-
-bool QWidgetPrivate::stealKeyboardGrab(bool grab)
-{
- // This is like a combination of grab/releaseKeyboard() but with error
- // checking and it has no effect on the result of keyboardGrabber().
- Q_Q(QWidget);
- QWindow *window = grabberWindow(q);
- return window ? window->setKeyboardGrabEnabled(grab) : false;
-}
-
-void QWidget::releaseKeyboard()
-{
- if (keyboardGrb == this) {
- if (QWindow *window = grabberWindow(this))
- window->setKeyboardGrabEnabled(false);
- keyboardGrb = 0;
- }
-}
-
-QWidget *QWidget::mouseGrabber()
-{
- if (qt_mouseGrb)
- return qt_mouseGrb;
- return qt_pressGrab;
-}
-
-QWidget *QWidget::keyboardGrabber()
-{
- return keyboardGrb;
-}
-
-void QWidget::activateWindow()
-{
- QWindow *const wnd = window()->windowHandle();
-
- if (wnd)
- wnd->requestActivate();
-}
-
-// move() was invoked with Qt::WA_WState_Created not set (frame geometry
-// unknown), that is, crect has a position including the frame.
-// If we can determine the frame strut, fix that and clear the flag.
-void QWidgetPrivate::fixPosIncludesFrame()
-{
- Q_Q(QWidget);
- if (QTLWExtra *te = maybeTopData()) {
- if (te->posIncludesFrame) {
- // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
- // example, in QGraphicsProxyWidget).
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- te->posIncludesFrame = 0;
- } else {
- if (q->windowHandle()) {
- updateFrameStrut();
- if (!q->data->fstrut_dirty) {
- data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
- te->posIncludesFrame = 0;
- }
- } // windowHandle()
- } // !WA_DontShowOnScreen
- } // posIncludesFrame
- } // QTLWExtra
-}
-
-void QWidgetPrivate::show_sys()
-{
- Q_Q(QWidget);
-
- QWindow *window = q->windowHandle();
-
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- invalidateBuffer(q->rect());
- q->setAttribute(Qt::WA_Mapped);
- if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
- // add our window to the modal window list
- QGuiApplicationPrivate::showModalWindow(window);
- }
- return;
- }
-
- if (renderToTexture && !q->isWindow())
- QApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
- else
- QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
-
- if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
- return;
-
- if (window) {
- if (q->isWindow())
- fixPosIncludesFrame();
- 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) {
- if (q->testAttribute(Qt::WA_Moved)
- || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
- window->setGeometry(geomRect);
- else
- window->resize(geomRect.size());
- }
-
-#ifndef QT_NO_CURSOR
- qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
-#endif
- invalidateBuffer(q->rect());
- window->setVisible(true);
- // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
- if (window->isTopLevel()) {
- const QPoint crectTopLeft = q->data->crect.topLeft();
- const QPoint windowTopLeft = window->geometry().topLeft();
- if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
- q->data->crect.moveTopLeft(windowTopLeft);
- }
- }
-}
-
-
-void QWidgetPrivate::hide_sys()
-{
- Q_Q(QWidget);
-
- QWindow *window = q->windowHandle();
-
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- q->setAttribute(Qt::WA_Mapped, false);
- if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
- // remove our window from the modal window list
- QGuiApplicationPrivate::hideModalWindow(window);
- }
- // do not return here, if window non-zero, we must hide it
- }
-
- deactivateWidgetCleanup();
-
- if (!q->isWindow()) {
- QWidget *p = q->parentWidget();
- if (p &&p->isVisible()) {
- if (renderToTexture)
- p->d_func()->invalidateBuffer(q->geometry());
- else
- invalidateBuffer(q->rect());
- }
- } else {
- invalidateBuffer(q->rect());
- }
-
- if (window)
- window->setVisible(false);
-}
-
-Qt::WindowState 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;
- Qt::WindowState newEffectiveState = effectiveState(newstate);
- Qt::WindowState oldEffectiveState = effectiveState(oldstate);
- if (isWindow() && newEffectiveState != oldEffectiveState) {
- // Ensure the initial size is valid, since we store it as normalGeometry below.
- if (!testAttribute(Qt::WA_Resized) && !isVisible())
- adjustSize();
-
- d->createTLExtra();
- if (oldEffectiveState == Qt::WindowNoState)
- d->topData()->normalGeometry = geometry();
-
- Q_ASSERT(windowHandle());
- windowHandle()->setWindowState(newEffectiveState);
- }
- data->in_set_window_state = 0;
-
- if (newstate & Qt::WindowActive)
- activateWindow();
-
- QWindowStateChangeEvent e(oldstate);
- QApplication::sendEvent(this, &e);
-}
-
-void QWidgetPrivate::setFocus_sys()
-{
- Q_Q(QWidget);
- // Embedded native widget may have taken the focus; get it back to toplevel if that is the case
- const QWidget *topLevel = q->window();
- if (topLevel->windowType() != Qt::Popup) {
- if (QWindow *nativeWindow = q->window()->windowHandle()) {
- if (nativeWindow != QGuiApplication::focusWindow()
- && q->testAttribute(Qt::WA_WState_Created)) {
- nativeWindow->requestActivate();
- }
- }
- }
-}
-
-void QWidgetPrivate::raise_sys()
-{
- Q_Q(QWidget);
- if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
- q->windowHandle()->raise();
- } else if (renderToTexture) {
- if (QWidget *p = q->parentWidget()) {
- setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
- }
- }
-}
-
-void QWidgetPrivate::lower_sys()
-{
- Q_Q(QWidget);
- if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
- 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);
- }
-
- if (q->isWindow() && q->windowHandle()) {
- QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
- if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
- x = 0;
- y = 0;
- w = q->windowHandle()->width();
- h = q->windowHandle()->height();
- }
- }
-
- 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;
-
- bool needsShow = false;
-
- if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
- q->setAttribute(Qt::WA_OutsideWSRange, true);
- if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
- hide_sys();
- data.crect = QRect(x, y, w, h);
- } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
- q->setAttribute(Qt::WA_OutsideWSRange, false);
- needsShow = true;
- }
-
- if (q->isVisible()) {
- if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
- 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()));
- }
-
- if (needsShow)
- show_sys();
- }
-
- if (!q->isWindow()) {
- if (renderToTexture) {
- QRegion updateRegion(q->geometry());
- updateRegion += QRect(oldPos, olds);
- q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
- } else if (isMove && !isResize) {
- moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
- } else {
- invalidateBuffer_resizeHelper(oldPos, olds);
- }
- }
- }
-
- // generate a move event for QWidgets without window handles. QWidgets with native
- // window handles already receive a move event from
- // QGuiApplicationPrivate::processGeometryChangeEvent.
- if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
- 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()
-{
- Q_Q(QWidget);
- if (extra && q->windowHandle()) {
- QWindow *win = q->windowHandle();
- QWindowPrivate *winp = qt_window_private(win);
-
- winp->minimumSize = QSize(extra->minw, extra->minh);
- winp->maximumSize = QSize(extra->maxw, extra->maxh);
-
- if (extra->topextra) {
- winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
- winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
- }
-
- if (winp->platformWindow) {
- fixPosIncludesFrame();
- winp->platformWindow->propagateSizeHints();
- }
- }
-}
-
-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);
-
- QWindow *topLevelWindow = 0;
- QScreen *screen = 0;
- if (QWidget *topLevel = window())
- topLevelWindow = topLevel->windowHandle();
-
- if (topLevelWindow) {
- QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
- if (platformScreen)
- screen = platformScreen->screen();
- }
- if (!screen && QGuiApplication::primaryScreen())
- screen = QGuiApplication::primaryScreen();
-
- 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) {
- 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->logicalDotsPerInchX());
- } else if (m == PdmDpiY) {
- 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->logicalDotsPerInchY());
- } else if (m == PdmPhysicalDpiX) {
- return qRound(screen->physicalDotsPerInchX());
- } else if (m == PdmPhysicalDpiY) {
- return qRound(screen->physicalDotsPerInchY());
- } else if (m == PdmDevicePixelRatio) {
- return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
- } else {
- val = QPaintDevice::metric(m);// XXX
- }
- return val;
-}
-
-/*!
- If this is a native widget, return the associated QWindow.
- Otherwise return null.
-
- Native widgets include toplevel widgets, QGLWidget, and child widgets
- on which winId() was called.
-
- \since 5.0
-
- \sa winId()
-*/
-QWindow *QWidget::windowHandle() const
-{
- Q_D(const QWidget);
- QTLWExtra *extra = d->maybeTopData();
- if (extra)
- return extra->window;
-
- return 0;
-}
-
-void QWidgetPrivate::createSysExtra()
-{
-}
-
-void QWidgetPrivate::deleteSysExtra()
-{
-
-}
-
-#ifdef Q_OS_WIN
-static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
-#endif
-
-void QWidgetPrivate::createTLSysExtra()
-{
- Q_Q(QWidget);
- if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
- extra->topextra->window = new QWidgetWindow(q);
- if (extra->minw || extra->minh)
- extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
- if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
- extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
- if (extra->topextra->opacity != 255 && q->isWindow())
- extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
-#ifdef Q_OS_WIN
- // Pass on native parent handle for Widget embedded into Active X.
- const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
- if (activeXNativeParentHandle.isValid())
- extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
- if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
- extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
-#endif
- }
-
-}
-
-void QWidgetPrivate::deleteTLSysExtra()
-{
- if (extra && extra->topextra) {
- //the qplatformbackingstore may hold a reference to the window, so the backingstore
- //needs to be deleted first. If the backingstore holds GL resources, we need to
- // make the context current here, since the platform bs does not have a reference
- // to the widget.
-
-#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->makeCurrent(extra->topextra->window);
-#endif
- extra->topextra->backingStoreTracker.destroy();
- delete extra->topextra->backingStore;
- extra->topextra->backingStore = 0;
-#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->doneCurrent();
- delete extra->topextra->shareContext;
- extra->topextra->shareContext = 0;
-#endif
-
- //the toplevel might have a context with a "qglcontext associated with it. We need to
- //delete the qglcontext before we delete the qplatformopenglcontext.
- //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);
- delete extra->topextra->window;
- extra->topextra->window = 0;
-
- }
-}
-
-void QWidgetPrivate::registerDropSite(bool on)
-{
- Q_UNUSED(on);
-}
-
-void QWidgetPrivate::setMask_sys(const QRegion &region)
-{
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowMasks)) {
- qWarning("%s: Not supported on %s.", Q_FUNC_INFO, qPrintable(QGuiApplication::platformName()));
- return;
- }
- Q_Q(QWidget);
- if (const QWindow *window = q->windowHandle())
- if (QPlatformWindow *platformWindow = window->handle())
- platformWindow->setMask(region);
-}
-
-void QWidgetPrivate::updateFrameStrut()
-{
- Q_Q(QWidget);
- if (q->data->fstrut_dirty) {
- if (QTLWExtra *te = maybeTopData()) {
- if (te->window) {
- if (const QPlatformWindow *pw = te->window->handle()) {
- const QMargins margins = pw->frameMargins();
- if (!margins.isNull()) {
- te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
- q->data->fstrut_dirty = false;
- }
- }
- }
- }
- }
-}
-
-void QWidgetPrivate::setWindowOpacity_sys(qreal level)
-{
- Q_Q(QWidget);
- if (q->windowHandle())
- q->windowHandle()->setOpacity(level);
-}
-
-void QWidgetPrivate::setWSGeometry()
-{
- Q_Q(QWidget);
- if (QWindow *window = q->windowHandle())
- window->setGeometry(data.crect);
-}
-
-QPaintEngine *QWidget::paintEngine() const
-{
- qWarning("QWidget::paintEngine: Should no longer be called");
-
-#ifdef Q_OS_WIN
- // We set this bit which is checked in setAttribute for
- // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
- //
- // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
- // Windows which would mean suddenly their widgets stop working.
- //
- // 2. Users set paint on screen and subclass paintEngine() to
- // return 0, in which case we have a "hole" in the backingstore
- // allowing use of GDI or DirectX directly.
- //
- // 1 is WRONG, but to minimize silent failures, we have set this
- // bit to ignore the setAttribute call. 2. needs to be
- // supported because its our only means of embedding native
- // graphics stuff.
- const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
-#endif
-
- return 0; //##### @@@
-}
-
-void QWidgetPrivate::setModal_sys()
-{
- Q_Q(QWidget);
- if (q->windowHandle())
- q->windowHandle()->setModality(q->windowModality());
-}
-
-#ifndef QT_NO_CURSOR
-static inline void applyCursor(QWidget *w, QCursor c)
-{
- if (QWindow *window = w->windowHandle())
- window->setCursor(c);
-}
-
-static inline void unsetCursor(QWidget *w)
-{
- if (QWindow *window = w->windowHandle())
- window->unsetCursor();
-}
-
-void qt_qpa_set_cursor(QWidget *w, bool force)
-{
- if (!w->testAttribute(Qt::WA_WState_Created))
- return;
-
- static QPointer<QWidget> lastUnderMouse = 0;
- if (force) {
- lastUnderMouse = w;
- } else if (lastUnderMouse) {
- const WId lastWinId = lastUnderMouse->effectiveWinId();
- const WId winId = w->effectiveWinId();
- if (lastWinId && lastWinId == winId)
- w = lastUnderMouse;
- } else if (!w->internalWinId()) {
- return; // The mouse is not under this widget, and it's not native, so don't change it.
- }
-
- while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
- && !w->testAttribute(Qt::WA_SetCursor))
- w = w->parentWidget();
-
- QWidget *nativeParent = w;
- if (!w->internalWinId())
- nativeParent = w->nativeParentWidget();
- if (!nativeParent || !nativeParent->internalWinId())
- return;
-
- if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
- if (w->isEnabled())
- applyCursor(nativeParent, w->cursor());
- else
- // Enforce the windows behavior of clearing the cursor on
- // disabled widgets.
- unsetCursor(nativeParent);
- } else {
- unsetCursor(nativeParent);
- }
-}
-#endif //QT_NO_CURSOR
-
-QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 9d024fd359..6f635611f0 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -74,7 +74,8 @@ extern QRegion qt_dirtyRegion(QWidget *);
* \a region is the region to be updated in \a widget coordinates.
*/
void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures)
+ QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures,
+ QWidgetBackingStore *widgetBackingStore)
{
#ifdef QT_NO_OPENGL
Q_UNUSED(widgetTextures);
@@ -92,33 +93,29 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
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
+ if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
+ return;
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 (!widgetBackingStore->perfFrames++)
+ widgetBackingStore->perfTime.start();
+ if (widgetBackingStore->perfTime.elapsed() > 5000) {
+ double fps = double(widgetBackingStore->perfFrames * 1000) / widgetBackingStore->perfTime.restart();
+ qDebug("FPS: %.1f\n", fps);
+ widgetBackingStore->perfFrames = 0;
}
}
- if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
- return;
-
QPoint offset = tlwOffset;
if (widget != tlw)
offset += widget->mapTo(tlw, QPoint());
#ifndef QT_NO_OPENGL
- if (widgetTextures)
+ if (widgetTextures) {
+ widget->window()->d_func()->sendComposeStatus(widget->window(), false);
backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, tlw->d_func()->shareContext());
- else
+ widget->window()->d_func()->sendComposeStatus(widget->window(), true);
+ } else
#endif
backingStore->flush(region, widget->windowHandle(), offset);
}
@@ -270,7 +267,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
return;
const QPoint offset = widget->mapTo(tlw, QPoint());
- qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset);
+ qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset, 0, tlw->d_func()->maybeBackingStore());
}
#endif // QT_NO_PAINT_DEBUG
@@ -519,6 +516,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,
const QPoint offset = widget->mapTo(tlw, QPoint());
if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!widget->d_func()->inDirtyList)
+ addDirtyRenderToTextureWidget(widget);
if (!updateRequestSent || updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return;
@@ -613,6 +612,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
}
if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!widget->d_func()->inDirtyList)
+ addDirtyRenderToTextureWidget(widget);
if (!updateRequestSent || updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return;
@@ -710,6 +711,7 @@ void QWidgetBackingStore::removeDirtyWidget(QWidget *w)
dirtyWidgetsRemoveAll(w);
dirtyOnScreenWidgetsRemoveAll(w);
+ dirtyRenderToTextureWidgets.removeAll(w);
resetWidget(w);
QWidgetPrivate *wd = w->d_func();
@@ -744,7 +746,8 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
widgetTextures(0),
fullUpdatePending(0),
updateRequestSent(0),
- textureListWatcher(0)
+ textureListWatcher(0),
+ perfFrames(0)
{
store = tlw->backingStore();
Q_ASSERT(store);
@@ -755,9 +758,11 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
QWidgetBackingStore::~QWidgetBackingStore()
{
- for (int c = 0; c < dirtyWidgets.size(); ++c) {
+ for (int c = 0; c < dirtyWidgets.size(); ++c)
resetWidget(dirtyWidgets.at(c));
- }
+ for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c)
+ resetWidget(dirtyRenderToTextureWidgets.at(c));
+
#ifndef QT_NO_OPENGL
delete dirtyOnScreenWidgets;
#endif
@@ -944,7 +949,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
// Nothing to repaint.
if (!isDirty() && store->size().isValid()) {
- qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures);
+ qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, this);
return;
}
@@ -961,7 +966,8 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
{
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
if (wd->renderToTexture)
- widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()));
+ widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()),
+ widget->testAttribute(Qt::WA_AlwaysStackOnTop));
for (int i = 0; i < wd->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
@@ -1125,13 +1131,47 @@ void QWidgetBackingStore::doSync()
#endif
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.
+ // Nothing to repaint. However renderToTexture widgets are handled
+ // specially, they are not in the regular dirty list, in order to
+ // prevent triggering unnecessary backingstore painting when only the
+ // OpenGL content changes. Check if we have such widgets in the special
+ // dirty list.
+ for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) {
+ QWidget *w = dirtyRenderToTextureWidgets.at(i);
+ w->d_func()->sendPaintEvent(w->rect());
+ resetWidget(w);
+ }
+ dirtyRenderToTextureWidgets.clear();
+
+ // 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. We also need to composite the renderToTexture widgets.
flush();
+
return;
}
+ // There is something other dirty than the renderToTexture widgets.
+ // Now it is time to include the renderToTexture ones among the others.
+ if (widgetTextures && widgetTextures->count()) {
+ for (int i = 0; i < widgetTextures->count(); ++i) {
+ const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already
+ dirty += rect;
+ toClean += rect;
+ }
+ }
+ // The dirtyRenderToTextureWidgets list is useless here, so just reset. As
+ // unintuitive as it is, we need to send paint events to renderToTexture
+ // widgets always when something (any widget) needs to be updated, even if
+ // the renderToTexture widget itself is clean, i.e. there was no update()
+ // call for it. This is because changing any widget will cause a flush and
+ // so a potentially blocking buffer swap for the window, and skipping paints
+ // for the renderToTexture widgets would make it impossible to have smoothly
+ // animated content in them.
+ for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i)
+ resetWidget(dirtyRenderToTextureWidgets.at(i));
+ dirtyRenderToTextureWidgets.clear();
+
#ifndef QT_NO_GRAPHICSVIEW
if (tlw->d_func()->extra->proxyWidget) {
updateStaticContentsSize();
@@ -1200,15 +1240,17 @@ void QWidgetBackingStore::flush(QWidget *widget)
{
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures);
+ qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this);
dirtyOnScreen = QRegion();
+ if (widgetTextures && widgetTextures->count())
+ return;
}
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures);
+ qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, this);
}
#endif
return;
@@ -1218,7 +1260,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
QWidget *w = dirtyOnScreenWidgets->at(i);
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
- qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset);
+ qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, 0, this);
*wd->needsFlush = QRegion();
}
dirtyOnScreenWidgets->clear();
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index 473e9deef4..0da85e33d5 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -133,6 +133,7 @@ private:
QRegion dirty; // needsRepaint
QRegion dirtyFromPreviousSync;
QVector<QWidget *> dirtyWidgets;
+ QVector<QWidget *> dirtyRenderToTextureWidgets;
QVector<QWidget *> *dirtyOnScreenWidgets;
QList<QWidget *> staticWidgets;
QPlatformTextureList *widgetTextures;
@@ -143,6 +144,8 @@ private:
QPoint tlwOffset;
QPlatformTextureListWatcher *textureListWatcher;
+ QElapsedTimer perfTime;
+ int perfFrames;
void sendUpdateRequest(QWidget *widget, UpdateTime updateTime);
@@ -150,7 +153,8 @@ private:
static void unflushPaint(QWidget *widget, const QRegion &rgn);
static void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
QWidget *tlw, const QPoint &tlwOffset,
- QPlatformTextureList *widgetTextures = 0);
+ QPlatformTextureList *widgetTextures,
+ QWidgetBackingStore *widgetBackingStore);
void doSync();
bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
@@ -184,6 +188,16 @@ private:
}
}
+ inline void addDirtyRenderToTextureWidget(QWidget *widget)
+ {
+ if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) {
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+ Q_ASSERT(widgetPrivate->renderToTexture);
+ dirtyRenderToTextureWidgets.append(widget);
+ widgetPrivate->inDirtyList = true;
+ }
+ }
+
inline void dirtyWidgetsRemoveAll(QWidget *widget)
{
int i = 0;
@@ -294,7 +308,6 @@ private:
friend QRegion qt_dirtyRegion(QWidget *);
friend class QWidgetPrivate;
friend class QWidget;
- friend class QETWidget;
friend class QBackingStore;
};
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index fc328e7af0..b255bc16f9 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "private/qwindow_p.h"
-#include "qwidgetwindow_qpa_p.h"
+#include "qwidgetwindow_p.h"
#include "private/qwidget_p.h"
#include "private/qapplication_p.h"
@@ -443,7 +443,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
// Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
const QPoint localPos = win->mapFromGlobal(event->globalPos());
QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
- e->spont = 1;
+ QCoreApplicationPrivate::setEventSpontaneous(e, true);
QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event));
e->setTimestamp(event->timestamp());
QCoreApplication::postEvent(win, e);
@@ -795,7 +795,7 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
QPointF mapped = qt_tablet_target->mapFromGlobal(event->globalPos()) + delta;
QTabletEvent ev(event->type(), mapped, event->globalPosF(), event->device(), event->pointerType(),
event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
- event->rotation(), event->z(), event->modifiers(), event->uniqueId());
+ event->rotation(), event->z(), event->modifiers(), event->uniqueId(), event->button(), event->buttons());
ev.setTimestamp(event->timestamp());
QGuiApplication::sendSpontaneousEvent(qt_tablet_target, &ev);
}
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 06ba8ea646..be2adddff5 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QWIDGETWINDOW_QPA_P_H
-#define QWIDGETWINDOW_QPA_P_H
+#ifndef QWIDGETWINDOW_P_H
+#define QWIDGETWINDOW_P_H
#include <QtGui/qwindow.h>
@@ -122,4 +122,4 @@ private:
QT_END_NAMESPACE
-#endif // QWIDGETWINDOW_QPA_P_H
+#endif // QWIDGETWINDOW_P_H
diff --git a/src/widgets/statemachine/qguistatemachine.cpp b/src/widgets/statemachine/qguistatemachine.cpp
index d737a1e323..9824b96334 100644
--- a/src/widgets/statemachine/qguistatemachine.cpp
+++ b/src/widgets/statemachine/qguistatemachine.cpp
@@ -312,6 +312,8 @@ static QEvent *cloneEvent(QEvent *e)
me2->setButtons(me->buttons());
me2->setButton(me->button());
me2->setModifiers(me->modifiers());
+ me2->setSource(me->source());
+ me2->setFlags(me->flags());
return me2;
}
diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp
index ceb95aa125..9f241c42e1 100644
--- a/src/widgets/styles/qandroidstyle.cpp
+++ b/src/widgets/styles/qandroidstyle.cpp
@@ -118,6 +118,7 @@ QAndroidStyle::QAndroidStyle()
: QFusionStyle()
{
QPixmapCache::clear();
+ checkBoxControl = NULL;
QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH")));
const QLatin1Char slashChar('/');
if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar))
@@ -127,8 +128,7 @@ QAndroidStyle::QAndroidStyle()
if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar))
androidTheme += slashChar;
- if (stylePath.isEmpty())
- {
+ if (stylePath.isEmpty()) {
stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/")
+ QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar;
}
@@ -143,7 +143,7 @@ QAndroidStyle::QAndroidStyle()
QJsonParseError error;
QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error);
- if (document.isNull()) {
+ if (document.isNull()) {
qCritical() << error.errorString();
return;
}
@@ -155,8 +155,8 @@ QAndroidStyle::QAndroidStyle()
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- QHash<int, QPalette> * palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes"));
- QHash<int, QFont> * fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts"));
+ QHash<int, QPalette> *palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes"));
+ QHash<int, QFont> *fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts"));
palettes->clear();
fonts->clear();
QJsonObject object = document.object();
@@ -214,7 +214,7 @@ QAndroidStyle::QAndroidStyle()
}
if (!qtClassName.isEmpty())
QApplication::setFont(font, qtClassName.toUtf8());
- if (ft>-1)
+ if (ft > -1)
fonts->insert(ft, font);
// Extract font information
}
@@ -256,6 +256,9 @@ QAndroidStyle::QAndroidStyle()
switch (itemType) {
case QC_Checkbox:
+ checkBoxControl = new AndroidCompoundButtonControl(item.toVariantMap(), itemType);
+ m_androidControlsHash[int(itemType)] = checkBoxControl;
+ break;
case QC_RadioButton:
m_androidControlsHash[int(itemType)] = new AndroidCompoundButtonControl(item.toVariantMap(),
itemType);
@@ -516,16 +519,31 @@ void QAndroidStyle::drawPrimitive(PrimitiveElement pe,
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end()) {
- if (itemType != QC_EditText)
+ if (itemType != QC_EditText) {
it.value()->drawControl(opt, p, w);
- else {
+ } else {
QStyleOption copy(*opt);
copy.state &= ~QStyle::State_Sunken;
it.value()->drawControl(&copy, p, w);
}
- }
- else
+ } else if (pe == PE_FrameGroupBox) {
+ if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt);
+ if (frame2 && (frame2->features & QStyleOptionFrameV2::Flat)) {
+ QRect fr = frame->rect;
+ QPoint p1(fr.x(), fr.y() + 1);
+ QPoint p2(fr.x() + fr.width(), p1.y());
+ qDrawShadeLine(p, p1, p2, frame->palette, true,
+ frame->lineWidth, frame->midLineWidth);
+ } else {
+ qDrawShadeRect(p, frame->rect.x(), frame->rect.y(), frame->rect.width(),
+ frame->rect.height(), frame->palette, true,
+ frame->lineWidth, frame->midLineWidth);
+ }
+ }
+ } else {
QFusionStyle::drawPrimitive(pe, opt, p, w);
+ }
}
@@ -575,6 +593,36 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element,
default:
break;
}
+ } else if (element == CE_ItemViewItem) {
+ const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt);
+ if (vopt && vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
+ p->save();
+ p->setClipRect(opt->rect);
+
+ QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, w);
+
+ // draw the background
+ proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, w);
+
+ // draw the check mark
+ QStyleOptionViewItem option(*vopt);
+ option.rect = checkRect;
+ option.state = option.state & ~QStyle::State_HasFocus;
+
+ switch (vopt->checkState) {
+ case Qt::Unchecked:
+ option.state |= QStyle::State_Off;
+ break;
+ default:
+ option.state |= QStyle::State_On;
+ break;
+ }
+ QPixmap pixmap = checkBoxControl->imgCheckBox(&option);
+ p->drawPixmap(checkRect, pixmap);
+ p->restore();
+ } else {
+ QFusionStyle::drawControl(element, opt, p, w);
+ }
} else {
QFusionStyle::drawControl(element, opt, p, w);
}
@@ -584,6 +632,8 @@ QRect QAndroidStyle::subElementRect(SubElement subElement,
const QStyleOption *option,
const QWidget *widget) const
{
+ if (subElement == SE_LineEditContents) // fix spinbox display problem
+ return QFusionStyle::subElementRect(subElement, option, widget);
const ItemType itemType = qtControl(subElement);
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
@@ -602,10 +652,74 @@ void QAndroidStyle::drawComplexControl(ComplexControl cc,
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
- if (it != m_androidControlsHash.end())
+ if (it != m_androidControlsHash.end()) {
it.value()->drawControl(opt, p, widget);
- else
- QFusionStyle::drawComplexControl(cc, opt, p, widget);
+ return;
+ }
+ if (cc == CC_GroupBox) {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ // Draw frame
+ QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect;
+ if (groupBox->subControls & SC_GroupBoxCheckBox)
+ checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
+ if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
+ QStyleOptionFrameV2 frame;
+ frame.QStyleOption::operator=(*groupBox);
+ frame.features = groupBox->features;
+ frame.lineWidth = groupBox->lineWidth;
+ frame.midLineWidth = groupBox->midLineWidth;
+ frame.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
+ p->save();
+ QRegion region(groupBox->rect);
+ if (!groupBox->text.isEmpty()) {
+ bool ltr = groupBox->direction == Qt::LeftToRight;
+ QRect finalRect;
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
+ finalRect = checkBoxRect.united(textRect);
+ finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
+ } else {
+ finalRect = textRect;
+ }
+ region -= finalRect;
+ }
+ p->setClipRegion(region);
+ drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
+ p->restore();
+ }
+
+ // Draw title
+ if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
+ QColor textColor = groupBox->textColor;
+ if (textColor.isValid())
+ p->setPen(textColor);
+ int alignment = int(groupBox->textAlignment);
+ if (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
+ alignment |= Qt::TextHideMnemonic;
+
+ drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
+ textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
+
+ if (groupBox->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*groupBox);
+ fropt.rect = textRect;
+ drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ }
+ }
+
+ // Draw checkbox
+ if (groupBox->subControls & SC_GroupBoxCheckBox) {
+ QStyleOptionButton box;
+ box.QStyleOption::operator=(*groupBox);
+ box.rect = checkBoxRect;
+ checkBoxControl->drawControl(&box, p, widget);
+ }
+ }
+ return;
+ }
+ QFusionStyle::drawComplexControl(cc, opt, p, widget);
}
QStyle::SubControl QAndroidStyle::hitTestComplexControl(ComplexControl cc,
@@ -649,6 +763,52 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc,
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->subControlRect(opt, sc, widget);
+ QRect rect = opt->rect;
+ switch (cc) {
+ case CC_GroupBox: {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
+ QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
+ int indicatorWidth = checkBoxSize.width();
+ int indicatorHeight = checkBoxSize.height();
+ QRect checkBoxRect;
+ if (opt->subControls & QStyle::SC_GroupBoxCheckBox) {
+ checkBoxRect.setWidth(indicatorWidth);
+ checkBoxRect.setHeight(indicatorHeight);
+ }
+ checkBoxRect.moveLeft(1);
+ QRect textRect = checkBoxRect;
+ textRect.setSize(textSize);
+ if (opt->subControls & QStyle::SC_GroupBoxCheckBox)
+ textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2);
+ if (sc == SC_GroupBoxFrame) {
+ rect = opt->rect.adjusted(0, 0, 0, 0);
+ rect.translate(0, textRect.height() / 2);
+ rect.setHeight(rect.height() - textRect.height() / 2);
+ } else if (sc == SC_GroupBoxContents) {
+ QRect frameRect = opt->rect.adjusted(0, 0, 0, -groupBox->lineWidth);
+ int margin = 3;
+ int leftMarginExtension = 0;
+ int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), opt->fontMetrics.height()) + groupBox->lineWidth;
+ frameRect.adjust(leftMarginExtension + margin, margin + topMargin, -margin, -margin - groupBox->lineWidth);
+ frameRect.translate(0, textRect.height() / 2);
+ rect = frameRect;
+ rect.setHeight(rect.height() - textRect.height() / 2);
+ } else if (sc == SC_GroupBoxCheckBox) {
+ rect = checkBoxRect;
+ } else if (sc == SC_GroupBoxLabel) {
+ rect = textRect;
+ }
+ return visualRect(opt->direction, opt->rect, rect);
+ }
+
+ return rect;
+ }
+
+ default:
+ break;
+ }
+
return QFusionStyle::subControlRect(cc, opt, sc, widget);
}
@@ -664,6 +824,10 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_SpinBoxFrameWidth:
case PM_ScrollBarExtent:
return 0;
+ case PM_IndicatorWidth:
+ return checkBoxControl->sizeCheckBox(option).width();
+ case PM_IndicatorHeight:
+ return checkBoxControl->sizeCheckBox(option).height();
default:
return QFusionStyle::pixelMetric(metric, option, widget);
}
@@ -676,12 +840,61 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct,
const QWidget *w) const
{
QSize sz = QFusionStyle::sizeFromContents(ct, opt, contentsSize, w);
+ if (ct == CT_HeaderSection) {
+ if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
+ bool nullIcon = hdr->icon.isNull();
+ int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w);
+ int iconSize = nullIcon ? 0 : checkBoxControl->sizeCheckBox(opt).width();
+ QSize txt;
+/*
+ * These next 4 lines are a bad hack to fix a bug in case a QStyleSheet is applied at QApplication level.
+ * In that case, even if the stylesheet does not refer to headers, the header font is changed to application
+ * font, which is wrong. Even worst, hdr->fontMetrics(...) does not report the proper size.
+ */
+ if (qApp->styleSheet().isEmpty())
+ txt = hdr->fontMetrics.size(0, hdr->text);
+ else
+ txt = qApp->fontMetrics().size(0, hdr->text);
+
+ sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
+ sz.setWidth((nullIcon ? 0 : margin) + iconSize
+ + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin);
+ if (hdr->sortIndicator != QStyleOptionHeader::None) {
+ int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w);
+ if (hdr->orientation == Qt::Horizontal)
+ sz.rwidth() += sz.height() + margin;
+ else
+ sz.rheight() += sz.width() + margin;
+ }
+ return sz;
+ }
+ }
const ItemType itemType = qtControl(ct);
AndroidControlsHash::const_iterator it = itemType != QC_UnknownType
? m_androidControlsHash.find(itemType)
: m_androidControlsHash.end();
if (it != m_androidControlsHash.end())
return it.value()->sizeFromContents(opt, sz, w);
+ if (ct == CT_GroupBox) {
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
+ QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
+ QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
+ int indicatorWidth = checkBoxSize.width();
+ int indicatorHeight = checkBoxSize.height();
+ QRect checkBoxRect;
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
+ checkBoxRect.setWidth(indicatorWidth);
+ checkBoxRect.setHeight(indicatorHeight);
+ }
+ checkBoxRect.moveLeft(1);
+ QRect textRect = checkBoxRect;
+ textRect.setSize(textSize);
+ if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)
+ textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2);
+ QRect u = textRect.united(checkBoxRect);
+ sz = QSize(sz.width(), sz.height() + u.height());
+ }
+ }
return sz;
}
@@ -712,7 +925,7 @@ int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option,
return RSIP_OnMouseClick;
default:
- return QFusionStyle::styleHint(hint,option, widget, returnData);
+ return QFusionStyle::styleHint(hint, option, widget, returnData);
}
}
@@ -761,6 +974,13 @@ QSize QAndroidStyle::AndroidDrawable::size() const
return QSize();
}
+QPixmap QAndroidStyle::AndroidDrawable::img() const
+{
+ if (type() == Image || type() == NinePatch)
+ return static_cast<const QAndroidStyle::AndroidImageDrawable *>(this)->img();
+
+ return QPixmap();
+}
QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable,
ItemType itemType)
@@ -828,6 +1048,18 @@ void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOp
painter->drawPixmap(opt->rect.x(), (opt->rect.height() - pm.height()) / 2, pm);
}
+QPixmap QAndroidStyle::AndroidImageDrawable::img() const
+{
+ if (m_hashKey.isEmpty())
+ m_hashKey = QFileInfo(m_filePath).fileName();
+
+ QPixmap pm;
+ if (!QPixmapCache::find(m_hashKey, &pm)) {
+ pm.load(m_filePath);
+ QPixmapCache::insert(m_hashKey, pm);
+ }
+ return pm;
+}
QSize QAndroidStyle::AndroidImageDrawable::size() const
{
@@ -886,7 +1118,7 @@ void QAndroidStyle::Android9PatchDrawable::extractIntArray(const QVariantList &v
}
-void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyleOption *opt) const
+void QAndroidStyle::Android9PatchDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
if (m_hashKey.isEmpty())
m_hashKey = QFileInfo(m_filePath).fileName();
@@ -897,7 +1129,7 @@ void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyle
QPixmapCache::insert(m_hashKey, pixmap);
}
- const QRect &bounds=opt->rect;
+ const QRect &bounds = opt->rect;
// shamelessly stolen from Android's sources (NinepatchImpl.cpp) and adapted for Qt
const int pixmapWidth = pixmap.width();
@@ -1052,11 +1284,11 @@ QAndroidStyle::AndroidGradientDrawable::AndroidGradientDrawable(const QVariantMa
QVariantList colors = drawable.value(QLatin1String("colors")).toList();
QVariantList positions = drawable.value(QLatin1String("positions")).toList();
- int min=colors.size() < positions.size() ? colors.size() : positions.size();
+ int min = colors.size() < positions.size() ? colors.size() : positions.size();
for (int i = 0; i < min; i++)
m_gradient.setColorAt(positions.at(i).toDouble(), QRgb(colors.at(i).toInt()));
- QByteArray orientation=drawable.value(QLatin1String("orientation")).toByteArray();
+ QByteArray orientation = drawable.value(QLatin1String("orientation")).toByteArray();
if (orientation == "TOP_BOTTOM") // draw the gradient from the top to the bottom
m_orientation = TOP_BOTTOM;
else if (orientation == "TR_BL") // draw the gradient from the top-right to the bottom-left
@@ -1089,43 +1321,43 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl
switch (m_orientation) {
case TOP_BOTTOM:
// draw the gradient from the top to the bottom
- m_gradient.setStart(width/2,0);
- m_gradient.setFinalStop(width/2,height);
+ m_gradient.setStart(width / 2, 0);
+ m_gradient.setFinalStop(width / 2, height);
break;
case TR_BL:
// draw the gradient from the top-right to the bottom-left
- m_gradient.setStart(width,0);
- m_gradient.setFinalStop(0,height);
+ m_gradient.setStart(width, 0);
+ m_gradient.setFinalStop(0, height);
break;
case RIGHT_LEFT:
// draw the gradient from the right to the left
- m_gradient.setStart(width,height/2);
- m_gradient.setFinalStop(0,height/2);
+ m_gradient.setStart(width, height / 2);
+ m_gradient.setFinalStop(0, height / 2);
break;
case BR_TL:
// draw the gradient from the bottom-right to the top-left
- m_gradient.setStart(width,height);
- m_gradient.setFinalStop(0,0);
+ m_gradient.setStart(width, height);
+ m_gradient.setFinalStop(0, 0);
break;
case BOTTOM_TOP:
// draw the gradient from the bottom to the top
- m_gradient.setStart(width/2,height);
- m_gradient.setFinalStop(width/2,0);
+ m_gradient.setStart(width / 2, height);
+ m_gradient.setFinalStop(width / 2, 0);
break;
case BL_TR:
// draw the gradient from the bottom-left to the top-right
- m_gradient.setStart(0,height);
- m_gradient.setFinalStop(width,0);
+ m_gradient.setStart(0, height);
+ m_gradient.setFinalStop(width, 0);
break;
case LEFT_RIGHT:
// draw the gradient from the left to the right
- m_gradient.setStart(0,height/2);
- m_gradient.setFinalStop(width,height/2);
+ m_gradient.setStart(0, height / 2);
+ m_gradient.setFinalStop(width, height / 2);
break;
case TL_BR:
// draw the gradient from the top-left to the bottom-right
- m_gradient.setStart(0,0);
- m_gradient.setFinalStop(width,height);
+ m_gradient.setStart(0, 0);
+ m_gradient.setFinalStop(width, height);
break;
}
@@ -1140,7 +1372,7 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl
QSize QAndroidStyle::AndroidGradientDrawable::size() const
{
- return QSize(m_radius*2, m_radius*2);
+ return QSize(m_radius * 2, m_radius * 2);
}
QAndroidStyle::AndroidClipDrawable::AndroidClipDrawable(const QVariantMap &drawable,
@@ -1172,9 +1404,9 @@ void QAndroidStyle::AndroidClipDrawable::draw(QPainter *painter, const QStyleOpt
{
QStyleOption copy(*opt);
if (m_orientation == Qt::Horizontal)
- copy.rect.setWidth(copy.rect.width()*m_factor);
+ copy.rect.setWidth(copy.rect.width() * m_factor);
else
- copy.rect.setHeight(copy.rect.height()*m_factor);
+ copy.rect.setHeight(copy.rect.height() * m_factor);
m_drawable->draw(painter, &copy);
}
@@ -1212,12 +1444,28 @@ QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidStateDrawable::type() c
void QAndroidStyle::AndroidStateDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
- const AndroidDrawable *drawable=bestAndroidStateMatch(opt);
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
if (drawable)
drawable->draw(painter, opt);
}
+QSize QAndroidStyle::AndroidStateDrawable::sizeImage(const QStyleOption *opt) const
+{
+ QSize s;
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
+ if (drawable)
+ s = drawable->size();
+ return s;
+}
+QPixmap QAndroidStyle::AndroidStateDrawable::img(const QStyleOption *opt) const
+{
+ QPixmap pm;
+ const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
+ if (drawable)
+ pm = drawable->img();
+ return pm;
+}
-const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const
+const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const
{
const AndroidDrawable *bestMatch = 0;
if (!opt) {
@@ -1226,7 +1474,7 @@ const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestA
return bestMatch;
}
- uint bestCost=0xffff;
+ uint bestCost = 0xffff;
foreach (const StateType & state, m_states) {
if (int(opt->state) == state.first)
return state.second;
@@ -1376,15 +1624,13 @@ void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::O
void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const
{
- foreach (const LayerType &layer, m_layers)
- {
- if (layer.first == m_id)
- {
+ foreach (const LayerType &layer, m_layers) {
+ if (layer.first == m_id) {
QStyleOption copy(*opt);
if (m_orientation == Qt::Horizontal)
- copy.rect.setWidth(copy.rect.width()*m_factor);
+ copy.rect.setWidth(copy.rect.width() * m_factor);
else
- copy.rect.setHeight(copy.rect.height()*m_factor);
+ copy.rect.setHeight(copy.rect.height() * m_factor);
layer.second->draw(painter, &copy);
} else {
layer.second->draw(painter, opt);
@@ -1418,7 +1664,7 @@ QAndroidStyle::AndroidControl::AndroidControl(const QVariantMap &control,
m_background = 0;
it = control.find(QLatin1String("View_minWidth"));
- if (it!=control.end())
+ if (it != control.end())
m_minSize.setWidth(it.value().toInt());
it = control.find(QLatin1String("View_minHeight"));
@@ -1534,10 +1780,9 @@ QSize QAndroidStyle::AndroidControl::sizeFromContents(const QStyleOption *opt,
QMargins QAndroidStyle::AndroidControl::padding()
{
- if (const AndroidDrawable *drawable = m_background)
- {
+ if (const AndroidDrawable *drawable = m_background) {
if (drawable->type() == State)
- drawable=static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0);
+ drawable = static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0);
return drawable->padding();
}
return QMargins();
@@ -1573,8 +1818,17 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption
if (m_button)
m_button->draw(p, opt);
}
-
-const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
+QSize QAndroidStyle::AndroidCompoundButtonControl::sizeCheckBox(const QStyleOption *opt) const
+{
+ const AndroidDrawable *drawable = m_button;
+ return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->sizeImage(opt);
+}
+QPixmap QAndroidStyle::AndroidCompoundButtonControl::imgCheckBox(const QStyleOption *opt) const
+{
+ const AndroidDrawable *drawable = m_button;
+ return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->img(opt);
+}
+const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
{
return m_background ? m_background : m_button;
}
@@ -1637,10 +1891,10 @@ void QAndroidStyle::AndroidProgressBarControl::drawControl(const QStyleOption *o
if (m_progressDrawable->type() == QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
- static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
+ static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum),
progressBarV2.orientation);
else
- static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId,double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum),
+ static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum),
progressBarV2.orientation);
}
m_progressDrawable->draw(p, option);
@@ -1659,11 +1913,11 @@ QRect QAndroidStyle::AndroidProgressBarControl::subElementRect(QStyle::SubElemen
return option->rect;
QMargins padding = m_background->padding();
- QRect p(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ QRect p(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
padding = m_indeterminateDrawable->padding();
- p |= QRect(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
padding = m_progressDrawable->padding();
- p |= QRect(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top());
+ p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top());
QRect r = option->rect.adjusted(p.left(), p.top(), -p.right(), -p.bottom());
@@ -1734,26 +1988,27 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio
if (const QStyleOptionSlider *styleOption =
qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- double factor = double(styleOption->sliderPosition)/double(styleOption->maximum-styleOption->minimum);
- if (m_progressDrawable->type()==QAndroidStyle::Layer) {
+ double factor = double(styleOption->sliderPosition - styleOption->minimum)
+ / double(styleOption->maximum - styleOption->minimum);
+ if (m_progressDrawable->type() == QAndroidStyle::Layer) {
QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId);
if (clipDrawable->type() == QAndroidStyle::Clip)
static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(factor, styleOption->orientation);
else
static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, factor, styleOption->orientation);
}
- const AndroidDrawable *drawable=m_seekBarThumb;
+ const AndroidDrawable *drawable = m_seekBarThumb;
if (drawable->type() == State)
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option);
QStyleOption copy(*option);
- copy.rect.setY((copy.rect.height()-m_minSize.height())/2);
+ copy.rect.setY((copy.rect.height() - m_minSize.height()) / 2);
copy.rect.setHeight(m_minSize.height());
copy.rect.setWidth(copy.rect.width() - drawable->size().width());
- copy.rect.translate(drawable->size().width()/2, 0);
+ copy.rect.translate(drawable->size().width() / 2, 0);
m_progressDrawable->draw(p, &copy);
if (styleOption->orientation == Qt::Vertical)
qCritical() << "Vertical slider are not supported";
- int pos = copy.rect.width()*factor - drawable->size().width()/2;
+ int pos = copy.rect.width()*factor - drawable->size().width() / 2;
copy.rect.translate(pos, 0);
copy.rect.setSize(drawable->size());
m_seekBarThumb->draw(p, &copy);
@@ -1767,7 +2022,7 @@ QSize QAndroidStyle::AndroidSeekBarControl::sizeFromContents(const QStyleOption
QSize sz = AndroidProgressBarControl::sizeFromContents(opt, contentsSize, w);
if (!m_seekBarThumb)
return sz;
- const AndroidDrawable *drawable=m_seekBarThumb;
+ const AndroidDrawable *drawable = m_seekBarThumb;
if (drawable->type() == State)
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(opt);
return sz.expandedTo(drawable->size());
@@ -1786,7 +2041,8 @@ QRect QAndroidStyle::AndroidSeekBarControl::subControlRect(const QStyleOptionCom
drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option);
QRect r(option->rect);
- double factor = double(styleOption->sliderPosition) / (styleOption->maximum - styleOption->minimum);
+ double factor = double(styleOption->sliderPosition - styleOption->minimum)
+ / (styleOption->maximum - styleOption->minimum);
int pos = option->rect.width() * factor - double(drawable->size().width() / 2);
r.setX(r.x() + pos);
r.setSize(drawable->size());
diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h
index d64e37b9db..5334882908 100644
--- a/src/widgets/styles/qandroidstyle_p.h
+++ b/src/widgets/styles/qandroidstyle_p.h
@@ -132,6 +132,7 @@ public:
static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType);
static QMargins extractMargins(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
+ QPixmap img() const;
protected:
ItemType m_itemType;
QMargins m_padding;
@@ -156,6 +157,7 @@ public:
virtual void draw(QPainter *painter,const QStyleOption *opt) const;
virtual QSize size() const;
+ QPixmap img() const;
protected:
QString m_filePath;
mutable QString m_hashKey;
@@ -228,7 +230,8 @@ public:
inline const AndroidDrawable *bestAndroidStateMatch(const QStyleOption *opt) const;
static int extractState(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
-
+ QSize sizeImage(const QStyleOption *opt) const;
+ QPixmap img(const QStyleOption *opt) const;
private:
typedef QPair<int, const AndroidDrawable *> StateType;
QList<StateType> m_states;
@@ -281,7 +284,8 @@ public:
AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType);
virtual ~AndroidCompoundButtonControl();
virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w);
-
+ QSize sizeCheckBox(const QStyleOption *opt) const;
+ QPixmap imgCheckBox(const QStyleOption *opt) const;
protected:
virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_button;
@@ -387,6 +391,7 @@ private:
typedef QHash<int, AndroidControl *> AndroidControlsHash;
AndroidControlsHash m_androidControlsHash;
QPalette m_standardPalette;
+ AndroidCompoundButtonControl *checkBoxControl;
};
#endif // QT_NO_STYLE_ANDROID
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index d7030c5d72..d8b67edff8 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -1155,7 +1155,7 @@ void QCommonStylePrivate::startAnimation(QStyleAnimation *animation) const
stopAnimation(animation->target());
q->connect(animation, SIGNAL(destroyed()), SLOT(_q_removeAnimation()), Qt::UniqueConnection);
animations.insert(animation->target(), animation);
- animation->start(QAbstractAnimation::DeleteWhenStopped);
+ animation->start();
}
/*! \internal */
@@ -4930,6 +4930,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = hint.toChar().unicode();
break;
}
+ case SH_LineEdit_PasswordMaskDelay:
+ ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ break;
case SH_ToolBox_SelectedPageTitleBold:
ret = 1;
break;
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 82c53def7d..d1b5bcc95c 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -749,6 +749,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->drawRect(rect);
QColor checkMarkColor = option->palette.text().color().darker(120);
+ const int checkMarkPadding = QStyleHelper::dpiScaled(3);
if (checkbox->state & State_NoChange) {
gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
@@ -759,10 +760,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
checkMarkColor.setAlpha(180);
painter->setPen(QPen(checkMarkColor, 1));
painter->setBrush(gradient);
- painter->drawRect(rect.adjusted(3, 3, -3, -3));
+ painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding));
} else if (checkbox->state & (State_On)) {
- QPen checkPen = QPen(checkMarkColor, 1.8);
+ QPen checkPen = QPen(checkMarkColor, QStyleHelper::dpiScaled(1.8));
checkMarkColor.setAlpha(210);
painter->translate(-1, 0.5);
painter->setPen(checkPen);
@@ -771,9 +772,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
// Draw checkmark
QPainterPath path;
- path.moveTo(5, rect.height() / 2.0);
- path.lineTo(rect.width() / 2.0 - 0, rect.height() - 3);
- path.lineTo(rect.width() - 2.5, 3);
+ path.moveTo(2 + checkMarkPadding, rect.height() / 2.0);
+ path.lineTo(rect.width() / 2.0, rect.height() - checkMarkPadding);
+ path.lineTo(rect.width() - checkMarkPadding - 0.5, checkMarkPadding);
painter->drawPath(path.translated(rect.topLeft()));
}
}
@@ -786,7 +787,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
painter->setRenderHint(QPainter::Antialiasing, true);
QPainterPath circle;
- circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5);
+ const QPointF circleCenter = rect.center() + QPoint(1, 1);
+ const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
+ circle.addEllipse(circleCenter, outlineRadius, outlineRadius);
painter->setPen(QPen(option->palette.background().color().darker(150)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
painter->setPen(QPen(highlightedOutline));
@@ -794,7 +797,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (state & (State_On )) {
circle = QPainterPath();
- circle.addEllipse(rect.center() + QPoint(1, 1), 2.8, 2.8);
+ const qreal checkmarkRadius = outlineRadius / 2.32;
+ circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius);
QColor checkMarkColor = option->palette.text().color().darker(120);
checkMarkColor.setAlpha(200);
painter->setPen(checkMarkColor);
@@ -1604,8 +1608,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
else
pixmap = menuItem->icon.pixmap(iconSize, mode);
- int pixw = pixmap.width();
- int pixh = pixmap.height();
+ const int pixw = pixmap.width() / pixmap.devicePixelRatio();
+ const int pixh = pixmap.height() / pixmap.devicePixelRatio();
QRect pmr(0, 0, pixw, pixh);
pmr.moveCenter(vCheckRect.center());
@@ -3016,97 +3020,120 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
*/
int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
+ int val = -1;
switch (metric) {
case PM_SliderTickmarkOffset:
- return 4;
+ val = 4;
+ break;
case PM_HeaderMargin:
- return 2;
case PM_ToolTipLabelFrameWidth:
- return 2;
+ val = 2;
+ break;
case PM_ButtonDefaultIndicator:
- return 0;
case PM_ButtonShiftHorizontal:
case PM_ButtonShiftVertical:
- return 0;
+ val = 0;
+ break;
case PM_MessageBoxIconSize:
- return 48;
+ val = 48;
+ break;
case PM_ListViewIconSize:
- return 24;
+ val = 24;
+ break;
case PM_DialogButtonsSeparator:
case PM_ScrollBarSliderMin:
- return 26;
+ val = 26;
+ break;
case PM_TitleBarHeight:
- return 24;
+ val = 24;
+ break;
case PM_ScrollBarExtent:
- return 14;
+ val = 14;
+ break;
case PM_SliderThickness:
- return 15;
case PM_SliderLength:
- return 15;
+ val = 15;
+ break;
case PM_DockWidgetTitleMargin:
- return 1;
- case PM_DefaultFrameWidth:
- return 1;
+ val = 1;
+ break;
case PM_SpinBoxFrameWidth:
- return 3;
+ val = 3;
+ break;
case PM_MenuVMargin:
case PM_MenuHMargin:
- return 0;
case PM_MenuPanelWidth:
- return 0;
+ val = 0;
+ break;
case PM_MenuBarItemSpacing:
- return 6;
+ val = 6;
+ break;
case PM_MenuBarVMargin:
- return 0;
case PM_MenuBarHMargin:
- return 0;
case PM_MenuBarPanelWidth:
- return 0;
+ val = 0;
+ break;
case PM_ToolBarHandleExtent:
- return 9;
+ val = 9;
+ break;
case PM_ToolBarItemSpacing:
- return 1;
+ val = 1;
+ break;
case PM_ToolBarFrameWidth:
- return 2;
case PM_ToolBarItemMargin:
- return 2;
+ val = 2;
+ break;
case PM_SmallIconSize:
- return 16;
case PM_ButtonIconSize:
- return 16;
+ val = 16;
+ break;
case PM_DockWidgetTitleBarButtonMargin:
- return 2;
+ val = 2;
+ break;
case PM_MaximumDragDistance:
- return -1;
+ val = -1;
+ break;
case PM_TabCloseIndicatorWidth:
case PM_TabCloseIndicatorHeight:
- return 20;
+ val = 20;
+ break;
case PM_TabBarTabVSpace:
- return 12;
+ val = 12;
+ break;
case PM_TabBarTabOverlap:
- return 1;
+ val = 1;
+ break;
case PM_TabBarBaseOverlap:
- return 2;
+ val = 2;
+ break;
case PM_SubMenuOverlap:
- return -1;
+ val = -1;
+ break;
case PM_DockWidgetHandleExtent:
case PM_SplitterWidth:
- return 4;
+ val = 4;
+ break;
case PM_IndicatorHeight:
case PM_IndicatorWidth:
case PM_ExclusiveIndicatorHeight:
case PM_ExclusiveIndicatorWidth:
- return 14;
+ val = 14;
+ break;
case PM_ScrollView_ScrollBarSpacing:
- return 0;
+ val = 0;
+ break;
case PM_ScrollView_ScrollBarOverlap:
if (proxy()->styleHint(SH_ScrollBar_Transient, option, widget))
return proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
- return 0;
- default:
+ val = 0;
break;
+ case PM_DefaultFrameWidth:
+ return 1; // Do not dpi-scale because the drawn frame is always exactly 1 pixel thick
+ break;
+ default:
+ return QCommonStyle::pixelMetric(metric, option, widget);
}
- return QCommonStyle::pixelMetric(metric, option, widget);
+ return QStyleHelper::dpiScaled(val);
}
/*!
@@ -3309,14 +3336,15 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
break;
case SC_SliderGroove: {
QPoint grooveCenter = slider->rect.center();
+ const int grooveThickness = QStyleHelper::dpiScaled(7);
if (slider->orientation == Qt::Horizontal) {
- rect.setHeight(7);
+ rect.setHeight(grooveThickness);
if (slider->tickPosition & QSlider::TicksAbove)
grooveCenter.ry() += tickSize;
if (slider->tickPosition & QSlider::TicksBelow)
grooveCenter.ry() -= tickSize;
} else {
- rect.setWidth(7);
+ rect.setWidth(grooveThickness);
if (slider->tickPosition & QSlider::TicksAbove)
grooveCenter.rx() += tickSize;
if (slider->tickPosition & QSlider::TicksBelow)
@@ -3332,27 +3360,25 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
break;
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- QSize bs;
int center = spinbox->rect.height() / 2;
- int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth
int y = fw;
- bs.setHeight(qMax(8, spinbox->rect.height()/2 - y));
- bs.setWidth(14);
+ const int buttonWidth = QStyleHelper::dpiScaled(14);
int x, lx, rx;
- x = spinbox->rect.width() - y - bs.width() + 2;
+ x = spinbox->rect.width() - y - buttonWidth + 2;
lx = fw;
rx = x - fw;
switch (subControl) {
case SC_SpinBoxUp:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- rect = QRect(x, fw, bs.width(), center - fw);
+ rect = QRect(x, fw, buttonWidth, center - fw);
break;
case SC_SpinBoxDown:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - fw + 1);
+ rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1);
break;
case SC_SpinBoxEditField:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index b3c0463bca..531f538820 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -152,13 +152,32 @@ static uint qHash(const QPointer<QObject> &ptr)
return qHash(ptr.data());
}
-// These colors specify the titlebar gradient colors on
-// Leopard. Ideally we should get them from the system.
-static const QColor titlebarGradientActiveBegin(220, 220, 220);
-static const QColor titlebarGradientActiveEnd(151, 151, 151);
+// Title bar gradient colors for Lion were determined by inspecting PSDs exported
+// using CoreUI's CoreThemeDocument; there is no public API to retrieve them
+
+static QLinearGradient titlebarGradientActive()
+{
+ static QLinearGradient gradient;
+ if (gradient == QLinearGradient()) {
+ gradient.setColorAt(0, QColor(235, 235, 235));
+ gradient.setColorAt(0.5, QColor(210, 210, 210));
+ gradient.setColorAt(0.75, QColor(195, 195, 195));
+ gradient.setColorAt(1, QColor(180, 180, 180));
+ }
+ return gradient;
+}
+
+static QLinearGradient titlebarGradientInactive()
+{
+ static QLinearGradient gradient;
+ if (gradient == QLinearGradient()) {
+ gradient.setColorAt(0, QColor(250, 250, 250));
+ gradient.setColorAt(1, QColor(225, 225, 225));
+ }
+ return gradient;
+}
+
static const QColor titlebarSeparatorLineActive(111, 111, 111);
-static const QColor titlebarGradientInactiveBegin(241, 241, 241);
-static const QColor titlebarGradientInactiveEnd(207, 207, 207);
static const QColor titlebarSeparatorLineInactive(131, 131, 131);
// Gradient colors used for the dock widget title bar and
@@ -526,25 +545,6 @@ public:
};
} // anonymous namespace
-static QColor qcolorFromCGColor(CGColorRef cgcolor)
-{
- QColor pc;
- CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
- const CGFloat *components = CGColorGetComponents(cgcolor);
- if (model == kCGColorSpaceModelRGB) {
- pc.setRgbF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelCMYK) {
- pc.setCmykF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelMonochrome) {
- pc.setRgbF(components[0], components[0], components[0], components[1]);
- } else {
- // Colorspace we can't deal with.
- qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
- Q_ASSERT(false);
- }
- return pc;
-}
-
OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon)
{
QRegion *region = static_cast<QRegion *>(inRefcon);
@@ -702,7 +702,6 @@ static bool qt_macWindowMainWindow(const QWidget *window)
const int qt_mac_hitheme_version = 0; //the HITheme version we speak
const int macItemFrame = 2; // menu item frame width
const int macItemHMargin = 3; // menu item hor text margin
-const int macItemVMargin = 2; // menu item ver text margin
const int macRightBorder = 12; // right border on mac
const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar.
QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background.
@@ -3150,7 +3149,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
[triangleCell setButtonType:NSOnOffButton];
[triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState];
[triangleCell setBezelStyle:NSDisclosureBezelStyle];
- [triangleCell setBackgroundStyle:((opt->state & State_Selected) && w->hasFocus()) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
+ bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
+ [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
CGContextSaveGState(cg);
[NSGraphicsContext saveGraphicsState];
@@ -3263,14 +3263,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} break;
case PE_PanelStatusBar: {
// Fill the status bar with the titlebar gradient.
- QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom());
+ QLinearGradient linearGrad;
if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) {
- linearGrad.setColorAt(0, titlebarGradientActiveBegin);
- linearGrad.setColorAt(1, titlebarGradientActiveEnd);
+ linearGrad = titlebarGradientActive();
} else {
- linearGrad.setColorAt(0, titlebarGradientInactiveBegin);
- linearGrad.setColorAt(1, titlebarGradientInactiveEnd);
+ linearGrad = titlebarGradientInactive();
}
+
+ linearGrad.setStart(0, opt->rect.top());
+ linearGrad.setFinalStop(0, opt->rect.bottom());
p->fillRect(opt->rect, linearGrad);
// Draw the black separator line at the top of the status bar.
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 4c5c7cd17e..8774d71c0c 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1784,6 +1784,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_LineEdit_PasswordCharacter The Unicode character to be
used for passwords.
+ \value SH_LineEdit_PasswordMaskDelay Determines the delay before visible character is masked
+ with password character, in milliseconds. This enum value was added in Qt 5.4.
+
\value SH_Table_GridLineColor The RGB value of the grid for a table.
\value SH_UnderlineShortcut Whether shortcuts are underlined.
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index 136daa9abd..ea012faf46 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -703,6 +703,7 @@ public:
SH_Widget_Animate,
SH_Splitter_OpaqueResize,
SH_ComboBox_UseNativePopup,
+ SH_LineEdit_PasswordMaskDelay,
// Add new style hint values here
SH_CustomBase = 0xf0000000
diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp
index 85dc357ab5..e6e47a98e9 100644
--- a/src/widgets/styles/qstyleanimation.cpp
+++ b/src/widgets/styles/qstyleanimation.cpp
@@ -50,7 +50,7 @@ static const qreal ScrollBarFadeOutDuration = 200.0;
static const qreal ScrollBarFadeOutDelay = 450.0;
QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(target),
- _delay(0), _duration(-1), _startTime(QTime::currentTime())
+ _delay(0), _duration(-1), _startTime(QTime::currentTime()), _fps(ThirtyFps), _skip(0)
{
}
@@ -93,6 +93,16 @@ void QStyleAnimation::setStartTime(const QTime &time)
_startTime = time;
}
+QStyleAnimation::FrameRate QStyleAnimation::frameRate() const
+{
+ return _fps;
+}
+
+void QStyleAnimation::setFrameRate(FrameRate fps)
+{
+ _fps = fps;
+}
+
void QStyleAnimation::updateTarget()
{
QEvent event(QEvent::StyleAnimationUpdate);
@@ -102,6 +112,12 @@ void QStyleAnimation::updateTarget()
stop();
}
+void QStyleAnimation::start()
+{
+ _skip = 0;
+ QAbstractAnimation::start(DeleteWhenStopped);
+}
+
bool QStyleAnimation::isUpdateNeeded() const
{
return currentTime() > _delay;
@@ -109,8 +125,11 @@ bool QStyleAnimation::isUpdateNeeded() const
void QStyleAnimation::updateCurrentTime(int)
{
- if (target() && isUpdateNeeded())
- updateTarget();
+ if (++_skip >= _fps) {
+ _skip = 0;
+ if (target() && isUpdateNeeded())
+ updateTarget();
+ }
}
QProgressStyleAnimation::QProgressStyleAnimation(int speed, QObject *target) :
diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h
index c344858812..19e629cb25 100644
--- a/src/widgets/styles/qstyleanimation_p.h
+++ b/src/widgets/styles/qstyleanimation_p.h
@@ -78,8 +78,21 @@ public:
QTime startTime() const;
void setStartTime(const QTime &time);
+ enum FrameRate {
+ DefaultFps,
+ SixtyFps,
+ ThirtyFps,
+ TwentyFps
+ };
+
+ FrameRate frameRate() const;
+ void setFrameRate(FrameRate fps);
+
void updateTarget();
+public Q_SLOTS:
+ void start();
+
protected:
virtual bool isUpdateNeeded() const;
virtual void updateCurrentTime(int time);
@@ -88,6 +101,8 @@ private:
int _delay;
int _duration;
QTime _startTime;
+ FrameRate _fps;
+ int _skip;
};
class QProgressStyleAnimation : public QStyleAnimation
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 5913b2f261..f642a05d13 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -3702,6 +3702,8 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
of the painter used to draw the item. By default, if no
transformations are applied, its value is 1. If zoomed out 1:2, the level
of detail will be 0.5, and if zoomed in 2:1, its value is 2.
+
+ \sa QGraphicsScene::minimumRenderSize()
*/
qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform)
{
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 60bfc8e075..b82aa1b5a0 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -645,6 +645,7 @@ static const char *knownStyleHints[] = {
"icon-size",
"leftarrow-icon",
"lineedit-password-character",
+ "lineedit-password-mask-delay",
"mdi-fill-space-on-maximize",
"menu-scrollable",
"menubar-altkey-navigation",
@@ -5143,6 +5144,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
QString s;
switch (sh) {
case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break;
+ case SH_LineEdit_PasswordMaskDelay: s = QLatin1String("lineedit-password-mask-delay"); break;
case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break;
case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break;
case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break;
@@ -5804,6 +5806,25 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
break;
#endif //QT_NO_TOOLBAR
+ // On mac we make pixel adjustments to layouts which are not
+ // desireable when you have custom style sheets on them
+ case SE_CheckBoxLayoutItem:
+ case SE_ComboBoxLayoutItem:
+ case SE_DateTimeEditLayoutItem:
+ case SE_LabelLayoutItem:
+ case SE_ProgressBarLayoutItem:
+ case SE_PushButtonLayoutItem:
+ case SE_RadioButtonLayoutItem:
+ case SE_SliderLayoutItem:
+ case SE_SpinBoxLayoutItem:
+ case SE_ToolButtonLayoutItem:
+ case SE_FrameLayoutItem:
+ case SE_GroupBoxLayoutItem:
+ case SE_TabWidgetLayoutItem:
+ if (!rule.hasNativeBorder())
+ return opt->rect;
+ break;
+
default:
break;
}
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index bc78ea3296..e3699da7ef 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -1421,15 +1421,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
break;
case CE_DockWidgetTitle:
- if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
+ if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
+ const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget);
QRect rect = option->rect;
- if (dockWidget->isFloating()) {
+ if (dockWidget && dockWidget->isFloating()) {
QWindowsXPStyle::drawControl(element, option, painter, widget);
break; //otherwise fall through
}
- if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
-
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
@@ -1490,7 +1489,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
}
break;
- }
#ifndef QT_NO_ITEMVIEWS
case CE_ItemViewItem:
{
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index b0cd4a9540..a372a7fe0d 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -101,6 +101,8 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
copy->setButtons(me->buttons());
copy->setButton(me->button());
copy->setModifiers(me->modifiers());
+ copy->setSource(me->source());
+ copy->setFlags(me->flags());
return copy;
#endif
}
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index f1a69e6b36..fa318f3233 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -672,6 +672,74 @@ void QBalloonTip::timerEvent(QTimerEvent *e)
QWidget::timerEvent(e);
}
+//////////////////////////////////////////////////////////////////////
+void QSystemTrayIconPrivate::install_sys_qpa()
+{
+ qpa_sys->init();
+ QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
+ q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
+ QObject::connect(qpa_sys, &QPlatformSystemTrayIcon::messageClicked,
+ q_func(), &QSystemTrayIcon::messageClicked);
+ updateMenu_sys();
+ updateIcon_sys();
+ updateToolTip_sys();
+}
+
+void QSystemTrayIconPrivate::remove_sys_qpa()
+{
+ qpa_sys->cleanup();
+}
+
+QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
+{
+ return qpa_sys->geometry();
+}
+
+void QSystemTrayIconPrivate::updateIcon_sys_qpa()
+{
+ qpa_sys->updateIcon(icon);
+}
+
+void QSystemTrayIconPrivate::updateMenu_sys_qpa()
+{
+ if (menu) {
+ if (!menu->platformMenu()) {
+ QPlatformMenu *platformMenu = qpa_sys->createMenu();
+ if (platformMenu)
+ menu->setPlatformMenu(platformMenu);
+ }
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
+}
+
+void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
+{
+ qpa_sys->updateToolTip(toolTip);
+}
+
+void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &message,
+ const QString &title,
+ QSystemTrayIcon::MessageIcon icon,
+ int msecs)
+{
+ QIcon notificationIcon;
+ switch (icon) {
+ case QSystemTrayIcon::Information:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
+ break;
+ case QSystemTrayIcon::Warning:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
+ break;
+ case QSystemTrayIcon::Critical:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
+ break;
+ default:
+ break;
+ }
+ qpa_sys->showMessage(message, title, notificationIcon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 211ef308f1..317664a365 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -98,6 +98,15 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
+
+private:
+ void install_sys_qpa();
+ void remove_sys_qpa();
+ void updateIcon_sys_qpa();
+ void updateToolTip_sys_qpa();
+ void updateMenu_sys_qpa();
+ QRect geometry_sys_qpa() const;
+ void showMessage_sys_qpa(const QString &msg, const QString &title, QSystemTrayIcon::MessageIcon icon, int secs);
};
class QBalloonTip : public QWidget
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index f98aeaf678..045641c509 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -65,28 +65,20 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
- if (qpa_sys) {
- qpa_sys->init();
- QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
- q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
- QObject::connect(qpa_sys, SIGNAL(messageClicked()),
- q_func(), SIGNAL(messageClicked()));
- updateMenu_sys();
- updateIcon_sys();
- updateToolTip_sys();
- }
+ if (qpa_sys)
+ install_sys_qpa();
}
void QSystemTrayIconPrivate::remove_sys()
{
if (qpa_sys)
- qpa_sys->cleanup();
+ remove_sys_qpa();
}
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return qpa_sys->geometry();
+ return geometry_sys_qpa();
else
return QRect();
}
@@ -94,25 +86,19 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys)
- qpa_sys->updateIcon(icon);
+ updateIcon_sys_qpa();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys && menu) {
- if (!menu->platformMenu()) {
- QPlatformMenu *platformMenu = qpa_sys->createMenu();
- if (platformMenu)
- menu->setPlatformMenu(platformMenu);
- }
- qpa_sys->updateMenu(menu->platformMenu());
- }
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys)
- qpa_sys->updateToolTip(toolTip);
+ updateToolTip_sys_qpa();
}
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
@@ -138,25 +124,8 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &message,
QSystemTrayIcon::MessageIcon icon,
int msecs)
{
- if (!qpa_sys)
- return;
-
- QIcon notificationIcon;
- switch (icon) {
- case QSystemTrayIcon::Information:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::Warning:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- default:
- break;
- }
- qpa_sys->showMessage(message, title, notificationIcon,
- static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+ if (qpa_sys)
+ showMessage_sys_qpa(message, title, icon, msecs);
}
QT_END_NAMESPACE
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 21ce23437f..e7007e4091 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -55,6 +55,9 @@
#include <qscreen.h>
#include <qbackingstore.h>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformsystemtrayicon.h>
+#include <qpa/qplatformtheme.h>
+#include <private/qguiapplication_p.h>
#include <qdebug.h>
#ifndef QT_NO_SYSTEMTRAYICON
@@ -101,11 +104,24 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setObjectName(QStringLiteral("QSystemTrayIconSys"));
setToolTip(q->toolTip());
setAttribute(Qt::WA_AlwaysShowToolTips, true);
- setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_QuitOnClose, false);
const QSize size(22, 22); // Gnome, standard size
setGeometry(QRect(QPoint(0, 0), size));
setMinimumSize(size);
+
+ // We need two different behaviors depending on whether the X11 visual for the system tray
+ // (a) exists and (b) supports an alpha channel, i.e. is 32 bits.
+ // If we have a visual that has an alpha channel, we can paint this widget with a transparent
+ // background and it will work.
+ // However, if there's no alpha channel visual, in order for transparent tray icons to work,
+ // we do not have a transparent background on the widget, but call xcb_clear_region before
+ // painting the icon
+ bool hasAlphaChannel = false;
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "systrayVisualHasAlphaChannel", Qt::DirectConnection,
+ Q_RETURN_ARG(bool, hasAlphaChannel));
+ setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel);
+
addToTray();
}
@@ -196,12 +212,21 @@ bool QSystemTrayIconSys::event(QEvent *e)
void QSystemTrayIconSys::paintEvent(QPaintEvent *)
{
- // Note: Transparent pixels require a particular Visual which XCB
- // currently does not support yet.
const QRect rect(QPoint(0, 0), geometry().size());
QPainter painter(this);
- painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(rect, Qt::transparent);
+
+ // If we have Qt::WA_TranslucentBackground set, during widget creation
+ // we detected the systray visual supported an alpha channel
+ if (testAttribute(Qt::WA_TranslucentBackground)) {
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(rect, Qt::transparent);
+ } else {
+ QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "clearRegion", Qt::DirectConnection,
+ Q_ARG(const QWindow *, windowHandle()),
+ Q_ARG(const QRect&, rect)
+ );
+ }
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
q->icon().paint(&painter, rect);
}
@@ -215,16 +240,22 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *)
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
+ qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
visible(false)
{
}
QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
{
+ delete qpa_sys;
}
void QSystemTrayIconPrivate::install_sys()
{
+ if (qpa_sys) {
+ install_sys_qpa();
+ return;
+ }
Q_Q(QSystemTrayIcon);
if (!sys && locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
@@ -235,6 +266,8 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
+ if (qpa_sys)
+ return geometry_sys_qpa();
if (!sys)
return QRect();
return sys->globalGeometry();
@@ -242,6 +275,10 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::remove_sys()
{
+ if (qpa_sys) {
+ remove_sys_qpa();
+ return;
+ }
if (!sys)
return;
QBalloonTip::hideBalloon();
@@ -252,17 +289,26 @@ void QSystemTrayIconPrivate::remove_sys()
void QSystemTrayIconPrivate::updateIcon_sys()
{
+ if (qpa_sys) {
+ updateIcon_sys_qpa();
+ return;
+ }
if (sys)
sys->updateIcon();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
-
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
+ if (qpa_sys) {
+ updateToolTip_sys_qpa();
+ return;
+ }
if (!sys)
return;
#ifndef QT_NO_TOOLTIP
@@ -272,6 +318,11 @@ void QSystemTrayIconPrivate::updateToolTip_sys()
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->isSystemTrayAvailable();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
const QString platform = QGuiApplication::platformName();
if (platform.compare(QStringLiteral("xcb"), Qt::CaseInsensitive) == 0)
return locateSystemTray();
@@ -280,12 +331,21 @@ bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
bool QSystemTrayIconPrivate::supportsMessages_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->supportsMessages();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
return true;
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title,
QSystemTrayIcon::MessageIcon icon, int msecs)
{
+ if (qpa_sys) {
+ showMessage_sys_qpa(message, title, icon, msecs);
+ return;
+ }
if (!sys)
return;
const QPoint g = sys->globalGeometry().topLeft();
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index b12e2836d4..d819436f66 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -9,8 +9,7 @@ win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
MODULE_PLUGIN_TYPES += \
- styles \
- accessible/libqtaccessiblewidgets.so
+ styles
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 98e715fc62..1b48441993 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -1191,6 +1191,10 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e)
case QEvent::DragMove:
case QEvent::DragLeave:
#endif
+ // QOpenGLWidget needs special support because it has to know
+ // its size has changed, so that it can resize its fbo.
+ if (e->type() == QEvent::Resize)
+ QWidgetPrivate::get(viewport())->resizeViewportFramebuffer();
return QFrame::event(e);
case QEvent::LayoutRequest:
#ifndef QT_NO_GESTURES
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 92af91b66e..43f5d6fd31 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -315,6 +315,8 @@ void QAbstractSpinBox::setReadOnly(bool enable)
Q_D(QAbstractSpinBox);
d->readOnly = enable;
d->edit->setReadOnly(enable);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
update();
}
diff --git a/src/widgets/widgets/qcheckbox.h b/src/widgets/widgets/qcheckbox.h
index 9adf5f6567..db6be7d1c0 100644
--- a/src/widgets/widgets/qcheckbox.h
+++ b/src/widgets/widgets/qcheckbox.h
@@ -86,6 +86,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QCheckBox)
Q_DISABLE_COPY(QCheckBox)
+ friend class QAccessibleButton;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 066b3c7a86..5a40ceb2f7 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -44,6 +44,7 @@
#include "QtWidgets/qtabbar.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qdesktopwidget.h"
+#include "QtWidgets/qapplication.h"
#include "QtCore/qvariant.h"
#include "qdockarealayout_p.h"
#include "qdockwidget.h"
@@ -2978,8 +2979,9 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
item.widgetItem = new QDockWidgetItem(dockWidget);
if (placeHolder->window) {
- QDesktopWidget desktop;
- QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
+ const QRect screenGeometry =
+ QApplication::desktop()->screenGeometry(placeHolder->topLevelRect.center());
+ const QRect r = constrainedRect(placeHolder->topLevelRect, screenGeometry);
dockWidget->d_func()->setWindowState(true, true, r);
}
dockWidget->setVisible(!placeHolder->hidden);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index ad9481a928..3efa89edb3 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -591,10 +591,6 @@ void QDockWidgetPrivate::init()
QObject::connect(button, SIGNAL(clicked()), q, SLOT(close()));
layout->setWidgetForRole(QDockWidgetLayout::CloseButton, button);
- resizer = new QWidgetResizeHandler(q);
- resizer->setMovingEnabled(false);
- resizer->setActive(false);
-
#ifndef QT_NO_ACTION
toggleViewAction = new QAction(q);
toggleViewAction->setCheckable(true);
@@ -760,13 +756,12 @@ void QDockWidgetPrivate::endDrag(bool abort)
Qt::WindowFlags flags = q->windowFlags();
flags &= ~Qt::X11BypassWindowManagerHint;
q->setWindowFlags(flags);
- resizer->setActive(QWidgetResizeHandler::Resize, true);
+ setResizerActive(true);
q->show();
} else {
QDockWidgetLayout *myLayout
= qobject_cast<QDockWidgetLayout*>(layout);
- resizer->setActive(QWidgetResizeHandler::Resize,
- myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
+ setResizerActive(myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
}
undockedGeometry = q->geometry();
q->activateWindow();
@@ -779,6 +774,17 @@ void QDockWidgetPrivate::endDrag(bool abort)
state = 0;
}
+void QDockWidgetPrivate::setResizerActive(bool active)
+{
+ Q_Q(QDockWidget);
+ if (active && !resizer) {
+ resizer = new QWidgetResizeHandler(q);
+ resizer->setMovingEnabled(false);
+ }
+ if (resizer)
+ resizer->setActive(QWidgetResizeHandler::Resize, active);
+}
+
bool QDockWidgetPrivate::isAnimating() const
{
Q_Q(const QDockWidget);
@@ -1052,7 +1058,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
}
}
- resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco);
+ setResizerActive(!unplug && floating && !nativeDeco);
}
/*!
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index f7cd8c0039..a4dc68dd7d 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -88,7 +88,7 @@ public:
features(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable),
- allowedAreas(Qt::AllDockWidgetAreas)
+ allowedAreas(Qt::AllDockWidgetAreas), resizer(0)
{ }
void init();
@@ -101,8 +101,6 @@ public:
QDockWidget::DockWidgetFeatures features;
Qt::DockWidgetAreas allowedAreas;
- QWidgetResizeHandler *resizer;
-
#ifndef QT_NO_ACTION
QAction *toggleViewAction;
#endif
@@ -124,8 +122,12 @@ public:
void unplug(const QRect &rect);
void plug(const QRect &rect);
+ void setResizerActive(bool active);
bool isAnimating() const;
+
+private:
+ QWidgetResizeHandler *resizer;
};
class Q_WIDGETS_EXPORT QDockWidgetLayout : public QLayout
diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp
index 168f0bbd67..42b0c68971 100644
--- a/src/widgets/widgets/qgroupbox.cpp
+++ b/src/widgets/widgets/qgroupbox.cpp
@@ -405,6 +405,8 @@ void QGroupBox::childEvent(QChildEvent *c)
if (c->type() != QEvent::ChildAdded || !c->child()->isWidgetType())
return;
QWidget *w = (QWidget*)c->child();
+ if (w->isWindow())
+ return;
if (d->checkable) {
if (d->checked) {
if (!w->testAttribute(Qt::WA_ForceDisabled))
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index ba4dbcc878..b6b7ffb1a2 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1348,6 +1348,8 @@ void QLineEdit::setReadOnly(bool enable)
#ifndef QT_NO_CURSOR
setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
+ QEvent event(QEvent::ReadOnlyChange);
+ QCoreApplication::sendEvent(this, &event);
update();
}
}
@@ -2188,6 +2190,7 @@ void QLineEdit::changeEvent(QEvent *ev)
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
+ d->control->setPasswordMaskDelay(style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, this));
}
d->m_iconSize = QSize();
update();
diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h
index 3d52863db2..d53437c479 100644
--- a/src/widgets/widgets/qlineedit.h
+++ b/src/widgets/widgets/qlineedit.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -261,6 +261,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &))
Q_PRIVATE_SLOT(d_func(), void _q_textChanged(const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_clearButtonClicked())
};
#endif // QT_NO_LINEEDIT
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 10689b2fc3..7ad893a54e 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -205,6 +205,7 @@ void QLineEditPrivate::init(const QString& txt)
QStyleOptionFrameV2 opt;
q->initStyleOption(&opt);
control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q));
+ control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
#ifndef QT_NO_CURSOR
q->setCursor(Qt::IBeamCursor);
#endif
@@ -372,6 +373,15 @@ void QLineEditPrivate::_q_textChanged(const QString &text)
}
}
+void QLineEditPrivate::_q_clearButtonClicked()
+{
+ Q_Q(QLineEdit);
+ if (!q->text().isEmpty()) {
+ q->clear();
+ emit q->textEdited(QString());
+ }
+}
+
QSize QLineEditPrivate::iconSize() const
{
if (!m_iconSize.isValid()) // This might require style-specific handling (pixel metric).
@@ -447,7 +457,7 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
toolButton->setIcon(newAction->icon());
toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0);
if (flags & SideWidgetClearButton)
- QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(clear()));
+ QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(_q_clearButtonClicked()));
toolButton->setDefaultAction(newAction);
w = toolButton;
}
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index db8edee005..08365521d5 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -195,6 +195,7 @@ public:
void drag();
#endif
void _q_textChanged(const QString &);
+ void _q_clearButtonClicked();
int leftTextMargin; // use effectiveLeftTextMargin() in case of icon.
int topTextMargin;
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 36ca90ba00..79f42a13ed 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -468,6 +468,10 @@ void QMainWindow::setIconSize(const QSize &iconSize)
/*! \property QMainWindow::toolButtonStyle
\brief style of toolbar buttons in this mainwindow.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
+
The default is Qt::ToolButtonIconOnly.
*/
diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h
index 8411bf9f6b..6c392ca4cc 100644
--- a/src/widgets/widgets/qmainwindow.h
+++ b/src/widgets/widgets/qmainwindow.h
@@ -155,7 +155,6 @@ public:
void removeToolBar(QToolBar *toolbar);
void removeToolBarBreak(QToolBar *before);
- void setUnifiedTitleAndToolBarOnMac(bool set);
bool unifiedTitleAndToolBarOnMac() const;
Qt::ToolBarArea toolBarArea(QToolBar *toolbar) const;
@@ -182,12 +181,14 @@ public:
virtual QMenu *createPopupMenu();
#endif
-
-#ifndef QT_NO_DOCKWIDGET
public Q_SLOTS:
+#ifndef QT_NO_DOCKWIDGET
void setAnimated(bool enabled);
void setDockNestingEnabled(bool enabled);
#endif
+#ifndef QT_NO_TOOLBAR
+ void setUnifiedTitleAndToolBarOnMac(bool set);
+#endif
Q_SIGNALS:
void iconSizeChanged(const QSize &iconSize);
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index c026b79103..757d70c64b 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -62,7 +62,10 @@
#include <qmap.h>
#include <qtimer.h>
-#include <qdebug.h>
+#ifndef QT_NO_DEBUG_STREAM
+# include <qdebug.h>
+# include <qtextstream.h>
+#endif
#include <private/qapplication_p.h>
#include <private/qlayoutengine_p.h>
@@ -71,23 +74,17 @@
# include <private/qt_cocoa_helpers_mac_p.h>
#endif
-#ifdef QT_NO_DOCKWIDGET
-extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
-#endif
+QT_BEGIN_NAMESPACE
-#ifdef Q_DEBUG_MAINWINDOW_LAYOUT
-# include <QTextStream>
+#ifndef QT_NO_DOCKWIDGET
+extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
#endif
-QT_BEGIN_NAMESPACE
-
/******************************************************************************
** debug
*/
-#if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
-
-static QTextStream qout(stderr, QIODevice::WriteOnly);
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_DEBUG_STREAM)
static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
@@ -101,7 +98,7 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QStri
if (item.widgetItem != 0) {
qout << indent << "widget: "
<< item.widgetItem->widget()->metaObject()->className()
- << ' ' << item.widgetItem->widget()->windowTitle() << '\n';
+ << " \"" << item.widgetItem->widget()->windowTitle() << "\"\n";
} else if (item.subinfo != 0) {
qout << indent << "subinfo:\n";
dumpLayout(qout, *item.subinfo, indent + QLatin1String(" "));
@@ -117,16 +114,17 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QStri
<< " rect:" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << '\n';
}
- qout.flush();
}
static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
{
+ const QSize minSize = layout.minimumSize();
qout << indent << "QDockAreaLayoutInfo: "
<< layout.rect.left() << ','
<< layout.rect.top() << ' '
<< layout.rect.width() << 'x'
<< layout.rect.height()
+ << " min size: " << minSize.width() << ',' << minSize.height()
<< " orient:" << layout.o
<< " tabbed:" << layout.tabbed
<< " tbshape:" << layout.tabBarShape << '\n';
@@ -137,36 +135,42 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QSt
qout << indent << "Item: " << i << '\n';
dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String(" "));
}
- qout.flush();
-};
+}
-static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent)
+static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout)
{
- qout << indent << "QDockAreaLayout: "
+ qout << "QDockAreaLayout: "
<< layout.rect.left() << ','
<< layout.rect.top() << ' '
<< layout.rect.width() << 'x'
<< layout.rect.height() << '\n';
- qout << indent << "TopDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String(" "));
- qout << indent << "LeftDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String(" "));
- qout << indent << "RightDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String(" "));
- qout << indent << "BottomDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String(" "));
+ qout << "TopDockArea:\n";
+ dumpLayout(qout, layout.docks[QInternal::TopDock], QLatin1String(" "));
+ qout << "LeftDockArea:\n";
+ dumpLayout(qout, layout.docks[QInternal::LeftDock], QLatin1String(" "));
+ qout << "RightDockArea:\n";
+ dumpLayout(qout, layout.docks[QInternal::RightDock], QLatin1String(" "));
+ qout << "BottomDockArea:\n";
+ dumpLayout(qout, layout.docks[QInternal::BottomDock], QLatin1String(" "));
+}
- qout.flush();
-};
+QDebug operator<<(QDebug debug, const QDockAreaLayout &layout)
+{
+ QString s;
+ QTextStream str(&s);
+ dumpLayout(str, layout);
+ debug << s;
+ return debug;
+}
-void qt_dumpLayout(QTextStream &qout, QMainWindow *window)
+QDebug operator<<(QDebug debug, const QMainWindowLayout *layout)
{
- QMainWindowLayout *layout = qt_mainwindow_layout(window);
- dumpLayout(qout, layout->layoutState.dockAreaLayout, QString());
+ debug << layout->layoutState.dockAreaLayout;
+ return debug;
}
-#endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
+#endif // !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_DEBUG)
/******************************************************************************
** QMainWindowLayoutState
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index f866a554dc..4b578e94b7 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -68,15 +68,6 @@
#include "qdockarealayout_p.h"
#include "qtoolbararealayout_p.h"
-//#define Q_DEBUG_MAINWINDOW_LAYOUT
-
-#if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
-QT_BEGIN_NAMESPACE
-class QTextStream;
-Q_WIDGETS_EXPORT void qt_dumpLayout(QTextStream &qout, QMainWindow *window);
-QT_END_NAMESPACE
-#endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
-
#ifdef Q_WS_MAC
// Forward defs to make avoid including Carbon.h (faster compile you know ;).
struct OpaqueHIObjectRef;
@@ -344,6 +335,13 @@ public:
#endif // Q_WS_MAC
};
+
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_DEBUG_STREAM)
+class QDebug;
+QDebug operator<<(QDebug debug, const QDockAreaLayout &layout);
+QDebug operator<<(QDebug debug, const QMainWindowLayout *layout);
+#endif
+
QT_END_NAMESPACE
#endif // QT_NO_MAINWINDOW
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 17f73b2809..beabaa87da 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -169,7 +169,7 @@
#include <QResizeEvent>
#include <QScrollBar>
#include <QtAlgorithms>
-#include <QMutableListIterator>
+#include <QMutableVectorIterator>
#include <QPainter>
#include <QFontMetrics>
#include <QStyleOption>
@@ -413,7 +413,7 @@ void IconTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const
\internal
Calculates the accumulated overlap (intersection area) between 'source' and 'rects'.
*/
-int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect> &rects)
+int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRect> &rects)
{
int accOverlap = 0;
foreach (const QRect &rect, rects) {
@@ -429,7 +429,7 @@ int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect>
Finds among 'source' the rectangle with the minimum accumulated overlap with the
rectangles in 'rects'.
*/
-QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects)
+QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects)
{
int minAccOverlap = -1;
QRect minAccOverlapRect;
@@ -447,28 +447,37 @@ QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QLi
\internal
Gets candidates for the final placement.
*/
-void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRect> &rects,
- const QRect &domain,QList<QRect> &candidates)
+QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QVector<QRect> &rects,
+ const QRect &domain)
{
- QSet<int> xset;
- QSet<int> yset;
- xset << domain.left() << domain.right() - size.width() + 1;
- yset << domain.top();
+ QVector<QRect> result;
+
+ QVector<int> xlist;
+ xlist.reserve(2 + rects.size());
+ xlist << domain.left() << domain.right() - size.width() + 1;
+
+ QVector<int> ylist;
+ ylist.reserve(2 + rects.size());
+ ylist << domain.top();
if (domain.bottom() - size.height() + 1 >= 0)
- yset << domain.bottom() - size.height() + 1;
+ ylist << domain.bottom() - size.height() + 1;
+
foreach (const QRect &rect, rects) {
- xset << rect.right() + 1;
- yset << rect.bottom() + 1;
+ xlist << rect.right() + 1;
+ ylist << rect.bottom() + 1;
}
- QList<int> xlist = xset.values();
std::sort(xlist.begin(), xlist.end());
- QList<int> ylist = yset.values();
+ xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());
+
std::sort(ylist.begin(), ylist.end());
+ ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());
+ result.reserve(ylist.size() * xlist.size());
foreach (int y, ylist)
foreach (int x, xlist)
- candidates << QRect(QPoint(x, y), size);
+ result << QRect(QPoint(x, y), size);
+ return result;
}
/*!
@@ -476,10 +485,12 @@ void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRe
Finds all rectangles in 'source' not completely inside 'domain'. The result is stored
in 'result' and also removed from 'source'.
*/
-void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)
{
- QMutableListIterator<QRect> it(source);
+ QVector<QRect> result;
+ result.reserve(source.size());
+
+ QMutableVectorIterator<QRect> it(source);
while (it.hasNext()) {
const QRect srcRect = it.next();
if (!domain.contains(srcRect)) {
@@ -487,6 +498,8 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
it.remove();
}
}
+
+ return result;
}
/*!
@@ -494,9 +507,11 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
Finds all rectangles in 'source' that overlaps 'domain' by the maximum overlap area
between 'domain' and any rectangle in 'source'. The result is stored in 'result'.
*/
-void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QVector<QRect> &source)
{
+ QVector<QRect> result;
+ result.reserve(source.size());
+
int maxOverlap = -1;
foreach (const QRect &srcRect, source) {
QRect intersection = domain.intersected(srcRect);
@@ -509,6 +524,8 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
result << srcRect;
}
}
+
+ return result;
}
/*!
@@ -517,17 +534,15 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
placement that overlaps the rectangles in 'rects' as little as possible while at the
same time being as much as possible inside 'domain'.
*/
-QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRect> &rects,
- QList<QRect> &source)
+QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QRect> &rects,
+ QVector<QRect> &source)
{
- QList<QRect> nonInsiders;
- findNonInsiders(domain, source, nonInsiders);
+ const QVector<QRect> nonInsiders = findNonInsiders(domain, source);
if (!source.empty())
return findMinOverlapRect(source, rects).topLeft();
- QList<QRect> maxOverlappers;
- findMaxOverlappers(domain, nonInsiders, maxOverlappers);
+ QVector<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);
return findMinOverlapRect(maxOverlappers, rects).topLeft();
}
@@ -538,7 +553,7 @@ QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRec
overlaps 'rects' as little as possible and 'domain' as much as possible.
Returns the position of the resulting rectangle.
*/
-QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
+QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,
const QRect &domain) const
{
if (size.isEmpty() || !domain.isValid())
@@ -548,8 +563,7 @@ QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
return QPoint();
}
- QList<QRect> candidates;
- getCandidatePlacements(size, rects, domain, candidates);
+ QVector<QRect> candidates = getCandidatePlacements(size, rects, domain);
return findBestPlacement(domain, rects, candidates);
}
@@ -882,7 +896,8 @@ void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child)
return;
}
- QList<QRect> rects;
+ QVector<QRect> rects;
+ rects.reserve(childWindows.size());
QRect parentRect = q->rect();
foreach (QMdiSubWindow *window, childWindows) {
if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q)
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 90db55438a..360ed2508c 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -59,6 +59,7 @@
#ifndef QT_NO_MDIAREA
#include <QList>
+#include <QVector>
#include <QRect>
#include <QPoint>
#include <QtWidgets/qapplication.h>
@@ -116,24 +117,19 @@ public:
// Places the rectangle defined by 'size' relative to 'rects' and 'domain'.
// Returns the position of the resulting rectangle.
virtual QPoint place(
- const QSize &size, const QList<QRect> &rects, const QRect &domain) const = 0;
+ const QSize &size, const QVector<QRect> &rects, const QRect &domain) const = 0;
virtual ~Placer() {}
};
class MinOverlapPlacer : public Placer
{
- QPoint place(const QSize &size, const QList<QRect> &rects, const QRect &domain) const;
- static int accumulatedOverlap(const QRect &source, const QList<QRect> &rects);
- static QRect findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects);
- static void getCandidatePlacements(
- const QSize &size, const QList<QRect> &rects, const QRect &domain,
- QList<QRect> &candidates);
- static QPoint findBestPlacement(
- const QRect &domain, const QList<QRect> &rects, QList<QRect> &source);
- static void findNonInsiders(
- const QRect &domain, QList<QRect> &source, QList<QRect> &result);
- static void findMaxOverlappers(
- const QRect &domain, const QList<QRect> &source, QList<QRect> &result);
+ QPoint place(const QSize &size, const QVector<QRect> &rects, const QRect &domain) const;
+ static int accumulatedOverlap(const QRect &source, const QVector<QRect> &rects);
+ static QRect findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects);
+ static QVector<QRect> getCandidatePlacements(const QSize &size, const QVector<QRect> &rects, const QRect &domain);
+ static QPoint findBestPlacement(const QRect &domain, const QVector<QRect> &rects, QVector<QRect> &source);
+ static QVector<QRect> findNonInsiders(const QRect &domain, QVector<QRect> &source);
+ static QVector<QRect> findMaxOverlappers(const QRect &domain, const QVector<QRect> &source);
};
} // namespace QMdi
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index 9104074122..5521d866b2 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1321,6 +1321,14 @@ void QMdiSubWindowPrivate::setNormalMode()
updateMask();
}
+inline void QMdiSubWindowPrivate::storeFocusWidget()
+{
+ if (QWidget *focus = QApplication::focusWidget()) {
+ if (!restoreFocusWidget && q_func()->isAncestorOf(focus))
+ restoreFocusWidget = focus;
+ }
+}
+
/*!
\internal
*/
@@ -1333,8 +1341,7 @@ void QMdiSubWindowPrivate::setMaximizeMode()
isShadeMode = false;
isMaximizeMode = true;
- if (!restoreFocusWidget && q->isAncestorOf(QApplication::focusWidget()))
- restoreFocusWidget = QApplication::focusWidget();
+ storeFocusWidget();
#ifndef QT_NO_SIZEGRIP
setSizeGripVisible(false);
@@ -1436,6 +1443,7 @@ void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus)
Qt::WindowStates oldWindowState = q->windowState();
q->overrideWindowState(q->windowState() & ~Qt::WindowActive);
if (changeFocus) {
+ storeFocusWidget();
QWidget *focusWidget = QApplication::focusWidget();
if (focusWidget && (focusWidget == q || q->isAncestorOf(focusWidget)))
focusWidget->clearFocus();
@@ -2026,6 +2034,9 @@ void QMdiSubWindowPrivate::setFocusWidget()
return;
}
+ if (!(q->windowState() & Qt::WindowMinimized) && restoreFocus())
+ return;
+
if (QWidget *focusWidget = baseWidget->focusWidget()) {
if (!focusWidget->hasFocus() && q->isAncestorOf(focusWidget)
&& focusWidget->isVisible() && !q->isMinimized()
@@ -2048,16 +2059,19 @@ void QMdiSubWindowPrivate::setFocusWidget()
q->setFocus();
}
-void QMdiSubWindowPrivate::restoreFocus()
+bool QMdiSubWindowPrivate::restoreFocus()
{
- if (!restoreFocusWidget)
- return;
- if (!restoreFocusWidget->hasFocus() && q_func()->isAncestorOf(restoreFocusWidget)
- && restoreFocusWidget->isVisible()
- && restoreFocusWidget->focusPolicy() != Qt::NoFocus) {
- restoreFocusWidget->setFocus();
+ if (restoreFocusWidget.isNull())
+ return false;
+ QWidget *candidate = restoreFocusWidget;
+ restoreFocusWidget.clear();
+ if (!candidate->hasFocus() && q_func()->isAncestorOf(candidate)
+ && candidate->isVisible()
+ && candidate->focusPolicy() != Qt::NoFocus) {
+ candidate->setFocus();
+ return true;
}
- restoreFocusWidget = 0;
+ return candidate->hasFocus();
}
/*!
@@ -2605,9 +2619,7 @@ void QMdiSubWindow::showShaded()
d->isMaximizeMode = false;
- QWidget *currentFocusWidget = QApplication::focusWidget();
- if (!d->restoreFocusWidget && isAncestorOf(currentFocusWidget))
- d->restoreFocusWidget = currentFocusWidget;
+ d->storeFocusWidget();
if (!d->isShadeRequestFromMinimizeMode) {
d->isShadeMode = true;
@@ -2621,7 +2633,7 @@ void QMdiSubWindow::showShaded()
// showMinimized() will reset Qt::WindowActive, which makes sense
// for top level widgets, but in MDI it makes sense to have an
// active window which is minimized.
- if (hasFocus() || isAncestorOf(currentFocusWidget))
+ if (hasFocus() || isAncestorOf(QApplication::focusWidget()))
d->ensureWindowState(Qt::WindowActive);
#ifndef QT_NO_SIZEGRIP
diff --git a/src/widgets/widgets/qmdisubwindow_p.h b/src/widgets/widgets/qmdisubwindow_p.h
index 90369ff526..6abbe89b4c 100644
--- a/src/widgets/widgets/qmdisubwindow_p.h
+++ b/src/widgets/widgets/qmdisubwindow_p.h
@@ -266,7 +266,8 @@ public:
QPalette desktopPalette() const;
void updateActions();
void setFocusWidget();
- void restoreFocus();
+ bool restoreFocus();
+ void storeFocusWidget();
void setWindowFlags(Qt::WindowFlags windowFlags);
void setVisible(WindowStateAction, bool visible = true);
#ifndef QT_NO_ACTION
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 7e48badea5..846199ebe2 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -187,8 +187,8 @@ void QMenuPrivate::syncPlatformMenu()
QPlatformMenuItem *menuItem = platformMenu->createMenuItem();
QAction *action = it.previous();
menuItem->setTag(reinterpret_cast<quintptr>(action));
- QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()));
- QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()));
+ QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
+ QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection);
copyActionToPlatformItem(action, menuItem);
platformMenu->insertMenuItem(menuItem, beforeItem);
beforeItem = menuItem;
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 23c1e99231..df13085dee 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2537,6 +2537,8 @@ void QPlainTextEdit::setReadOnly(bool ro)
}
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qradiobutton.h b/src/widgets/widgets/qradiobutton.h
index 104d4a12e0..8888ccf86d 100644
--- a/src/widgets/widgets/qradiobutton.h
+++ b/src/widgets/widgets/qradiobutton.h
@@ -73,6 +73,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QRadioButton)
Q_DISABLE_COPY(QRadioButton)
+ friend class QAccessibleButton;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 789ec2f6fd..e8fdc65711 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -632,6 +632,14 @@ void QTabBarPrivate::layoutWidgets(int start)
}
}
+void QTabBarPrivate::autoHideTabs()
+{
+ Q_Q(QTabBar);
+
+ if (autoHide)
+ q->setVisible(q->count() > 1);
+}
+
void QTabBarPrivate::_q_closeTab()
{
Q_Q(QTabBar);
@@ -861,6 +869,7 @@ int QTabBar::insertTab(int index, const QIcon& icon, const QString &text)
}
tabInserted(index);
+ d->autoHideTabs();
return index;
}
@@ -936,6 +945,7 @@ void QTabBar::removeTab(int index)
setCurrentIndex(d->currentIndex - 1);
}
d->refresh();
+ d->autoHideTabs();
tabRemoved(index);
}
}
@@ -2267,6 +2277,36 @@ void QTabBar::setDocumentMode(bool enabled)
}
/*!
+ \property QTabBar::autoHide
+ \brief If true, the tab bar is automatically hidden when it contains less
+ than 2 tabs.
+ \since 5.4
+
+ By default, this property is false.
+
+ \sa QWidget::visible
+*/
+
+bool QTabBar::autoHide() const
+{
+ Q_D(const QTabBar);
+ return d->autoHide;
+}
+
+void QTabBar::setAutoHide(bool hide)
+{
+ Q_D(QTabBar);
+ if (d->autoHide == hide)
+ return;
+
+ d->autoHide = hide;
+ if (hide)
+ d->autoHideTabs();
+ else
+ setVisible(true);
+}
+
+/*!
Sets \a widget on the tab \a index. The widget is placed
on the left or right hand side depending upon the \a position.
\since 4.5
diff --git a/src/widgets/widgets/qtabbar.h b/src/widgets/widgets/qtabbar.h
index a0e52c2f86..a1616b1524 100644
--- a/src/widgets/widgets/qtabbar.h
+++ b/src/widgets/widgets/qtabbar.h
@@ -70,6 +70,7 @@ class Q_WIDGETS_EXPORT QTabBar: public QWidget
Q_PROPERTY(bool expanding READ expanding WRITE setExpanding)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode)
+ Q_PROPERTY(bool autoHide READ autoHide WRITE setAutoHide)
public:
explicit QTabBar(QWidget* parent=0);
@@ -166,6 +167,9 @@ public:
bool documentMode() const;
void setDocumentMode(bool set);
+ bool autoHide() const;
+ void setAutoHide(bool hide);
+
public Q_SLOTS:
void setCurrentIndex(int index);
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index 3228308bc6..1238057e2a 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -77,7 +77,7 @@ public:
:currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
drawBase(true), scrollOffset(0), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
- dragInProgress(false), documentMode(false), movingTab(0)
+ dragInProgress(false), documentMode(false), autoHide(false), movingTab(0)
#ifdef Q_WS_MAC
, previousPressedIndex(-1)
#endif
@@ -184,6 +184,7 @@ public:
void updateMacBorderMetrics();
bool isTabInMacUnifiedToolbarArea() const;
void setupMovableTab();
+ void autoHideTabs();
void makeVisible(int index);
QSize iconSize;
@@ -201,6 +202,7 @@ public:
bool movable;
bool dragInProgress;
bool documentMode;
+ bool autoHide;
QWidget *movingTab;
#ifdef Q_WS_MAC
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index fced1c01ec..616b66b80b 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -1351,6 +1351,29 @@ void QTabWidget::setDocumentMode(bool enabled)
}
/*!
+ \property QTabWidget::tabBarAutoHide
+ \brief If true, the tab bar is automatically hidden when it contains less
+ than 2 tabs.
+ \since 5.4
+
+ By default, this property is false.
+
+ \sa QWidget::visible
+*/
+
+bool QTabWidget::tabBarAutoHide() const
+{
+ Q_D(const QTabWidget);
+ return d->tabs->autoHide();
+}
+
+void QTabWidget::setTabBarAutoHide(bool enabled)
+{
+ Q_D(QTabWidget);
+ return d->tabs->setAutoHide(enabled);
+}
+
+/*!
Removes all the pages, but does not delete them. Calling this function
is equivalent to calling removeTab() until the tab widget is empty.
*/
diff --git a/src/widgets/widgets/qtabwidget.h b/src/widgets/widgets/qtabwidget.h
index 83c2e31d28..046e544bf0 100644
--- a/src/widgets/widgets/qtabwidget.h
+++ b/src/widgets/widgets/qtabwidget.h
@@ -68,6 +68,7 @@ class Q_WIDGETS_EXPORT QTabWidget : public QWidget
Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode)
Q_PROPERTY(bool tabsClosable READ tabsClosable WRITE setTabsClosable)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
+ Q_PROPERTY(bool tabBarAutoHide READ tabBarAutoHide WRITE setTabBarAutoHide)
public:
explicit QTabWidget(QWidget *parent = 0);
@@ -140,6 +141,9 @@ public:
bool documentMode() const;
void setDocumentMode(bool set);
+ bool tabBarAutoHide() const;
+ void setTabBarAutoHide(bool enabled);
+
void clear();
QTabBar* tabBar() const;
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index a33ac0817f..f106b70c12 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -2122,6 +2122,8 @@ void QTextEdit::setReadOnly(bool ro)
}
d->control->setTextInteractionFlags(flags);
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index 1c05529cd6..834c2fe56b 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -720,6 +720,10 @@ void QToolBar::setIconSize(const QSize &iconSize)
as \l{QAction}s. Note that if you add a QToolButton with the
addWidget() method, it will not get this button style.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
+
The default is Qt::ToolButtonIconOnly.
*/
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 497bc52109..1b5ba8cd58 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -384,8 +384,9 @@ QSize QToolButton::minimumSizeHint() const
The default is Qt::ToolButtonIconOnly.
- To have the style of toolbuttons follow the system settings (as available
- in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle.
+ To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
+ On Unix, the user settings from the desktop environment will be used.
+ On other platforms, Qt::ToolButtonFollowStyle means icon only.
QToolButton automatically connects this slot to the relevant
signal in the QMainWindow in which is resides.
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 75f30599be..b927004773 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -355,8 +355,10 @@ void QWidgetLineControl::init(const QString &txt)
m_text = txt;
updateDisplayText();
m_cursor = m_text.length();
- if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
m_keyboardScheme = theme->themeHint(QPlatformTheme::KeyboardScheme).toInt();
+ m_passwordMaskDelay = theme->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ }
// Generalize for X11
if (m_keyboardScheme == QPlatformTheme::KdeKeyboardScheme
|| m_keyboardScheme == QPlatformTheme::GnomeKeyboardScheme
@@ -787,7 +789,7 @@ void QWidgetLineControl::internalInsert(const QString &s)
if (m_echoMode == QLineEdit::Password) {
if (m_passwordEchoTimer != 0)
killTimer(m_passwordEchoTimer);
- int delay = qGuiApp->styleHints()->passwordMaskDelay();
+ int delay = m_passwordMaskDelay;
#ifdef QT_BUILD_INTERNAL
if (m_passwordMaskDelayOverride >= 0)
delay = m_passwordMaskDelayOverride;
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index 1cee67bfd2..ba73e9e25e 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -90,6 +90,7 @@ public:
m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
, m_passwordEchoTimer(0)
+ , m_passwordMaskDelay(-1)
#if defined(Q_WS_MAC)
, m_threadChecks(false)
, m_textLayoutThread(0)
@@ -313,6 +314,9 @@ public:
QChar passwordCharacter() const { return m_passwordCharacter; }
void setPasswordCharacter(QChar character) { m_passwordCharacter = character; updateDisplayText(); }
+ int passwordMaskDelay() const { return m_passwordMaskDelay; }
+ void setPasswordMaskDelay(int delay) { m_passwordMaskDelay = delay; }
+
Qt::LayoutDirection layoutDirection() const {
if (m_layoutDirection == Qt::LayoutDirectionAuto) {
if (m_text.isEmpty())
@@ -481,6 +485,7 @@ private:
bool m_passwordEchoEditing;
QChar m_passwordCharacter;
int m_passwordEchoTimer;
+ int m_passwordMaskDelay;
void cancelPasswordEchoTimer()
{
if (m_passwordEchoTimer != 0) {
diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp
index ba4e69126a..d4d44e60cd 100644
--- a/src/widgets/widgets/qwidgetresizehandler.cpp
+++ b/src/widgets/widgets/qwidgetresizehandler.cpp
@@ -58,6 +58,10 @@ QT_BEGIN_NAMESPACE
static bool resizeHorizontalDirectionFixed = false;
static bool resizeVerticalDirectionFixed = false;
+// ### fixme: Qt 6: No longer export QWidgetResizeHandler and remove "Move"
+// functionality. Currently, only the resize functionality is used by QDockWidget.
+// Historically, the class was used in Qt 3's QWorkspace (predecessor to QMdiArea).
+
QWidgetResizeHandler::QWidgetResizeHandler(QWidget *parent, QWidget *cw)
: QObject(parent), widget(parent), childWidget(cw ? cw : parent),
fw(0), extrahei(0), buttonDown(false), moveResizeMode(false), sizeprotect(true), movingEnabled(true)
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 96438a0bdf..5f60bf02d0 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -645,13 +645,15 @@ void QWidgetTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someC
void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, int charsAdded)
{
- Q_Q(QWidgetTextControl);
#ifndef QT_NO_ACCESSIBILITY
+ Q_Q(QWidgetTextControl);
if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) {
QTextCursor tmp(doc);
tmp.setPosition(from);
- tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);
+ // when setting a new text document the length is off
+ // QTBUG-32583 - characterCount is off by 1 requires the -1
+ tmp.setPosition(qMin(doc->characterCount() - 1, from + charsAdded), QTextCursor::KeepAnchor);
QString newText = tmp.selectedText();
// always report the right number of removed chars, but in lack of the real string use spaces
@@ -668,6 +670,10 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
QAccessible::updateAccessibility(ev);
delete ev;
}
+#else
+ Q_UNUSED(from)
+ Q_UNUSED(charsRemoved)
+ Q_UNUSED(charsAdded)
#endif
}