summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure7
-rw-r--r--dist/changes-5.4.04
-rw-r--r--mkspecs/features/mac/sdk.prf4
-rw-r--r--mkspecs/macx-ios-clang/features/sdk.prf4
-rw-r--r--qtbase.pro5
-rw-r--r--src/corelib/global/qnamespace.qdoc2
-rw-r--r--src/corelib/io/qurl.cpp42
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp6
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2
-rw-r--r--src/corelib/tools/qbytearraylist.h1
-rw-r--r--src/corelib/tools/qlocale.cpp4
-rw-r--r--src/corelib/tools/qlocale_p.h4
-rw-r--r--src/corelib/tools/qstring.cpp57
-rw-r--r--src/gui/kernel/qguiapplication.cpp25
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qwindow.cpp4
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp36
-rw-r--r--src/gui/painting/qbrush.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/text/qfontengine_ft.cpp75
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/util/qvalidator.cpp26
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp19
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp21
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp2
-rw-r--r--src/opengl/qgl.cpp29
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qglframebufferobject.cpp31
-rw-r--r--src/opengl/qglpaintdevice.cpp13
-rw-r--r--src/opengl/qglpixelbuffer.cpp2
-rw-r--r--src/platformsupport/fontdatabases/basic/basic.pri1
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp12
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux_p.h2
-rw-r--r--src/plugins/bearer/networkmanager/main.cpp5
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp310
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h13
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp22
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm19
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm11
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp6
-rw-r--r--src/widgets/accessible/simplewidgets.cpp2
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp14
-rw-r--r--src/widgets/kernel/qapplication.cpp38
-rw-r--r--src/widgets/kernel/qapplication_p.h3
-rw-r--r--src/widgets/kernel/qgesture_p.h3
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp20
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp10
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp53
-rw-r--r--src/widgets/kernel/qstandardgestures_p.h5
-rw-r--r--src/widgets/kernel/qwidget.cpp5
-rw-r--r--src/widgets/styles/qfusionstyle.cpp4
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp5
-rw-r--r--src/widgets/widgets/qmainwindow.cpp7
-rw-r--r--src/widgets/widgets/qmdiarea.cpp16
-rw-r--r--src/widgets/widgets/qmdiarea_p.h9
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp14
-rw-r--r--src/widgets/widgets/qtextedit.cpp14
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp9
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp9
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp74
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp19
-rw-r--r--tests/auto/corelib/kernel/qvariant/qvariant.pro1
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp22
-rw-r--r--tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp27
-rw-r--r--tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp3
-rw-r--r--tests/auto/network/access/qnetworkreply/BLACKLIST3
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/BLACKLIST4
-rw-r--r--tests/auto/network/ssl/ssl.pro8
-rw-r--r--tests/auto/opengl/qgl/tst_qgl.cpp90
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro1
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp2
-rw-r--r--tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp9
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp4
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp10
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp8
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp2
-rw-r--r--tests/manual/diaglib/README.txt34
-rw-r--r--tests/manual/diaglib/diaglib.pri43
-rw-r--r--tests/manual/diaglib/eventfilter.cpp113
-rw-r--r--tests/manual/diaglib/eventfilter.h77
-rw-r--r--tests/manual/diaglib/glinfo.cpp112
-rw-r--r--tests/manual/diaglib/glinfo.h48
-rw-r--r--tests/manual/diaglib/nativewindowdump.cpp46
-rw-r--r--tests/manual/diaglib/nativewindowdump.h46
-rw-r--r--tests/manual/diaglib/nativewindowdump_win.cpp207
-rw-r--r--tests/manual/diaglib/qwidgetdump.cpp94
-rw-r--r--tests/manual/diaglib/qwidgetdump.h45
-rw-r--r--tests/manual/diaglib/qwindowdump.cpp176
-rw-r--r--tests/manual/diaglib/qwindowdump.h63
99 files changed, 2221 insertions, 308 deletions
diff --git a/configure b/configure
index 1a002b4081..df51b0d406 100755
--- a/configure
+++ b/configure
@@ -1409,7 +1409,8 @@ while [ "$#" -gt 0 ]; do
fi
;;
feature-*)
- FEATURE=`echo $VAR | sed 's,^[^-]*-\([^-]*\),\1,' | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
+ FEATURE=`echo $VAR | sed 's,^[^-]*-\([^-]*\),\1,' | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
+ if grep "^Feature: *${FEATURE} *\$" "$relpath"/src/corelib/global/qfeatures.txt >/dev/null 2>&1; then
if [ "$VAL" = "no" ]; then
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_$FEATURE"
elif [ "$VAL" = "yes" ] || [ "$VAL" = "unknown" ]; then
@@ -1417,6 +1418,10 @@ while [ "$#" -gt 0 ]; do
else
UNKNOWN_OPT=yes
fi
+ else
+ echo "ERROR: Unknown feature $FEATURE"
+ UNKNOWN_OPT=yes
+ fi
;;
shared)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
diff --git a/dist/changes-5.4.0 b/dist/changes-5.4.0
index 614f57afe2..c3c7f532a3 100644
--- a/dist/changes-5.4.0
+++ b/dist/changes-5.4.0
@@ -25,6 +25,10 @@ QtCore
- Added QEnableSharedFromThis, a class that allows obtaining a
QSharedPointer for an object already managed by a shared pointer.
+QtGui
+-----
+
+ - QImageReader now automatically rotates JPEG images according to Exif orientation
QtSql
-----
diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf
index 36bff00496..97be211595 100644
--- a/mkspecs/features/mac/sdk.prf
+++ b/mkspecs/features/mac/sdk.prf
@@ -9,8 +9,12 @@ isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path) {
QMAKE_MAC_SDK_PATH = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version Path 2>/dev/null")
isEmpty(QMAKE_MAC_SDK_PATH): error("Could not resolve SDK path for \'$$QMAKE_MAC_SDK\'")
cache(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path, set stash, QMAKE_MAC_SDK_PATH)
+ QMAKE_MAC_SDK_VERSION = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version SDKVersion 2>/dev/null")
+ isEmpty(QMAKE_MAC_SDK_VERSION): error("Could not resolve SDK version for \'$$QMAKE_MAC_SDK\'")
+ cache(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version, set stash, QMAKE_MAC_SDK_VERSION)
} else {
QMAKE_MAC_SDK_PATH = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path)
+ QMAKE_MAC_SDK_VERSION = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version)
}
!equals(MAKEFILE_GENERATOR, XCODE) {
diff --git a/mkspecs/macx-ios-clang/features/sdk.prf b/mkspecs/macx-ios-clang/features/sdk.prf
new file mode 100644
index 0000000000..607a71bb26
--- /dev/null
+++ b/mkspecs/macx-ios-clang/features/sdk.prf
@@ -0,0 +1,4 @@
+load(sdk)
+
+lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \
+ error("Current $$QMAKE_MAC_SDK SDK version ($$QMAKE_MAC_SDK_VERSION) is too old. Please upgrade Xcode.")
diff --git a/qtbase.pro b/qtbase.pro
index d6861cf09f..6d0de44f6d 100644
--- a/qtbase.pro
+++ b/qtbase.pro
@@ -140,7 +140,7 @@ for (ft, features) {
"$${LITERAL_HASH} define QT_NO_$$ft" \
"$${LITERAL_HASH}endif"
FEATURES_PRI += \
- "contains(QT_DISABLED_FEATURES, "^($$lower($$join($$list($$replace(features.$${ft}.depends, _, -)), "|")))$"): \\" \
+ "contains(QT_DISABLED_FEATURES, "$$lower($$join($$list($$replace(features.$${ft}.depends, _, -)), "|"))"): \\" \
" QT_DISABLED_FEATURES += $$lower($$replace(ft, _, -))"
}
}
@@ -168,7 +168,8 @@ for (def, QT_NO_DEFINES) {
}
no_features = $$unique(no_features)
-# Can't simply add these to QT_CONFIG, as e.g., contains(QT_CONFIG, accessibility) matches no-accessibililty.
+# Don't simply add these to QT_CONFIG, as then one might expect them to be there without load(qfeatures).
+# And we don't want to do that automatically, as the dynamic dependency resolution is somewhat expensive.
FEATURES_PRI = \
"$${LITERAL_HASH} Features disabled by configure:" \
"QT_DISABLED_FEATURES =$$lower($$join($$list($$replace(no_features, _, -)), " ", " "))" \
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 8d6f7834b0..53d2b7b58b 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -2804,11 +2804,11 @@
This enum type describes the state of a gesture.
+ \value NoGesture No gesture has been detected.
\value GestureStarted A continuous gesture has started.
\value GestureUpdated A gesture continues.
\value GestureFinished A gesture has finished.
\value GestureCanceled A gesture was canceled.
- \omitvalue NoGesture
\sa QGesture
*/
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index d4c5e03058..b21e9b51e1 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -403,6 +403,7 @@
#include "qdebug.h"
#include "qhash.h"
#include "qdir.h" // for QDir::fromNativeSeparators
+#include "qdatastream.h"
#include "qtldurl_p.h"
#include "private/qipaddress_p.h"
#include "qurlquery.h"
@@ -429,6 +430,16 @@ static inline QString fileScheme()
return QStringLiteral("file");
}
+static inline QString webDavScheme()
+{
+ return QStringLiteral("webdavs");
+}
+
+static inline QString webDavSslTag()
+{
+ return QStringLiteral("@SSL");
+}
+
#ifdef Q_COMPILER_CLASS_ENUM
# define colon_uchar : uchar
#else
@@ -992,10 +1003,15 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
}
// did we set to the file protocol?
- if (scheme == fileScheme())
+ if (scheme == fileScheme()
+#ifdef Q_OS_WIN
+ || scheme == webDavScheme()
+#endif
+ ) {
flags |= IsLocalFile;
- else
+ } else {
flags &= ~IsLocalFile;
+ }
return true;
}
@@ -3738,7 +3754,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
QUrl url;
if (localFile.isEmpty())
return url;
- url.setScheme(fileScheme());
+ QString scheme = fileScheme();
QString deslashified = QDir::fromNativeSeparators(localFile);
// magic for drives on windows
@@ -3747,13 +3763,21 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
} else if (deslashified.startsWith(QLatin1String("//"))) {
// magic for shared drive on windows
int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
- url.setHost(deslashified.mid(2, indexOfPath - 2));
+ QString hostSpec = deslashified.mid(2, indexOfPath - 2);
+ // Check for Windows-specific WebDAV specification: "//host@SSL/path".
+ if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) {
+ hostSpec.chop(4);
+ scheme = webDavScheme();
+ }
+ url.setHost(hostSpec);
+
if (indexOfPath > 2)
deslashified = deslashified.right(deslashified.length() - indexOfPath);
else
deslashified.clear();
}
+ url.setScheme(scheme);
url.setPath(deslashified, DecodedMode);
return url;
}
@@ -3783,8 +3807,14 @@ QString QUrl::toLocalFile() const
// magic for shared drive on windows
if (!d->host.isEmpty()) {
- tmp = QStringLiteral("//") + host() + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/')
- ? QLatin1Char('/') + ourPath : ourPath);
+ tmp = QStringLiteral("//") + host();
+#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
+ if (scheme() == webDavScheme())
+ tmp += webDavSslTag();
+#endif
+ if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
+ tmp += QLatin1Char('/');
+ tmp += ourPath;
} else {
tmp = ourPath;
#ifdef Q_OS_WIN
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index a95c7dc8b3..3c383532bb 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1196,11 +1196,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
parents << q->mapFromSource(source_parent);
emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
QModelIndexPairList source_indexes = store_persistent_indexes();
- remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- sort_source_rows(source_rows_resort, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
+ sort_source_rows(m->source_rows, source_parent);
update_persistent_indexes(source_indexes);
emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
// Make sure we also emit dataChanged for the rows
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 45647f2056..77900ba906 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -714,9 +714,7 @@ void QCoreApplication::init()
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = this;
-#ifndef QT_BOOTSTRAPPED
QLoggingRegistry::instance()->init();
-#endif
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h
index 9d7e776028..dd84ec642c 100644
--- a/src/corelib/tools/qbytearraylist.h
+++ b/src/corelib/tools/qbytearraylist.h
@@ -63,6 +63,7 @@ class QByteArrayList : public QList<QByteArray>
template <> struct QListSpecialMethods<QByteArray>
#endif
{
+public:
inline QByteArray join() const
{ return QtPrivate::QByteArrayList_join(self(), 0, 0); }
inline QByteArray join(const QByteArray &sep) const
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index a253057435..a923be50c0 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -3144,7 +3144,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len,
}
bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
- int decDigits) const
+ int decDigits, bool rejectGroupSeparators) const
{
buff->clear();
buff->reserve(str.length());
@@ -3205,7 +3205,7 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr
case ',':
//it can only be placed after a digit which is before the decimal point
- if (!lastWasDigit || decPointCnt > 0)
+ if (rejectGroupSeparators || !lastWasDigit || decPointCnt > 0)
return false;
break;
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index c33ced35d5..c5e62027c4 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -251,7 +251,9 @@ public:
inline char digitToCLocale(QChar c) const;
// this function is used in QIntValidator (QtGui)
- Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const;
+ Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode,
+ QByteArray *buff, int decDigits = -1,
+ bool rejectGroupSeparators = false) const;
public:
quint16 m_language_id, m_script_id, m_country_id;
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index ef12c1b8e3..29b546770c 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -3863,28 +3863,31 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
{
QStringList sections = split(sep, KeepEmptyParts,
(flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
- if (sections.isEmpty())
- return QString();
+ const int sectionsSize = sections.size();
+
if (!(flags & SectionSkipEmpty)) {
if (start < 0)
- start += sections.count();
+ start += sectionsSize;
if (end < 0)
- end += sections.count();
+ end += sectionsSize;
} else {
int skip = 0;
- for (int k=0; k<sections.size(); ++k) {
+ for (int k = 0; k < sectionsSize; ++k) {
if (sections.at(k).isEmpty())
skip++;
}
if (start < 0)
- start += sections.count() - skip;
+ start += sectionsSize - skip;
if (end < 0)
- end += sections.count() - skip;
+ end += sectionsSize - skip;
}
+ if (start >= sectionsSize || end < 0 || start > end)
+ return QString();
+
int x = 0;
QString ret;
int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sections.size(); ++i) {
+ for (int i = 0; x <= end && i < sectionsSize; ++i) {
QString section = sections.at(i);
const bool empty = section.isEmpty();
if (x >= start) {
@@ -3892,16 +3895,16 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
first_i = i;
if(x == end)
last_i = i;
- if(x > start)
+ if (x > start && i > 0)
ret += sep;
ret += section;
}
if (!empty || !(flags & SectionSkipEmpty))
x++;
}
- if((flags & SectionIncludeLeadingSep) && first_i)
+ if ((flags & SectionIncludeLeadingSep) && first_i > 0)
ret.prepend(sep);
- if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1)
+ if ((flags & SectionIncludeTrailingSep) && last_i < sectionsSize - 1)
ret += sep;
return ret;
}
@@ -3919,15 +3922,32 @@ static QString extractSections(const QList<qt_section_chunk> &sections,
int end,
QString::SectionFlags flags)
{
- if (start < 0)
- start += sections.count();
- if (end < 0)
- end += sections.count();
+ const int sectionsSize = sections.size();
+
+ if (!(flags & QString::SectionSkipEmpty)) {
+ if (start < 0)
+ start += sectionsSize;
+ if (end < 0)
+ end += sectionsSize;
+ } else {
+ int skip = 0;
+ for (int k = 0; k < sectionsSize; ++k) {
+ const qt_section_chunk &section = sections.at(k);
+ if (section.length == section.string.length())
+ skip++;
+ }
+ if (start < 0)
+ start += sectionsSize - skip;
+ if (end < 0)
+ end += sectionsSize - skip;
+ }
+ if (start >= sectionsSize || end < 0 || start > end)
+ return QString();
QString ret;
int x = 0;
int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sections.size(); ++i) {
+ for (int i = 0; x <= end && i < sectionsSize; ++i) {
const qt_section_chunk &section = sections.at(i);
const bool empty = (section.length == section.string.length());
if (x >= start) {
@@ -3944,12 +3964,13 @@ static QString extractSections(const QList<qt_section_chunk> &sections,
x++;
}
- if ((flags & QString::SectionIncludeLeadingSep) && first_i < sections.size()) {
+ if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) {
const qt_section_chunk &section = sections.at(first_i);
ret.prepend(section.string.left(section.length));
}
- if ((flags & QString::SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
+ if ((flags & QString::SectionIncludeTrailingSep)
+ && last_i < sectionsSize - 1) {
const qt_section_chunk &section = sections.at(last_i+1);
ret += section.string.left(section.length);
}
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 59bcd37251..fe92ead846 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -163,7 +163,6 @@ QWindow *QGuiApplicationPrivate::focus_window = 0;
static QBasicMutex applicationFontMutex;
QFont *QGuiApplicationPrivate::app_font = 0;
bool QGuiApplicationPrivate::obey_desktop_settings = true;
-bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
@@ -1196,20 +1195,10 @@ void QGuiApplicationPrivate::eventDispatcherReady()
platform_integration->initialize();
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
-// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc.
-static bool runningUnderDebugger()
-{
- const QFileInfo parentProcExe(QStringLiteral("/proc/") + QString::number(getppid()) + QStringLiteral("/exe"));
- return parentProcExe.isSymLink() && parentProcExe.symLinkTarget().endsWith(QLatin1String("/gdb"));
-}
-#endif
-
void QGuiApplicationPrivate::init()
{
QCoreApplicationPrivate::is_app_running = false; // Starting up.
- bool doGrabUnderDebugger = false;
bool loadTestability = false;
QList<QByteArray> pluginList;
// Get command line params
@@ -1244,10 +1233,6 @@ void QGuiApplicationPrivate::init()
QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
}
#endif
- } else if (arg == "-nograb") {
- QGuiApplicationPrivate::noGrab = true;
- } else if (arg == "-dograb") {
- doGrabUnderDebugger = true;
#ifndef QT_NO_SESSIONMANAGER
} else if (arg == "-session" && i < argc-1) {
++i;
@@ -1273,16 +1258,6 @@ void QGuiApplicationPrivate::init()
argc = j;
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- if (!doGrabUnderDebugger && !QGuiApplicationPrivate::noGrab && runningUnderDebugger()) {
- QGuiApplicationPrivate::noGrab = true;
- qDebug("Qt: gdb: -nograb added to command-line options.\n"
- "\t Use the -dograb option to enforce grabbing.");
- }
-#else
- Q_UNUSED(doGrabUnderDebugger)
-#endif
-
// Load environment exported generic plugins
foreach (const QByteArray &plugin, qgetenv("QT_QPA_GENERIC_PLUGINS").split(','))
pluginList << plugin;
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 8988bd461d..eed3d5c10e 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -221,7 +221,6 @@ public:
QStyleHints *styleHints;
static bool obey_desktop_settings;
- static bool noGrab;
QInputMethod *inputMethod;
QString firstWindowTitle;
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index d5a3126176..975553e7cd 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -203,6 +203,7 @@ public:
, workaround_brokenTexSubImage(false)
, workaround_missingPrecisionQualifiers(false)
, active_engine(0)
+ , qgl_current_fbo_invalid(false)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -237,6 +238,8 @@ public:
QPaintEngineEx *active_engine;
+ bool qgl_current_fbo_invalid;
+
QVariant nativeHandle;
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 99bf469f87..c6dd0955aa 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1639,8 +1639,6 @@ QPlatformSurface *QWindow::surfaceHandle() const
bool QWindow::setKeyboardGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setKeyboardGrabEnabled(grab);
return false;
@@ -1658,8 +1656,6 @@ bool QWindow::setKeyboardGrabEnabled(bool grab)
bool QWindow::setMouseGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setMouseGrabEnabled(grab);
return false;
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index b185e332e6..124d9d53f6 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -469,6 +469,8 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
funcs.glGenFramebuffers(1, &fbo);
funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+
GLuint color_buffer = 0;
QT_CHECK_GLERROR();
@@ -997,7 +999,11 @@ bool QOpenGLFramebufferObject::bind()
if (current->shareGroup() != d->fbo_guard->group())
qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
#endif
+
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+
if (d->texture_guard || d->format.samples() != 0)
d->valid = d->checkFramebufferStatus(current);
else
@@ -1029,9 +1035,12 @@ bool QOpenGLFramebufferObject::release()
qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
#endif
- if (current)
+ if (current) {
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+ }
+
return true;
}
@@ -1194,9 +1203,23 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value
of QOpenGLPaintDevice::paintFlipped().
- Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
- a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. Since 5.4 an
- A2BGR30 image is returned if the internal format is RGB10_A2.
+ The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
+ only when internalTextureFormat() is set to \c GL_RGB.
+
+ If the rendering in the framebuffer was not done with premultiplied alpha in mind,
+ create a wrapper QImage with a non-premultiplied format. This is necessary before
+ performing operations like QImage::save() because otherwise the image data would get
+ unpremultiplied, even though it was not premultiplied in the first place. To create
+ such a wrapper without performing a copy of the pixel data, do the following:
+
+ \code
+ QImage fboImage(fbo.toImage());
+ QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
+ \endcode
+
+ Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when
+ reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the
+ internal format is RGB10_A2.
For multisampled framebuffer objects the samples are resolved using the
\c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents
@@ -1272,8 +1295,10 @@ bool QOpenGLFramebufferObject::bindDefault()
{
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- if (ctx)
+ if (ctx) {
ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+ }
#ifdef QT_DEBUG
else
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
@@ -1342,6 +1367,7 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen
qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
#endif
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
d->initAttachments(current, attachment);
}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index d120175108..d136f3a903 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -708,6 +708,9 @@ void QBrush::setStyle(Qt::BrushStyle style)
void QBrush::setColor(const QColor &c)
{
+ if (d->color == c)
+ return;
+
detach(d->style);
d->color = c;
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index f2d27a0e2a..6482cc50f7 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6829,7 +6829,7 @@ void qInitDrawhelperAsm()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#endif
-#ifdef Q_PROCESSOR_MIPS_32
+#if defined(Q_PROCESSOR_MIPS_32) && defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
qt_memfill32 = qt_memfill32_asm_mips_dsp;
#endif // Q_PROCESSOR_MIPS_32
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index b0cfa49b36..83d9edab94 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
- // The freetype engine falls back to QFontEngine for tranformed glyphs,
- // which uses fast-tranform and produces very ugly results, so we claim
- // to support just translations.
- return transform.type() <= QTransform::TxTranslate;
+ return transform.type() <= QTransform::TxRotate;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
currentlyLockedAlphaMap = QImage();
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ const QTransform &t)
{
- return defaultGlyphSet.outline_drawing ? 0 :
- loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
+ FT_Face face = 0;
+ QGlyphSet *glyphSet = 0;
+ FT_Matrix ftMatrix = QTransformToFTMatrix(t);
+ if (cacheEnabled) {
+ if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
+ for (int i = 0; i < transformedGlyphSets.count(); ++i) {
+ const QGlyphSet &g = transformedGlyphSets.at(i);
+ if (g.transformationMatrix.xx == ftMatrix.xx
+ && g.transformationMatrix.xy == ftMatrix.xy
+ && g.transformationMatrix.yx == ftMatrix.yx
+ && g.transformationMatrix.yy == ftMatrix.yy) {
+
+ // found a match, move it to the front
+ transformedGlyphSets.move(i, 0);
+ glyphSet = &transformedGlyphSets[0];
+ break;
+ }
+ }
+
+ if (!glyphSet) {
+ // don't cache more than 10 transformations
+ if (transformedGlyphSets.count() >= 10) {
+ transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
+ } else {
+ transformedGlyphSets.prepend(QGlyphSet());
+ }
+ glyphSet = &transformedGlyphSets[0];
+ glyphSet->clear();
+ glyphSet->transformationMatrix = ftMatrix;
+ }
+ } else {
+ glyphSet = &defaultGlyphSet;
+ }
+ Q_ASSERT(glyphSet != 0);
+ }
+
+ if (glyphSet != 0 && glyphSet->outline_drawing)
+ return 0;
+
+ Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
+ if (!glyph || glyph->format != format) {
+ face = lockFace();
+ FT_Matrix m = this->matrix;
+ FT_Matrix_Multiply(&ftMatrix, &m);
+ freetype->matrix = m;
+ glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
+ }
+
+ if (face)
+ unlockFace();
+
+ return glyph;
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
+ return alphaMapForGlyph(g, subPixelPosition, QTransform());
+}
+
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+{
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1987,12 +2042,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
- if (t.type() > QTransform::TxTranslate)
+ if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index a73c281f1d..1894d25d70 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -233,6 +233,7 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
virtual QImage alphaMapForGlyph(glyph_t, QFixed);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
QFixed subPixelPosition,
@@ -265,7 +266,7 @@ private:
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
- Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
+ Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 1b5a10f733..f879847935 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -316,7 +316,12 @@ void QValidator::fixup(QString &) const
QIntValidator uses its locale() to interpret the number. For example,
in Arabic locales, QIntValidator will accept Arabic digits.
- \sa QDoubleValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toInt() to obtain the numeric value.
+
+ \sa QDoubleValidator, QRegExpValidator, QLocale::toInt(), {Line Edits Example}
*/
/*!
@@ -393,7 +398,8 @@ static qlonglong pow10(int exp)
QValidator::State QIntValidator::validate(QString & input, int&) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return Invalid;
}
@@ -432,7 +438,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
void QIntValidator::fixup(QString &input) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return;
}
bool ok, overflow;
@@ -548,7 +555,12 @@ public:
in the German locale, "1,234" will be accepted as the fractional number
1.234. In Arabic locales, QDoubleValidator will accept Arabic digits.
- \sa QIntValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toDouble() to obtain the numeric value.
+
+ \sa QIntValidator, QRegExpValidator, QLocale::toDouble(), {Line Edits Example}
*/
/*!
@@ -648,8 +660,10 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
{
Q_Q(const QDoubleValidator);
QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec))
+ if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec,
+ locale.numberOptions() & QLocale::RejectGroupSeparator)) {
return QValidator::Invalid;
+ }
if (buff.isEmpty())
return QValidator::Intermediate;
@@ -1003,7 +1017,7 @@ QValidator::State QRegularExpressionValidator::validate(QString &input, int &pos
const QRegularExpressionMatch m = d->usedRe.match(input, 0, QRegularExpression::PartialPreferCompleteMatch);
if (m.hasMatch()) {
return Acceptable;
- } else if (m.hasPartialMatch()) {
+ } else if (input.isEmpty() || m.hasPartialMatch()) {
return Intermediate;
} else {
pos = input.size();
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index f50a79b061..66f093e490 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -151,7 +151,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
}
if (request.d->operation == QHttpNetworkRequest::Post) {
// add content type, if not set in the request
- if (request.headerField("content-type").isEmpty()) {
+ if (request.headerField("content-type").isEmpty() && ((request.d->uploadByteDevice && request.d->uploadByteDevice->size() > 0) || request.d->url.hasQuery())) {
//Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work.
//This warning indicates a bug in application code not setting a required header.
//Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index f4562cdb21..71b8237e03 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -63,6 +63,9 @@
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#include <link.h>
#endif
+#ifdef Q_OS_DARWIN
+#include "private/qcore_mac_p.h"
+#endif
#include <algorithm>
@@ -452,6 +455,15 @@ static QStringList libraryPathList()
# ifdef Q_OS_DARWIN
paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH"))
.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ // search in .app/Contents/Frameworks
+ UInt32 packageType;
+ CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, NULL);
+ if (packageType == FOUR_CHAR_CODE('APPL')) {
+ QUrl bundleUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyBundleURL(CFBundleGetMainBundle())));
+ QUrl frameworksUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle())));
+ paths << bundleUrl.resolved(frameworksUrl).path();
+ }
# else
paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
.split(QLatin1Char(':'), QString::SkipEmptyParts);
@@ -601,7 +613,13 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
}
#endif
+#ifndef Q_OS_DARWIN
// second attempt: find the development files libssl.so and libcrypto.so
+ //
+ // disabled on OS X/iOS:
+ // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
+ // attempt, _after_ <bundle>/Contents/Frameworks has been searched.
+ // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1);
if (libcrypto->load() && libssl->load()) {
@@ -611,6 +629,7 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
libssl->unload();
libcrypto->unload();
}
+#endif
// third attempt: loop on the most common library paths and find libssl
QStringList sslList = findAllLibSsl();
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 43df311636..1fa5723d85 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -612,6 +612,21 @@ void QGL2PaintEngineExPrivate::resetGLState()
#endif
}
+bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine()
+{
+ QOpenGLContext *guiGlContext = ctx->contextHandle();
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate && guiGlContextPrivate->active_engine) {
+ ctx->d_func()->refreshCurrentFbo();
+ guiGlContextPrivate->active_engine = 0;
+ return true;
+ }
+
+ return false;
+}
+
void QGL2PaintEngineEx::endNativePainting()
{
Q_D(QGL2PaintEngineEx);
@@ -2015,6 +2030,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->ctx = d->device->context();
d->ctx->d_ptr->active_engine = this;
+ d->resetOpenGLContextActiveEngine();
+
const QSize sz = d->device->size();
d->width = sz.width();
d->height = sz.height();
@@ -2080,6 +2097,8 @@ bool QGL2PaintEngineEx::end()
ctx->d_ptr->active_engine = 0;
+ d->resetOpenGLContextActiveEngine();
+
d->resetGLState();
delete d->shaderManager;
@@ -2105,7 +2124,7 @@ void QGL2PaintEngineEx::ensureActive()
Q_D(QGL2PaintEngineEx);
QGLContext *ctx = d->ctx;
- if (isActive() && ctx->d_ptr->active_engine != this) {
+ if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) {
ctx->d_ptr->active_engine = this;
d->needsSync = true;
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 528bfdeeb9..ac1d63df17 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -191,6 +191,7 @@ public:
void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
void resetGLState();
+ bool resetOpenGLContextActiveEngine();
// fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
// however writeClip can also be thought of as en entry point as it does similar things.
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 211fad267f..8cd26f1ea4 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -167,6 +167,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
+ ctx->d_ptr->refreshCurrentFbo();
+
funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo);
GLuint tmp_texture;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 1e49d95087..35f08e0092 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -510,6 +510,35 @@ void QGLContextPrivate::setupSharing() {
}
}
+void QGLContextPrivate::refreshCurrentFbo()
+{
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value
+ if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) {
+ GLint current;
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &current);
+
+ current_fbo = current;
+
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+ }
+}
+
+void QGLContextPrivate::setCurrentFbo(GLuint fbo)
+{
+ current_fbo = fbo;
+
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate)
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+}
+
+
/*!
\fn bool QGLFormat::doubleBuffer() const
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index c4151a3d34..4cf656fd86 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -238,6 +238,8 @@ public:
bool ownContext;
void setupSharing();
+ void refreshCurrentFbo();
+ void setCurrentFbo(GLuint fbo);
QGLFormat glFormat;
QGLFormat reqFormat;
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 4ef50e9334..4537f5bfae 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -472,6 +472,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return;
+ ctx->d_ptr->refreshCurrentFbo();
+
size = sz;
target = texture_target;
// texture dimensions
@@ -1027,7 +1029,7 @@ bool QGLFramebufferObject::bind()
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
d->valid = d->checkFramebufferStatus();
if (d->valid && current)
- current->d_ptr->current_fbo = d->fbo();
+ current->d_ptr->setCurrentFbo(d->fbo());
return d->valid;
}
@@ -1060,7 +1062,7 @@ bool QGLFramebufferObject::release()
#endif
if (current) {
- current->d_ptr->current_fbo = current->d_ptr->default_fbo;
+ current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo);
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo);
}
@@ -1109,6 +1111,20 @@ QGLFramebufferObjectFormat QGLFramebufferObject::format() const
Returns the contents of this framebuffer object as a QImage.
+ The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
+ only when internalTextureFormat() is set to \c GL_RGB.
+
+ If the rendering in the framebuffer was not done with premultiplied alpha in mind,
+ create a wrapper QImage with a non-premultiplied format. This is necessary before
+ performing operations like QImage::save() because otherwise the image data would get
+ unpremultiplied, even though it was not premultiplied in the first place. To create
+ such a wrapper without performing a copy of the pixel data, do the following:
+
+ \code
+ QImage fboImage(fbo.toImage());
+ QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
+ \endcode
+
On QNX the back buffer is not preserved when a buffer swap occures. So this function
might return old content.
*/
@@ -1173,7 +1189,7 @@ bool QGLFramebufferObject::bindDefault()
if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return false;
- ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo;
+ ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo);
functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo);
#ifdef QT_DEBUG
} else {
@@ -1320,7 +1336,12 @@ bool QGLFramebufferObject::isBound() const
{
Q_D(const QGLFramebufferObject);
const QGLContext *current = QGLContext::currentContext();
- return current ? current->d_ptr->current_fbo == d->fbo() : false;
+ if (current) {
+ current->d_ptr->refreshCurrentFbo();
+ return current->d_ptr->current_fbo == d->fbo();
+ }
+
+ return false;
}
/*!
@@ -1400,6 +1421,8 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q
const int ty0 = th - (targetRect.top() + targetRect.height());
const int ty1 = th - targetRect.top();
+ ctx->d_ptr->refreshCurrentFbo();
+
functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index 40cc7bb71d..c07d0a761b 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -74,6 +74,8 @@ void QGLPaintDevice::beginPaint()
QGLContext *ctx = context();
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
// Record the currently bound FBO so we can restore it again
// in endPaint() and bind this device's FBO
//
@@ -85,7 +87,7 @@ void QGLPaintDevice::beginPaint()
m_previousFBO = ctx->d_func()->current_fbo;
if (m_previousFBO != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -102,8 +104,10 @@ void QGLPaintDevice::ensureActiveTarget()
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
if (ctx->d_ptr->current_fbo != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -114,8 +118,11 @@ void QGLPaintDevice::endPaint()
{
// Make sure the FBO bound at beginPaint is re-bound again here:
QGLContext *ctx = context();
+
+ ctx->d_func()->refreshCurrentFbo();
+
if (m_previousFBO != ctx->d_func()->current_fbo) {
- ctx->d_ptr->current_fbo = m_previousFBO;
+ ctx->d_func()->setCurrentFbo(m_previousFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO);
}
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 56bfaebe4f..63b624aea2 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -344,6 +344,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
QOpenGLExtensions extensions(ctx->contextHandle());
+ ctx->d_ptr->refreshCurrentFbo();
+
if (d->blit_fbo) {
QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());
diff --git a/src/platformsupport/fontdatabases/basic/basic.pri b/src/platformsupport/fontdatabases/basic/basic.pri
index 88be809cd8..c2b882ed5a 100644
--- a/src/platformsupport/fontdatabases/basic/basic.pri
+++ b/src/platformsupport/fontdatabases/basic/basic.pri
@@ -17,6 +17,7 @@ contains(QT_CONFIG, freetype) {
$$QT_FREETYPE_DIR/src/base/ftbbox.c \
$$QT_FREETYPE_DIR/src/base/ftdebug.c \
$$QT_FREETYPE_DIR/src/base/ftglyph.c \
+ $$QT_FREETYPE_DIR/src/base/ftlcdfil.c \
$$QT_FREETYPE_DIR/src/base/ftinit.c \
$$QT_FREETYPE_DIR/src/base/ftmm.c \
$$QT_FREETYPE_DIR/src/base/fttype1.c \
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
index b2e2131a92..abbfd445a5 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
@@ -269,6 +269,18 @@ QStringList QOfonoDataConnectionManagerInterface::contexts()
return contextList;
}
+PathPropertiesList QOfonoDataConnectionManagerInterface::contextsWithProperties()
+{
+ if (contextListProperties.isEmpty()) {
+ QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ contextListProperties = reply.value();
+ }
+ }
+ return contextListProperties;
+}
+
bool QOfonoDataConnectionManagerInterface::roamingAllowed()
{
QVariant var = getProperty(QStringLiteral("RoamingAllowed"));
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
index 0ed00d94ff..3b97e06dd3 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
@@ -153,6 +153,7 @@ public:
~QOfonoDataConnectionManagerInterface();
QStringList contexts();
+ PathPropertiesList contextsWithProperties();
bool roamingAllowed();
QVariant getProperty(const QString &);
QString bearer();
@@ -162,6 +163,7 @@ private:
QVariantMap getProperties();
QVariantMap propertiesMap;
QStringList contextList;
+ PathPropertiesList contextListProperties;
private slots:
void propertyChanged(const QString &, const QDBusVariant &value);
};
diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp
index f416bb42a6..3576ddc37c 100644
--- a/src/plugins/bearer/networkmanager/main.cpp
+++ b/src/plugins/bearer/networkmanager/main.cpp
@@ -66,10 +66,7 @@ QBearerEngine *QNetworkManagerEnginePlugin::create(const QString &key) const
{
if (key == QLatin1String("networkmanager")) {
QNetworkManagerEngine *engine = new QNetworkManagerEngine;
- if (engine->networkManagerAvailable())
- return engine;
- else
- delete engine;
+ return engine;
}
return 0;
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index a8244f05cf..f0977b4735 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -56,29 +56,34 @@ QT_BEGIN_NAMESPACE
QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent)
: QBearerEngineImpl(parent),
- managerInterface(new QNetworkManagerInterface(this)),
- systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)),
- ofonoManager(new QOfonoManagerInterface(this))
+ managerInterface(NULL),
+ systemSettings(NULL),
+ ofonoManager(NULL),
+ nmAvailable(false)
{
-
- if (!managerInterface->isValid())
- return;
-
qDBusRegisterMetaType<QNmSettingsMap>();
- connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
- this, SLOT(deviceAdded(QDBusObjectPath)));
- connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
- this, SLOT(deviceRemoved(QDBusObjectPath)));
- connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
- this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
- connect(managerInterface, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
- this, SLOT(interfacePropertiesChanged(QMap<QString,QVariant>)));
- managerInterface->setConnections();
-
- connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)),
- this, SLOT(newConnection(QDBusObjectPath)));
- systemSettings->setConnections();
+ nmWatcher = new QDBusServiceWatcher(NM_DBUS_SERVICE,QDBusConnection::systemBus(),
+ QDBusServiceWatcher::WatchForRegistration |
+ QDBusServiceWatcher::WatchForUnregistration, this);
+ connect(nmWatcher, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(nmRegistered(QString)));
+ connect(nmWatcher, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(nmUnRegistered(QString)));
+
+ ofonoWatcher = new QDBusServiceWatcher("org.ofono",QDBusConnection::systemBus(),
+ QDBusServiceWatcher::WatchForRegistration |
+ QDBusServiceWatcher::WatchForUnregistration, this);
+ connect(ofonoWatcher, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(ofonoRegistered(QString)));
+ connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(ofonoUnRegistered(QString)));
+
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono"))
+ ofonoRegistered();
+
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_SERVICE))
+ nmRegistered();
}
QNetworkManagerEngine::~QNetworkManagerEngine()
@@ -105,15 +110,13 @@ QNetworkManagerEngine::~QNetworkManagerEngine()
void QNetworkManagerEngine::initialize()
{
- QMutexLocker locker(&mutex);
+ if (nmAvailable)
+ setupConfigurations();
+}
- if (ofonoManager->isValid()) {
- Q_FOREACH (const QString &modem, ofonoManager->getModems()) {
- QOfonoDataConnectionManagerInterface *ofonoContextManager
- = new QOfonoDataConnectionManagerInterface(modem,this);
- ofonoContextManagers.insert(modem, ofonoContextManager);
- }
- }
+void QNetworkManagerEngine::setupConfigurations()
+{
+ QMutexLocker locker(&mutex);
// Get active connections.
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
@@ -151,7 +154,7 @@ void QNetworkManagerEngine::initialize()
bool QNetworkManagerEngine::networkManagerAvailable() const
{
- return managerInterface->isValid();
+ return nmAvailable;
}
QString QNetworkManagerEngine::getInterfaceFromId(const QString &settingsPath)
@@ -180,6 +183,9 @@ void QNetworkManagerEngine::connectToId(const QString &id)
const QString settingsPath = connection->connectionInterface()->path();
QString specificPath = configuredAccessPoints.key(settingsPath);
+ if (isConnectionActive(settingsPath))
+ return;
+
QHashIterator<QString, QNetworkManagerInterfaceDevice*> i(interfaceDevices);
while (i.hasNext()) {
i.next();
@@ -229,7 +235,7 @@ void QNetworkManagerEngine::disconnectFromId(const QString &id)
void QNetworkManagerEngine::requestUpdate()
{
- if (managerInterface->wirelessEnabled()) {
+ if (managerInterface && managerInterface->wirelessEnabled()) {
QHashIterator<QString, QNetworkManagerInterfaceDeviceWireless *> i(wirelessDevices);
while (i.hasNext()) {
i.next();
@@ -282,8 +288,9 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QMap<QString, QVari
if (ptr) {
ptr->mutex.lock();
if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
- ptr->state != QNetworkConfiguration::Active) {
- ptr->state = QNetworkConfiguration::Active;
+ (ptr->state & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
+
+ ptr->state |= QNetworkConfiguration::Active;
if (activeConnectionsList.value(id) && activeConnectionsList.value(id)->defaultRoute()
&& managerInterface->state() < QNetworkManagerInterface::NM_STATE_CONNECTED_GLOBAL) {
@@ -339,23 +346,25 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QMap<QString
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (ptr) {
- ptr->mutex.lock();
- if (properties.value("State").toUInt() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
- QStringList devices = activeConnection->devices();
- if (!devices.isEmpty()) {
- QNetworkManagerInterfaceDevice device(devices.at(0),this);
- connectionInterfaces.insert(id,device.networkInterface());
- }
+ if (properties.contains(QStringLiteral("State"))) {
+ ptr->mutex.lock();
+ if (properties.value("State").toUInt() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ QStringList devices = activeConnection->devices();
+ if (!devices.isEmpty()) {
+ QNetworkManagerInterfaceDevice device(devices.at(0),this);
+ connectionInterfaces.insert(id,device.networkInterface());
+ }
- ptr->state |= QNetworkConfiguration::Active;
- ptr->mutex.unlock();
+ ptr->state |= QNetworkConfiguration::Active;
+ ptr->mutex.unlock();
- locker.unlock();
- emit configurationChanged(ptr);
- locker.relock();
- } else {
- connectionInterfaces.remove(id);
- ptr->mutex.unlock();
+ locker.unlock();
+ emit configurationChanged(ptr);
+ locker.relock();
+ } else {
+ connectionInterfaces.remove(id);
+ ptr->mutex.unlock();
+ }
}
}
}
@@ -403,9 +412,6 @@ void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path)
connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished()));
wirelessDevice->setConnections();
- foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints())
- newAccessPoint(apPath.path());
-
wirelessDevices.insert(path.path(), wirelessDevice);
}
@@ -518,14 +524,9 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
parseConnection(settingsPath, connection->getSettings());
// Check if connection is active.
- QHashIterator<QString, QNetworkManagerConnectionActive*> i(activeConnectionsList);
- while (i.hasNext()) {
- i.next();
- if (i.value()->connection().path() == settingsPath) {
- cpPriv->state |= QNetworkConfiguration::Active;
- break;
- }
- }
+ if (isConnectionActive(settingsPath))
+ cpPriv->state |= QNetworkConfiguration::Active;
+
if (deviceType == DEVICE_TYPE_ETHERNET) {
QHashIterator<QString, QNetworkManagerInterfaceDevice*> i(interfaceDevices);
while (i.hasNext()) {
@@ -539,12 +540,36 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
}
}
}
+
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
locker.unlock();
emit configurationAdded(ptr);
}
+bool QNetworkManagerEngine::isConnectionActive(const QString &settingsPath)
+{
+ QHashIterator<QString, QNetworkManagerConnectionActive*> i(activeConnectionsList);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value()->connection().path() == settingsPath) {
+ if (i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
+ || i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ return true;
+ } else {
+ break;
+ }
+ }
+ }
+
+ QNetworkManagerSettingsConnection *settingsConnection = connectionFromId(settingsPath);
+ if (settingsConnection->getType() == DEVICE_TYPE_MODEM) {
+ return isActiveContext(settingsConnection->connectionInterface()->path());
+ }
+
+ return false;
+}
+
void QNetworkManagerEngine::removeConnection(const QString &path)
{
QMutexLocker locker(&mutex);
@@ -652,7 +677,6 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
void QNetworkManagerEngine::newAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
-
QNetworkManagerInterfaceAccessPoint *accessPoint =
new QNetworkManagerInterfaceAccessPoint(path,this);
@@ -683,6 +707,9 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path)
ptr->mutex.lock();
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
+
+ if (isConnectionActive(settingsPath))
+ ptr->state = (flag | QNetworkConfiguration::Active);
ptr->mutex.unlock();
locker.unlock();
@@ -762,7 +789,6 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
QMutexLocker locker(&mutex);
QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate;
cpPriv->name = map.value("connection").value("id").toString();
-
cpPriv->isValid = true;
cpPriv->id = settingsPath;
cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
@@ -811,18 +837,46 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
}
} else if (connectionType == QLatin1String("gsm")) {
- const QString contextPath = map.value("connection").value("id").toString();
- cpPriv->name = contextName(contextPath);
- cpPriv->bearerType = currentBearerType(contextPath);
-
- if (map.value("connection").contains("timestamp")) {
- cpPriv->state |= QNetworkConfiguration::Discovered;
+ const QString connectionPath = map.value("connection").value("id").toString();
+ cpPriv->name = contextName(connectionPath);
+ cpPriv->bearerType = currentBearerType(connectionPath);
+
+ if (ofonoManager && ofonoManager->isValid()) {
+ const QString contextPart = connectionPath.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ const QString path = i.key() +"/"+contextPart;
+ if (isActiveContext(path)) {
+ cpPriv->state |= QNetworkConfiguration::Active;
+ break;
+ }
+ }
}
}
return cpPriv;
}
+bool QNetworkManagerEngine::isActiveContext(const QString &contextPath)
+{
+ if (ofonoManager && ofonoManager->isValid()) {
+ const QString contextPart = contextPath.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ PathPropertiesList list = i.value()->contextsWithProperties();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).path.path().contains(contextPart)) {
+ return list.at(i).properties.value(QStringLiteral("Active")).toBool();
+
+ }
+ }
+ }
+ }
+ return false;
+}
+
QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QString &id) const
{
for (int i = 0; i < connections.count(); ++i) {
@@ -967,53 +1021,111 @@ QNetworkConfigurationPrivatePointer QNetworkManagerEngine::defaultConfiguration(
QNetworkConfiguration::BearerType QNetworkManagerEngine::currentBearerType(const QString &id)
{
- if (ofonoManager->isValid()) {
- QString contextPart = id.section('/', -1);
-
- QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
- while (i.hasNext()) {
- i.next();
- QString contextPath = i.key() +"/"+contextPart;
- if (i.value()->contexts().contains(contextPath)) {
-
- QString bearer = i.value()->bearer();
- if (bearer == QStringLiteral("gsm")) {
- return QNetworkConfiguration::Bearer2G;
- } else if (bearer == QStringLiteral("edge")) {
- return QNetworkConfiguration::Bearer2G;
- } else if (bearer == QStringLiteral("umts")) {
- return QNetworkConfiguration::BearerWCDMA;
- } else if (bearer == QStringLiteral("hspa")
- || bearer == QStringLiteral("hsdpa")
- || bearer == QStringLiteral("hsupa")) {
- return QNetworkConfiguration::BearerHSPA;
- } else if (bearer == QStringLiteral("lte")) {
- return QNetworkConfiguration::BearerLTE;
- }
+ QString contextPart = id.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ QString contextPath = i.key() +"/"+contextPart;
+
+ if (i.value()->contexts().contains(contextPath)) {
+
+ QString bearer = i.value()->bearer();
+
+ if (bearer == QStringLiteral("gsm")) {
+ return QNetworkConfiguration::Bearer2G;
+ } else if (bearer == QStringLiteral("edge")) {
+ return QNetworkConfiguration::Bearer2G;
+ } else if (bearer == QStringLiteral("umts")) {
+ return QNetworkConfiguration::BearerWCDMA;
+ } else if (bearer == QStringLiteral("hspa")
+ || bearer == QStringLiteral("hsdpa")
+ || bearer == QStringLiteral("hsupa")) {
+ return QNetworkConfiguration::BearerHSPA;
+ } else if (bearer == QStringLiteral("lte")) {
+ return QNetworkConfiguration::BearerLTE;
}
}
}
+
return QNetworkConfiguration::BearerUnknown;
}
QString QNetworkManagerEngine::contextName(const QString &path)
{
- if (ofonoManager->isValid()) {
- QString contextPart = path.section('/', -1);
- QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
- while (i.hasNext()) {
- i.next();
- Q_FOREACH (const QString &oContext, i.value()->contexts()) {
- if (oContext.contains(contextPart)) {
- QOfonoConnectionContextInterface contextInterface(oContext,this);
- return contextInterface.name();
- }
+ QString contextPart = path.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ PathPropertiesList list = i.value()->contextsWithProperties();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).path.path().contains(contextPart)) {
+ return list.at(i).properties.value(QStringLiteral("Name")).toString();
}
}
}
return path;
}
+void QNetworkManagerEngine::nmRegistered(const QString &)
+{
+ if (ofonoManager) {
+ delete ofonoManager;
+ ofonoManager = NULL;
+ }
+ managerInterface = new QNetworkManagerInterface(this);
+ systemSettings = new QNetworkManagerSettings(NM_DBUS_SERVICE, this);
+
+ connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
+ this, SLOT(deviceAdded(QDBusObjectPath)));
+ connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
+ this, SLOT(deviceRemoved(QDBusObjectPath)));
+ connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
+ this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
+ connect(managerInterface, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
+ this, SLOT(interfacePropertiesChanged(QMap<QString,QVariant>)));
+ managerInterface->setConnections();
+
+ connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)),
+ this, SLOT(newConnection(QDBusObjectPath)));
+ systemSettings->setConnections();
+ nmAvailable = true;
+
+ setupConfigurations();
+}
+
+void QNetworkManagerEngine::nmUnRegistered(const QString &)
+{
+ if (systemSettings) {
+ delete systemSettings;
+ systemSettings = NULL;
+ }
+ if (managerInterface) {
+ delete managerInterface;
+ managerInterface = NULL;
+ }
+}
+
+void QNetworkManagerEngine::ofonoRegistered(const QString &)
+{
+ if (ofonoManager) {
+ delete ofonoManager;
+ ofonoManager = NULL;
+ }
+ ofonoManager = new QOfonoManagerInterface(this);
+ if (ofonoManager && ofonoManager->isValid()) {
+ Q_FOREACH (const QString &modem, ofonoManager->getModems()) {
+ QOfonoDataConnectionManagerInterface *ofonoContextManager
+ = new QOfonoDataConnectionManagerInterface(modem,this);
+ ofonoContextManagers.insert(modem, ofonoContextManager);
+ }
+ }
+}
+
+void QNetworkManagerEngine::ofonoUnRegistered(const QString &)
+{
+ ofonoContextManagers.clear();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
index 671ed80dab..da6af14c00 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -109,6 +109,12 @@ private Q_SLOTS:
void wiredCarrierChanged(bool);
+ void nmRegistered(const QString &serviceName = QString());
+ void nmUnRegistered(const QString &serviceName = QString());
+
+ void ofonoRegistered(const QString &serviceName = QString());
+ void ofonoUnRegistered(const QString &serviceName = QString());
+
private:
QNetworkConfigurationPrivate *parseConnection(const QString &settingsPath,
const QNmSettingsMap &map);
@@ -132,6 +138,13 @@ private:
QNetworkConfiguration::BearerType currentBearerType(const QString &id);
QString contextName(const QString &path);
+ bool isConnectionActive(const QString &settingsPath);
+ QDBusServiceWatcher *ofonoWatcher;
+ QDBusServiceWatcher *nmWatcher;
+
+ bool isActiveContext(const QString &contextPath);
+ bool nmAvailable;
+ void setupConfigurations();
};
QT_END_NAMESPACE
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
index dc3b71ec8e..fad94f069d 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
@@ -688,6 +688,15 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
+
+ QDBusPendingReply<QList<QDBusObjectPath> > reply
+ = d->connectionInterface->asyncCall(QLatin1String("GetAccessPoints"));
+
+ QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply);
+ connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(accessPointsFinished(QDBusPendingCallWatcher*)));
+
+
d->valid = true;
}
@@ -749,6 +758,19 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections()
return allOk;
}
+void QNetworkManagerInterfaceDeviceWireless::accessPointsFinished(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<QList<QDBusObjectPath> > reply(*watcher);
+ watcher->deleteLater();
+ if (!reply.isError()) {
+ accessPointsList = reply.value();
+ }
+
+ for (int i = 0; i < accessPointsList.size(); i++) {
+ Q_EMIT accessPointAdded(accessPointsList.at(i).path());
+ }
+}
+
QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const
{
return d->connectionInterface;
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
index da909c443a..e645159d71 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -369,6 +369,8 @@ private Q_SLOTS:
void slotAccessPointAdded(QDBusObjectPath);
void slotAccessPointRemoved(QDBusObjectPath);
+ void accessPointsFinished(QDBusPendingCallWatcher *watcher);
+
private:
QNetworkManagerInterfaceDeviceWirelessPrivate *d;
QVariantMap propertyMap;
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 791b0805d0..251fe9485c 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -323,17 +323,22 @@ NSMenuItem *QCocoaMenuItem::sync()
text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")");
QString finalString = qt_mac_removeMnemonics(text);
+ bool useAttributedTitle = false;
// Cocoa Font and title
if (m_font.resolve()) {
NSFont *customMenuFont = [NSFont fontWithName:QCFString::toNSString(m_font.family())
size:m_font.pointSize()];
- NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
- NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
- NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString)
- attributes:attributes] autorelease];
- [m_native setAttributedTitle: str];
- } else {
+ if (customMenuFont) {
+ NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
+ NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
+ NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString)
+ attributes:attributes] autorelease];
+ [m_native setAttributedTitle: str];
+ useAttributedTitle = true;
+ }
+ }
+ if (!useAttributedTitle) {
[m_native setTitle: QCFString::toNSString(finalString)];
}
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
index 6565e08302..7e1cb9a4fd 100644
--- a/src/plugins/platforms/ios/quiview_accessibility.mm
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -48,7 +48,7 @@
- (void)createAccessibleElement:(QAccessibleInterface *)iface
{
- if (!iface || iface->state().invisible)
+ if (!iface || iface->state().invisible || (iface->text(QAccessible::Name).isEmpty() && iface->text(QAccessible::Value).isEmpty() && iface->text(QAccessible::Description).isEmpty()))
return;
QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
@@ -60,12 +60,9 @@
if (!iface)
return;
- if (iface->childCount() == 0) {
- [self createAccessibleElement: iface];
- } else {
- for (int i = 0; i < iface->childCount(); ++i)
- [self createAccessibleContainer: iface->child(i)];
- }
+ [self createAccessibleElement: iface];
+ for (int i = 0; i < iface->childCount(); ++i)
+ [self createAccessibleContainer: iface->child(i)];
}
- (void)initAccessibility
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index cfa5914ff8..d8ccb8cd56 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -804,10 +804,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
uint format = GGO_METRICS;
if (ttf)
format |= GGO_GLYPH_INDEX;
- int res = GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat);
- if (res == GDI_ERROR) {
+ if (GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat) == GDI_ERROR)
return false;
- }
// #### obey scale
*metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y,
(int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY,
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index f31ecf8e03..7286b6b89b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -471,6 +471,7 @@ public:
QXcbEventReader *eventReader() const { return m_reader; }
+ bool canGrab() const { return m_canGrabServer; }
protected:
bool event(QEvent *e) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 52269bafea..3818494d99 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -92,11 +92,11 @@
QT_BEGIN_NAMESPACE
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,.
// or, for older Linuxes, read out 'cmdline'.
static bool runningUnderDebugger()
{
+#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
const QString parentProc = QLatin1String("/proc/") + QString::number(getppid());
const QFileInfo parentProcExe(parentProc + QLatin1String("/exe"));
if (parentProcExe.isSymLink())
@@ -113,12 +113,15 @@ static bool runningUnderDebugger()
s += c;
}
return s == "gdb";
-}
+#else
+ return false;
#endif
+}
QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
: m_services(new QGenericUnixServices)
, m_instanceName(0)
+ , m_canGrab(true)
{
qRegisterMetaType<QXcbWindow*>();
#ifdef XCB_USE_XLIB
@@ -126,16 +129,10 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
#endif
m_nativeInterface.reset(new QXcbNativeInterface);
- bool canGrab = true;
- #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- canGrab = !runningUnderDebugger();
- #endif
- static bool canNotGrabEnv = qgetenv("QT_XCB_NO_GRAB_SERVER").length();
- if (canNotGrabEnv)
- canGrab = false;
-
// Parse arguments
const char *displayName = 0;
+ bool noGrabArg = false;
+ bool doGrabArg = false;
if (argc) {
int j = 1;
for (int i = 1; i < argc; i++) {
@@ -146,13 +143,35 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
displayName = argv[++i];
else if (arg == "-name" && i < argc - 1)
m_instanceName = argv[++i];
+ else if (arg == "-nograb")
+ noGrabArg = true;
+ else if (arg == "-dograb")
+ doGrabArg = true;
else
argv[j++] = argv[i];
}
argc = j;
} // argc
- m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab, displayName);
+ bool underDebugger = runningUnderDebugger();
+ if (noGrabArg && doGrabArg && underDebugger) {
+ qWarning() << "Both -nograb and -dograb command line arguments specified. Please pick one. -nograb takes prcedence";
+ doGrabArg = false;
+ }
+
+#if defined(QT_DEBUG)
+ if (!noGrabArg && !doGrabArg && underDebugger) {
+ qDebug("Qt: gdb: -nograb added to command-line options.\n"
+ "\t Use the -dograb option to enforce grabbing.");
+ }
+#endif
+ m_canGrab = (!underDebugger && noGrabArg) || (underDebugger && doGrabArg);
+
+ static bool canNotGrabEnv = qEnvironmentVariableIsSet("QT_XCB_NO_GRAB_SERVER");
+ if (canNotGrabEnv)
+ m_canGrab = false;
+
+ m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName);
for (int i = 0; i < parameters.size() - 1; i += 2) {
#ifdef Q_XCB_DEBUG
@@ -408,12 +427,14 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::StartDragTime:
case QPlatformIntegration::KeyboardAutoRepeatRate:
case QPlatformIntegration::PasswordMaskDelay:
- case QPlatformIntegration::FontSmoothingGamma:
case QPlatformIntegration::StartDragVelocity:
case QPlatformIntegration::UseRtlExtensions:
case QPlatformIntegration::PasswordMaskCharacter:
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
+ case QPlatformIntegration::FontSmoothingGamma:
+ // Match Qt 4.8 text rendering, and rendering of other X11 toolkits.
+ return qreal(1.0);
case QPlatformIntegration::StartDragDistance: {
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index ffb068ecb3..db6ad541ea 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -117,6 +117,7 @@ private:
mutable QByteArray m_wmClass;
const char *m_instanceName;
+ bool m_canGrab;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 5d3206b097..85af8ee1d2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2170,6 +2170,9 @@ void QXcbWindow::updateSyncRequestCounter()
bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
@@ -2185,6 +2188,9 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index ade5cfe3dc..41692d11bd 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -414,12 +414,14 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const
if (qobject_cast<QLabel*>(object())) {
QLabel *label = qobject_cast<QLabel*>(object());
str = label->text();
+#ifndef QT_NO_TEXTHTMLPARSER
if (label->textFormat() == Qt::RichText
|| (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) {
QTextDocument doc;
doc.setHtml(str);
str = doc.toPlainText();
}
+#endif
if (label->buddy())
str = qt_accStripAmp(str);
#ifndef QT_NO_LCDNUMBER
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 300e2f492b..03f22a270f 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -2447,7 +2447,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
Items are visible by default; it is unnecessary to call
setVisible() on a new item.
- \sa isVisible(), show(), hide()
+ \note An item with opacity set to 0 will still be considered visible,
+ although it will be treated like an invisible item: mouse events will pass
+ through it, it will not be included in the items returned by
+ QGraphicsView::items(), and so on. However, the item will retain the focus.
+
+ \sa isVisible(), show(), hide(), setOpacity()
*/
void QGraphicsItem::setVisible(bool visible)
{
@@ -2715,7 +2720,11 @@ qreal QGraphicsItem::effectiveOpacity() const
with the parent: ItemIgnoresParentOpacity and
ItemDoesntPropagateOpacityToChildren.
- \sa opacity(), effectiveOpacity()
+ \note Setting the opacity of an item to 0 will not make the item invisible
+ (according to isVisible()), but the item will be treated like an invisible
+ one. See the documentation of setVisible() for more information.
+
+ \sa opacity(), effectiveOpacity(), setVisible()
*/
void QGraphicsItem::setOpacity(qreal opacity)
{
@@ -9782,6 +9791,7 @@ QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const
using textWidth().
\note In order to align HTML text in the center, the item's text width must be set.
+ Otherwise, you can call adjustSize() after setting the item's text.
\image graphicsview-textitem.png
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 8f6c5d748c..82b9fec37f 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -53,6 +53,7 @@
#include "qtranslator.h"
#include "qvariant.h"
#include "qwidget.h"
+#include "qgraphicssceneevent.h"
#include "private/qdnd_p.h"
#include "private/qguiapplication_p.h"
#include "qcolormap.h"
@@ -2286,6 +2287,31 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
return w;
}
+Qt::MouseEventSource QApplicationPrivate::mouseEventSource(const QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ case QEvent::NonClientAreaMouseButtonPress:
+ case QEvent::NonClientAreaMouseButtonRelease:
+ case QEvent::NonClientAreaMouseMove:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ return static_cast<const QMouseEvent *>(e)->source();
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseMove:
+ return static_cast<const QGraphicsSceneMouseEvent *>(e)->source();
+#endif // !QT_NO_GRAPHICSVIEW
+ default:
+ break;
+ }
+ return Qt::MouseEventNotSynthesized;
+}
+
/*!
\fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
\internal
@@ -4230,8 +4256,9 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
return true;
}
-void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
{
+ bool containsPress = false;
for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i];
@@ -4244,7 +4271,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
touchPoint.d->rect = rect;
touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
+
+ if (touchPoint.state() == Qt::TouchPointPressed)
+ containsPress = true;
}
+ return containsPress;
}
void QApplicationPrivate::initializeMultitouch()
@@ -4391,11 +4422,14 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
QApplication::keyboardModifiers(),
it.value().first,
it.value().second);
- updateTouchPointsForWidget(widget, &touchEvent);
+ bool containsPress = updateTouchPointsForWidget(widget, &touchEvent);
touchEvent.setTimestamp(timestamp);
touchEvent.setWindow(window->windowHandle());
touchEvent.setTarget(widget);
+ if (containsPress)
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
+
switch (touchEvent.type()) {
case QEvent::TouchBegin:
{
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 156bf34194..b24b592fbe 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -168,6 +168,7 @@ public:
static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next,
bool *wrappingOccurred = 0);
+ static Qt::MouseEventSource mouseEventSource(const QEvent *e);
#ifndef QT_NO_GRAPHICSVIEW
// Maintain a list of all scenes to ensure font and palette propagation to
@@ -275,7 +276,7 @@ public:
QPixmap *ignore_cursor;
#endif
- static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+ static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
void initializeMultitouch();
void initializeMultitouch_sys();
void cleanupMultitouch();
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index 183a2eba0f..26d9ede59d 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -80,7 +80,7 @@ class QPanGesturePrivate : public QGesturePrivate
public:
QPanGesturePrivate()
- : acceleration(0), xVelocity(0), yVelocity(0)
+ : acceleration(0), xVelocity(0), yVelocity(0), pointCount(2)
{
}
@@ -95,6 +95,7 @@ public:
qreal acceleration;
qreal xVelocity;
qreal yVelocity;
+ int pointCount; // ### fixme Qt 5.5: Add accessor to QPanGesture.
};
class QPinchGesturePrivate : public QGesturePrivate
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 739e6b1870..c9af3062d3 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -63,6 +63,24 @@
QT_BEGIN_NAMESPACE
+static inline int panTouchPoints()
+{
+ // Override by environment variable for testing.
+ static const char panTouchPointVariable[] = "QT_PAN_TOUCHPOINTS";
+ if (qEnvironmentVariableIsSet(panTouchPointVariable)) {
+ bool ok;
+ const int result = qgetenv(panTouchPointVariable).toInt(&ok);
+ if (ok && result >= 1)
+ return result;
+ qWarning() << "Ignoring invalid value of " << panTouchPointVariable;
+ }
+ // Pan should use 1 finger on a touch screen and 2 fingers on touch pads etc.
+ // where 1 finger movements are used for mouse event synthetization. For now,
+ // default to 2 until all classes inheriting QScrollArea are fixed to handle it
+ // correctly.
+ return 2;
+}
+
QGestureManager::QGestureManager(QObject *parent)
: QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
{
@@ -73,7 +91,7 @@ QGestureManager::QGestureManager(QObject *parent)
registerGestureRecognizer(new QMacPinchGestureRecognizer);
registerGestureRecognizer(new QMacPanGestureRecognizer);
#else
- registerGestureRecognizer(new QPanGestureRecognizer);
+ registerGestureRecognizer(new QPanGestureRecognizer(panTouchPoints()));
registerGestureRecognizer(new QPinchGestureRecognizer);
registerGestureRecognizer(new QSwipeGestureRecognizer);
registerGestureRecognizer(new QTapGestureRecognizer);
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 23bb1f7050..db116b070c 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -578,12 +578,22 @@ GLuint QOpenGLWidgetPrivate::textureId() const
void QOpenGLWidgetPrivate::reset()
{
+ Q_Q(QOpenGLWidget);
+
+ // Destroy the OpenGL resources first. These need the context to be current.
+ if (initialized)
+ q->makeCurrent();
+
delete paintDevice;
paintDevice = 0;
delete fbo;
fbo = 0;
delete resolvedFbo;
resolvedFbo = 0;
+
+ if (initialized)
+ q->doneCurrent();
+
// Delete the context first, then the surface. Slots connected to
// the context's aboutToBeDestroyed() may still call makeCurrent()
// to perform some cleanup.
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index 9e3cb473e5..53e5d091fa 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -38,16 +38,13 @@
#include "qwidget.h"
#include "qabstractscrollarea.h"
#include <qgraphicssceneevent.h>
+#include <QtGui/QTouchDevice>
#include "qdebug.h"
#ifndef QT_NO_GESTURES
QT_BEGIN_NAMESPACE
-QPanGestureRecognizer::QPanGestureRecognizer()
-{
-}
-
QGesture *QPanGestureRecognizer::create(QObject *target)
{
if (target && target->isWidgetType()) {
@@ -62,8 +59,35 @@ QGesture *QPanGestureRecognizer::create(QObject *target)
return new QPanGesture;
}
+static QPointF panOffset(const QList<QTouchEvent::TouchPoint> &touchPoints, int maxCount)
+{
+ QPointF result;
+ const int count = qMin(touchPoints.size(), maxCount);
+ for (int p = 0; p < count; ++p)
+ result += touchPoints.at(p).pos() - touchPoints.at(p).startPos();
+ return result / qreal(count);
+}
+
+// ### fixme: Remove this
+// Use single finger pan to scroll QPlainTextEdit/QTextEdit
+// by changing the number of pan points to 1 for these classes.
+// This used to be Qt 4's behavior on Windows which was achieved using native
+// Windows gesture recognizers for these classes.
+// The other classes inheriting QScrollArea still use standard 2 finger pan.
+// In the long run, they should also use single finger pan to
+// scroll on touch screens, however, this requires a distinct Tap&Hold-followed-by-pan
+// type gesture to avoid clashes with item view selection and DnD.
+
+static inline int panTouchPoints(const QTouchEvent *event, const QObject *object,
+ int defaultTouchPoints)
+{
+ return event->device()->type() == QTouchDevice::TouchScreen && object && object->parent()
+ && (object->parent()->inherits("QPlainTextEdit") || object->parent()->inherits("QTextEdit"))
+ ? 1 : defaultTouchPoints;
+}
+
QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
- QObject *,
+ QObject *object,
QEvent *event)
{
QPanGesture *q = static_cast<QPanGesture *>(state);
@@ -76,18 +100,15 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
result = QGestureRecognizer::MayBeGesture;
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastOffset = d->offset = QPointF();
+ d->pointCount = panTouchPoints(ev, object, m_pointCount);
break;
}
case QEvent::TouchEnd: {
if (q->state() != Qt::NoGesture) {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
- if (ev->touchPoints().size() == 2) {
- QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
- QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ if (ev->touchPoints().size() == d->pointCount) {
d->lastOffset = d->offset;
- d->offset =
- QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
- p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ d->offset = panOffset(ev->touchPoints(), d->pointCount);
}
result = QGestureRecognizer::FinishGesture;
} else {
@@ -97,16 +118,12 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
}
case QEvent::TouchUpdate: {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
- if (ev->touchPoints().size() >= 2) {
- QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
- QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ if (ev->touchPoints().size() >= d->pointCount) {
d->lastOffset = d->offset;
- d->offset =
- QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
- p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ d->offset = panOffset(ev->touchPoints(), d->pointCount);
if (d->offset.x() > 10 || d->offset.y() > 10 ||
d->offset.x() < -10 || d->offset.y() < -10) {
- q->setHotSpot(p1.startScreenPos());
+ q->setHotSpot(ev->touchPoints().first().startScreenPos());
result = QGestureRecognizer::TriggerGesture;
} else {
result = QGestureRecognizer::MayBeGesture;
diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h
index aeabd9cc7e..15ba31f26a 100644
--- a/src/widgets/kernel/qstandardgestures_p.h
+++ b/src/widgets/kernel/qstandardgestures_p.h
@@ -55,11 +55,14 @@ QT_BEGIN_NAMESPACE
class QPanGestureRecognizer : public QGestureRecognizer
{
public:
- QPanGestureRecognizer();
+ explicit QPanGestureRecognizer(int pointCount = 2) : m_pointCount(pointCount) {}
QGesture *create(QObject *target);
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
void reset(QGesture *state);
+
+private:
+ const int m_pointCount;
};
class QPinchGestureRecognizer : public QGestureRecognizer
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 315d615d89..78eabf3c4c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -10511,8 +10511,9 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
QWidget *parentWithWindow =
newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
if (parentWithWindow) {
- if (f & Qt::Window) {
- q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
+ QWidget *topLevel = parentWithWindow->window();
+ if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
+ q->windowHandle()->setTransientParent(topLevel->windowHandle());
q->windowHandle()->setParent(0);
} else {
q->windowHandle()->setTransientParent(0);
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index c1d6d879a8..71a9b1abd7 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -553,7 +553,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
} else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
- } if (!arrow.isNull()) {
+ }
+
+ if (!arrow.isNull()) {
r.setSize(QSize(arrow.width()/2, arrow.height()/2));
r.moveCenter(header->rect.center());
painter->drawPixmap(r.translated(offset), arrow);
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp
index c18bbb3431..c1f7b599b3 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/widgets/styles/qwindowsxpstyle.cpp
@@ -963,7 +963,8 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
QImage img;
if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
- buffer(w, h); // Ensure a buffer of at least (w, h) in size
+ if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size
+ return;
HDC dc = bufferHDC();
// Clear the buffer
@@ -2539,7 +2540,7 @@ QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const
const int hSpace = theme->rect.width() - size.width();
const int vSpace = theme->rect.height() - size.height();
- const bool sufficientSpace = horizontal && hSpace > (contentsMargin.left() + contentsMargin.right())
+ const bool sufficientSpace = (horizontal && hSpace > (contentsMargin.left() + contentsMargin.right()))
|| vSpace > contentsMargin.top() + contentsMargin.bottom();
return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect();
}
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index f9376a78d5..ddecea81bf 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -1500,6 +1500,13 @@ bool QMainWindow::event(QEvent *event)
/*!
\property QMainWindow::unifiedTitleAndToolBarOnMac
\brief whether the window uses the unified title and toolbar look on Mac OS X
+
+ Note that the Qt 5 implementation has several limitations compared to Qt 4:
+ \list
+ \li Use in windows with OpenGL content is not supported. This includes QGLWidget and QOpenGLWidget.
+ \li Using dockable or movable toolbars may result in painting errors and is not recommended
+ \endlist
+
\since 5.2
*/
void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 1e291f469e..3553baf68a 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -1511,7 +1511,7 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)
#ifndef QT_NO_RUBBERBAND
if (!rubberBand) {
- rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport);
+ rubberBand = new QRubberBand(QRubberBand::Rectangle, q);
// For accessibility to identify this special widget.
rubberBand->setObjectName(QLatin1String("qt_rubberband"));
rubberBand->setWindowFlags(rubberBand->windowFlags() | Qt::WindowStaysOnTopHint);
@@ -1528,6 +1528,20 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)
Q_ASSERT(indexToHighlighted >= 0);
}
+void QMdiAreaPrivate::showRubberBandFor(QMdiSubWindow *subWindow)
+{
+ if (!subWindow || !rubberBand)
+ return;
+
+ if (viewMode == QMdiArea::TabbedView)
+ rubberBand->setGeometry(tabBar->tabRect(childWindows.indexOf(subWindow)));
+ else
+ rubberBand->setGeometry(subWindow->geometry());
+
+ rubberBand->raise();
+ rubberBand->show();
+}
+
/*!
\internal
\since 4.4
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 1092fd9a30..ba531adaad 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -248,14 +248,7 @@ public:
}
#ifndef QT_NO_RUBBERBAND
- inline void showRubberBandFor(QMdiSubWindow *subWindow)
- {
- if (!subWindow || !rubberBand)
- return;
- rubberBand->setGeometry(subWindow->geometry());
- rubberBand->raise();
- rubberBand->show();
- }
+ void showRubberBandFor(QMdiSubWindow *subWindow);
inline void hideRubberBand()
{
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index b6a21f183a..72a556db7c 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2042,11 +2042,13 @@ void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e)
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
- QRect visible = d->viewport->rect();
- if (visible.contains(pos))
- d->autoScrollTimer.stop();
- else if (!d->autoScrollTimer.isActive())
- d->autoScrollTimer.start(100, this);
+ if (e->source() == Qt::MouseEventNotSynthesized) {
+ const QRect visible = d->viewport->rect();
+ if (visible.contains(pos))
+ d->autoScrollTimer.stop();
+ else if (!d->autoScrollTimer.isActive())
+ d->autoScrollTimer.start(100, this);
+ }
}
/*! \reimp
@@ -2055,7 +2057,7 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QPlainTextEdit);
d->sendControlEvent(e);
- if (d->autoScrollTimer.isActive()) {
+ if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
d->autoScrollTimer.stop();
d->ensureCursorVisible();
}
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 2d95009eb3..7ef864139f 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1574,11 +1574,13 @@ void QTextEdit::mouseMoveEvent(QMouseEvent *e)
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
- QRect visible = d->viewport->rect();
- if (visible.contains(pos))
- d->autoScrollTimer.stop();
- else if (!d->autoScrollTimer.isActive())
- d->autoScrollTimer.start(100, this);
+ if (e->source() == Qt::MouseEventNotSynthesized) {
+ const QRect visible = d->viewport->rect();
+ if (visible.contains(pos))
+ d->autoScrollTimer.stop();
+ else if (!d->autoScrollTimer.isActive())
+ d->autoScrollTimer.start(100, this);
+ }
}
/*! \reimp
@@ -1587,7 +1589,7 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QTextEdit);
d->sendControlEvent(e);
- if (d->autoScrollTimer.isActive()) {
+ if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
d->autoScrollTimer.stop();
ensureCursorVisible();
}
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index dfec6a14d4..8f017b7b87 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1580,8 +1580,10 @@ void QWidgetTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton butto
cursor.clearSelection();
}
}
+ // Do not start selection on a mouse event synthesized from a touch event.
if (!(button & Qt::LeftButton) ||
- !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
+ !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))
+ || QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) {
e->ignore();
return;
}
@@ -1752,6 +1754,11 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but
{
Q_Q(QWidgetTextControl);
+ if (QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) {
+ setCursorPosition(pos); // Emulate Tap to set cursor for events synthesized from touch.
+ return;
+ }
+
const QTextCursor oldSelection = cursor;
if (sendMouseEventToInputContext(
e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) {
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 5b5161e24a..6d801f75c1 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -1179,6 +1179,12 @@ void tst_QUrl::toLocalFile_data()
QTest::newRow("data0") << QString::fromLatin1("file:/a.txt") << QString::fromLatin1("/a.txt");
QTest::newRow("data4") << QString::fromLatin1("file:///a.txt") << QString::fromLatin1("/a.txt");
+ QTest::newRow("data4a") << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile")
+#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
+ << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile");
+#else
+ << QString();
+#endif
#ifdef Q_OS_WIN
QTest::newRow("data5") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("c:/a.txt");
#else
@@ -1227,6 +1233,9 @@ void tst_QUrl::fromLocalFile_data()
QTest::newRow("data3") << QString::fromLatin1("c:/a.txt") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("/c:/a.txt");
QTest::newRow("data4") << QString::fromLatin1("//somehost/somedir/somefile") << QString::fromLatin1("file://somehost/somedir/somefile")
<< QString::fromLatin1("/somedir/somefile");
+ QTest::newRow("data4a") << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile")
+ << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile")
+ << QString::fromLatin1("/somedir/somefile");
QTest::newRow("data5") << QString::fromLatin1("//somehost") << QString::fromLatin1("file://somehost")
<< QString::fromLatin1("");
QTest::newRow("data6") << QString::fromLatin1("//somehost/") << QString::fromLatin1("file://somehost/")
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index ed84c111c6..38a274947f 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -95,6 +95,7 @@ private slots:
void changeFilter();
void changeSourceData_data();
void changeSourceData();
+ void changeSourceDataKeepsStableSorting_qtbug1548();
void sortFilterRole();
void selectionFilteredOut();
void match_data();
@@ -2009,6 +2010,79 @@ void tst_QSortFilterProxyModel::changeSourceData()
}
}
+// Checks that the model is a table, and that each and every row is like this:
+// i-th row: ( rows.at(i), i )
+static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows)
+{
+ QCOMPARE(model->rowCount(), rows.length());
+ QCOMPARE(model->columnCount(), 2);
+
+ for (int row = 0; row < model->rowCount(); ++row) {
+ const QString column0 = model->index(row, 0).data().toString();
+ const int column1 = model->index(row, 1).data().toString().toInt();
+
+ QCOMPARE(column0, rows.at(row));
+ QCOMPARE(column1, row);
+ }
+}
+
+void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548()
+{
+ // Check that emitting dataChanged from the source model
+ // for a change of a role which is not the sorting role
+ // doesn't alter the sorting. In this case, we sort on the DisplayRole,
+ // and play with other roles.
+
+ static const QStringList rows
+ = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x";
+
+ // Build a table of pairs (string, #row) in each row
+ QStandardItemModel model(0, 2);
+
+ for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) {
+ QStandardItem *column0 = new QStandardItem(rows.at(rowNumber));
+ column0->setCheckable(true);
+ column0->setCheckState(Qt::Unchecked);
+
+ QStandardItem *column1 = new QStandardItem(QString::number(rowNumber));
+
+ const QList<QStandardItem *> row
+ = QList<QStandardItem *>() << column0 << column1;
+
+ model.appendRow(row);
+ }
+
+ checkSortedTableModel(&model, rows);
+
+ // Build the proxy model
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(true);
+ proxy.sort(0);
+
+ // The proxy is now sorted by the first column, check that the sorting
+ // * is correct (the input is already sorted, so it must not have changed)
+ // * was stable (by looking at the second column)
+ checkSortedTableModel(&model, rows);
+
+ // Change the check status of an item. That must not break the stable sorting
+ // changes the middle "b"
+ model.item(2)->setCheckState(Qt::Checked);
+ checkSortedTableModel(&model, rows);
+
+ // changes the starting "a"
+ model.item(0)->setCheckState(Qt::Checked);
+ checkSortedTableModel(&model, rows);
+
+ // change the background color of the first "c"
+ model.item(4)->setBackground(Qt::red);
+ checkSortedTableModel(&model, rows);
+
+ // change the background color of the second "c"
+ model.item(5)->setBackground(Qt::red);
+ checkSortedTableModel(&model, rows);
+}
+
void tst_QSortFilterProxyModel::sortFilterRole()
{
QStandardItemModel model;
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 78c75b44e8..5833123dfe 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -642,18 +642,25 @@ struct CountedStruct
QThread *thread;
};
-static QEventLoop _e;
+static QScopedPointer<QEventLoop> _e;
static QThread *_t = Q_NULLPTR;
class StaticEventLoop
{
public:
- static void quitEventLoop() { _e.quit(); if (_t) QCOMPARE(QThread::currentThread(), _t); }
+ static void quitEventLoop()
+ {
+ QVERIFY(!_e.isNull());
+ _e->quit();
+ if (_t)
+ QCOMPARE(QThread::currentThread(), _t);
+ }
};
void tst_QTimer::singleShotToFunctors()
{
int count = 0;
+ _e.reset(new QEventLoop);
QEventLoop e;
QTimer::singleShot(0, CountedStruct(&count));
@@ -661,7 +668,7 @@ void tst_QTimer::singleShotToFunctors()
QCOMPARE(count, 1);
QTimer::singleShot(0, &StaticEventLoop::quitEventLoop);
- QCOMPARE(_e.exec(), 0);
+ QCOMPARE(_e->exec(), 0);
QThread t1;
QObject c1;
@@ -687,7 +694,7 @@ void tst_QTimer::singleShotToFunctors()
QCOMPARE(e.exec(), 0);
QTimer::singleShot(0, &c2, &StaticEventLoop::quitEventLoop);
- QCOMPARE(_e.exec(), 0);
+ QCOMPARE(_e->exec(), 0);
_t->quit();
_t->wait();
@@ -721,8 +728,10 @@ void tst_QTimer::singleShotToFunctors()
thread.quit();
thread.wait();
#endif
-}
+ _e.reset();
+ _t = Q_NULLPTR;
+}
class DontBlockEvents : public QObject
{
diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro
index f8d054f70c..39178ba9e6 100644
--- a/tests/auto/corelib/kernel/qvariant/qvariant.pro
+++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro
@@ -6,3 +6,4 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qvariant.cpp
RESOURCES += qvariant.qrc
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+contains(QT_CONFIG, c++11): CONFIG += c++11
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 3edc9cc965..ea40c64c89 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -4389,6 +4389,28 @@ void tst_QString::section_data()
<< QString("o") << 1 << 2
<< int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep)
<< QString("o1o2o") << false;
+ QTest::newRow( "range1" ) << QString("o1o2o")
+ << QString("o") << -5 << -5
+ << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep)
+ << QString() << false;
+ QTest::newRow( "range2" ) << QString("oo1o2o")
+ << QString("o") << -5 << 1
+ << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep
+ |QString::SectionSkipEmpty)
+ << QString("oo1o2o") << false;
+ QTest::newRow( "range3" ) << QString("o1o2o")
+ << QString("o") << 2 << 1
+ << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep)
+ << QString() << false;
+ QTest::newRow( "range4" ) << QString("o1o2o")
+ << QString("o") << 4 << 4
+ << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep)
+ << QString() << false;
+ QTest::newRow( "range5" ) << QString("o1oo2o")
+ << QString("o") << -2 << -1
+ << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep
+ |QString::SectionSkipEmpty)
+ << QString("o1oo2o") << false;
QTest::newRow( "rx1" ) << QString("o1o2o")
<< QString("[a-z]") << 0 << 0
<< int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep)
diff --git a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
index e08af2491d..a63183e5fc 100644
--- a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
+++ b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
@@ -59,30 +59,39 @@ void tst_QDoubleValidator::validateThouSep_data()
{
QTest::addColumn<QString>("localeName");
QTest::addColumn<QString>("value");
+ QTest::addColumn<bool>("rejectGroupSeparator");
QTest::addColumn<QValidator::State>("result");
- QTest::newRow("1,000C") << "C" << QString("1,000") << ACC;
- QTest::newRow("1.000C") << "C" << QString("1.000") << ACC;
+ QTest::newRow("1,000C") << "C" << QString("1,000") << false << ACC;
+ QTest::newRow("1,000.1C") << "C" << QString("1,000.1") << false << ACC;
+ QTest::newRow("1,000.1C_reject") << "C" << QString("1,000.1") << true << INV;
+ QTest::newRow("1.000C") << "C" << QString("1.000") << false << ACC;
- QTest::newRow("1,000de") << "de" << QString("1,000") << ACC;
- QTest::newRow("1.000de") << "de" << QString("1.000") << ACC;
+ QTest::newRow("1,000de") << "de" << QString("1,000") << false << ACC;
+ QTest::newRow("1.000de") << "de" << QString("1.000") << false << ACC;
- QTest::newRow(".C") << "C" << QString(".") << ITM;
- QTest::newRow(".de") << "de" << QString(".") << INV;
- QTest::newRow(",C") << "C" << QString(",") << INV;
- QTest::newRow(",de") << "de" << QString(",") << ITM;
+ QTest::newRow(".C") << "C" << QString(".") << false << ITM;
+ QTest::newRow(".de") << "de" << QString(".") << false << INV;
+ QTest::newRow("1.000,1de") << "de" << QString("1.000,1") << false << ACC;
+ QTest::newRow("1.000,1de_reject") << "de" << QString("1.000,1") << true << INV;
+ QTest::newRow(",C") << "C" << QString(",") << false << INV;
+ QTest::newRow(",de") << "de" << QString(",") << false << ITM;
}
void tst_QDoubleValidator::validateThouSep()
{
QFETCH(QString, localeName);
QFETCH(QString, value);
+ QFETCH(bool, rejectGroupSeparator);
QFETCH(QValidator::State, result);
int dummy = 0;
QDoubleValidator iv(-10000, 10000, 3, 0);
iv.setNotation(QDoubleValidator::ScientificNotation);
- iv.setLocale(QLocale(localeName));
+ QLocale locale(localeName);
+ if (rejectGroupSeparator)
+ locale.setNumberOptions(QLocale::RejectGroupSeparator);
+ iv.setLocale(locale);
QCOMPARE(iv.validate(value, dummy), result);
}
diff --git a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp
index 31853f7015..eff07ad07f 100644
--- a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp
+++ b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp
@@ -74,6 +74,9 @@ void tst_QRegularExpressionValidator::validate_data()
QTest::newRow("data14") << QRegularExpression("\\w\\d\\d") << QString("E5") << QValidator::Intermediate;
QTest::newRow("data15") << QRegularExpression("\\w\\d\\d") << QString("+9") << QValidator::Invalid;
+ QTest::newRow("emptystr1") << QRegularExpression("[T][e][s][t]") << QString("") << QValidator::Intermediate;
+ QTest::newRow("emptystr2") << QRegularExpression("[T][e][s][t]") << QString() << QValidator::Intermediate;
+
QTest::newRow("empty01") << QRegularExpression() << QString() << QValidator::Acceptable;
QTest::newRow("empty02") << QRegularExpression() << QString("test") << QValidator::Acceptable;
}
diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST
index fbd72492d8..7792e05e0f 100644
--- a/tests/auto/network/access/qnetworkreply/BLACKLIST
+++ b/tests/auto/network/access/qnetworkreply/BLACKLIST
@@ -7,3 +7,6 @@ osx
[SslHandshakeFailedError]
osx
[httpAbort]
+*
+[backgroundRequestInterruption:ftp, bg, nobg]
+*
diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
new file mode 100644
index 0000000000..bf4afa8c45
--- /dev/null
+++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
@@ -0,0 +1,4 @@
+[udpTest]
+*
+[passwordAuth]
+*
diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro
index 0cf910df73..4e30a9cded 100644
--- a/tests/auto/network/ssl/ssl.pro
+++ b/tests/auto/network/ssl/ssl.pro
@@ -5,19 +5,21 @@ SUBDIRS=\
qsslerror \
qsslkey \
-contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked):
+contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
contains(QT_CONFIG, private_tests) {
SUBDIRS += \
qsslsocket \
qsslsocket_onDemandCertificates_member \
qsslsocket_onDemandCertificates_static \
}
+}
winrt: SUBDIRS -= \
qsslsocket_onDemandCertificates_member \
qsslsocket_onDemandCertificates_static \
-contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked):
+contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
contains(QT_CONFIG, private_tests) {
- SUBDIRS += qasn1element
+ SUBDIRS += qasn1element
+ }
}
diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp
index 0ba464a82c..56198ceb65 100644
--- a/tests/auto/opengl/qgl/tst_qgl.cpp
+++ b/tests/auto/opengl/qgl/tst_qgl.cpp
@@ -42,6 +42,8 @@
#include <qglcolormap.h>
#include <qpaintengine.h>
#include <qopenglfunctions.h>
+#include <qopenglframebufferobject.h>
+#include <qopenglpaintdevice.h>
#include <QGraphicsView>
#include <QGraphicsProxyWidget>
@@ -78,6 +80,7 @@ private slots:
void glWidgetRendering();
void glFBOSimpleRendering();
void glFBORendering();
+ void currentFboSync();
void multipleFBOInterleavedRendering();
void glFBOUseInGLWidget();
void glPBufferRendering();
@@ -1138,6 +1141,93 @@ void tst_QGL::glFBORendering()
qt_opengl_check_test_pattern(fb);
}
+class QOpenGLFramebufferObjectPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLFramebufferObjectPaintDevice(int width, int height)
+ : QOpenGLPaintDevice(width, height)
+ , m_fbo(width, height, QOpenGLFramebufferObject::CombinedDepthStencil)
+ {
+ }
+
+ void ensureActiveTarget()
+ {
+ m_fbo.bind();
+ }
+
+ QImage toImage() const
+ {
+ return m_fbo.toImage();
+ }
+
+private:
+ QOpenGLFramebufferObject m_fbo;
+};
+
+void tst_QGL::currentFboSync()
+{
+ if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
+ QSKIP("QGLFramebufferObject not supported on this platform");
+
+#if defined(Q_OS_QNX)
+ QSKIP("Reading the QGLFramebufferObject is unsupported on this platform");
+#endif
+
+ QGLWidget glw;
+ glw.makeCurrent();
+
+ {
+ QGLFramebufferObject fbo1(256, 256, QGLFramebufferObject::CombinedDepthStencil);
+
+ QOpenGLFramebufferObjectPaintDevice fbo2(256, 256);
+
+ QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied);
+ QPainter sourcePainter(&sourceImage);
+ qt_opengl_draw_test_pattern(&sourcePainter, 256, 256);
+
+ QPainter fbo1Painter(&fbo1);
+
+ QPainter fbo2Painter(&fbo2);
+ fbo2Painter.drawImage(0, 0, sourceImage);
+ fbo2Painter.end();
+
+ QImage fbo2Image = fbo2.toImage();
+
+ fbo1Painter.drawImage(0, 0, sourceImage);
+ fbo1Painter.end();
+
+ QGLFramebufferObject::bindDefault();
+
+ QCOMPARE(fbo1.toImage(), fbo2Image);
+ }
+
+ {
+ QGLFramebufferObject fbo1(512, 512, QGLFramebufferObject::CombinedDepthStencil);
+
+ QOpenGLFramebufferObjectPaintDevice fbo2(256, 256);
+
+ QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied);
+ QPainter sourcePainter(&sourceImage);
+ qt_opengl_draw_test_pattern(&sourcePainter, 256, 256);
+
+ QPainter fbo2Painter(&fbo2);
+ fbo2Painter.drawImage(0, 0, sourceImage);
+ QImage fbo2Image1 = fbo2.toImage();
+ fbo2Painter.fillRect(0, 0, 256, 256, Qt::white);
+
+ QPainter fbo1Painter(&fbo1);
+ fbo1Painter.drawImage(0, 0, sourceImage);
+ fbo1Painter.end();
+
+ // check that the OpenGL paint engine now knows it needs to sync
+ fbo2Painter.drawImage(0, 0, sourceImage);
+ QImage fbo2Image2 = fbo2.toImage();
+
+ fbo2Painter.end();
+
+ QCOMPARE(fbo2Image1, fbo2Image2);
+ }
+}
// Tests multiple QPainters active on different FBOs at the same time, with
// interleaving painting. Performance-wise, this is sub-optimal, but it still
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro
index 5239614fc7..fb432a7d21 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro
+++ b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro
@@ -20,4 +20,3 @@ wince* {
DEFINES += SRCDIR=\\\"$$PWD/\\\"
}
-macx:CONFIG += insignificant_test # QTBUG-39183
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index 2ffb81a751..241e6d0e7e 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -448,6 +448,8 @@ void tst_QFileDialog2::task180459_lastDirectory_data()
void tst_QFileDialog2::task180459_lastDirectory()
{
+ if (qApp->platformName().toLower() == QStringLiteral("cocoa"))
+ QSKIP("Insignificant on OSX"); //QTBUG-39183
//first visit the temp directory and close the dialog
QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", tempDir.path());
QFileSystemModel *model = dlg->findChild<QFileSystemModel*>("qt_filesystem_model");
diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
index 833494f25e..bdf610e426 100644
--- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -71,6 +71,7 @@ tst_QGestureRecognizer::tst_QGestureRecognizer()
: m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0))
, m_touchDevice(new QTouchDevice)
{
+ qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count.
}
void tst_QGestureRecognizer::initTestCase()
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
index 201085aecd..d1f9bede0b 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
@@ -9,5 +9,4 @@ SOURCES += tst_qgraphicsview.cpp tst_qgraphicsview_2.cpp
HEADERS += tst_qgraphicsview.h
DEFINES += QT_NO_CAST_TO_ASCII
-mac:CONFIG+=insignificant_test # QTBUG-26580
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index afd8be71e8..250790d9fa 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -143,6 +143,10 @@ class tst_QGraphicsView : public QObject
{
Q_OBJECT
+public:
+ tst_QGraphicsView()
+ : platformName(qApp->platformName().toLower())
+ { }
private slots:
void initTestCase();
void cleanup();
@@ -272,6 +276,7 @@ private:
#if defined Q_OS_BLACKBERRY
QScopedPointer<QWidget> rootWindow;
#endif
+ QString platformName;
};
void tst_QGraphicsView::initTestCase()
@@ -2828,6 +2833,8 @@ void tst_QGraphicsView::scrollBarRanges()
if (style == QLatin1String("GTK+") && useStyledPanel)
QSKIP("GTK + style test skipped, see QTBUG-29002");
+ if (useStyledPanel && style == QStringLiteral("Macintosh") && platformName == QStringLiteral("cocoa"))
+ QSKIP("Insignificant on OSX");
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
@@ -4734,6 +4741,8 @@ public:
void tst_QGraphicsView::hoverLeave()
{
+ if (platformName == QStringLiteral("cocoa"))
+ QSKIP("Insignificant on OSX");
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
QGraphicsScene scene;
QGraphicsView view(&scene);
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
index 766065acda..f000907e0e 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -782,10 +782,8 @@ void tst_QItemDelegate::dateTimeEditor()
widget.setFocus();
widget.editItem(item2);
- QTestEventLoop::instance().enterLoop(1);
-
+ QTRY_VERIFY(widget.viewport()->findChild<QDateEdit *>());
QDateEdit *dateEditor = widget.viewport()->findChild<QDateEdit *>();
- QVERIFY(dateEditor);
QCOMPARE(dateEditor->date(), date);
dateEditor->setDate(date.addDays(60));
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 7904848faf..4b7e2a7198 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -61,6 +61,7 @@ private slots:
void setText();
void setIconText_data() { setText_data(); }
void setIconText();
+ void setUnknownFont();
void actionEvent();
void setStandardKeys();
void alternateShortcuts();
@@ -184,6 +185,15 @@ void tst_QAction::setIconText()
QCOMPARE(action.text(), textFromIconText);
}
+void tst_QAction::setUnknownFont() // QTBUG-42728
+{
+ QAction action(0);
+ QFont font("DoesNotExist", 11);
+ action.setFont(font);
+
+ QMenu menu;
+ menu.addAction(&action); // should not crash
+}
void tst_QAction::updateState(QActionEvent *e)
{
diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
index 27c803b43d..751a16c59d 100644
--- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
+++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
@@ -104,6 +104,7 @@ public:
tst_QMainWindow();
private slots:
+ void cleanup();
void getSetCheck();
void constructor();
void iconSize();
@@ -147,6 +148,12 @@ private slots:
void QTBUG21378_animationFinished();
};
+
+void tst_QMainWindow::cleanup()
+{
+ QVERIFY(QApplication::topLevelWidgets().isEmpty());
+}
+
// Testing get/set functions
void tst_QMainWindow::getSetCheck()
{
@@ -854,6 +861,7 @@ void tst_QMainWindow::takeCentralWidget() {
QVERIFY(!w2.isNull());
QCOMPARE(w2.data(), hopefullyW2);
+ delete w2;
}
void tst_QMainWindow::corner()
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
index f457955657..ff9bc7c4a2 100644
--- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -104,7 +104,7 @@ static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool re
if (tabCount > 1)
QTest::qWait(500);
if (walkThrough) {
- QRubberBand *rubberBand = mdiArea->viewport()->findChild<QRubberBand *>();
+ QRubberBand *rubberBand = mdiArea->findChild<QRubberBand *>();
if (!rubberBand) {
qWarning("No rubber band");
return false;
diff --git a/tests/manual/diaglib/README.txt b/tests/manual/diaglib/README.txt
new file mode 100644
index 0000000000..13387f5a2a
--- /dev/null
+++ b/tests/manual/diaglib/README.txt
@@ -0,0 +1,34 @@
+This is a collection of functions and classes helpful for diagnosing bugs
+in Qt 4 and Qt 5. It can be included in the application's .pro file by
+adding:
+
+include([path to Qt sources]/tests/manual/diaglib/diaglib.pri)
+
+For Qt 4, the environment variable QTDIR may be used:
+include($$(QTDIR)/tests/manual/diaglib/diaglib.pri)
+
+The .pri file adds the define QT_DIAG_LIB, so, diagnostic
+code can be enlosed within #ifdef to work without it as well.
+
+All functions and classes are in the QtDiag namespace.
+
+class EventFilter (eventfilter.h):
+ An event filter that logs Qt events to qDebug() depending on
+ configured categories (for example mouse, keyboard, etc).
+
+function glInfo() (glinfo.h):
+ Returns a string describing the Open GL configuration (obtained
+ by querying GL_VENDOR and GL_RENDERER). Available only
+ when the QT qmake variable contains opengl.
+
+functions dumpNativeWindows(), dumpNativeQtTopLevels():
+ These functions du,p out the hierarchy of native Windows. Currently
+ implemented for Windows only.
+
+function dumpAllWidgets() (qwidgetdump.h):
+ Dumps the hierarchy of QWidgets including information about flags,
+ visibility, geometry, etc.
+
+function dumpAllWindows() (qwindowdump.h):
+ Dumps the hierarchy of QWindows including information about flags,
+ visibility, geometry, etc.
diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri
new file mode 100644
index 0000000000..138660f85e
--- /dev/null
+++ b/tests/manual/diaglib/diaglib.pri
@@ -0,0 +1,43 @@
+INCLUDEPATH += $$PWD
+SOURCES += \
+ $$PWD/eventfilter.cpp \
+ $$PWD/qwindowdump.cpp \
+
+HEADERS += \
+ $$PWD/eventfilter.h \
+ $$PWD/qwindowdump.h \
+ $$PWD/nativewindowdump.h
+
+win32 {
+ SOURCES += $$PWD/nativewindowdump_win.cpp
+ LIBS *= -luser32
+} else {
+ SOURCES += $$PWD/nativewindowdump.cpp
+}
+
+greaterThan(QT_MAJOR_VERSION, 4) {
+ QT += gui-private core-private
+ contains(QT, widgets) {
+ HEADERS += \
+ $$PWD/$$PWD/qwidgetdump.h
+
+ SOURCES += \
+ $$PWD/qwidgetdump.cpp
+ }
+} else {
+ HEADERS += \
+ $$PWD/$$PWD/qwidgetdump.h
+
+ SOURCES += \
+ $$PWD/qwidgetdump.cpp
+}
+
+contains(QT, opengl) {
+HEADERS += \
+ $$PWD/glinfo.h
+
+SOURCES += \
+ $$PWD/glinfo.cpp
+}
+
+DEFINES += QT_DIAG_LIB
diff --git a/tests/manual/diaglib/eventfilter.cpp b/tests/manual/diaglib/eventfilter.cpp
new file mode 100644
index 0000000000..f0573975f6
--- /dev/null
+++ b/tests/manual/diaglib/eventfilter.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "eventfilter.h"
+#include <QtGui/QMouseEvent>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+namespace QtDiag {
+
+EventFilter::EventFilter(EventCategories eventCategories, QObject *p)
+ : QObject(p)
+{
+ init(eventCategories);
+}
+
+EventFilter::EventFilter(QObject *p)
+ : QObject(p)
+{
+ init(EventCategories(0xFFFFFFF));
+}
+
+void EventFilter::init(EventCategories eventCategories)
+{
+ if (eventCategories & MouseEvents) {
+ m_eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease
+ << QEvent::MouseButtonDblClick << QEvent::NonClientAreaMouseButtonPress
+ << QEvent::NonClientAreaMouseButtonRelease
+ << QEvent::NonClientAreaMouseButtonDblClick
+ << QEvent::Enter << QEvent::Leave;
+ }
+ if (eventCategories & MouseMoveEvents)
+ m_eventTypes << QEvent::MouseMove << QEvent::NonClientAreaMouseMove;
+ if (eventCategories & TouchEvents) {
+ m_eventTypes << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd;
+#if QT_VERSION >= 0x050000
+ m_eventTypes << QEvent::TouchCancel;
+#endif
+ }
+ if (eventCategories & TabletEvents) {
+ m_eventTypes << QEvent::TabletEnterProximity << QEvent::TabletLeaveProximity
+ << QEvent::TabletMove << QEvent::TabletPress << QEvent::TabletRelease;
+ }
+ if (eventCategories & DragAndDropEvents) {
+ m_eventTypes << QEvent::DragEnter << QEvent::DragMove << QEvent::DragLeave
+ << QEvent::Drop << QEvent::DragResponse;
+ }
+ if (eventCategories & KeyEvents) {
+ m_eventTypes << QEvent::KeyPress << QEvent::KeyRelease << QEvent::ShortcutOverride
+ << QEvent::Shortcut;
+ }
+ if (eventCategories & GeometryEvents)
+ m_eventTypes << QEvent::Move << QEvent::Resize;
+ if (eventCategories & PaintEvents) {
+ m_eventTypes << QEvent::UpdateRequest << QEvent::Paint
+ << QEvent::Show << QEvent::Hide;
+#if QT_VERSION >= 0x050000
+ m_eventTypes << QEvent::Expose;
+#endif
+ }
+ if (eventCategories & TimerEvents)
+ m_eventTypes << QEvent::Timer << QEvent::ZeroTimerEvent;
+ if (eventCategories & ObjectEvents) {
+ m_eventTypes << QEvent::ChildAdded << QEvent::ChildPolished
+ << QEvent::ChildRemoved << QEvent::Create << QEvent::Destroy;
+ }
+}
+
+bool EventFilter::eventFilter(QObject *o, QEvent *e)
+{
+ static int n = 0;
+ if (m_eventTypes.contains(e->type())) {
+ QDebug debug = qDebug().nospace();
+ const QString on = o->objectName();
+ debug << '#' << n++ << ' ' << o->metaObject()->className();
+ if (!on.isEmpty())
+ debug << '/' << on;
+ debug << ' ' << e;
+ }
+ return false;
+}
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/eventfilter.h b/tests/manual/diaglib/eventfilter.h
new file mode 100644
index 0000000000..d87ac68b07
--- /dev/null
+++ b/tests/manual/diaglib/eventfilter.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _EVENTFILTER_
+#define _EVENTFILTER_
+
+#include <QtCore/QObject>
+#include <QtCore/QEvent>
+#include <QtCore/QList>
+
+namespace QtDiag {
+
+// Event filter that can for example be installed on QApplication
+// to log relevant events.
+
+class EventFilter : public QObject {
+public:
+ enum EventCategory {
+ MouseEvents = 0x00001,
+ MouseMoveEvents = 0x00002,
+ TouchEvents = 0x00004,
+ TabletEvents = 0x00008,
+ DragAndDropEvents = 0x00010,
+ KeyEvents = 0x00020,
+ GeometryEvents = 0x00040,
+ PaintEvents = 0x00080,
+ TimerEvents = 0x00100,
+ ObjectEvents = 0x00200
+ };
+ Q_DECLARE_FLAGS(EventCategories, EventCategory)
+
+ explicit EventFilter(EventCategories eventCategories, QObject *p = 0);
+ explicit EventFilter(QObject *p = 0);
+
+ bool eventFilter(QObject *, QEvent *);
+
+private:
+ void init(EventCategories eventCategories);
+
+ QList<QEvent::Type> m_eventTypes;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(EventFilter::EventCategories)
+
+} // namespace QtDiag
+
+#endif
diff --git a/tests/manual/diaglib/glinfo.cpp b/tests/manual/diaglib/glinfo.cpp
new file mode 100644
index 0000000000..cd30e46b45
--- /dev/null
+++ b/tests/manual/diaglib/glinfo.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "glinfo.h"
+
+#include <QtOpenGL/QGLFunctions>
+#include <QtOpenGL/QGLWidget>
+#if QT_VERSION > 0x050000
+# if QT_VERSION >= 0x050400
+# include <QtWidgets/QOpenGLWidget>
+# include <QtGui/QOpenGLWindow>
+# else // 5.4
+# include <QtGui/QWindow>
+# endif // 5.0..5.4
+# include <QtGui/QOpenGLContext>
+# include <QtGui/QOpenGLFunctions>
+# include <QtGui/QWindow>
+#endif
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QTimer>
+
+namespace QtDiag {
+
+#if QT_VERSION > 0x050000
+
+static QString getGlString(const QOpenGLContext *ctx, GLenum name)
+{
+ if (const GLubyte *p = ctx->functions()->glGetString(name))
+ return QString::fromLatin1(reinterpret_cast<const char *>(p));
+ return QString();
+}
+
+static QString glInfo(const QOpenGLContext *ctx)
+{
+ return getGlString(ctx, GL_VENDOR)
+ + QLatin1Char('\n')
+ + getGlString(ctx, GL_RENDERER);
+}
+
+static QString glInfo(const QGLContext *ctx)
+{
+ return glInfo(ctx->contextHandle());
+}
+
+QString glInfo(const QObject *o)
+{
+# if QT_VERSION >= 0x050400
+ if (o->isWindowType()) {
+ if (const QOpenGLWindow *oglw = qobject_cast<const QOpenGLWindow *>(o))
+ return glInfo(oglw->context());
+ return QString();
+ }
+# endif // 5.4
+ if (o->isWidgetType()) {
+ if (const QGLWidget *g = qobject_cast<const QGLWidget *>(o))
+ return glInfo(g->context());
+# if QT_VERSION >= 0x050400
+ if (const QOpenGLWidget *g = qobject_cast<const QOpenGLWidget *>(o))
+ return glInfo(g->context());
+# endif // 5.4
+ }
+ return QString();
+}
+
+#else // Qt4:
+
+static QString getGlString(GLenum name)
+{
+ if (const GLubyte *p = glGetString(name))
+ return QString::fromLatin1(reinterpret_cast<const char *>(p));
+ return QString();
+}
+
+QString glInfo(const QWidget *)
+{
+ return getGlString(GL_VENDOR) + QLatin1Char('\n') + getGlString(GL_RENDERER);
+}
+
+#endif
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/glinfo.h b/tests/manual/diaglib/glinfo.h
new file mode 100644
index 0000000000..1f515267f2
--- /dev/null
+++ b/tests/manual/diaglib/glinfo.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLINFO_
+#define _GLINFO_
+
+#include <QtCore/QtGlobal>
+
+QT_FORWARD_DECLARE_CLASS(QObject)
+QT_FORWARD_DECLARE_CLASS(QString)
+
+namespace QtDiag {
+
+QString glInfo(const QObject *o);
+
+} // namespace QtDiag
+
+#endif
diff --git a/tests/manual/diaglib/nativewindowdump.cpp b/tests/manual/diaglib/nativewindowdump.cpp
new file mode 100644
index 0000000000..a6c741a085
--- /dev/null
+++ b/tests/manual/diaglib/nativewindowdump.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nativewindowdump.h"
+
+namespace QtDiag {
+
+void dumpNativeWindows(WId)
+{
+}
+
+void dumpNativeQtTopLevels()
+{
+}
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/nativewindowdump.h b/tests/manual/diaglib/nativewindowdump.h
new file mode 100644
index 0000000000..405998feea
--- /dev/null
+++ b/tests/manual/diaglib/nativewindowdump.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _NATIVEWINDOWDUMP_
+#define _NATIVEWINDOWDUMP_
+
+#include <QtGui/qwindowdefs.h>
+
+namespace QtDiag {
+
+void dumpNativeWindows(WId root = 0);
+void dumpNativeQtTopLevels();
+
+} // namespace QtDiag
+
+#endif
diff --git a/tests/manual/diaglib/nativewindowdump_win.cpp b/tests/manual/diaglib/nativewindowdump_win.cpp
new file mode 100644
index 0000000000..814b580f4b
--- /dev/null
+++ b/tests/manual/diaglib/nativewindowdump_win.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nativewindowdump.h"
+#include "qwindowdump.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QDebug>
+#include <QtCore/QVector>
+
+#include <QtCore/qt_windows.h>
+
+namespace QtDiag {
+
+struct DumpContext {
+ DumpContext() : indentation(0) {}
+
+ int indentation;
+ QSharedPointer<QTextStream> stream;
+};
+
+#define debugWinStyle(str, style, styleConstant) \
+if (style & styleConstant) \
+ str << ' ' << #styleConstant;
+
+static void formatNativeWindow(HWND hwnd, QTextStream &str)
+{
+ str << hex << showbase << quintptr(hwnd) << noshowbase << dec;
+ RECT rect;
+ if (GetWindowRect(hwnd, &rect)) {
+ str << ' ' << (rect.right - rect.left) << 'x' << (rect.bottom - rect.top)
+ << '+' << rect.left << '+' << rect.top;
+ }
+ if (IsWindowVisible(hwnd))
+ str << " [visible]";
+
+ str << hex << showbase;
+ if (const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE)) {
+ str << " style=" << style;
+ debugWinStyle(str, style, WS_OVERLAPPED)
+ debugWinStyle(str, style, WS_POPUP)
+ debugWinStyle(str, style, WS_MINIMIZE)
+ debugWinStyle(str, style, WS_CHILD)
+ debugWinStyle(str, style, WS_VISIBLE)
+ debugWinStyle(str, style, WS_DISABLED)
+ debugWinStyle(str, style, WS_CLIPSIBLINGS)
+ debugWinStyle(str, style, WS_CLIPCHILDREN)
+ debugWinStyle(str, style, WS_MAXIMIZE)
+ debugWinStyle(str, style, WS_CAPTION)
+ debugWinStyle(str, style, WS_BORDER)
+ debugWinStyle(str, style, WS_DLGFRAME)
+ debugWinStyle(str, style, WS_VSCROLL)
+ debugWinStyle(str, style, WS_HSCROLL)
+ debugWinStyle(str, style, WS_SYSMENU)
+ debugWinStyle(str, style, WS_THICKFRAME)
+ debugWinStyle(str, style, WS_GROUP)
+ debugWinStyle(str, style, WS_TABSTOP)
+ debugWinStyle(str, style, WS_MINIMIZEBOX)
+ debugWinStyle(str, style, WS_MAXIMIZEBOX)
+ }
+ if (const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE)) {
+ str << " exStyle=" << exStyle;
+ debugWinStyle(str, exStyle, WS_EX_DLGMODALFRAME)
+ debugWinStyle(str, exStyle, WS_EX_NOPARENTNOTIFY)
+ debugWinStyle(str, exStyle, WS_EX_TOPMOST)
+ debugWinStyle(str, exStyle, WS_EX_ACCEPTFILES)
+ debugWinStyle(str, exStyle, WS_EX_TRANSPARENT)
+ debugWinStyle(str, exStyle, WS_EX_MDICHILD)
+ debugWinStyle(str, exStyle, WS_EX_TOOLWINDOW)
+ debugWinStyle(str, exStyle, WS_EX_WINDOWEDGE)
+ debugWinStyle(str, exStyle, WS_EX_CLIENTEDGE)
+ debugWinStyle(str, exStyle, WS_EX_CONTEXTHELP)
+ debugWinStyle(str, exStyle, WS_EX_RIGHT)
+ debugWinStyle(str, exStyle, WS_EX_LEFT)
+ debugWinStyle(str, exStyle, WS_EX_RTLREADING)
+ debugWinStyle(str, exStyle, WS_EX_LTRREADING)
+ debugWinStyle(str, exStyle, WS_EX_LEFTSCROLLBAR)
+ debugWinStyle(str, exStyle, WS_EX_RIGHTSCROLLBAR)
+ debugWinStyle(str, exStyle, WS_EX_CONTROLPARENT)
+ debugWinStyle(str, exStyle, WS_EX_STATICEDGE)
+ debugWinStyle(str, exStyle, WS_EX_APPWINDOW)
+ debugWinStyle(str, exStyle, WS_EX_LAYERED)
+ debugWinStyle(str, exStyle, WS_EX_NOINHERITLAYOUT)
+ debugWinStyle(str, exStyle, WS_EX_NOREDIRECTIONBITMAP)
+ debugWinStyle(str, exStyle, WS_EX_LAYOUTRTL)
+ debugWinStyle(str, exStyle, WS_EX_COMPOSITED)
+ debugWinStyle(str, exStyle, WS_EX_NOACTIVATE)
+ }
+ str << noshowbase << dec;
+
+ wchar_t buf[512];
+ if (GetWindowText(hwnd, buf, sizeof(buf)/sizeof(buf[0])))
+ str << " title=\"" << QString::fromWCharArray(buf) << '"';
+ if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0])))
+ str << " class=\"" << QString::fromWCharArray(buf) << '"';
+ str << '\n';
+}
+
+static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc);
+
+BOOL CALLBACK dumpWindowEnumChildProc(HWND hwnd, LPARAM lParam)
+{
+ dumpNativeWindowRecursion(hwnd, reinterpret_cast<DumpContext *>(lParam));
+ return TRUE;
+}
+
+static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc)
+{
+ indentStream(*dc->stream, dc->indentation);
+ formatNativeWindow(hwnd, *dc->stream);
+ DumpContext nextLevel = *dc;
+ nextLevel.indentation += 2;
+ EnumChildWindows(hwnd, dumpWindowEnumChildProc, reinterpret_cast<LPARAM>(&nextLevel));
+}
+
+/* recurse by Z order, same result */
+static void dumpNativeWindowRecursionByZ(HWND hwnd, DumpContext *dc)
+{
+ indentStream(*dc->stream, dc->indentation);
+ formatNativeWindow(hwnd, *dc->stream);
+ if (const HWND topChild = GetTopWindow(hwnd)) {
+ DumpContext nextLevel = *dc;
+ nextLevel.indentation += 2;
+ for (HWND child = topChild; child ; child = GetNextWindow(child, GW_HWNDNEXT))
+ dumpNativeWindowRecursionByZ(child, &nextLevel);
+ }
+}
+
+typedef QVector<WId> WIdVector;
+
+static void dumpNativeWindows(const WIdVector& wins)
+{
+ DumpContext dc;
+ QString s;
+ dc.stream = QSharedPointer<QTextStream>(new QTextStream(&s));
+ foreach (WId win, wins)
+ dumpNativeWindowRecursion(reinterpret_cast<HWND>(win), &dc);
+#if QT_VERSION > 0x050000
+ qDebug().noquote() << s;
+#else
+ qDebug("%s", qPrintable(s));
+#endif
+}
+
+void dumpNativeWindows(WId rootIn)
+{
+ const WId root = rootIn ? rootIn : reinterpret_cast<WId>(GetDesktopWindow());
+ dumpNativeWindows(WIdVector(1, root));
+}
+
+BOOL CALLBACK findQtTopLevelEnumChildProc(HWND hwnd, LPARAM lParam)
+{
+ WIdVector *v = reinterpret_cast<WIdVector *>(lParam);
+ wchar_t buf[512];
+ if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) {
+ if (wcsstr(buf, L"Qt"))
+ v->append(reinterpret_cast<WId>(hwnd));
+ }
+ return TRUE;
+}
+
+static WIdVector findQtTopLevels()
+{
+ WIdVector result;
+ EnumChildWindows(GetDesktopWindow(),
+ findQtTopLevelEnumChildProc,
+ reinterpret_cast<LPARAM>(&result));
+ return result;
+}
+
+void dumpNativeQtTopLevels()
+{
+ dumpNativeWindows(findQtTopLevels());
+}
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp
new file mode 100644
index 0000000000..d4f985c7c8
--- /dev/null
+++ b/tests/manual/diaglib/qwidgetdump.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidgetdump.h"
+
+#include <QWidget>
+#if QT_VERSION > 0x050000
+# include <QtGui/QScreen>
+# include <QtGui/QWindow>
+#endif
+#include <QApplication>
+#include <QtCore/QMetaObject>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+namespace QtDiag {
+
+static void dumpWidgetRecursion(QTextStream &str, const QWidget *w,
+ FormatWindowOptions options, int depth = 0)
+{
+ indentStream(str, 2 * depth);
+ formatObject(str, w);
+ str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] ");
+ if (const WId nativeWinId = w->internalWinId())
+ str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] ";
+ if (w->isWindow())
+ str << "[top] ";
+ str << (w->testAttribute(Qt::WA_Mapped) ? "[mapped] " : "[not mapped] ");
+ if (w->testAttribute(Qt::WA_DontCreateNativeAncestors))
+ str << "[NoNativeAncestors] ";
+ formatRect(str, w->geometry());
+ if (!(options & DontPrintWindowFlags)) {
+ str << ' ';
+ formatWindowFlags(str, w->windowFlags());
+ }
+ str << '\n';
+#if QT_VERSION > 0x050000
+ if (const QWindow *win = w->windowHandle()) {
+ indentStream(str, 2 * (1 + depth));
+ formatWindow(str, win, options);
+ str << '\n';
+ }
+#endif // Qt 5
+ foreach (const QObject *co, w->children()) {
+ if (co->isWidgetType())
+ dumpWidgetRecursion(str, static_cast<const QWidget *>(co), options, depth + 1);
+ }
+}
+
+void dumpAllWidgets(FormatWindowOptions options)
+{
+ QString d;
+ QTextStream str(&d);
+ str << "### QWidgets:\n";
+ foreach (QWidget *tw, QApplication::topLevelWidgets())
+ dumpWidgetRecursion(str, tw, options);
+#if QT_VERSION > 0x050000
+ qDebug().noquote() << d;
+#else
+ qDebug("%s", qPrintable(d));
+#endif
+}
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/qwidgetdump.h b/tests/manual/diaglib/qwidgetdump.h
new file mode 100644
index 0000000000..f9615b5d2f
--- /dev/null
+++ b/tests/manual/diaglib/qwidgetdump.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _WIDGETDUMP_
+#define _WIDGETDUMP_
+
+#include "qwindowdump.h"
+
+namespace QtDiag {
+
+void dumpAllWidgets(FormatWindowOptions options = 0);
+
+} // namespace QtDiag
+
+#endif
diff --git a/tests/manual/diaglib/qwindowdump.cpp b/tests/manual/diaglib/qwindowdump.cpp
new file mode 100644
index 0000000000..2ecc52ca77
--- /dev/null
+++ b/tests/manual/diaglib/qwindowdump.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowdump.h"
+
+#if QT_VERSION > 0x050000
+# include <QtGui/QGuiApplication>
+# include <QtGui/QScreen>
+# include <QtGui/QWindow>
+# include <qpa/qplatformwindow.h>
+#endif
+#include <QtCore/QMetaObject>
+#include <QtCore/QRect>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+namespace QtDiag {
+
+void indentStream(QTextStream &s, int indent)
+{
+ for (int i = 0; i < indent; ++i)
+ s << ' ';
+}
+
+void formatObject(QTextStream &str, const QObject *o)
+{
+ str << o->metaObject()->className();
+ const QString on = o->objectName();
+ if (!on.isEmpty())
+ str << "/\"" << on << '"';
+}
+
+void formatRect(QTextStream &str, const QRect &geom)
+{
+ str << geom.width() << 'x' << geom.height()
+ << forcesign << geom.x() << geom.y() << noforcesign;
+}
+
+#define debugType(s, type, typeConstant) \
+if ((type & typeConstant) == typeConstant) \
+ s << ' ' << #typeConstant;
+
+#define debugFlag(s, flags, flagConstant) \
+if (flags & flagConstant) \
+ s << ' ' << #flagConstant;
+
+void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags)
+{
+ str << showbase << hex << unsigned(flags) << dec << noshowbase;
+ const Qt::WindowFlags windowType = flags & Qt::WindowType_Mask;
+ debugFlag(str, flags, Qt::Window)
+ debugType(str, windowType, Qt::Dialog)
+ debugType(str, windowType, Qt::Sheet)
+ debugType(str, windowType, Qt::Drawer)
+ debugType(str, windowType, Qt::Popup)
+ debugType(str, windowType, Qt::Tool)
+ debugType(str, windowType, Qt::ToolTip)
+ debugType(str, windowType, Qt::SplashScreen)
+ debugType(str, windowType, Qt::Desktop)
+ debugType(str, windowType, Qt::SubWindow)
+#if QT_VERSION > 0x050000
+ debugType(str, windowType, Qt::ForeignWindow)
+ debugType(str, windowType, Qt::CoverWindow)
+#endif
+ debugFlag(str, flags, Qt::MSWindowsFixedSizeDialogHint)
+ debugFlag(str, flags, Qt::MSWindowsOwnDC)
+ debugFlag(str, flags, Qt::X11BypassWindowManagerHint)
+ debugFlag(str, flags, Qt::FramelessWindowHint)
+ debugFlag(str, flags, Qt::WindowTitleHint)
+ debugFlag(str, flags, Qt::WindowSystemMenuHint)
+ debugFlag(str, flags, Qt::WindowMinimizeButtonHint)
+ debugFlag(str, flags, Qt::WindowMaximizeButtonHint)
+ debugFlag(str, flags, Qt::WindowContextHelpButtonHint)
+ debugFlag(str, flags, Qt::WindowShadeButtonHint)
+ debugFlag(str, flags, Qt::WindowStaysOnTopHint)
+ debugFlag(str, flags, Qt::CustomizeWindowHint)
+#if QT_VERSION > 0x050000
+ debugFlag(str, flags, Qt::WindowTransparentForInput)
+ debugFlag(str, flags, Qt::WindowOverridesSystemGestures)
+ debugFlag(str, flags, Qt::WindowDoesNotAcceptFocus)
+ debugFlag(str, flags, Qt::NoDropShadowWindowHint)
+ debugFlag(str, flags, Qt::WindowFullscreenButtonHint)
+#endif
+ debugFlag(str, flags, Qt::WindowStaysOnBottomHint)
+ debugFlag(str, flags, Qt::MacWindowToolBarButtonHint)
+ debugFlag(str, flags, Qt::BypassGraphicsProxyWidget)
+ debugFlag(str, flags, Qt::WindowOkButtonHint)
+ debugFlag(str, flags, Qt::WindowCancelButtonHint)
+}
+
+#if QT_VERSION > 0x050000
+
+void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options)
+{
+ const QPlatformWindow *pw = w->handle();
+ formatObject(str, w);
+ str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] ");
+ if (const WId nativeWinId = pw ? pw->winId() : WId(0))
+ str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] ";
+ if (w->isTopLevel())
+ str << "[top] ";
+ if (w->isExposed())
+ str << "[exposed] ";
+ formatRect(str, w->geometry());
+ if (!(options & DontPrintWindowFlags)) {
+ str << ' ';
+ formatWindowFlags(str, w->flags());
+ }
+ str << '\n';
+}
+
+static void dumpWindowRecursion(QTextStream &str, const QWindow *w,
+ FormatWindowOptions options = 0, int depth = 0)
+{
+ indentStream(str, 2 * depth);
+ formatWindow(str, w);
+ foreach (const QObject *co, w->children()) {
+ if (co->isWindowType())
+ dumpWindowRecursion(str, static_cast<const QWindow *>(co), options, depth + 1);
+ }
+}
+
+void dumpAllWindows(FormatWindowOptions options)
+{
+ QString d;
+ QTextStream str(&d);
+ str << "### QWindows:\n";
+ foreach (QWindow *w, QGuiApplication::topLevelWindows())
+ dumpWindowRecursion(str, w, options);
+ qDebug().noquote() << d;
+}
+
+#else // Qt 5
+class QWindow {};
+
+void formatWindow(QTextStream &, const QWindow *, FormatWindowOptions)
+{
+}
+
+void dumpAllWindows(FormatWindowOptions options)
+{
+}
+
+#endif // Qt 4
+
+} // namespace QtDiag
diff --git a/tests/manual/diaglib/qwindowdump.h b/tests/manual/diaglib/qwindowdump.h
new file mode 100644
index 0000000000..ab7c0243e9
--- /dev/null
+++ b/tests/manual/diaglib/qwindowdump.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _WINDOWDUMP_
+#define _WINDOWDUMP_
+
+#include <QtCore/qnamespace.h>
+
+QT_FORWARD_DECLARE_CLASS(QRect)
+QT_FORWARD_DECLARE_CLASS(QObject)
+QT_FORWARD_DECLARE_CLASS(QWindow)
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+namespace QtDiag {
+
+enum FormatWindowOption {
+ DontPrintWindowFlags = 0x001
+};
+
+Q_DECLARE_FLAGS(FormatWindowOptions, FormatWindowOption)
+Q_DECLARE_OPERATORS_FOR_FLAGS(FormatWindowOptions)
+
+void indentStream(QTextStream &s, int indent);
+void formatObject(QTextStream &str, const QObject *o);
+void formatRect(QTextStream &str, const QRect &geom);
+void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags);
+
+void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options = 0);
+void dumpAllWindows(FormatWindowOptions options = 0);
+
+} // namespace QtDiag
+
+#endif