summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2012-03-08 01:27:27 +0100
committerJoão Abecasis <joao.abecasis@nokia.com>2012-03-08 01:27:39 +0100
commit12f221410fbe41d0b2efda4cd3289dfcf9044aa8 (patch)
tree897cf6bfb1814b0935982ff5975a6cbfb48d6d9e
parent3d19422ef16a230bb11dbbfe4a8cc9667f39bf15 (diff)
parent6c612c933803ef57ea45e907d0181b40659148ac (diff)
Merge remote-tracking branch 'origin/master' into api_changes
-rw-r--r--config.tests/unix/iconv/iconv.pro2
-rw-r--r--config.tests/unix/libudev/libudev.pro3
-rwxr-xr-xconfigure9
-rw-r--r--dist/changes-5.0.022
-rw-r--r--doc/src/examples/widgets/mousebuttons.qdoc94
-rw-r--r--doc/src/images/widgets/mousebutton-buttontester.pngbin0 -> 14492 bytes
-rw-r--r--doc/src/network/files-and-resources/datastreamformat.qdoc5
-rw-r--r--doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp289
-rw-r--r--examples/sql/sqlbrowser/browser.cpp75
-rw-r--r--examples/sql/sqlbrowser/browser.h20
-rw-r--r--examples/sql/sqlbrowser/browserwidget.ui184
-rw-r--r--examples/widgets/mousebuttons/buttontester.cpp172
-rw-r--r--examples/widgets/mousebuttons/buttontester.h64
-rw-r--r--examples/widgets/mousebuttons/main.cpp66
-rw-r--r--examples/widgets/mousebuttons/mousebuttons.pro18
-rw-r--r--examples/widgets/widgets.pro1
-rw-r--r--mkspecs/cmake/Qt5BasicConfig.cmake.in55
-rw-r--r--mkspecs/common/linux.conf1
-rw-r--r--mkspecs/features/qt.prf34
-rw-r--r--mkspecs/unsupported/qnx-X11-g++/qmake.conf (renamed from mkspecs/unsupported/qnx-g++/qmake.conf)2
-rw-r--r--mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h (renamed from mkspecs/unsupported/qnx-g++/qplatformdefs.h)0
-rw-r--r--mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf (renamed from mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf)2
-rw-r--r--mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h (renamed from mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h)0
-rw-r--r--mkspecs/unsupported/qnx-x86-qcc/qmake.conf (renamed from mkspecs/unsupported/blackberry-x86-qcc/qmake.conf)2
-rw-r--r--mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h (renamed from mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h)0
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp1
-rw-r--r--qmake/generators/metamakefile.cpp4
-rw-r--r--qmake/generators/win32/mingw_make.cpp8
-rw-r--r--qmake/option.cpp11
-rw-r--r--qmake/project.cpp20
-rw-r--r--qmake/project.h2
-rw-r--r--qtbase.pro4
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp26
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.h8
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp6
-rw-r--r--src/corelib/animation/qvariantanimation.cpp22
-rw-r--r--src/corelib/codecs/qtextcodec.cpp37
-rw-r--r--src/corelib/codecs/qtextcodec.h7
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qlibraryinfo.cpp2
-rw-r--r--src/corelib/global/qprocessordetection.h6
-rw-r--r--src/corelib/io/qprocess_win.cpp2
-rw-r--r--src/corelib/json/qjsonparser.cpp4
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp19
-rw-r--r--src/corelib/kernel/qcoreapplication.h6
-rw-r--r--src/corelib/kernel/qcoreevent.h1
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp5
-rw-r--r--src/corelib/kernel/qmetaobject.cpp2
-rw-r--r--src/corelib/kernel/qmetatype.cpp7
-rw-r--r--src/corelib/kernel/qmetatype.h3
-rw-r--r--src/corelib/kernel/qobject.cpp7
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp2
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp13
-rw-r--r--src/corelib/thread/qmutexpool.cpp3
-rw-r--r--src/corelib/thread/qmutexpool_p.h2
-rw-r--r--src/corelib/thread/qthread.cpp28
-rw-r--r--src/corelib/thread/qthread.h3
-rw-r--r--src/corelib/thread/qthread_unix.cpp2
-rw-r--r--src/corelib/thread/qthreadpool.cpp25
-rw-r--r--src/corelib/thread/qthreadpool_p.h1
-rw-r--r--src/corelib/tools/qcryptographichash.cpp32
-rw-r--r--src/corelib/tools/qdatetime.cpp18
-rw-r--r--src/corelib/tools/qharfbuzz.cpp7
-rw-r--r--src/corelib/tools/qharfbuzz_p.h1
-rw-r--r--src/corelib/tools/qregularexpression.cpp2134
-rw-r--r--src/corelib/tools/qregularexpression.h248
-rw-r--r--src/corelib/tools/qstring.h4
-rw-r--r--src/corelib/tools/tools.pri8
-rw-r--r--src/gui/accessible/qaccessible.cpp4
-rw-r--r--src/gui/kernel/qcursor.cpp46
-rw-r--r--src/gui/kernel/qcursor.h4
-rw-r--r--src/gui/kernel/qcursor_qpa.cpp40
-rw-r--r--src/gui/kernel/qevent.cpp7
-rw-r--r--src/gui/kernel/qguiapplication.cpp69
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.cpp15
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.h10
-rw-r--r--src/gui/kernel/qplatformscreen_qpa.cpp11
-rw-r--r--src/gui/kernel/qplatformscreen_qpa.h2
-rw-r--r--src/gui/kernel/qplatformtheme_qpa.cpp6
-rw-r--r--src/gui/kernel/qplatformtheme_qpa.h41
-rw-r--r--src/gui/painting/qplatformbackingstore_qpa.cpp3
-rw-r--r--src/gui/text/qfontengine.cpp15
-rw-r--r--src/gui/text/qfontengine_p.h1
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp12
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.h2
-rw-r--r--src/gui/text/qtextengine.cpp2
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp106
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp67
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h11
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp10
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h3
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp4
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp2
-rw-r--r--src/network/ssl/qsslcertificate.cpp9
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp2
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h1
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp51
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes_p.h23
-rw-r--r--src/platformsupport/udev/udev.pri2
-rw-r--r--src/plugins/generic/evdevkeyboard/evdevkeyboard.pro4
-rw-r--r--src/plugins/generic/evdevmouse/evdevmouse.pro2
-rw-r--r--src/plugins/generic/evdevtouch/evdevtouch.pro2
-rw-r--r--src/plugins/generic/evdevtouch/qevdevtouch.cpp2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro6
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h76
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm99
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm58
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm129
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm2
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.h93
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm653
-rw-r--r--src/plugins/platforms/cocoa/qmacmime.h77
-rw-r--r--src/plugins/platforms/cocoa/qmacmime.mm938
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm74
-rw-r--r--src/plugins/platforms/cocoa/qt_mac_p.h38
-rw-r--r--src/plugins/platforms/directfb/qdirectfbcursor.cpp4
-rw-r--r--src/plugins/platforms/directfb/qdirectfbcursor.h1
-rw-r--r--src/plugins/platforms/directfb/qdirectfbscreen.h1
-rw-r--r--src/plugins/platforms/kms/qkmscursor.cpp2
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp5
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h1
-rw-r--r--src/plugins/platforms/windows/qtwindows_additional.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsaccessibility.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp49
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h5
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h9
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp148
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h8
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
-rw-r--r--src/plugins/platforms/xlib/qxlibcursor.cpp8
-rw-r--r--src/plugins/platforms/xlib/qxlibcursor.h5
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.cpp5
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.h1
-rw-r--r--src/printsupport/dialogs/qprintpreviewdialog.cpp6
-rw-r--r--src/printsupport/kernel/qplatformprintersupport_qpa.cpp20
-rw-r--r--src/printsupport/kernel/qplatformprintersupport_qpa.h3
-rw-r--r--src/printsupport/kernel/qplatformprintplugin.cpp26
-rw-r--r--src/printsupport/kernel/qprinter.cpp7
-rw-r--r--src/printsupport/widgets/qprintpreviewwidget.cpp2
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp33
-rw-r--r--src/sql/models/qsqltablemodel.cpp174
-rw-r--r--src/sql/models/qsqltablemodel.h1
-rw-r--r--src/sql/models/qsqltablemodel_p.h73
-rw-r--r--src/testlib/qtestkeyboard.h12
-rw-r--r--src/widgets/kernel/qapplication.cpp11
-rw-r--r--src/widgets/kernel/qapplication_p.h6
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp79
-rw-r--r--src/widgets/kernel/qwidget.cpp1
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp14
-rw-r--r--src/widgets/statemachine/qguistatemachine.cpp2
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp2
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h2
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp2
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp2
-rw-r--r--src/widgets/widgets/qmenu.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.cpp1
-rw-r--r--src/widgets/widgets/qtabbar.cpp4
-rw-r--r--tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp45
-rw-r--r--tests/auto/corelib/io/qsettings/qsettings.pro2
-rw-r--r--tests/auto/corelib/json/test.bjsonbin60992 -> 60992 bytes
-rw-r--r--tests/auto/corelib/json/tst_qtjson.cpp16
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp1
-rw-r--r--tests/auto/corelib/tools/qregularexpression/.gitignore2
-rw-r--r--tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp64
-rw-r--r--tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp52
-rw-r--r--tests/auto/corelib/tools/qregularexpression/qregularexpression.pro3
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp1198
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h77
-rw-r--r--tests/auto/corelib/tools/tools.pro1
-rw-r--r--tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp77
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp56
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp72
-rw-r--r--tests/auto/other/headersclean/headersclean.pri38
-rw-r--r--tests/auto/other/headersclean/headersclean.pro28
-rw-r--r--tests/auto/other/headersclean/qt_headersclean_headers.h70
-rw-r--r--tests/auto/other/headersclean/tst_headersclean.cpp36
-rw-r--r--tests/auto/other/headersclean/tst_headersclean.h61
-rw-r--r--tests/auto/other/other.pro3
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp1
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp118
-rw-r--r--tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp11
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp87
-rw-r--r--tests/auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp13
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp3
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp3
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp7
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp11
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro3
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp2
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp5
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp6
-rw-r--r--tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp21
-rw-r--r--tests/manual/qcursor/allcursors/allcursors.pro2
-rw-r--r--tests/manual/qcursor/allcursors/main.cpp2
-rw-r--r--tests/manual/qcursor/allcursors/mainwindow.h2
-rw-r--r--tests/manual/qcursor/grab_override/grab_override.pro2
-rw-r--r--tests/manual/qcursor/grab_override/main.cpp2
-rw-r--r--tests/manual/qcursor/grab_override/mainwindow.h2
220 files changed, 8822 insertions, 992 deletions
diff --git a/config.tests/unix/iconv/iconv.pro b/config.tests/unix/iconv/iconv.pro
index ec573ce590..876c6f3589 100644
--- a/config.tests/unix/iconv/iconv.pro
+++ b/config.tests/unix/iconv/iconv.pro
@@ -1,3 +1,3 @@
SOURCES = iconv.cpp
CONFIG -= qt dylib app_bundle
-mac|win32-g++*|blackberry-*-qcc:LIBS += -liconv
+mac|win32-g++*|qnx-*-qcc:LIBS += -liconv
diff --git a/config.tests/unix/libudev/libudev.pro b/config.tests/unix/libudev/libudev.pro
index 7f571b5a6d..28b8980e2e 100644
--- a/config.tests/unix/libudev/libudev.pro
+++ b/config.tests/unix/libudev/libudev.pro
@@ -1,3 +1,4 @@
SOURCES = libudev.cpp
CONFIG -= qt
-LIBS += -ludev
+LIBS += $$QMAKE_LIBS_LIBUDEV
+INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
diff --git a/configure b/configure
index 90e0a5fcda..f29df99ae9 100755
--- a/configure
+++ b/configure
@@ -5294,7 +5294,13 @@ if [ "$PLATFORM_QPA" = "yes" ]; then
fi
if [ "$CFG_LIBUDEV" != "no" ]; then
- if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/libudev "libudev" $L_FLAGS $I_FLAGS $l_FLAGS; then
+ if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists libudev 2>/dev/null; then
+ QMAKE_INCDIR_LIBUDEV=`$PKG_CONFIG --cflags-only-I libudev 2>/dev/null | sed -e 's,^-I,,g' -e 's, -I, ,g'`
+ QMAKE_LIBS_LIBUDEV=`$PKG_CONFIG --libs libudev 2>/dev/null`
+ QMakeVar set QMAKE_INCDIR_LIBUDEV "$QMAKE_INCDIR_LIBUDEV"
+ QMakeVar set QMAKE_LIBS_LIBUDEV "$QMAKE_LIBS_LIBUDEV"
+ fi
+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/libudev "libudev" $L_FLAGS $I_FLAGS $l_FLAGS $QMAKE_INCDIR_LIBUDEV $QMAKE_LIBS_LIBUDEV; then
CFG_LIBUDEV=yes
QT_CONFIG="$QT_CONFIG libudev"
elif [ "$CFG_LIBUDEV" = "yes" ]; then
@@ -6890,6 +6896,7 @@ else
fi
echo "zlib support ........... $CFG_ZLIB"
echo "Session management ..... $CFG_SM"
+echo "libudev support ........ $CFG_LIBUDEV"
if [ "$CFG_OPENGL" = "desktop" ]; then
echo "OpenGL support ......... yes (Desktop OpenGL)"
diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0
index 47994aa774..500e97085b 100644
--- a/dist/changes-5.0.0
+++ b/dist/changes-5.0.0
@@ -203,6 +203,8 @@ information about a particular change.
- qmake
* Projects which explicitly set an empty TARGET are considered broken now.
* The makespec and .qmake.cache do not see build pass specific variables any more.
+ * load()/include() with a target namespace and infile()/$$fromfile() now start with
+ an entirely pristine context.
* Configure's -sysroot and -hostprefix are now handled slightly differently.
The QT_INSTALL_... properties are now automatically prefixed with the sysroot;
the raw values are available as QT_RAW_INSTALL_... and the sysroot as QT_SYSROOT.
@@ -308,9 +310,18 @@ QtCore
libraries, creating uncertainty/bugs in using QString easily, and (to a lesser
extent) performance issues.
+* QTextCodec::codecForTr() and QTextCodec::setCodecForTr() have been removed,
+ QCoreApplication::Encoding value CodecForTr is now obsolete, use
+ DefaultCodec instead. For reasoning, see the codecForCStrings() removal above.
+
* QIntValidator and QDoubleValidator no longer fall back to using the C locale if
the requested locale fails to validate the input.
+* A new set of classes for doing pattern matching with Perl-compatible regular
+ expressions has been added: QRegularExpression, QRegularExpressionMatch and
+ QRegularExpressionMatchIterator. They aim to replace QRegExp with a more
+ powerful and flexible regular expression engine.
+
QtGui
-----
* Accessibility has been refactored. The hierachy of accessible objects is implemented via
@@ -395,6 +406,17 @@ ignore the rest of the range.
QSqlTableModel::indexInQuery() as example of how to implement in a
subclass.
+* QSqlTableModel::selectRow(): This is a new method that refreshes a single
+row in the model from the database.
+
+* QSqlTableModel edit strategies OnFieldChange/OnRowChange QTBUG-2875
+Previously, after changes were submitted in these edit strategies, select()
+was called which removed and inserted all rows. This ruined navigation
+in QTableView. Now, with these edit strategies, there is no implicit select()
+done after committing. This includes deleted rows which remain in
+the model as blank rows until the application calls select(). Instead,
+selectRow() is called to refresh only the affected row.
+
****************************************************************************
* Database Drivers *
****************************************************************************
diff --git a/doc/src/examples/widgets/mousebuttons.qdoc b/doc/src/examples/widgets/mousebuttons.qdoc
new file mode 100644
index 0000000000..bf63cd5076
--- /dev/null
+++ b/doc/src/examples/widgets/mousebuttons.qdoc
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Rick Stockton <rickstockton@reno-computerhelp.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms
+** and conditions contained in a signed written agreement between you
+** and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example widgets/mousebuttons/buttontester
+ \title Mouse Button Tester
+
+ \brief The 'Mouse Button Tester' example demonstrates how to reimplement
+ mouse events within a custom class. You can also use this program to
+ verify that Qt is actually receiving mouse events from your mouse.
+
+ Many 'gamer' mouse devices are configured with high-numbered "buttons"
+ sending text shortcuts for certain games. With such a mouse, no mouse
+ button events occur: The "mouse" sends keystrokes, and the
+ 'Mouse Button Tester' Window will not see the event. Receving no event,
+ it will not repaint the Window with new text describing a \button event.
+
+ And so, in addition to it's use as Qt example code, the program may be
+ useful s a mouse device tester. Note that there is another example
+ muouse buttons example which provides the same function, written in QML.
+
+ This program (the Widget-based example) consists of three classes,
+ in addition to the main() parent program:
+
+ \list
+ \o \c A QPushButton, "Quit".
+ \o \c ButtonTester. This is derived from Qt's TextArea class, for
+ purpose of customizing/re-implementing the mouse and wheel event
+ member functions.
+ \o \c A simple QVBoxLayout layout.
+ \endlist
+
+ First we will review the main program, with it's layout and "Quit"
+ QPushButton. Then we will take a look at the \c ButtonTester class.
+
+ \section1 The Main Program
+
+ Note that the QPushButton, "Quit", is defined directly within the main()
+ program, rather than another class. This is a correct way of defining a
+ "Quit" QPushButton: A "Quit" Button defined inside another
+ class would result in the destructor of that second class being
+ called twice. This "Quit" Button uses the traditional Signal/Slot
+ connection to invoke termination of the QApp, which will properly destroy
+ its child classes \before terminating itself.
+
+ The remainder of the main() program is concerned with defining the layout,
+ and applying a minimum size to the customized ButtonTester.
+
+ \section1 ButtonTester Class Definition
+
+ The \c ButtonTester class inherits from QTextEdit, and listens for
+ mouse events on all possible Qt::MouseButton values. It also listens for
+ wheel events from the mouse, and indicates the direction of wheel motion
+ ("up", down", "left", or "right"). It prints short debug messages into
+ the Window, and also on the console QDebug() stream, when mouse button
+ and wheel events occur. Our reimplementation of mousePressEvent(),
+ mouseReleaseEvent(), mouseDoubleClickEvent(), and wheelEvent() "drive"
+ the program; the other functions simply convert the Qt::MouseButton
+ values into text strings.
+
+ You should call the ignore() function on any mouse event (or other event)
+ which your widget-based classes do not use and consume. This function
+ assures that Qt will propagate the event through each parent widget,
+ until it is used or propagated to the Window Manager. (Qt attempts to do
+ this automatically, but it is better programming practice to explicitly
+ invoke the function.)
+
+ \image widgets/mousebutton-buttontester.png
+*/
diff --git a/doc/src/images/widgets/mousebutton-buttontester.png b/doc/src/images/widgets/mousebutton-buttontester.png
new file mode 100644
index 0000000000..82fcb7617f
--- /dev/null
+++ b/doc/src/images/widgets/mousebutton-buttontester.png
Binary files differ
diff --git a/doc/src/network/files-and-resources/datastreamformat.qdoc b/doc/src/network/files-and-resources/datastreamformat.qdoc
index 17a0044a69..8ff31371a2 100644
--- a/doc/src/network/files-and-resources/datastreamformat.qdoc
+++ b/doc/src/network/files-and-resources/datastreamformat.qdoc
@@ -298,6 +298,11 @@
\li Regular expression syntax (quint8)
\li Minimal matching (quint8)
\endlist
+ \row \li QRegularExpression
+ \li \list
+ \li The regular expression pattern (QString)
+ \li The pattern options (quint32)
+ \endlist
\row \li QRegion
\li \list
\li The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32)
diff --git a/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp b/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp
new file mode 100644
index 0000000000..cab89d9c9e
--- /dev/null
+++ b/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+QRegularExpression re("a pattern");
+//! [0]
+
+
+//! [1]
+QRegularExpression re;
+re.setPattern("another pattern");
+//! [1]
+
+
+//! [2]
+// matches two digits followed by a space and a word
+QRegularExpression re("\\d\\d \\w+");
+
+// matches a backslash
+QRegularExpression re2("\\\\");
+//! [2]
+
+
+//! [3]
+QRegularExpression re("a third pattern");
+QString pattern = re.pattern(); // pattern == "a third pattern"
+//! [3]
+
+
+//! [4]
+// matches "Qt rocks", but also "QT rocks", "QT ROCKS", "qT rOcKs", etc.
+QRegularExpression re("Qt rocks", QRegularExpression::CaseInsensitiveOption);
+//! [4]
+
+
+//! [5]
+QRegularExpression re("^\\d+$");
+re.setPatternOptions(QRegularExpression::MultilineOption);
+// re matches any line in the subject string that contains only digits (but at least one)
+//! [5]
+
+
+//! [6]
+QRegularExpression re = QRegularExpression("^two.*words$", QRegularExpression::MultilineOption
+ | QRegularExpression::DotMatchesEverythingOption);
+
+QRegularExpression::PatternOptions options = re.patternOptions();
+// options == QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption
+//! [6]
+
+
+//! [7]
+// match two digits followed by a space and a word
+QRegularExpression re("\\d\\d \\w+");
+QRegularExpressionMatch match = re.match("abc123 def");
+bool hasMatch = match.hasMatch(); // true
+//! [7]
+
+
+//! [8]
+QRegularExpression re("\\d\\d \\w+");
+QRegularExpressionMatch match = re.match("abc123 def");
+if (match.hasMatch()) {
+ QString matched = match.captured(0); // matched == "23 def"
+ // ...
+}
+//! [8]
+
+
+//! [9]
+QRegularExpression re("\\d\\d \\w+");
+QRegularExpressionMatch match = re.match("12 abc 45 def", 1);
+if (match.hasMatch()) {
+ QString matched = match.captured(0); // matched == "45 def"
+ // ...
+}
+//! [9]
+
+
+//! [10]
+QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$");
+QRegularExpressionMatch match = re.match("08/12/1985");
+if (match.hasMatch()) {
+ QString day = re.captured(1); // day == "08"
+ QString month = re.captured(2); // month == "12"
+ QString year = re.captured(3); // year == "1985"
+ // ...
+}
+//! [10]
+
+
+//! [11]
+QRegularExpression re("abc(\\d+)def");
+QRegularExpressionMatch match = re.match("XYZabc123defXYZ");
+if (match.hasMatch()) {
+ int startOffset = re.capturedStart(1); // startOffset == 6
+ int endOffset = re.capturedEnd(1); // endOffset == 9
+ // ...
+}
+//! [11]
+
+
+//! [12]
+QRegularExpression re("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$");
+QRegularExpressionMatch match = re.match("08/12/1985");
+if (match.hasMatch()) {
+ QString date = match.captured("date"); // date == "08"
+ QString month = match.captured("month"); // month == "12"
+ QString year = match.captured("year"); // year == 1985
+}
+//! [12]
+
+
+//! [13]
+QRegularExpression re("(\\w+)");
+QRegularExpressionMatchIterator i = re.globalMatch("the quick fox");
+//! [13]
+
+
+//! [14]
+QStringList words;
+while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ QString word = match.captured(1);
+ words << word;
+}
+// words contains "the", "quick", "fox"
+//! [14]
+
+
+//! [15]
+QString pattern("^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d\\d?, \\d\\d\\d\\d$");
+QRegularExpression re(pattern);
+
+QString input("Jan 21,");
+QRegularExpressionMatch match = re.match(input, 0, QRegularExpressionMatch::PartialPreferCompleteMatch);
+bool hasMatch = match.hasMatch(); // false
+bool hasPartialMatch = match.hasPartialMatch(); // true
+//! [15]
+
+
+//! [16]
+QString input("Dec 8, 1985");
+QRegularExpressionMatch match = re.match(input, 0, QRegularExpressionMatch::PartialPreferCompleteMatch);
+bool hasMatch = match.hasMatch(); // true
+bool hasPartialMatch = match.hasPartialMatch(); // false
+//! [16]
+
+
+//! [17]
+QRegularExpression re("abc\\w+X|def");
+QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpressionMatch::PartialPreferCompleteMatch);
+bool hasMatch = match.hasMatch(); // true
+bool hasPartialMatch = match.hasPartialMatch(); // false
+QString captured = match.captured(0); // captured == "def"
+//! [17]
+
+
+//! [18]
+QRegularExpression re("abc\\w+X|defY");
+QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpressionMatch::PartialPreferCompleteMatch);
+bool hasMatch = match.hasMatch(); // false
+bool hasPartialMatch = match.hasPartialMatch(); // true
+QString captured = match.captured(0); // captured == "abcdef"
+//! [18]
+
+
+//! [19]
+QRegularExpression re("abc|ab");
+QRegularExpressionMatch match = re.match("ab", 0, QRegularExpressionMatch::PartialPreferFirstMatch);
+bool hasMatch = match.hasMatch(); // false
+bool hasPartialMatch = match.hasPartialMatch(); // true
+//! [19]
+
+
+//! [20]
+QRegularExpression re("abc(def)?");
+QRegularExpressionMatch match = re.match("abc", 0, QRegularExpressionMatch::PartialPreferFirstMatch);
+bool hasMatch = match.hasMatch(); // false
+bool hasPartialMatch = match.hasPartialMatch(); // true
+//! [20]
+
+//! [21]
+QRegularExpression re("(abc)*");
+QRegularExpressionMatch match = re.match("abc", 0, QRegularExpressionMatch::PartialPreferFirstMatch);
+bool hasMatch = match.hasMatch(); // false
+bool hasPartialMatch = match.hasPartialMatch(); // true
+//! [21]
+
+//! [22]
+QRegularExpression invalidRe("(unmatched|parenthesis");
+bool isValid = invalidRe.isValid(); // false
+//! [22]
+
+//! [23]
+QRegularExpression invalidRe("(unmatched|parenthesis");
+if (!invalidRe.isValid()) {
+ QString errorString = invalidRe.errorString(); // errorString == "missing )"
+ int errorOffset = invalidRe.patternErrorOffset(); // errorOffset == 22
+ // ...
+}
+//! [23]
+
+//! [24]
+QRegularExpression re("^this pattern must match exactly$");
+//! [24]
+
+//! [25]
+QString p("a .*|pattern");
+QRegularExpression re("\\A(?:" + p + ")\\z"); // re matches exactly the pattern string p
+//! [25]
+
+//! [26]
+QString escaped = QRegularExpression::escape("a(x) = f(x) + g(x)");
+// escaped == "a\\(x\\)\\ \\=\\ f\\(x\\)\\ \\+\\ g\\(x\\)"
+//! [26]
+
+//! [27]
+QString pattern = "(" + QRegularExpression::escape(name) +
+ "|" + QRegularExpression::escape(nickname) + ")";
+QRegularExpression re(pattern);
+//! [27]
+
+//! [28]
+QRegularExpressionMatch match = re.match(...);
+for (int i = 0; i <= match.lastCapturedIndex(); ++i) {
+ QString captured = match.captured(i);
+ // ...
+}
+//! [28]
+
+//! [29]
+QRegularExpression("(\d\d) (?<name>\w+)");
+QRegularExpressionMatch match = re.match("23 Jordan");
+if (match.hasMatch()) {
+ QString number = match.captured(1); // first == "23"
+ QString name = match.captured("name"); // name == "Jordan"
+}
+//! [29]
+
+//! [30]
+// extracts the words
+QRegularExpression re("(\w+)");
+QString subject("the quick fox");
+QRegularExpressionMatchIterator i = re.globalMatch(subject);
+while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ // ...
+}
+//! [30]
+
+
diff --git a/examples/sql/sqlbrowser/browser.cpp b/examples/sql/sqlbrowser/browser.cpp
index 3aa330e227..eaaec25b16 100644
--- a/examples/sql/sqlbrowser/browser.cpp
+++ b/examples/sql/sqlbrowser/browser.cpp
@@ -52,6 +52,12 @@ Browser::Browser(QWidget *parent)
table->addAction(insertRowAction);
table->addAction(deleteRowAction);
+ table->addAction(fieldStrategyAction);
+ table->addAction(rowStrategyAction);
+ table->addAction(manualStrategyAction);
+ table->addAction(submitAction);
+ table->addAction(revertAction);
+ table->addAction(selectAction);
if (QSqlDatabase::drivers().isEmpty())
QMessageBox::information(this, tr("No database drivers found"),
@@ -144,7 +150,7 @@ void Browser::addConnection()
void Browser::showTable(const QString &t)
{
- QSqlTableModel *model = new QSqlTableModel(table, connectionWidget->currentDatabase());
+ QSqlTableModel *model = new CustomModel(table, connectionWidget->currentDatabase());
model->setEditStrategy(QSqlTableModel::OnRowChange);
model->setTable(connectionWidget->currentDatabase().driver()->escapeIdentifier(t, QSqlDriver::TableName));
model->select();
@@ -215,8 +221,6 @@ void Browser::deleteRow()
if (!model)
return;
- model->setEditStrategy(QSqlTableModel::OnManualSubmit);
-
QModelIndexList currentSelection = table->selectionModel()->selectedIndexes();
for (int i = 0; i < currentSelection.count(); ++i) {
if (currentSelection.at(i).column() != 0)
@@ -224,24 +228,79 @@ void Browser::deleteRow()
model->removeRow(currentSelection.at(i).row());
}
- model->submitAll();
- model->setEditStrategy(QSqlTableModel::OnRowChange);
-
updateActions();
}
void Browser::updateActions()
{
- bool enableIns = qobject_cast<QSqlTableModel *>(table->model());
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ bool enableIns = tm;
bool enableDel = enableIns && table->currentIndex().isValid();
insertRowAction->setEnabled(enableIns);
deleteRowAction->setEnabled(enableDel);
+
+ fieldStrategyAction->setEnabled(tm);
+ rowStrategyAction->setEnabled(tm);
+ manualStrategyAction->setEnabled(tm);
+ submitAction->setEnabled(tm);
+ revertAction->setEnabled(tm);
+ selectAction->setEnabled(tm);
+
+ if (tm) {
+ QSqlTableModel::EditStrategy es = tm->editStrategy();
+ fieldStrategyAction->setChecked(es == QSqlTableModel::OnFieldChange);
+ rowStrategyAction->setChecked(es == QSqlTableModel::OnRowChange);
+ manualStrategyAction->setChecked(es == QSqlTableModel::OnManualSubmit);
+ }
}
void Browser::about()
{
QMessageBox::about(this, tr("About"), tr("The SQL Browser demonstration "
"shows how a data browser can be used to visualize the results of SQL"
- "statements on a live database"));
+ "statements on a live database"));
+}
+
+void Browser::on_fieldStrategyAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->setEditStrategy(QSqlTableModel::OnFieldChange);
+}
+
+void Browser::on_rowStrategyAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->setEditStrategy(QSqlTableModel::OnRowChange);
+}
+
+void Browser::on_manualStrategyAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->setEditStrategy(QSqlTableModel::OnManualSubmit);
+}
+
+void Browser::on_submitAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->submitAll();
+}
+
+void Browser::on_revertAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->revertAll();
+}
+
+void Browser::on_selectAction_triggered()
+{
+ QSqlTableModel * tm = qobject_cast<QSqlTableModel *>(table->model());
+ if (tm)
+ tm->select();
}
+
diff --git a/examples/sql/sqlbrowser/browser.h b/examples/sql/sqlbrowser/browser.h
index 0769812ec8..e9f45345df 100644
--- a/examples/sql/sqlbrowser/browser.h
+++ b/examples/sql/sqlbrowser/browser.h
@@ -43,6 +43,7 @@
#define BROWSER_H
#include <QWidget>
+#include <QSqlTableModel>
#include "ui_browserwidget.h"
class ConnectionWidget;
@@ -77,6 +78,12 @@ public slots:
{ insertRow(); }
void on_deleteRowAction_triggered()
{ deleteRow(); }
+ void on_fieldStrategyAction_triggered();
+ void on_rowStrategyAction_triggered();
+ void on_manualStrategyAction_triggered();
+ void on_submitAction_triggered();
+ void on_revertAction_triggered();
+ void on_selectAction_triggered();
void on_connectionWidget_tableActivated(const QString &table)
{ showTable(table); }
void on_connectionWidget_metaDataRequested(const QString &table)
@@ -96,4 +103,17 @@ signals:
void statusMessage(const QString &message);
};
+class CustomModel: public QSqlTableModel
+{
+ Q_OBJECT
+public:
+ CustomModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase()):QSqlTableModel(parent, db) {}
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (role == Qt::BackgroundRole && isDirty(idx))
+ return QBrush(QColor(Qt::yellow));
+ return QSqlTableModel::data(idx, role);
+ }
+};
+
#endif
diff --git a/examples/sql/sqlbrowser/browserwidget.ui b/examples/sql/sqlbrowser/browserwidget.ui
index 20946f0ede..ff65b1f199 100644
--- a/examples/sql/sqlbrowser/browserwidget.ui
+++ b/examples/sql/sqlbrowser/browserwidget.ui
@@ -1,10 +1,8 @@
-<ui version="4.0" >
- <author></author>
- <comment></comment>
- <exportmacro></exportmacro>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
<class>Browser</class>
- <widget class="QWidget" name="Browser" >
- <property name="geometry" >
+ <widget class="QWidget" name="Browser">
+ <property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@@ -12,100 +10,90 @@
<height>515</height>
</rect>
</property>
- <property name="windowTitle" >
+ <property name="windowTitle">
<string>Qt SQL Browser</string>
</property>
- <layout class="QVBoxLayout" >
- <property name="margin" >
- <number>8</number>
- </property>
- <property name="spacing" >
+ <layout class="QVBoxLayout">
+ <property name="spacing">
<number>6</number>
</property>
+ <property name="margin">
+ <number>8</number>
+ </property>
<item>
- <widget class="QSplitter" name="splitter_2" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>7</hsizetype>
- <vsizetype>7</vsizetype>
+ <widget class="QSplitter" name="splitter_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation" >
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <widget class="ConnectionWidget" name="connectionWidget" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>13</hsizetype>
- <vsizetype>7</vsizetype>
+ <widget class="ConnectionWidget" name="connectionWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
- <widget class="QTableView" name="table" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>7</hsizetype>
- <vsizetype>7</vsizetype>
+ <widget class="QTableView" name="table">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="contextMenuPolicy" >
+ <property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
- <property name="selectionBehavior" >
+ <property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>5</hsizetype>
- <vsizetype>3</vsizetype>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="maximumSize" >
+ <property name="maximumSize">
<size>
<width>16777215</width>
<height>180</height>
</size>
</property>
- <property name="title" >
+ <property name="title">
<string>SQL Query</string>
</property>
- <layout class="QVBoxLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
+ <layout class="QVBoxLayout">
+ <property name="spacing">
<number>6</number>
</property>
+ <property name="margin">
+ <number>9</number>
+ </property>
<item>
- <widget class="QTextEdit" name="sqlEdit" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>7</hsizetype>
- <vsizetype>3</vsizetype>
+ <widget class="QTextEdit" name="sqlEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumSize" >
+ <property name="minimumSize">
<size>
<width>0</width>
<height>18</height>
</size>
</property>
- <property name="baseSize" >
+ <property name="baseSize">
<size>
<width>0</width>
<height>120</height>
@@ -114,19 +102,19 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout" >
- <property name="margin" >
- <number>1</number>
- </property>
- <property name="spacing" >
+ <layout class="QHBoxLayout">
+ <property name="spacing">
<number>6</number>
</property>
+ <property name="margin">
+ <number>1</number>
+ </property>
<item>
<spacer>
- <property name="orientation" >
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" >
+ <property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
@@ -135,15 +123,15 @@
</spacer>
</item>
<item>
- <widget class="QPushButton" name="clearButton" >
- <property name="text" >
+ <widget class="QPushButton" name="clearButton">
+ <property name="text">
<string>&amp;Clear</string>
</property>
</widget>
</item>
<item>
- <widget class="QPushButton" name="submitButton" >
- <property name="text" >
+ <widget class="QPushButton" name="submitButton">
+ <property name="text">
<string>&amp;Submit</string>
</property>
</widget>
@@ -154,37 +142,91 @@
</widget>
</item>
</layout>
- <action name="insertRowAction" >
- <property name="enabled" >
+ <action name="insertRowAction">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="text" >
+ <property name="text">
<string>&amp;Insert Row</string>
</property>
- <property name="statusTip" >
+ <property name="statusTip">
<string>Inserts a new Row</string>
</property>
</action>
- <action name="deleteRowAction" >
- <property name="enabled" >
+ <action name="deleteRowAction">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="text" >
+ <property name="text">
<string>&amp;Delete Row</string>
</property>
- <property name="statusTip" >
+ <property name="statusTip">
<string>Deletes the current Row</string>
</property>
</action>
+ <action name="fieldStrategyAction">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Submit on &amp;Field Change</string>
+ </property>
+ <property name="toolTip">
+ <string>Commit on Field Change</string>
+ </property>
+ </action>
+ <action name="rowStrategyAction">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Submit on &amp;Row Change</string>
+ </property>
+ <property name="toolTip">
+ <string>Commit on Row Change</string>
+ </property>
+ </action>
+ <action name="manualStrategyAction">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Submit &amp;Manually</string>
+ </property>
+ <property name="toolTip">
+ <string>Commit Manually</string>
+ </property>
+ </action>
+ <action name="submitAction">
+ <property name="text">
+ <string>&amp;Submit All</string>
+ </property>
+ <property name="toolTip">
+ <string>Submit Changes</string>
+ </property>
+ </action>
+ <action name="revertAction">
+ <property name="text">
+ <string>&amp;Revert All</string>
+ </property>
+ <property name="toolTip">
+ <string>Revert</string>
+ </property>
+ </action>
+ <action name="selectAction">
+ <property name="text">
+ <string>S&amp;elect</string>
+ </property>
+ <property name="toolTip">
+ <string>Refresh Data from Database</string>
+ </property>
+ </action>
</widget>
- <pixmapfunction></pixmapfunction>
<customwidgets>
<customwidget>
<class>ConnectionWidget</class>
<extends>QTreeView</extends>
<header>connectionwidget.h</header>
- <container>0</container>
- <pixmap></pixmap>
</customwidget>
</customwidgets>
<tabstops>
diff --git a/examples/widgets/mousebuttons/buttontester.cpp b/examples/widgets/mousebuttons/buttontester.cpp
new file mode 100644
index 0000000000..32f73ebb72
--- /dev/null
+++ b/examples/widgets/mousebuttons/buttontester.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Rick Stockton <rickstockton@reno-computerhelp.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "buttontester.h"
+
+void ButtonTester::mousePressEvent(QMouseEvent *e)
+{
+ int j = ButtonTester::buttonByNumber (e->button());
+ QString result = "Mouse Press: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button());
+ qDebug() << result;
+ this->setText(result);
+ if (j == 2) {
+ this->repaint();
+ }
+}
+
+void ButtonTester::mouseReleaseEvent(QMouseEvent *e)
+{
+ int j = ButtonTester::buttonByNumber (e->button());
+ QString result = "Mouse Release: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button());
+ qDebug() << result;
+ this->setText(result);
+}
+
+void ButtonTester::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ int j = ButtonTester::buttonByNumber (e->button());
+ QString result = "Mouse DoubleClick: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button());
+ qDebug() << result;
+ this->setText(result);
+}
+
+void ButtonTester::wheelEvent (QWheelEvent *e)
+{
+ QString result;
+ if (e->delta() > 0) {
+
+ if (e->orientation() == Qt::Vertical) {
+ result = "Mouse Wheel Event: UP";
+ } else {
+ result = "Mouse Wheel Event: LEFT";
+ }
+ } else if (e->delta() < 0) {
+ if (e->orientation() == Qt::Vertical) {
+ result = "Mouse Wheel Event: DOWN";
+ } else {
+ result = "Mouse Wheel Event: RIGHT";
+ }
+ }
+ qDebug() << result;
+ this->setText(result);
+}
+
+int ButtonTester::buttonByNumber(const Qt::MouseButton button)
+{
+ if (button == Qt::NoButton) return 0;
+ if (button == Qt::LeftButton) return 1;
+ if (button == Qt::RightButton) return 2;
+ if (button == Qt::MiddleButton) return 3;
+
+/* Please note that Qt Button #4 corresponds to button #8 on all
+ * platforms which EMULATE wheel events by creating button events
+ * (Button #4 = Scroll Up; Button #5 = Scroll Down; Button #6 = Scroll
+ * Left; and Button #7 = Scroll Right.) This includes X11, with both
+ * Xlib and XCB. So, the "raw button" for "Qt::BackButton" is
+ * usually described as "Button #8".
+
+ * If your platform supports "smooth scrolling", then, for the cases of
+ * Qt::BackButton and higher, this program will show "raw button" with a
+ * value which is too large. Subtract 4 to get the correct button ID for
+ * your platform.
+ */
+
+ if (button == Qt::BackButton) return 8;
+ if (button == Qt::ForwardButton) return 9;
+ if (button == Qt::TaskButton) return 10;
+ if (button == Qt::ExtraButton4) return 11;
+ if (button == Qt::ExtraButton5) return 12;
+ if (button == Qt::ExtraButton6) return 13;
+ if (button == Qt::ExtraButton7) return 14;
+ if (button == Qt::ExtraButton8) return 15;
+ if (button == Qt::ExtraButton9) return 16;
+ if (button == Qt::ExtraButton10) return 17;
+ if (button == Qt::ExtraButton11) return 18;
+ if (button == Qt::ExtraButton12) return 19;
+ if (button == Qt::ExtraButton13) return 20;
+ if (button == Qt::ExtraButton14) return 21;
+ if (button == Qt::ExtraButton15) return 22;
+ if (button == Qt::ExtraButton16) return 23;
+ if (button == Qt::ExtraButton17) return 24;
+ if (button == Qt::ExtraButton18) return 25;
+ if (button == Qt::ExtraButton19) return 26;
+ if (button == Qt::ExtraButton20) return 27;
+ if (button == Qt::ExtraButton21) return 28;
+ if (button == Qt::ExtraButton22) return 29;
+ if (button == Qt::ExtraButton23) return 30;
+ if (button == Qt::ExtraButton24) return 31;
+ qDebug("QMouseShortcutEntry::addShortcut contained Invalid Qt::MouseButton value");
+ return 0;
+}
+
+QString ButtonTester::enumNameFromValue(const Qt::MouseButton button)
+{
+ if (button == Qt::NoButton) return "NoButton";
+ if (button == Qt::LeftButton) return "LeftButton";
+ if (button == Qt::RightButton) return "RightButton";
+ if (button == Qt::MiddleButton) return "MiddleButton";
+ if (button == Qt::BackButton) return "BackButton";
+ if (button == Qt::ForwardButton) return "ForwardButton";
+ if (button == Qt::TaskButton) return "TaskButton";
+ if (button == Qt::ExtraButton4) return "ExtraButton4";
+ if (button == Qt::ExtraButton5) return "ExtraButton5";
+ if (button == Qt::ExtraButton6) return "ExtraButton6";
+ if (button == Qt::ExtraButton7) return "ExtraButton7";
+ if (button == Qt::ExtraButton8) return "ExtraButton8";
+ if (button == Qt::ExtraButton9) return "ExtraButton9";
+ if (button == Qt::ExtraButton10) return "ExtraButton10";
+ if (button == Qt::ExtraButton11) return "ExtraButton11";
+ if (button == Qt::ExtraButton12) return "ExtraButton12";
+ if (button == Qt::ExtraButton13) return "ExtraButton13";
+ if (button == Qt::ExtraButton14) return "ExtraButton14";
+ if (button == Qt::ExtraButton15) return "ExtraButton15";
+ if (button == Qt::ExtraButton16) return "ExtraButton16";
+ if (button == Qt::ExtraButton17) return "ExtraButton17";
+ if (button == Qt::ExtraButton18) return "ExtraButton18";
+ if (button == Qt::ExtraButton19) return "ExtraButton19";
+ if (button == Qt::ExtraButton20) return "ExtraButton20";
+ if (button == Qt::ExtraButton21) return "ExtraButton21";
+ if (button == Qt::ExtraButton22) return "ExtraButton22";
+ if (button == Qt::ExtraButton23) return "ExtraButton23";
+ if (button == Qt::ExtraButton24) return "ExtraButton24";
+ qDebug("QMouseShortcutEntry::addShortcut contained Invalid Qt::MouseButton value");
+ return "NoButton";
+}
diff --git a/examples/widgets/mousebuttons/buttontester.h b/examples/widgets/mousebuttons/buttontester.h
new file mode 100644
index 0000000000..0801a9ae5c
--- /dev/null
+++ b/examples/widgets/mousebuttons/buttontester.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Rick Stockton <rickstockton@reno-computerhelp.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BUTTONTESTER_H
+#define BUTTONTESTER_H
+
+#include <QtWidgets>
+#include <QTextEdit>
+#include <QString>
+#include <QDebug>
+#include <QMouseEvent>
+#include <QWheelEvent>
+
+class ButtonTester : public QTextEdit
+{
+ Q_OBJECT
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void wheelEvent(QWheelEvent * event);
+ int buttonByNumber(const Qt::MouseButton button);
+ QString enumNameFromValue(const Qt::MouseButton button);
+};
+
+#endif // BUTTONTESTER_H
diff --git a/examples/widgets/mousebuttons/main.cpp b/examples/widgets/mousebuttons/main.cpp
new file mode 100644
index 0000000000..7c9674a9d9
--- /dev/null
+++ b/examples/widgets/mousebuttons/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Rick Stockton <rickstockton@reno-computerhelp.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "buttontester.h"
+#include <QtGui>
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+
+ ButtonTester *testArea = new ButtonTester;
+ testArea->setMinimumSize(500, 350);
+ testArea->setText("To test your mouse with Qt, press buttons in this area.\nYou may also scroll or tilt your mouse wheel.");
+ QPushButton *quitButton = new QPushButton("Quit");
+
+ QObject::connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(testArea);
+ layout->addWidget(quitButton);
+
+ QWidget window;
+ window.setLayout(layout);
+ window.setWindowTitle("Mouse Button Tester");
+ window.show();
+
+ return app.exec();
+}
diff --git a/examples/widgets/mousebuttons/mousebuttons.pro b/examples/widgets/mousebuttons/mousebuttons.pro
new file mode 100644
index 0000000000..823b04657e
--- /dev/null
+++ b/examples/widgets/mousebuttons/mousebuttons.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+
+TARGET = buttontester
+TEMPLATE = app
+
+SOURCES += \
+ main.cpp\
+ buttontester.cpp \
+
+HEADERS += \
+ buttontester.h \
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS buttontester.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons
+INSTALLS += target sources
+QT += core widgets
diff --git a/examples/widgets/widgets.pro b/examples/widgets/widgets.pro
index 51a92bcc29..f5c98c3c77 100644
--- a/examples/widgets/widgets.pro
+++ b/examples/widgets/widgets.pro
@@ -12,6 +12,7 @@ SUBDIRS = analogclock \
imageviewer \
lineedits \
movie \
+ mousebuttons \
orientation \
scribble \
shapedclock \
diff --git a/mkspecs/cmake/Qt5BasicConfig.cmake.in b/mkspecs/cmake/Qt5BasicConfig.cmake.in
index 45a0722ef5..0334b6f6e2 100644
--- a/mkspecs/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/cmake/Qt5BasicConfig.cmake.in
@@ -35,6 +35,57 @@ if (Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS)
endif()
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+# For static builds, we also list the dependencies of
+# Qt so that consumers can build.
+
+!!IF isEqual(CMAKE_MODULE_NAME, Core)
+
+set(Qt5Core_LIB_DEPENDENCIES)
+!!IF contains(QT_CONFIG, system-zlib)
+find_package(ZLIB REQUIRED)
+list(APPEND Qt5Core_LIB_DEPENDENCIES ${ZLIB_LIBRARIES})
+!!ENDIF
+
+!!IF contains(QT_CONFIG, glib)
+find_package(GTK2 REQUIRED glib-2.0 gthread-2.0)
+list(APPEND Qt5Core_LIB_DEPENDENCIES ${GTK2_LIBRARIES})
+!!ENDIF
+
+!!IF contains(QT_CONFIG, clock-monotonic)
+find_library(QT_RT_LIBRARY NAMES rt)
+mark_as_advanced(QT_RT_LIBRARY)
+list(APPEND Qt5Core_LIB_DEPENDENCIES ${QT_RT_LIBRARY})
+!!ENDIF
+
+set(CMAKE_THREAD_PREFER_PTHREADS 1)
+find_package(Threads)
+if(CMAKE_USE_PTHREADS_INIT)
+ list(APPEND Qt5Core_LIB_DEPENDENCIES ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
+endif()
+
+!!ENDIF # Core
+
+!!IF isEqual(CMAKE_MODULE_NAME, Gui)
+
+set(Qt5Gui_LIB_DEPENDENCIES)
+
+!!IF contains(QT_CONFIG, system-png)
+find_package(PNG REQUIRED)
+list(APPEND Qt5Gui_LIB_DEPENDENCIES ${PNG_LIBRARIES})
+!!ENDIF
+
+!!IF contains(QT_CONFIG, system-jpeg)
+find_package(JPEG REQUIRED)
+list(APPEND Qt5Gui_LIB_DEPENDENCIES ${JPEG_LIBRARIES})
+!!ENDIF
+
+!!ENDIF # Gui
+
+!!ENDIF # Static
+
+list(APPEND Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES "$${CMAKE_QT5_MODULE_DEPS}")
+
if (NOT _Qt5$${CMAKE_MODULE_NAME}_target)
set(_Qt5$${CMAKE_MODULE_NAME}_target 1)
!!IF !isEmpty(CMAKE_STATIC_TYPE)
@@ -50,7 +101,7 @@ endif()
!!IF !isEmpty(debug_type)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
- IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG \"$${CMAKE_QT5_MODULE_DEPS}\"
+ IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG \"${Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
IMPORTED_LOCATION_DEBUG \"${_qt5_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_LIB_FILE_LOCATION_DEBUG}\"
!!ELSE
@@ -67,7 +118,7 @@ set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
!!IF !isEmpty(release_type)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
- IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE \"$${CMAKE_QT5_MODULE_DEPS}\"
+ IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE \"${Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
IMPORTED_LOCATION_RELEASE \"${_qt5_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_LIB_FILE_LOCATION_RELEASE}\"
!!ELSE
diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf
index a809a6b6f9..384c013309 100644
--- a/mkspecs/common/linux.conf
+++ b/mkspecs/common/linux.conf
@@ -34,6 +34,7 @@ QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
QMAKE_LIBS_OPENVG = -lOpenVG
QMAKE_LIBS_THREAD = -lpthread
+QMAKE_LIBS_LIBUDEV = -ludev
QMAKE_CFLAGS_WAYLAND =
QMAKE_INCDIR_WAYLAND =
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 5328e6ccff..21443aa5b5 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -152,21 +152,22 @@ for(QT_CURRENT_VERIFY, $$list($$QT_PLUGIN_VERIFY)) {
!isEmpty(QT_BUILD_TREE):QMAKE_LIBDIR = $$QT_BUILD_TREE/lib $$QMAKE_LIBDIR #as above, prepending prevents us from picking up "stale" libs
QMAKE_LIBDIR += $$QMAKE_LIBDIR_QT
-# Topological ordering of modules based on their QT.<module>.depends variable
-QT = $$sort_depends(QT, "QT.")
-
-QT_DEPENDS=
-
+# Figure out from which modules we're wanting to use the private headers
unset(using_privates)
+NEWQT =
for(QTLIB, QT) {
- # Figure out if we're wanting to use the private headers of a module
- contains(QTLIB, .*-private) {
- QTLIB ~= s/-private//
- use_private = UsePrivate
- } else {
- use_private = NoPrivate
+ QTLIBRAW = $$replace(QTLIB, -private$, )
+ !isEqual(QTLIBRAW, $$QTLIB) {
+ want_var = QT.$${QTLIBRAW}.want_private
+ $$want_var = UsePrivate
+ using_privates = true
}
-
+ NEWQT += $$QTLIBRAW
+}
+# Topological resolution of modules based on their QT.<module>.depends variable
+QT = $$resolve_depends(NEWQT, "QT.")
+# Finally actually add the modules
+for(QTLIB, QT) {
isEmpty(QT.$${QTLIB}.name) {
message("Warning: unknown QT module: $$QTLIB")
next()
@@ -176,14 +177,9 @@ for(QTLIB, QT) {
warning($$TARGET cannot have a QT of $$QTLIB)
next()
}
- qtAddModule($$QTLIB, $$use_private)
- QT_DEPENDS += $$eval(QT.$${QTLIB}.depends)
- isEqual(use_private, UsePrivate):using_privates = true
-}
-# add include paths for all .depends, since module/application might need f.ex. template specializations etc.
-QT_DEPENDS -= $$QT
-for(QTLIB, $$list($$lower($$unique(QT_DEPENDS)))):INCLUDEPATH *= $$INCLUDEPATH $$eval(QT.$${QTLIB}.includes)
+ qtAddModule($$QTLIB, $$eval(QT.$${QTLIB}.want_private))
+}
!isEmpty(using_privates):!no_private_qt_headers_warning:if(!debug_and_release|!build_pass) {
message("This project is using private headers and will therefore be tied to this specific Qt module build version.")
diff --git a/mkspecs/unsupported/qnx-g++/qmake.conf b/mkspecs/unsupported/qnx-X11-g++/qmake.conf
index bc96c21e9f..94f207aff6 100644
--- a/mkspecs/unsupported/qnx-g++/qmake.conf
+++ b/mkspecs/unsupported/qnx-X11-g++/qmake.conf
@@ -1,5 +1,5 @@
#
-# qmake configuration for qnx-g++
+# qmake configuration for qnx-x11-g++
#
# Written for QNX RTOS v6 with X11
#
diff --git a/mkspecs/unsupported/qnx-g++/qplatformdefs.h b/mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h
index 489e1be114..489e1be114 100644
--- a/mkspecs/unsupported/qnx-g++/qplatformdefs.h
+++ b/mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h
diff --git a/mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf b/mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf
index f2407a6c13..ea206e28ec 100644
--- a/mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf
+++ b/mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf
@@ -1,5 +1,5 @@
#
-# qmake configuration for blackberry-qcc
+# qmake configuration for qnx-qcc armv7 targets
#
MAKEFILE_GENERATOR = UNIX
diff --git a/mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h b/mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h
index 8ef80c4bd7..8ef80c4bd7 100644
--- a/mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h
+++ b/mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h
diff --git a/mkspecs/unsupported/blackberry-x86-qcc/qmake.conf b/mkspecs/unsupported/qnx-x86-qcc/qmake.conf
index 93f1df2e07..fef8d443c1 100644
--- a/mkspecs/unsupported/blackberry-x86-qcc/qmake.conf
+++ b/mkspecs/unsupported/qnx-x86-qcc/qmake.conf
@@ -1,5 +1,5 @@
#
-# qmake configuration for blackberry-qcc
+# qmake configuration for qnx-qcc x86 targets
#
MAKEFILE_GENERATOR = UNIX
diff --git a/mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h b/mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h
index 8ef80c4bd7..8ef80c4bd7 100644
--- a/mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h
+++ b/mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 70efff0bcd..770a1ad34e 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -178,7 +178,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
}
if(tmp_proj.first("TEMPLATE") == "subdirs") {
QMakeProject *pp = new QMakeProject(&tmp_proj);
- pp->read(0);
pb_subdirs += new ProjectBuilderSubDirs(pp, dir);
} else if(tmp_proj.first("TEMPLATE") == "app" || tmp_proj.first("TEMPLATE") == "lib") {
QString pbxproj = qmake_getpwd() + Option::dir_sep + tmp_proj.first("TARGET") + projectSuffix();
diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp
index 39dd4ab797..b855585500 100644
--- a/qmake/generators/metamakefile.cpp
+++ b/qmake/generators/metamakefile.cpp
@@ -447,6 +447,8 @@ QT_END_INCLUDE_NAMESPACE
MakefileGenerator *
MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO)
{
+ Option::postProcessProject(proj);
+
MakefileGenerator *mkfile = NULL;
if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
mkfile = new ProjectGenerator;
@@ -492,6 +494,8 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO)
MetaMakefileGenerator *
MetaMakefileGenerator::createMetaGenerator(QMakeProject *proj, const QString &name, bool op, bool *success)
{
+ Option::postProcessProject(proj);
+
MetaMakefileGenerator *ret = 0;
if ((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL)) {
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index 03460551a9..c088e8e480 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -404,14 +404,14 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
QString ar_cmd = project->values("QMAKE_LIB").join(" ");
if (ar_cmd.isEmpty())
ar_cmd = "armar --create";
- objectsLinkLine = ar_cmd + " " + var("DEST_TARGET") + " --via " + ar_script_file;
+ objectsLinkLine = ar_cmd + " " + var("DEST_TARGET") + " --via " + escapeFilePath(ar_script_file);
} else {
// Strip off any options since the ar commands will be read from file.
QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0);;
if (ar_cmd.isEmpty())
ar_cmd = "ar";
createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS"));
- objectsLinkLine = ar_cmd + " -M < " + ar_script_file;
+ objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file);
}
} else {
QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
@@ -420,10 +420,10 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
}
if (project->isActiveConfig("rvct_linker")) {
createRvctObjectScriptFile(ld_script_file, project->values("OBJECTS"));
- objectsLinkLine = QString::fromLatin1("--via ") + ld_script_file;
+ objectsLinkLine = QString::fromLatin1("--via ") + escapeFilePath(ld_script_file);
} else {
createLdObjectScriptFile(ld_script_file, project->values("OBJECTS"));
- objectsLinkLine = ld_script_file;
+ objectsLinkLine = escapeFilePath(ld_script_file);
}
}
Win32MakefileGenerator::writeObjectsPart(t);
diff --git a/qmake/option.cpp b/qmake/option.cpp
index 4e0d5b198e..b2a1e6982f 100644
--- a/qmake/option.cpp
+++ b/qmake/option.cpp
@@ -149,8 +149,11 @@ static QString detectProjectFile(const QString &path)
static QString cleanSpec(const QString &spec)
{
QString ret = QDir::cleanPath(spec);
- if (ret.contains('/'))
- ret = QDir::cleanPath(QFileInfo(ret).absoluteFilePath());
+ if (ret.contains('/')) {
+ const QFileInfo specDirInfo(ret);
+ if (specDirInfo.exists() && specDirInfo.isDir())
+ ret = QDir::cleanPath(specDirInfo.absoluteFilePath());
+ }
return ret;
}
@@ -591,10 +594,12 @@ QStringList Option::mkspecPaths()
for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it)
ret << ((*it) + concat);
}
- ret << Option::mkfile::project_build_root + concat;
+ if (!Option::mkfile::project_build_root.isEmpty())
+ ret << Option::mkfile::project_build_root + concat;
if (!Option::mkfile::project_root.isEmpty())
ret << Option::mkfile::project_root + concat;
ret << QLibraryInfo::location(QLibraryInfo::HostDataPath) + concat;
+ ret.removeDuplicates();
return ret;
}
diff --git a/qmake/project.cpp b/qmake/project.cpp
index f6e26254c5..7655f05f2e 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -593,6 +593,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
concat_it != concat.end(); ++concat_it)
feature_roots << (QLibraryInfo::location(QLibraryInfo::HostDataPath) +
mkspecs_concat + (*concat_it));
+ feature_roots.removeDuplicates();
return feature_roots;
}
@@ -627,10 +628,11 @@ QMakeProject::init(QMakeProperty *p)
reset();
}
-QMakeProject::QMakeProject(QMakeProject *p, const QHash<QString, QStringList> *vars)
+// Duplicate project. It is *not* allowed to call the complex read() functions on the copy.
+QMakeProject::QMakeProject(QMakeProject *p, const QHash<QString, QStringList> *_vars)
{
init(p->properties());
- base_vars = vars ? *vars : p->variables();
+ vars = _vars ? *_vars : p->variables();
for(QHash<QString, FunctionBlock*>::iterator it = p->replaceFunctions.begin(); it != p->replaceFunctions.end(); ++it) {
it.value()->ref();
replaceFunctions.insert(it.key(), it.value());
@@ -1256,7 +1258,7 @@ QMakeProject::read(const QString &project, uchar cmd)
bool
QMakeProject::read(uchar cmd)
{
- if(cfile.isEmpty()) {
+ if ((cmd & ReadSetup) && base_vars.isEmpty()) {
// hack to get the Option stuff in there
base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext;
base_vars["QMAKE_EXT_C"] = Option::c_ext;
@@ -1265,12 +1267,12 @@ QMakeProject::read(uchar cmd)
if(!Option::user_template_prefix.isEmpty())
base_vars["TEMPLATE_PREFIX"] = QStringList(Option::user_template_prefix);
- if ((cmd & ReadSetup) && Option::mkfile::do_cache) { // parse the cache
+ if (Option::mkfile::do_cache) { // parse the cache
if (Option::output_dir.startsWith(Option::mkfile::project_build_root))
Option::mkfile::cachefile_depth =
Option::output_dir.mid(Option::mkfile::project_build_root.length()).count('/');
}
- if (cmd & ReadSetup) { // parse mkspec
+ { // parse mkspec
QString qmakespec = Option::mkfile::qmakespec;
while(qmakespec.endsWith(QLatin1Char('/')))
qmakespec.truncate(qmakespec.length()-1);
@@ -1306,7 +1308,6 @@ QMakeProject::read(uchar cmd)
//before commandline
if (cmd & ReadSetup) {
- cfile = pfile;
parser.file = "(internal)";
parser.from_file = false;
parser.line_no = 1; //really arg count now.. duh
@@ -1385,7 +1386,6 @@ QMakeProject::read(uchar cmd)
break;
}
}
- Option::postProcessProject(this); // let Option post-process
return true;
}
@@ -1633,12 +1633,8 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
if(flags & (IncludeFlagNewProject|IncludeFlagNewParser)) {
// The "project's variables" are used in other places (eg. export()) so it's not
// possible to use "place" everywhere. Instead just set variables and grab them later
- QMakeProject proj(this, &place);
+ QMakeProject proj(prop);
if(flags & IncludeFlagNewParser) {
-#if 1
- if(proj.doProjectInclude("default_pre", IncludeFlagFeature, proj.variables()) == IncludeNoExist)
- proj.doProjectInclude("default", IncludeFlagFeature, proj.variables());
-#endif
parsed = proj.read(file, proj.variables()); // parse just that file (fromfile, infile)
} else {
parsed = proj.read(file); // parse all aux files (load/include into)
diff --git a/qmake/project.h b/qmake/project.h
index 6422ed1f32..979f1480bd 100644
--- a/qmake/project.h
+++ b/qmake/project.h
@@ -81,7 +81,7 @@ class QMakeProject
bool recursive;
bool own_prop;
bool backslashWarned;
- QString pfile, cfile;
+ QString pfile;
QMakeProperty *prop;
void reset();
QStringList extra_configs;
diff --git a/qtbase.pro b/qtbase.pro
index 01a5aa33dc..9290d5adcd 100644
--- a/qtbase.pro
+++ b/qtbase.pro
@@ -39,9 +39,6 @@ confclean.depends += clean
confclean.commands =
unix {
confclean.commands += (cd config.tests/unix/stl && $(MAKE) distclean); \
- (cd config.tests/unix/endian && $(MAKE) distclean); \
- (cd config.tests/unix/ipv6 && $(MAKE) distclean); \
- (cd config.tests/unix/largefile && $(MAKE) distclean); \
(cd config.tests/unix/ptrsize && $(MAKE) distclean); \
(cd config.tests/x11/notype && $(MAKE) distclean); \
(cd config.tests/unix/getaddrinfo && $(MAKE) distclean); \
@@ -50,7 +47,6 @@ unix {
(cd config.tests/unix/mysql && $(MAKE) distclean); \
(cd config.tests/unix/mysql_r && $(MAKE) distclean); \
(cd config.tests/unix/nis && $(MAKE) distclean); \
- (cd config.tests/unix/nix && $(MAKE) distclean); \
(cd config.tests/unix/iodbc && $(MAKE) distclean); \
(cd config.tests/unix/odbc && $(MAKE) distclean); \
(cd config.tests/unix/oci && $(MAKE) distclean); \
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index af0ee52e9a..f6900325bc 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -995,7 +995,7 @@ static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Ta
return stream;
}
-HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
+HB_Face HB_AllocFace(void *font, HB_GetFontTableFunc tableFunc)
{
HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec));
if (!face)
@@ -1012,6 +1012,30 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
face->tmpLogClusters = 0;
face->glyphs_substituted = false;
face->buffer = 0;
+ face->font_for_init = font;
+ face->get_font_table_func = tableFunc;
+
+ return face;
+}
+
+HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
+{
+ HB_Face face = HB_AllocFace(font, tableFunc);
+ if (face)
+ face = HB_LoadFace(face);
+ return face;
+}
+
+HB_Face HB_LoadFace(HB_Face face)
+{
+ void *font = face->font_for_init;
+ if (!font)
+ return face;
+
+ HB_GetFontTableFunc tableFunc = face->get_font_table_func;
+
+ face->get_font_table_func = 0;
+ face->font_for_init = 0;
HB_Error error = HB_Err_Ok;
HB_Stream stream;
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
index 470e27b6f9..f225a86525 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
@@ -201,6 +201,8 @@ typedef struct {
hb_bitfield combiningClass :8;
} HB_GlyphAttributes;
+typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length);
+
typedef struct HB_FaceRec_ {
HB_Bool isSymbolFont;
@@ -217,11 +219,15 @@ typedef struct HB_FaceRec_ {
unsigned int *tmpLogClusters;
int length;
int orig_nglyphs;
+ void *font_for_init;
+ HB_GetFontTableFunc get_font_table_func;
} HB_FaceRec;
-typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length);
+
HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc);
+HB_Face HB_AllocFace(void *font, HB_GetFontTableFunc tableFunc);
+HB_Face HB_LoadFace(HB_Face face);
void HB_FreeFace(HB_Face face);
typedef struct {
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index fc51a20a15..f7ba49c3cd 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -92,7 +92,7 @@
#include "qanimationgroup.h"
#include "qpropertyanimation_p.h"
-#include <private/qmutexpool_p.h>
+#include <QtCore/QMutex>
#ifndef QT_NO_ANIMATION
@@ -268,7 +268,8 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
QPropertyAnimation *animToStop = 0;
{
#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&staticMetaObject));
+ static QBasicMutex mutex;
+ QMutexLocker locker(&mutex);
#endif
typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
@@ -280,6 +281,7 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
d->updateMetaProperty();
animToStop = hash.value(key, 0);
hash.insert(key, this);
+ locker.unlock();
// update the default start value
if (oldState == Stopped) {
d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData()));
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index 2262a3836e..59b2d6abf3 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -45,7 +45,6 @@
#include <QtCore/qrect.h>
#include <QtCore/qline.h>
#include <QtCore/qmutex.h>
-#include <private/qmutexpool_p.h>
#ifndef QT_NO_ANIMATION
@@ -399,6 +398,7 @@ void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
typedef QVector<QVariantAnimation::Interpolator> QInterpolatorVector;
Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
+static QBasicMutex registeredInterpolatorsMutex;
/*!
\fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
@@ -435,9 +435,7 @@ void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator fun
// in such an order that we get here with interpolators == NULL,
// to continue causes the app to crash on exit with a SEGV
if (interpolators) {
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
-#endif
+ QMutexLocker locker(&registeredInterpolatorsMutex);
if (int(interpolationType) >= interpolators->count())
interpolators->resize(int(interpolationType) + 1);
interpolators->replace(interpolationType, func);
@@ -452,14 +450,14 @@ template<typename T> static inline QVariantAnimation::Interpolator castToInterpo
QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
{
- QInterpolatorVector *interpolators = registeredInterpolators();
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
-#endif
- QVariantAnimation::Interpolator ret = 0;
- if (interpolationType < interpolators->count()) {
- ret = interpolators->at(interpolationType);
- if (ret) return ret;
+ {
+ QInterpolatorVector *interpolators = registeredInterpolators();
+ QMutexLocker locker(&registeredInterpolatorsMutex);
+ QVariantAnimation::Interpolator ret = 0;
+ if (interpolationType < interpolators->count()) {
+ ret = interpolators->at(interpolationType);
+ if (ret) return ret;
+ }
}
switch(interpolationType)
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index f6f0cd8699..13f0ec8ce5 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -145,8 +145,6 @@ static bool destroying_is_ok = false;
#endif
static QTextCodec *localeMapper = 0;
-QTextCodec *QTextCodec::cftr = 0;
-
class QTextCodecCleanup
{
@@ -1463,41 +1461,6 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
return c->toUnicode(ba.constData(), ba.length(), &state);
}
-
-/*!
- \fn QTextCodec* QTextCodec::codecForTr()
-
- Returns the codec used by QObject::tr() on its argument. If this
- function returns 0 (the default), tr() assumes Latin-1.
-
- \sa setCodecForTr()
-*/
-
-/*!
- \fn void QTextCodec::setCodecForTr(QTextCodec *c)
- \nonreentrant
-
- Sets the codec used by QObject::tr() on its argument to \a c. If
- \a c is 0 (the default), tr() assumes Latin-1.
-
- If the literal quoted text in the program is not in the Latin-1
- encoding, this function can be used to set the appropriate
- encoding. For example, software developed by Korean programmers
- might use eucKR for all the text in the program, in which case the
- main() function might look like this:
-
- \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 3
-
- Note that this is not the way to select the encoding that the \e
- user has chosen. For example, to convert an application containing
- literal English strings to Korean, all that is needed is for the
- English strings to be passed through tr() and for translation
- files to be loaded. For details of internationalization, see
- \l{Internationalization with Qt}.
-
- \sa codecForTr()
-*/
-
/*!
\since 4.4
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index ad37005e92..b4b170f7d7 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -72,9 +72,6 @@ public:
static QTextCodec* codecForLocale();
static void setCodecForLocale(QTextCodec *c);
- static QTextCodec* codecForTr();
- static void setCodecForTr(QTextCodec *c);
-
static QTextCodec *codecForHtml(const QByteArray &ba);
static QTextCodec *codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec);
@@ -129,14 +126,10 @@ protected:
private:
friend class QTextCodecCleanup;
- static QTextCodec *cftr;
static bool validCodecs();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextCodec::ConversionFlags)
- inline QTextCodec* QTextCodec::codecForTr() { return validCodecs() ? cftr : 0; }
-inline void QTextCodec::setCodecForTr(QTextCodec *c) { cftr = c; }
-
class Q_CORE_EXPORT QTextEncoder {
Q_DISABLE_COPY(QTextEncoder)
public:
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index a30250df81..09d178639d 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2233,9 +2233,7 @@ int qrand()
The macro QT_TR_NOOP_UTF8() is identical except that it tells lupdate
that the source string is encoded in UTF-8. Corresponding variants
- exist in the QT_TRANSLATE_NOOP() family of macros, too. Note that
- using these macros is not required if \c CODECFORTR is already set to
- UTF-8 in the qmake project file.
+ exist in the QT_TRANSLATE_NOOP() family of macros, too.
\sa QT_TRANSLATE_NOOP(), {Internationalization with Qt}
*/
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 4caacece2d..cb4e0e753f 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -226,7 +226,7 @@ static const struct {
{ "Imports", "imports" },
{ "Data", "" },
{ "Translations", "translations" },
- { "Examples", "" },
+ { "Examples", "examples" },
{ "Tests", "tests" },
#ifdef QT_BUILD_QMAKE
{ "Sysroot", "" },
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index 4213d5830e..1f16f090a9 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -93,7 +93,7 @@
|| defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) \
|| defined(__ARM_ARCH_7M__) \
- || (__TARGET_ARCH_ARM-0 >= 7)
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
# define Q_PROCESSOR_ARM_V7
# define Q_PROCESSOR_ARM_V6
# define Q_PROCESSOR_ARM_V5
@@ -104,11 +104,11 @@
|| defined(__ARM_ARCH_6K__) \
|| defined(__ARM_ARCH_6ZK__) \
|| defined(__ARM_ARCH_6M__) \
- || (__TARGET_ARCH_ARM-0 >= 6)
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
# define Q_PROCESSOR_ARM_V6
# define Q_PROCESSOR_ARM_V5
# elif defined(__ARM_ARCH_5TEJ__) \
- || (__TARGET_ARCH_ARM-0 >= 5)
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
# define Q_PROCESSOR_ARM_V5
# endif
# if defined(__ARMEL__)
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index a52fd46c97..f7c2f965d5 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -530,8 +530,6 @@ void QProcessPrivate::startProcess()
notifier->start(NOTIFYTIMEOUT);
}
- // give the process a chance to start ...
- Sleep(SLEEPMIN * 2);
_q_startupNotification();
}
diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp
index 16eedadf1a..a83685da22 100644
--- a/src/corelib/json/qjsonparser.cpp
+++ b/src/corelib/json/qjsonparser.cpp
@@ -584,9 +584,9 @@ static inline bool addHexDigit(char digit, uint *result)
if (digit >= '0' && digit <= '9')
*result |= (digit - '0');
else if (digit >= 'a' && digit <= 'f')
- *result |= (digit - 'a');
+ *result |= (digit - 'a') + 10;
else if (digit >= 'A' && digit <= 'F')
- *result |= (digit - 'A');
+ *result |= (digit - 'A') + 10;
else
return false;
return true;
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 515732bc68..967ed447d5 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -543,10 +543,6 @@ void QCoreApplication::init()
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = this;
-#ifndef QT_NO_THREAD
- QThread::initialize();
-#endif
-
// use the event dispatcher created by the app programmer (if any)
if (!QCoreApplicationPrivate::eventDispatcher)
QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
@@ -602,7 +598,6 @@ QCoreApplication::~QCoreApplication()
}
if (globalThreadPool)
globalThreadPool->waitForDone();
- QThread::cleanup();
#endif
d_func()->threadData->eventDispatcher = 0;
@@ -1438,11 +1433,9 @@ bool QCoreApplication::event(QEvent *e)
This enum type defines the 8-bit encoding of character string
arguments to translate():
- \value CodecForTr The encoding specified by
- QTextCodec::codecForTr() (Latin-1 if none has
- been set).
- \value UnicodeUTF8 UTF-8.
- \value DefaultCodec (Obsolete) Use CodecForTr instead.
+ \value UnicodeUTF8 UTF-8.
+ \value Latin1 Latin-1.
+ \value DefaultCodec Latin-1.
\sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8()
*/
@@ -1617,7 +1610,7 @@ static void replacePercentN(QString *result, int n)
If none of the translation files contain a translation for \a
sourceText in \a context, this function returns a QString
equivalent of \a sourceText. The encoding of \a sourceText is
- specified by \e encoding; it defaults to CodecForTr.
+ specified by \e encoding; it defaults to DefaultCodec.
This function is not virtual. You can use alternative translation
techniques by subclassing \l QTranslator.
@@ -1628,7 +1621,7 @@ static void replacePercentN(QString *result, int n)
so will most likely result in crashes or other undesirable
behavior.
- \sa QObject::tr() installTranslator() QTextCodec::codecForTr()
+ \sa QObject::tr() installTranslator()
*/
@@ -1657,8 +1650,6 @@ QString QCoreApplication::translate(const char *context, const char *sourceText,
#else
if (encoding == UnicodeUTF8)
result = QString::fromUtf8(sourceText);
- else if (QTextCodec::codecForTr() != 0)
- result = QTextCodec::codecForTr()->toUnicode(sourceText);
else
#endif
result = QString::fromLatin1(sourceText);
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 18266a9a2c..0a5181a508 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -137,11 +137,11 @@ public:
static void installTranslator(QTranslator * messageFile);
static void removeTranslator(QTranslator * messageFile);
#endif
- enum Encoding { CodecForTr, UnicodeUTF8, DefaultCodec = CodecForTr };
+ enum Encoding { UnicodeUTF8, Latin1, DefaultCodec = Latin1 };
static QString translate(const char * context,
const char * key,
const char * disambiguation = 0,
- Encoding encoding = CodecForTr,
+ Encoding encoding = DefaultCodec,
int n = -1);
static void flush();
@@ -240,7 +240,7 @@ inline QString QCoreApplication::translate(const char *, const char *sourceText,
public: \
static inline QString tr(const char *sourceText, const char *disambiguation = 0, int n = -1) \
{ return QCoreApplication::translate(#context, sourceText, disambiguation, \
- QCoreApplication::CodecForTr, n); } \
+ QCoreApplication::DefaultCodec, n); } \
static inline QString trUtf8(const char *sourceText, const char *disambiguation = 0, int n = -1) \
{ return QCoreApplication::translate(#context, sourceText, disambiguation, \
QCoreApplication::UnicodeUTF8, n); } \
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index cac89f2b13..1d54b32dfa 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -127,7 +127,6 @@ public:
DeactivateControl = 81, // ActiveX deactivation
ContextMenu = 82, // context popup menu
InputMethod = 83, // input method
- AccessibilityPrepare = 86, // accessibility information is requested
TabletMove = 87, // Wacom tablet event
LocaleChange = 88, // the system locale changed
LanguageChange = 89, // the application language changed
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 4adcb7678c..3f272a2512 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -42,7 +42,6 @@
#include "qeventdispatcher_glib_p.h"
#include "qeventdispatcher_unix_p.h"
-#include <private/qmutexpool_p.h>
#include <private/qthread_p.h>
#include "qcoreapplication.h"
@@ -295,8 +294,8 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
: mainContext(context)
{
if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) {
- static int dummyValue = 0; // only used for its address
- QMutexLocker locker(QMutexPool::instance()->get(&dummyValue));
+ static QBasicMutex mutex;
+ QMutexLocker locker(&mutex);
if (!g_thread_supported())
g_thread_init(NULL);
}
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index f962fb7831..cacd999869 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -307,7 +307,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n);
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::DefaultCodec, n);
}
/*!
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 003ad1c32d..410a5cc712 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -456,7 +456,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
int QMetaType::registerType(const char *typeName, Deleter deleter,
Creator creator)
{
- return registerType(typeName, deleter, creator, 0, 0, 0, TypeFlags());
+ return registerType(typeName, deleter, creator, qMetaTypeDestructHelper<void>, qMetaTypeConstructHelper<void>, 0, TypeFlags());
}
/*! \internal
@@ -474,7 +474,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
int size, TypeFlags flags)
{
QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct || !typeName || !deleter || !creator)
+ if (!ct || !typeName || !deleter || !creator || !destructor || !constructor)
return -1;
#ifdef QT_NO_QOBJECT
@@ -1331,6 +1331,7 @@ private:
return;
deleter = ct->at(type - QMetaType::User).deleter;
}
+ Q_ASSERT_X(deleter, "void QMetaType::destroy(int type, void *data)", "The type was not properly registered");
deleter(where);
}
@@ -1393,6 +1394,7 @@ private:
return 0;
ctor = ct->at(type - QMetaType::User).constructor;
}
+ Q_ASSERT_X(ctor, "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
return ctor(where, copy);
}
@@ -1481,6 +1483,7 @@ private:
return;
dtor = ct->at(type - QMetaType::User).destructor;
}
+ Q_ASSERT_X(dtor, "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
dtor(where);
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 06ada136a6..8dc45bb2ed 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -255,7 +255,7 @@ public:
static bool load(QDataStream &stream, int type, void *data);
#endif
- QMetaType(const int type);
+ explicit QMetaType(const int type);
inline ~QMetaType();
inline bool isValid() const;
@@ -494,6 +494,7 @@ inline int qMetaTypeId(
#endif
)
{
+ Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use Q_DECLARE_METATYPE macro to make it know to Qt's meta-object system");
return QMetaTypeId2<T>::qt_metatype_id();
}
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 19440e9368..3a4d1da592 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1859,7 +1859,7 @@ void QObject::deleteLater()
translators while performing translations is not supported. Doing
so will probably result in crashes or other undesirable behavior.
- \sa trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt}
+ \sa trUtf8(), QApplication::translate(), {Internationalization with Qt}
*/
/*!
@@ -1871,11 +1871,6 @@ void QObject::deleteLater()
version. It is otherwise identical to tr(\a sourceText, \a
disambiguation, \a n).
- Note that using the Utf8 variants of the translation functions
- is not required if \c CODECFORTR is already set to UTF-8 in the
- qmake project file and QTextCodec::setCodecForTr("UTF-8") is
- used.
-
\warning This method is reentrant only if all translators are
installed \e before calling this method. Installing or removing
translators while performing translations is not supported. Doing
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 8ef0ee8881..0c2f25a1f9 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -283,6 +283,8 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
QStringList QMimeBinaryProvider::findByFileName(const QString &fileName, QString *foundSuffix)
{
checkCache();
+ if (fileName.isEmpty())
+ return QStringList();
const QString lowerFileName = fileName.toLower();
QMimeGlobMatchResult result;
// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 566ece77c9..cdc72cf35d 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -128,6 +128,7 @@ void QFactoryLoader::update()
QLibraryPrivate *library = 0;
for (int j = 0; j < plugins.count(); ++j) {
QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
+
if (qt_debug_component()) {
qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
}
@@ -140,7 +141,9 @@ void QFactoryLoader::update()
library->release();
continue;
}
+
QStringList keys;
+ bool metaDataOk = false;
if (library->compatPlugin) {
qWarning("Qt plugin loader: Compatibility plugin '%s', need to load for accessing meta data.",
qPrintable(QDir::toNativeSeparators(fileName)));
@@ -164,10 +167,17 @@ void QFactoryLoader::update()
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
if (instance && factory && instance->qt_metacast(d->iid))
keys = factory->keys();
+
+ if (!keys.isEmpty())
+ metaDataOk = true;
+
} else {
QString iid = library->metaData.value(QLatin1String("IID")).toString();
if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
+ if (!object.isEmpty())
+ metaDataOk = true;
+
QJsonArray k = object.value(QLatin1String("Keys")).toArray();
for (int i = 0; i < k.size(); ++i) {
QString s = k.at(i).toString();
@@ -178,11 +188,12 @@ void QFactoryLoader::update()
qDebug() << "Got keys from plugin meta data" << keys;
}
- if (keys.isEmpty()) {
+ if (!metaDataOk) {
library->unload();
library->release();
continue;
}
+
d->libraryList += library;
for (int k = 0; k < keys.count(); ++k) {
// first come first serve, unless the first
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
index b102770d23..6b6674ccdf 100644
--- a/src/corelib/thread/qmutexpool.cpp
+++ b/src/corelib/thread/qmutexpool.cpp
@@ -46,9 +46,6 @@
QT_BEGIN_NAMESPACE
-// qt_global_mutexpool is here for backwards compatibility only,
-// use QMutexpool::instance() in new clode.
-Q_CORE_EXPORT QMutexPool *qt_global_mutexpool = 0;
Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
/*!
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
index ce55a40bb8..f5428bed52 100644
--- a/src/corelib/thread/qmutexpool_p.h
+++ b/src/corelib/thread/qmutexpool_p.h
@@ -84,8 +84,6 @@ private:
QMutex::RecursionMode recursionMode;
};
-extern Q_CORE_EXPORT QMutexPool *qt_global_mutexpool;
-
QT_END_NAMESPACE
#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 64fd8776ce..ea6760a1b9 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -42,7 +42,6 @@
#include "qthread.h"
#include "qthreadstorage.h"
#include "qmutex.h"
-#include "qmutexpool_p.h"
#include "qreadwritelock.h"
#include "qabstracteventdispatcher.h"
@@ -537,33 +536,6 @@ void QThread::run()
(void) exec();
}
-/*! \internal
- Initializes the QThread system.
-*/
-#if defined (Q_OS_WIN)
-void qt_create_tls();
-#endif
-
-void QThread::initialize()
-{
- if (qt_global_mutexpool)
- return;
- qt_global_mutexpool = QMutexPool::instance();
-
-#if defined (Q_OS_WIN)
- qt_create_tls();
-#endif
-}
-
-
-/*! \internal
- Cleans up the QThread system.
-*/
-void QThread::cleanup()
-{
- qt_global_mutexpool = 0;
-}
-
/*! \fn void QThread::setPriority(Priority priority)
\since 4.1
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index ba119afb5d..953632c6fc 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -128,9 +128,6 @@ private:
Q_OBJECT
Q_DECLARE_PRIVATE(QThread)
- static void initialize();
- static void cleanup();
-
friend class QCoreApplication;
friend class QThreadData;
};
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index d458ee9472..a0913e5dbc 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -287,7 +287,7 @@ void *QThreadPrivate::start(void *arg)
else
createEventDispatcher(data);
-#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC))
+#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC))
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index af8c99197e..b7021817c5 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -308,31 +308,6 @@ bool QThreadPoolPrivate::waitForDone(int msecs)
}
/*! \internal
- Pulls a runnable from the front queue and runs it in the current thread. Blocks
- until the runnable has completed. Returns true if a runnable was found.
-*/
-bool QThreadPoolPrivate::startFrontRunnable()
-{
- QMutexLocker locker(&mutex);
- if (queue.isEmpty())
- return false;
-
- QRunnable *runnable = queue.takeFirst().first;
- const bool autoDelete = runnable->autoDelete();
- bool del = autoDelete && !--runnable->ref;
-
- locker.unlock();
- runnable->run();
- locker.relock();
-
- if (del) {
- delete runnable;
- }
-
- return true;
-}
-
-/*! \internal
Seaches for \a runnable in the queue, removes it from the queue and
runs it if found. This functon does not return until the runnable
has completed.
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 9a7c09695f..910e0b0714 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -83,7 +83,6 @@ public:
void startThread(QRunnable *runnable = 0);
void reset();
bool waitForDone(int msecs = -1);
- bool startFrontRunnable();
void stealRunnable(QRunnable *);
mutable QMutex mutex;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 3730a6c580..be124c94f7 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -48,23 +48,16 @@
#include "../../3rdparty/sha1/sha1.cpp"
/*
- These typedefs are needed by the RFC6234 code. Normally they would come
- from from stdint.h, but since this header is not available on all platforms
- (MSVC 2008, for example), we need to define them ourselves.
+ These #defines replace the typedefs needed by the RFC6234 code. Normally
+ the typedefs would come from from stdint.h, but since this header is not
+ available on all platforms (MSVC 2008, for example), we #define them to the
+ Qt equivalents.
*/
-#ifndef _UINT64_T_DECLARED
-typedef QT_PREPEND_NAMESPACE(quint64) uint64_t;
-#endif
+#define uint64_t QT_PREPEND_NAMESPACE(quint64)
+#define uint32_t QT_PREPEND_NAMESPACE(quint32)
+#define uint8_t QT_PREPEND_NAMESPACE(quint8)
+#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
-#ifndef _UINT32_T_DECLARED
-typedef QT_PREPEND_NAMESPACE(quint32) uint32_t;
-#endif
-
-#ifndef _UINT8_T_DECLARED
-typedef QT_PREPEND_NAMESPACE(quint8) uint8_t;
-#endif
-
-typedef QT_PREPEND_NAMESPACE(qint16) int_least16_t;
// Header from rfc6234 with 1 modification:
// sha1.h - commented out '#include <stdint.h>' on line 74
#include "../../3rdparty/rfc6234/sha.h"
@@ -90,16 +83,21 @@ static int SHA384_512AddLength(SHA512Context *context, unsigned int length);
// sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304
#include "../../3rdparty/rfc6234/sha384-512.c"
+#undef uint64_t
+#undef uint32_t
+#undef uint68_t
+#undef int_least16_t
+
#include <qiodevice.h>
static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length)
{
- uint32_t addTemp;
+ QT_PREPEND_NAMESPACE(quint32) addTemp;
return SHA224_256AddLengthM(context, length);
}
static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length)
{
- uint64_t addTemp;
+ QT_PREPEND_NAMESPACE(quint64) addTemp;
return SHA384_512AddLengthM(context, length);
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 64ad3121d0..fa5eed4f86 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -3511,7 +3511,10 @@ void QDateTime::detach()
QDataStream &operator<<(QDataStream &out, const QDate &date)
{
- return out << (qint64)(date.jd);
+ if (out.version() < QDataStream::Qt_5_0)
+ return out << quint32(date.jd);
+ else
+ return out << qint64(date.jd);
}
/*!
@@ -3524,9 +3527,16 @@ QDataStream &operator<<(QDataStream &out, const QDate &date)
QDataStream &operator>>(QDataStream &in, QDate &date)
{
- qint64 jd;
- in >> jd;
- date.jd = jd;
+ if (in.version() < QDataStream::Qt_5_0) {
+ quint32 jd;
+ in >> jd;
+ date.jd = jd;
+ } else {
+ qint64 jd;
+ in >> jd;
+ date.jd = jd;
+ }
+
return in;
}
diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp
index 7d08547ab8..11126b814d 100644
--- a/src/corelib/tools/qharfbuzz.cpp
+++ b/src/corelib/tools/qharfbuzz.cpp
@@ -122,7 +122,12 @@ HB_Bool qShapeItem(HB_ShaperItem *item)
HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc)
{
- return HB_NewFace(font, tableFunc);
+ return HB_AllocFace(font, tableFunc);
+}
+
+HB_Face qHBLoadFace(HB_Face face)
+{
+ return HB_LoadFace(face);
}
void qHBFreeFace(HB_Face face)
diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h
index cc575ddffa..3cef3a55dd 100644
--- a/src/corelib/tools/qharfbuzz_p.h
+++ b/src/corelib/tools/qharfbuzz_p.h
@@ -68,6 +68,7 @@ Q_CORE_EXPORT HB_Bool qShapeItem(HB_ShaperItem *item);
// ### temporary
Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc);
Q_CORE_EXPORT void qHBFreeFace(HB_Face);
+Q_CORE_EXPORT HB_Face qHBLoadFace(HB_Face face);
Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE);
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
new file mode 100644
index 0000000000..0fa7d6459e
--- /dev/null
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -0,0 +1,2134 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qregularexpression.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+
+#include <pcre.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRegularExpression
+ \reentrant
+
+ \brief The QRegularExpression class provides pattern matching using regular
+ expressions.
+
+ \since 5.0
+
+ \ingroup tools
+ \ingroup shared
+
+ \keyword regular expression
+
+ Regular expressions, or \e{regexps}, are a very powerful tool to handle
+ strings and texts. This is useful in many contexts, e.g.,
+
+ \table
+ \row \li Validation
+ \li A regexp can test whether a substring meets some criteria,
+ e.g. is an integer or contains no whitespace.
+ \row \li Searching
+ \li A regexp provides more powerful pattern matching than
+ simple substring matching, e.g., match one of the words
+ \e{mail}, \e{letter} or \e{correspondence}, but none of the
+ words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc.
+ \row \li Search and Replace
+ \li A regexp can replace all occurrences of a substring with a
+ different substring, e.g., replace all occurrences of \e{&}
+ with \e{\&amp;} except where the \e{&} is already followed by
+ an \e{amp;}.
+ \row \li String Splitting
+ \li A regexp can be used to identify where a string should be
+ split apart, e.g. splitting tab-delimited strings.
+ \endtable
+
+ This document is by no means a complete reference to pattern matching using
+ regular expressions, and the following parts will require the reader to
+ have some basic knowledge about Perl-like regular expressions and their
+ pattern syntax.
+
+ Good references about regular expressions include:
+
+ \list
+ \li \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F.
+ Friedl, ISBN 0-596-52812-4;
+ \li the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing
+ the pattern syntax supported by PCRE (the reference implementation of
+ Perl-compatible regular expressions);
+ \li the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression
+ documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's
+ regular expression tutorial}.
+ \endlist
+
+ \tableofcontents
+
+ \section1 Introduction
+
+ QRegularExpression implements Perl-compatible regular expressions. It fully
+ supports Unicode. For an overview of the regular expression syntax
+ supported by QRegularExpression, please refer to the aforementioned
+ pcrepattern(3) man page. A regular expression is made up of two things: a
+ \b{pattern string} and a set of \b{pattern options} that change the
+ meaning of the pattern string.
+
+ You can set the pattern string by passing a string to the QRegularExpression
+ constructor:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 0
+
+ This sets the pattern string to \c{a pattern}. You can also use the
+ setPattern() function to set a pattern on an existing QRegularExpression
+ object:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 1
+
+ Note that due to C++ literal strings rules, you must escape all backslashes
+ inside the pattern string with another backslash:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 2
+
+ The pattern() function returns the pattern that it's currently set for a
+ QRegularExpression object:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 3
+
+ \section1 Pattern options
+
+ The meaning of the pattern string can be modified by setting one or more
+ \e{pattern options}. For instance, it is possible to set a pattern to match
+ case insensitively by setting the QRegularExpression::CaseInsensitiveOption.
+
+ You can set the options by passing them to the QRegularExpression
+ constructor, as in:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 4
+
+ Alternatively, you can use the setPatternOptions() function on an existing
+ QRegularExpressionObject:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 5
+
+ It is possible to get the pattern options currently set on a
+ QRegularExpression object by using the patternOptions() function:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 6
+
+ Please refer to the QRegularExpression::PatternOption enum documentation for
+ more information about each pattern option.
+
+ \section1 Match type and match options
+
+ The last two arguments of the match() and the globalMatch() functions set
+ the match type and the match options. The match type is a value of the
+ QRegularExpression::MatchType enum; the "traditional" matching algorithm is
+ chosen by using the NormalMatch match type (the default). It is also
+ possible to enable partial matching of the regular expression against a
+ subject string: see the \l{partial matching} section for more details.
+
+ The match options are a set of one or more QRegularExpression::MatchOption
+ values. They change the way a specific match of a regular expression
+ against a subject string is done. Please refer to the
+ QRegularExpression::MatchOption enum documentation for more details.
+
+ \target normal matching
+ \section1 Normal matching
+
+ In order to perform a match you can simply invoke the match() function
+ passing a string to match against. We refer to this string as the
+ \e{subject string}. The result of the match() function is a
+ QRegularExpressionMatch object that can be used to inspect the results of
+ the match. For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 7
+
+ If a match is successful, the (implicit) capturing group number 0 can be
+ used to retrieve the substring matched by the entire pattern (see also the
+ section about \l{extracting captured substrings}):
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 8
+
+ It's also possible to start a match at an arbitrary offset inside the
+ subject string by passing the offset as an argument of the
+ match() function. In the following example \c{"12 abc"}
+ is not matched because the match is started at offset 1:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 9
+
+ \target extracting captured substrings
+ \section2 Extracting captured substrings
+
+ The QRegularExpressionMatch object contains also information about the
+ substrings captured by the capturing groups in the pattern string. The
+ \l{QRegularExpressionMatch::}{captured()} function will return the string
+ captured by the n-th capturing group:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 10
+
+ Capturing groups in the pattern are numbered starting from 1, and the
+ implicit capturing group 0 is used to capture the substring that matched
+ the entire pattern.
+
+ It's also possible to retrieve the starting and the ending offsets (inside
+ the subject string) of each captured substring, by using the
+ \l{QRegularExpressionMatch::}{capturedStart()} and the
+ \l{QRegularExpressionMatch::}{capturedEnd()} functions:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 11
+
+ All of these functions have an overload taking a QString as a parameter
+ in order to extract \e{named} captured substrings. For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 12
+
+ \target global matching
+ \section1 Global matching
+
+ \e{Global matching} is useful to find all the occurrences of a given
+ regular expression inside a subject string. Suppose that we want to extract
+ all the words from a given string, where a word is a substring matching
+ the pattern \c{\w+}.
+
+ QRegularExpression::globalMatch returns a QRegularExpressionMatchIterator,
+ which is a Java-like forward iterator that can be used to iterate over the
+ results. For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 13
+
+ Since it's a Java-like iterator, the QRegularExpressionMatchIterator will
+ point immediately before the first result. Every result is returned as a
+ QRegularExpressionMatch object. The
+ \l{QRegularExpressionMatchIterator::}{hasNext()} function will return true
+ if there's at least one more result, and
+ \l{QRegularExpressionMatchIterator::}{next()} will return the next result
+ and advance the iterator. Continuing from the previous example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 14
+
+ You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get
+ the next result without advancing the iterator.
+
+ It is possible to pass a starting offset and one or more match options to
+ the globalMatch() function, exactly like normal matching with match().
+
+ \target partial matching
+ \section1 Partial matching
+
+ A \e{partial match} is obtained when the end of the subject string is
+ reached, but more characters are needed to successfully complete the match.
+ Note that a partial match is usually much more inefficient than a normal
+ match because many optimizations of the matching algorithm cannot be
+ employed.
+
+ A partial match must be explicitly requested by specifying a match type of
+ PartialPreferCompleteMatch or PartialPreferFirstMatch when calling
+ QRegularExpression::match or QRegularExpression::globalMatch. If a partial
+ match is found, then calling the \l{QRegularExpressionMatch::}{hasMatch()}
+ function on the QRegularExpressionMatch object returned by match() will
+ return \c{false}, but \l{QRegularExpressionMatch::}{hasPartialMatch()} will return
+ \c{true}.
+
+ When a partial match is found, no captured substrings are returned, and the
+ (implicit) capturing group 0 corresponding to the whole match captures the
+ partially matched substring of the subject string.
+
+ Note that asking for a partial match can still lead to a complete match, if
+ one is found; in this case, \l{QRegularExpressionMatch::}{hasMatch()} will
+ return \c{true} and \l{QRegularExpressionMatch::}{hasPartialMatch()}
+ \c{false}. It never happens that a QRegularExpressionMatch reports both a
+ partial and a complete match.
+
+ Partial matching is mainly useful in two scenarios: validating user input
+ in real time and incremental/multi-segment matching.
+
+ \target
+ \section2 Validating user input
+
+ Suppose that we would like the user to input a date in a specific
+ format, for instance "MMM dd, yyyy". We can check the input validity with
+ a pattern like:
+
+ \c{^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?, \d\d\d\d$}
+
+ (This pattern doesn't catch invalid days, but let's keep it for the
+ example's purposes).
+
+ We would like to validate the input with this regular expression \e{while}
+ the user is typing it, so that we can report an error in the input as soon
+ as it is committed (for instance, the user typed the wrong key). In order
+ to do so we must distinguish three cases:
+
+ \list
+ \li the input cannot possibly match the regular expression;
+ \li the input does match the regular expression;
+ \li the input does not match the regular expression right now,
+ but it will if more charaters will be added to it.
+ \endlist
+
+ Note that these three cases represent exactly the possible states of a
+ QValidator (see the QValidator::State enum).
+
+ In particular, in the last case we want the regular expression engine to
+ report a partial match: we are successfully matching the pattern against
+ the subject string but the matching cannot continue because the end of the
+ subject is encountered. Notice, however, that the matching algorithm should
+ continue and try all possibilities, and in case a complete (non-partial)
+ match is found, then this one should be reported, and the input string
+ accepted as fully valid.
+
+ This behaviour is implemented by the PartialPreferCompleteMatch match type.
+ For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 15
+
+ If matching the same regular expression against the subject string leads to
+ a complete match, it is reported as usual:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 16
+
+ Another example with a different pattern, showing the behaviour of
+ preferring a complete match over a partial one:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 17
+
+ In this case, the subpattern \c{abc\\w+X} partially matches the subject
+ string; however, the subpattern \c{def} matches the subject string
+ completely, and therefore a complete match is reported.
+
+ In case multiple partial matches are found when matching (but no complete
+ match), then the QRegularExpressionMatch will report the first one that it
+ is found. For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 18
+
+ \section2 Incremental/multi-segment matching
+
+ Incremental matching is another use case of partial matching. Suppose that
+ we want to find the occurrences of a regular expression inside a large text
+ (that is, substrings matching the regular expression). In order to do so we
+ would like to "feed" the large text to the regular expression engines in
+ smaller chunks. The obvious problem is what happens if the substring that
+ matches the regular expression spans across two or more chunks.
+
+ In this case, the regular expression engine should report a partial match,
+ so that we can match again adding new data and (eventually) get a complete
+ match. This implies that the regular expression engine may assume that
+ there are other characters \e{beyond the end} of the subject string. This
+ is not to be taken literally -- the engine will never try to access
+ any character after the last one in the subject.
+
+ QRegularExpression implements this behaviour when using the
+ PartialPreferFirstMatch match type. This match type reports a partial match
+ as soon as it is found, and other match alternatives are not tried
+ (even if they could lead to a complete match). For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 19
+
+ This happens because when matching the first branch of the alternation
+ operator a partial match is found, and therefore matching stops, without
+ trying the second branch. Another example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 20
+
+ This shows what could seem a counterintuitve behaviour of quantifiers:
+ since \c{?} is greedy, then the engine tries first to continue the match
+ after having matched \c{"abc"}; but then the matching reaches the end of the
+ subject string, and therefore a partial match is reported. This is
+ even more surprising in the following example:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 21
+
+ It's easy to understand this behaviour if we remember that the engine
+ expects the subject string to be only a substring of the whole text we're
+ looking for a match into (that is, how we said before, that the engine
+ assumes that there are other characters beyond the end of the subject
+ string).
+
+ Since the \c{*} quantifier is greedy, then reporting a complete match could
+ be an error, because after the current subject \c{"abc"} there may be other
+ occurrences of \c{"abc"}. For instance, the complete text could have been
+ "abcabcX", and therefore the \e{right} match to report (in the complete
+ text) would have been \c{"abcabc"}; by matching only against the leading
+ \c{"abc"} we instead get a partial match.
+
+ \section1 Error handling
+
+ It is possible for a QRegularExpression object to be invalid because of
+ syntax errors in the pattern string. The isValid() function will return
+ true if the regular expression is valid, or false otherwise:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 22
+
+ You can get more information about the specific error by calling the
+ errorString() function; moreover, the patternErrorOffset() function
+ will return the offset inside the pattern string
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 23
+
+ If a match is attempted with an invalid QRegularExpression, then the
+ returned QRegularExpressionMatch object will be invalid as well (that is,
+ its \l{QRegularExpressionMatch::}{isValid()} function will return false).
+ The same applies for attempting a global match.
+
+ \section1 Unsupported Perl-compatible regular expressions features
+
+ QRegularExpression does not support all the features available in
+ Perl-compatible regular expressions. The most notable one is the fact that
+ duplicated names for capturing groups are not supported, and using them can
+ lead to undefined behaviour.
+
+ This may change in a future version of Qt.
+
+ \section1 Notes for QRegExp users
+
+ The QRegularExpression class introduced in Qt 5 is a big improvement upon
+ QRegExp, in terms of APIs offered, supported pattern syntax and speed of
+ execution. The biggest difference is that QRegularExpression simply holds a
+ regular expression, and it's \e{not} modified when a match is requested.
+ Instead, a QRegularExpressionMatch object is returned, in order to check
+ the result of a match and extract the captured substring. The same applies
+ with global matching and QRegularExpressionMatchIterator.
+
+ Other differences are outlined below.
+
+ \section2 Exact matching
+
+ QRegExp::exactMatch in Qt 4 served for two purposes: it exactly matched
+ a regular expression against a subject string, and it implemented partial
+ matching. In fact, if an exact match was not found, one could still find
+ out how much of the subject string was matched by the regular expression
+ by calling QRegExp::matchedLength(). If the returned length was equal
+ to the subject string's length, then one could desume that a partial match
+ was found.
+
+ QRegularExpression supports partial matching explicitly by means of the
+ appropriate MatchType. If instead you simply want to be sure that the
+ subject string matches the regular expression exactly, you can wrap the
+ pattern between a couple of anchoring expressions. Simply
+ putting the pattern between the \c{^} and the \c{$} anchors is enough
+ in most cases:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 24
+
+ However, remember that the \c{$} anchor not only matches at the end of the
+ string, but also at a newline character right before the end of the string;
+ that is, the previous pattern matches against the string "this pattern must
+ match exactly\n". Also, the behaviour of both the \c{^} and the \c{$}
+ anchors changes if the MultiLineOption is set either explicitely (as a
+ pattern option) or implicitly (as a directive inside the pattern string).
+
+ Therefore, in the most general case, you should wrap the pattern between
+ the \c{\A} and the \c{\z} anchors:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 25
+
+ Note the usage of the non-capturing group in order to preserve the meaning
+ of the branch operator inside the pattern.
+
+ \section2 Global matching
+
+ Due to limitations of the QRegExp API it was impossible to implement global
+ matching correctly (that is, like Perl does). In particular, patterns that
+ can match 0 characters (like \c{"a*"}) are problematic.
+
+ QRegularExpression::globalMatch implements Perl global match correctly, and
+ the returned iterator can be used to examine each result.
+
+ \section2 Wildcard matching
+
+ There is no equivalent of wildcard matching in QRegularExpression.
+ Nevertheless, rewriting a regular expression in wildcard syntax to a
+ Perl-compatible regular expression is a very easy task, given the fact
+ that wildcard syntax supported by QRegExp is very simple.
+
+ \section2 Other pattern syntaxes
+
+ QRegularExpression supports only Perl-compatible regular expressions.
+
+ \section2 Minimal matching
+
+ QRegExp::setMinimal implemented minimal matching by simply reversing the
+ greediness of the quantifiers (QRegExp did not support lazy quantifiers,
+ like \c{*?}, \c{+?}, etc.). QRegularExpression instead does support greedy,
+ lazy and possessive quantifiers. The InvertedGreedinessOption
+ pattern option can be useful to emulate the effects of QRegExp::setMinimal:
+ if enabled, it inverts the greediness of quantifiers (greedy ones become
+ lazy and vice versa).
+
+ \section2 Caret modes
+
+ The AnchoredMatchOption match option can be used to emulate the
+ QRegExp::CaretAtOffset behaviour. There is no equivalent for the other
+ QRegExp::CaretMode modes.
+
+ \section1 Debugging code that uses QRegularExpression
+
+ QRegularExpression internally uses a just in time compiler (JIT) to
+ optimize the execution of the matching algorithm. The JIT makes extensive
+ usage of self-modifying code, which can lead debugging tools such as
+ Valgrind to crash. You must enable all checks for self-modifying code if
+ you want to debug programs using QRegularExpression (f.i., see Valgrind's
+ \c{--smc-check} command line option). The downside of enabling such checks
+ is that your program will run considerably slower.
+
+ To avoid that, the JIT is disabled by default if you compile Qt in debug
+ mode. It is possible to override the default and enable or disable the JIT
+ usage (both in debug or release mode) by setting the
+ \c{QT_ENABLE_REGEXP_JIT} environment variable to a non-zero or zero value
+ respectively.
+
+ \sa QRegularExpressionMatch, QRegularExpressionMatchIterator
+*/
+
+/*!
+ \class QRegularExpressionMatch
+ \reentrant
+
+ \brief The QRegularExpressionMatch class provides the results of a matching
+ a QRegularExpression against a string.
+
+ \since 5.0
+
+ \ingroup tools
+ \ingroup shared
+
+ \keyword regular expression match
+
+ A QRegularExpressionMatch object can be obtained by calling the
+ QRegularExpression::match() function, or as a single result of a global
+ match from a QRegularExpressionMatchIterator.
+
+ The success or the failure of a match attempt can be inspected by calling
+ the hasMatch() function. QRegularExpressionMatch also reports a successful
+ partial match through the hasPartialMatch() function.
+
+ In addition, QRegularExpressionMatch returns the substrings captured by the
+ capturing groups in the pattern string. The implicit capturing group with
+ index 0 captures the result of the whole match. The captured() function
+ returns each substring captured, either by the capturing group's index or
+ by its name:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 29
+
+ For each captured substring it is possible to query its starting and ending
+ offsets in the subject string by calling the capturedStart() and the
+ capturedEnd() function, respectively. The length of each captured
+ substring is available using the capturedLength() function.
+
+ The convenience function capturedTexts() will return \e{all} the captured
+ substrings at once (including the substring matched by the entire pattern)
+ in the order they have been captured by captring groups; that is,
+ \c{captured(i) == capturedTexts().at(i)}.
+
+ You can retrieve the QRegularExpression object the subject string was
+ matched against by calling the regularExpression() function; the
+ match type and the match options are available as well by calling
+ the matchType() and the matchOptions() respectively.
+
+ Please refer to the QRegularExpression documentation for more information
+ about the Qt regular expression classes.
+
+ \sa QRegularExpression
+*/
+
+/*!
+ \class QRegularExpressionMatchIterator
+ \reentrant
+
+ \brief The QRegularExpressionMatchIterator class provides an iterator on
+ the results of a global match of a QRegularExpression object against a string.
+
+ \since 5.0
+
+ \ingroup tools
+ \ingroup shared
+
+ \keyword regular expression iterator
+
+ A QRegularExpressionMatchIterator object is a forward only Java-like
+ iterator; it can be obtained by calling the
+ QRegularExpression::globalMatch() function. A new
+ QRegularExpressionMatchIterator will be positioned before the first result.
+ You can then call the hasNext() function to check if there are more
+ results available; if so, the next() function will return the next
+ result and advance the iterator.
+
+ Each result is a QRegularExpressionMatch object holding all the information
+ for that result (including captured substrings).
+
+ For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 30
+
+ Moreover, QRegularExpressionMatchIterator offers a peekNext() function
+ to get the next result \e{without} advancing the iterator.
+
+ You can retrieve the QRegularExpression object the subject string was
+ matched against by calling the regularExpression() function; the
+ match type and the match options are available as well by calling
+ the matchType() and the matchOptions() respectively.
+
+ Please refer to the QRegularExpression documentation for more information
+ about the Qt regular expression classes.
+
+ \sa QRegularExpression, QRegularExpressionMatch
+*/
+
+
+/*!
+ \enum QRegularExpression::PatternOption
+
+ The PatternOption enum defines modifiers to the way the pattern string
+ should be interpreted, and therefore the way the pattern matches against a
+ subject string.
+
+ \value NoPatternOption
+ No pattern options are set.
+
+ \value CaseInsensitiveOption
+ The pattern should match against the subject string in a case
+ insensitive way. This option corresponds to the /i modifier in Perl
+ regular expressions.
+
+ \value DotMatchesEverythingOption
+ The dot metacharacter (\c{.}) in the pattern string is allowed to match
+ any character in the subject string, including newlines (normally, the
+ dot does not match newlines). This option corresponds to the \c{/s}
+ modifier in Perl regular expressions.
+
+ \value MultilineOption
+ The caret (\c{^}) and the dollar (\c{$}) metacharacters in the pattern
+ string are allowed to match, respectively, immediately after and
+ immediately before any newline in the subject string, as well as at the
+ very beginning and at the very end of the subject string. This option
+ corresponds to the \c{/m} modifier in Perl regular expressions.
+
+ \value ExtendedPatternSyntaxOption
+ Any whitespace in the pattern string which is not escaped and outside a
+ character class is ignored. Moreover, an unescaped sharp (\b{#})
+ outside a character class causes all the following characters, until
+ the first newline (included), to be ignored. This can be used to
+ increase the readability of a pattern string as well as put comments
+ inside regular expressions; this is particulary useful if the pattern
+ string is loaded from a file or written by the user, because in C++
+ code it is always possible to use the rules for string literals to put
+ comments outside the pattern string. This option corresponds to the \c{/x}
+ modifier in Perl regular expressions.
+
+ \value InvertedGreedinessOption
+ The greediness of the quantifiers is inverted: \c{*}, \c{+}, \c{?},
+ \c{{m,n}}, etc. become lazy, while their lazy versions (\c{*?},
+ \c{+?}, \c{??}, \c{{m,n}?}, etc.) become greedy. There is no equivalent
+ for this option in Perl regular expressions.
+
+ \value DontCaptureOption
+ The non-named capturing groups do not capture substrings; named
+ capturing groups still work as intended, as well as the implicit
+ capturing group number 0 corresponding to the entire match. There is no
+ equivalent for this option in Perl regular expressions.
+
+ \value UseUnicodePropertiesOption
+ The meaning of the \c{\w}, \c{\d}, etc., character types, as well as
+ the meaning of their counterparts (\c{\W}, \c{\D}, etc.), is changed
+ from matching ASCII charaters only to matching any character with the
+ corresponding Unicode property. For instance, \c{\d} is changed to
+ match any character with the Unicode Nd (decimal digit) property;
+ \c{\w} to match any character with either the Unicode L (letter) or N
+ (digit) property, plus underscore, and so on. This option corresponds
+ to the \c{/u} modifier in Perl regular expressions.
+*/
+
+/*!
+ \enum QRegularExpression::MatchType
+
+ The MatchType enum defines the type of the match that should be attempted
+ against the subject string.
+
+ \value NormalMatch
+ A normal match is done.
+
+ \value PartialPreferCompleteMatch
+ The pattern string is matched partially against the subject string. If
+ a partial match is found, then it is recorded, and other matching
+ alternatives are tried as usual. If a complete match is then found,
+ then it's preferred to the partial match; in this case only the
+ complete match is reported. If instead no complete match is found (but
+ only the partial one), then the partial one is reported.
+
+ \value PartialPreferFirstMatch
+ The pattern string is matched partially against the subject string. If
+ a partial match is found, then matching stops and the partial match is
+ reported. In this case, other matching alternatives (potentially
+ leading to a complete match) are not tried. Moreover, this match type
+ assumes that the subject string only a substring of a larger text, and
+ that (in this text) there are other characters beyond the end of the
+ subject string. This can lead to surprising results; see the discussion
+ in the \l{partial matching} section for more details.
+*/
+
+/*!
+ \enum QRegularExpression::MatchOption
+
+ \value NoMatchOption
+ No match options are set.
+
+ \value AnchoredMatchOption
+ The match is constrained to start exactly at the offset passed to
+ match() in order to be successful, even if the pattern string does not
+ contain any metacharacter that anchors the match at that point.
+*/
+
+// after how many usages we optimize the regexp
+#ifdef QT_BUILD_INTERNAL
+Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = 10;
+#else
+static const unsigned int qt_qregularexpression_optimize_after_use_count = 10;
+#endif // QT_BUILD_INTERNAL
+
+/*!
+ \internal
+*/
+static int convertToPcreOptions(QRegularExpression::PatternOptions patternOptions)
+{
+ int options = 0;
+
+ if (patternOptions & QRegularExpression::CaseInsensitiveOption)
+ options |= PCRE_CASELESS;
+ if (patternOptions & QRegularExpression::DotMatchesEverythingOption)
+ options |= PCRE_DOTALL;
+ if (patternOptions & QRegularExpression::MultilineOption)
+ options |= PCRE_MULTILINE;
+ if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption)
+ options |= PCRE_EXTENDED;
+ if (patternOptions & QRegularExpression::InvertedGreedinessOption)
+ options |= PCRE_UNGREEDY;
+ if (patternOptions & QRegularExpression::DontCaptureOption)
+ options |= PCRE_NO_AUTO_CAPTURE;
+ if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
+ options |= PCRE_UCP;
+
+ return options;
+}
+
+/*!
+ \internal
+*/
+static int convertToPcreOptions(QRegularExpression::MatchOptions matchOptions)
+{
+ int options = 0;
+
+ if (matchOptions & QRegularExpression::AnchoredMatchOption)
+ options |= PCRE_ANCHORED;
+
+ return options;
+}
+
+struct QRegularExpressionPrivate : QSharedData
+{
+ QRegularExpressionPrivate();
+ ~QRegularExpressionPrivate();
+ QRegularExpressionPrivate(const QRegularExpressionPrivate &other);
+
+ void cleanCompiledPattern();
+ void compilePattern();
+ void getPatternInfo();
+ pcre16_extra *optimizePattern();
+
+ QRegularExpressionMatchPrivate *doMatch(const QString &subject,
+ int offset,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ const QRegularExpressionMatchPrivate *previous = 0) const;
+
+ int captureIndexForName(const QString &name) const;
+
+ QString pattern;
+ QRegularExpression::PatternOptions patternOptions;
+
+ // *All* of the following members are set managed while holding this mutex,
+ // except for isDirty which is set to true by QRegularExpression setters
+ // (right after a detach happened).
+ // On the other hand, after the compilation and studying,
+ // it's safe to *use* (i.e. read) them from multiple threads at the same time.
+ // Therefore, doMatch doesn't need to lock this mutex.
+ QMutex mutex;
+
+ // The PCRE pointers are reference-counted by the QRegularExpressionPrivate
+ // objects themselves; when the private is copied (i.e. a detach happened)
+ // they are set to 0
+ pcre16 *compiledPattern;
+ pcre16_extra *studyData;
+ const char *errorString;
+ int errorOffset;
+ int capturingCount;
+ unsigned int usedCount;
+ bool usingCrLfNewlines;
+ bool isDirty;
+};
+
+struct QRegularExpressionMatchPrivate : QSharedData
+{
+ QRegularExpressionMatchPrivate(const QRegularExpression &re,
+ const QString &subject,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ int capturingCount);
+
+ QRegularExpressionMatch nextMatch() const;
+
+ const QRegularExpression regularExpression;
+ const QString subject;
+ // the capturedOffsets vector contains pairs of (start, end) positions
+ // for each captured substring
+ QVector<int> capturedOffsets;
+
+ const QRegularExpression::MatchType matchType;
+ const QRegularExpression::MatchOptions matchOptions;
+
+ int capturedCount;
+
+ bool hasMatch;
+ bool hasPartialMatch;
+ bool isValid;
+};
+
+struct QRegularExpressionMatchIteratorPrivate : QSharedData
+{
+ QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ const QRegularExpressionMatch &next);
+
+ bool hasNext() const;
+ QRegularExpressionMatch next;
+ const QRegularExpression regularExpression;
+ const QRegularExpression::MatchType matchType;
+ const QRegularExpression::MatchOptions matchOptions;
+};
+
+/*!
+ \internal
+*/
+QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd)
+ : d(&dd)
+{
+}
+
+/*!
+ \internal
+*/
+QRegularExpressionPrivate::QRegularExpressionPrivate()
+ : pattern(), patternOptions(0),
+ mutex(),
+ compiledPattern(0), studyData(0),
+ errorString(0), errorOffset(-1),
+ capturingCount(0),
+ usedCount(0),
+ usingCrLfNewlines(false),
+ isDirty(true)
+{
+}
+
+/*!
+ \internal
+*/
+QRegularExpressionPrivate::~QRegularExpressionPrivate()
+{
+ cleanCompiledPattern();
+}
+
+/*!
+ \internal
+
+ Copies the private, which means copying only the pattern and the pattern
+ options. The compiledPattern and the studyData pointers are NOT copied (we
+ do not own them any more), and in general all the members set when
+ compiling a pattern are set to default values. isDirty is set back to true
+ so that the pattern has to be recompiled again.
+*/
+QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPrivate &other)
+ : QSharedData(other),
+ pattern(other.pattern), patternOptions(other.patternOptions),
+ mutex(),
+ compiledPattern(0), studyData(0),
+ errorString(0),
+ errorOffset(-1), capturingCount(0),
+ usedCount(0),
+ usingCrLfNewlines(false), isDirty(true)
+{
+}
+
+/*!
+ \internal
+*/
+void QRegularExpressionPrivate::cleanCompiledPattern()
+{
+ pcre16_free(compiledPattern);
+ pcre16_free_study(studyData);
+ usedCount = 0;
+ compiledPattern = 0;
+ studyData = 0;
+ usingCrLfNewlines = false;
+ errorOffset = -1;
+ capturingCount = 0;
+}
+
+/*!
+ \internal
+*/
+void QRegularExpressionPrivate::compilePattern()
+{
+ QMutexLocker lock(&mutex);
+
+ if (!isDirty)
+ return;
+
+ isDirty = false;
+ cleanCompiledPattern();
+
+ int options = convertToPcreOptions(patternOptions);
+ options |= PCRE_UTF16;
+
+ int errorCode;
+ compiledPattern = pcre16_compile2(pattern.utf16(), options,
+ &errorCode, &errorString, &errorOffset, 0);
+
+ if (!compiledPattern)
+ return;
+
+ Q_ASSERT(errorCode == 0);
+ Q_ASSERT(studyData == 0); // studying (=>optimizing) is always done later
+ errorOffset = -1;
+
+ getPatternInfo();
+}
+
+/*!
+ \internal
+*/
+void QRegularExpressionPrivate::getPatternInfo()
+{
+ Q_ASSERT(compiledPattern);
+
+ pcre16_fullinfo(compiledPattern, 0, PCRE_INFO_CAPTURECOUNT, &capturingCount);
+
+ // detect the settings for the newline
+ int patternNewlineSetting;
+ pcre16_fullinfo(compiledPattern, studyData, PCRE_INFO_OPTIONS, &patternNewlineSetting);
+ patternNewlineSetting &= PCRE_NEWLINE_CR | PCRE_NEWLINE_LF | PCRE_NEWLINE_CRLF
+ | PCRE_NEWLINE_ANY | PCRE_NEWLINE_ANYCRLF;
+ if (patternNewlineSetting == 0) {
+ // no option was specified in the regexp, grab PCRE build defaults
+ int pcreNewlineSetting;
+ pcre16_config(PCRE_CONFIG_NEWLINE, &pcreNewlineSetting);
+ switch (pcreNewlineSetting) {
+ case 13:
+ patternNewlineSetting = PCRE_NEWLINE_CR; break;
+ case 10:
+ patternNewlineSetting = PCRE_NEWLINE_LF; break;
+ case 3338: // (13<<8 | 10)
+ patternNewlineSetting = PCRE_NEWLINE_CRLF; break;
+ case -2:
+ patternNewlineSetting = PCRE_NEWLINE_ANYCRLF; break;
+ case -1:
+ patternNewlineSetting = PCRE_NEWLINE_ANY; break;
+ default:
+ qWarning("QRegularExpressionPrivate::compilePattern(): "
+ "PCRE_CONFIG_NEWLINE returned an unknown newline");
+ break;
+ }
+ }
+
+ usingCrLfNewlines = (patternNewlineSetting == PCRE_NEWLINE_CRLF) ||
+ (patternNewlineSetting == PCRE_NEWLINE_ANY) ||
+ (patternNewlineSetting == PCRE_NEWLINE_ANYCRLF);
+}
+
+/*!
+ \internal
+*/
+static bool isJitEnabled()
+{
+ QByteArray jitEnvironment = qgetenv("QT_ENABLE_REGEXP_JIT");
+ if (!jitEnvironment.isEmpty()) {
+ bool ok;
+ int enableJit = jitEnvironment.toInt(&ok);
+ return ok ? (enableJit != 0) : true;
+ }
+
+#ifdef QT_DEBUG
+ return false;
+#else
+ return true;
+#endif
+}
+
+/*!
+ \internal
+
+ The purpose of the function is to call pcre16_study (which allows some
+ optimizations to be performed, including JIT-compiling the pattern), and
+ setting the studyData member variable to the result of the study. It gets
+ called by doMatch() every time a match is performed. As of now, the
+ optimizations on the pattern are performed after a certain number of usages
+ (i.e. the qt_qregularexpression_optimize_after_use_count constant).
+
+ Notice that although the method is protected by a mutex, one thread may
+ invoke this function and return immediately (i.e. not study the pattern,
+ leaving studyData to NULL); but before calling pcre16_exec to perform the
+ match, another thread performs the studying and sets studyData to something
+ else. Although the assignment to studyData is itself atomic, the release of
+ the memory pointed by studyData isn't. Therefore, the current studyData
+ value is returned and used by doMatch.
+*/
+pcre16_extra *QRegularExpressionPrivate::optimizePattern()
+{
+ Q_ASSERT(compiledPattern);
+
+ QMutexLocker lock(&mutex);
+
+ if (studyData || (++usedCount != qt_qregularexpression_optimize_after_use_count))
+ return studyData;
+
+ static const bool enableJit = isJitEnabled();
+
+ int studyOptions = 0;
+ if (enableJit)
+ studyOptions |= PCRE_STUDY_JIT_COMPILE;
+
+ const char *err;
+ studyData = pcre16_study(compiledPattern, studyOptions, &err);
+
+ if (!studyData && err)
+ qWarning("QRegularExpressionPrivate::optimizePattern(): pcre_study failed: %s", err);
+
+ return studyData;
+}
+
+/*!
+ \internal
+
+ Returns the capturing group number for the given name. Duplicated names for
+ capturing groups are not supported.
+*/
+int QRegularExpressionPrivate::captureIndexForName(const QString &name) const
+{
+ Q_ASSERT(!name.isEmpty());
+
+ int index = pcre16_get_stringnumber(compiledPattern, name.utf16());
+ if (index >= 0)
+ return index;
+
+ return -1;
+}
+
+/*!
+ \internal
+
+ Performs a match of type \a matchType on the given \a subject string with
+ options \a matchOptions and returns the QRegularExpressionMatchPrivate of
+ the result. It also advances a match if a previous result is given as \a
+ previous.
+
+ Advancing a match is a tricky algorithm. If the previous match matched a
+ non-empty string, we just do an ordinary match at the offset position.
+
+ If the previous match matched an empty string, then an anchored, non-empty
+ match is attempted at the offset position. If that succeeds, then we got
+ the next match and we can return it. Otherwise, we advance by 1 position
+ (which can be one or two code units in UTF-16!) and reattempt a "normal"
+ match. We also have the problem of detecting the current newline format: if
+ the new advanced offset is pointing to the beginning of a CRLF sequence, we
+ must advance over it.
+*/
+QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString &subject,
+ int offset,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ const QRegularExpressionMatchPrivate *previous) const
+{
+ if (offset < 0)
+ offset += subject.length();
+
+ QRegularExpression re(*const_cast<QRegularExpressionPrivate *>(this));
+
+ if (offset < 0 || offset > subject.length())
+ return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions, 0);
+
+ if (!compiledPattern) {
+ qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
+ return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions, 0);
+ }
+
+ QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject,
+ matchType, matchOptions,
+ capturingCount);
+
+ // this is mutex protected
+ const pcre16_extra *currentStudyData = const_cast<QRegularExpressionPrivate *>(this)->optimizePattern();
+
+ int pcreOptions = convertToPcreOptions(matchOptions);
+
+ if (matchType == QRegularExpression::PartialPreferCompleteMatch)
+ pcreOptions |= PCRE_PARTIAL_SOFT;
+ else if (matchType == QRegularExpression::PartialPreferFirstMatch)
+ pcreOptions |= PCRE_PARTIAL_HARD;
+
+ bool previousMatchWasEmpty = false;
+ if (previous && previous->hasMatch &&
+ (previous->capturedOffsets.at(0) == previous->capturedOffsets.at(1))) {
+ previousMatchWasEmpty = true;
+ }
+
+ int * const captureOffsets = priv->capturedOffsets.data();
+ const int captureOffsetsCount = priv->capturedOffsets.size();
+
+ const unsigned short * const subjectUtf16 = subject.utf16();
+ const int subjectLength = subject.length();
+
+ int result;
+
+ if (!previousMatchWasEmpty) {
+ result = pcre16_exec(compiledPattern, currentStudyData,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
+ captureOffsets, captureOffsetsCount);
+ } else {
+ result = pcre16_exec(compiledPattern, currentStudyData,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
+ captureOffsets, captureOffsetsCount);
+
+ if (result == PCRE_ERROR_NOMATCH) {
+ ++offset;
+
+ if (usingCrLfNewlines
+ && offset < subjectLength
+ && subjectUtf16[offset - 1] == QLatin1Char('\r')
+ && subjectUtf16[offset] == QLatin1Char('\n')) {
+ ++offset;
+ } else if (offset < subjectLength
+ && QChar::isLowSurrogate(subjectUtf16[offset])) {
+ ++offset;
+ }
+
+ result = pcre16_exec(compiledPattern, currentStudyData,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
+ captureOffsets, captureOffsetsCount);
+ }
+ }
+
+#ifdef QREGULAREXPRESSION_DEBUG
+ qDebug() << "Matching" << pattern << "against" << subject
+ << offset << matchType << matchOptions << previousMatchWasEmpty
+ << "result" << result;
+#endif
+
+ // result == 0 means not enough space in captureOffsets; should never happen
+ Q_ASSERT(result != 0);
+
+ if (result > 0) {
+ // full match
+ priv->isValid = true;
+ priv->hasMatch = true;
+ priv->capturedCount = result;
+ priv->capturedOffsets.resize(result * 2);
+ } else {
+ // no match, partial match or error
+ priv->hasPartialMatch = (result == PCRE_ERROR_PARTIAL);
+ priv->isValid = (result == PCRE_ERROR_NOMATCH || result == PCRE_ERROR_PARTIAL);
+
+ if (result == PCRE_ERROR_PARTIAL) {
+ // partial match:
+ // leave the start and end capture offsets (i.e. cap(0))
+ priv->capturedCount = 1;
+ priv->capturedOffsets.resize(2);
+ } else {
+ // no match or error
+ priv->capturedCount = 0;
+ priv->capturedOffsets.clear();
+ }
+ }
+
+ return priv;
+}
+
+/*!
+ \internal
+*/
+QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExpression &re,
+ const QString &subject,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ int capturingCount)
+ : regularExpression(re), subject(subject),
+ matchType(matchType), matchOptions(matchOptions),
+ capturedCount(0),
+ hasMatch(false), hasPartialMatch(false), isValid(false)
+{
+ Q_ASSERT(capturingCount >= 0);
+ const int captureOffsetsCount = (capturingCount + 1) * 3;
+ capturedOffsets.resize(captureOffsetsCount);
+}
+
+
+/*!
+ \internal
+*/
+QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
+{
+ Q_ASSERT(isValid);
+ Q_ASSERT(hasMatch || hasPartialMatch);
+
+ QRegularExpressionMatchPrivate *nextPrivate = regularExpression.d->doMatch(subject,
+ capturedOffsets.at(1),
+ matchType,
+ matchOptions,
+ this);
+ return QRegularExpressionMatch(*nextPrivate);
+}
+
+/*!
+ \internal
+*/
+QRegularExpressionMatchIteratorPrivate::QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re,
+ QRegularExpression::MatchType matchType,
+ QRegularExpression::MatchOptions matchOptions,
+ const QRegularExpressionMatch &next)
+ : next(next),
+ regularExpression(re),
+ matchType(matchType), matchOptions(matchOptions)
+{
+}
+
+/*!
+ \internal
+*/
+bool QRegularExpressionMatchIteratorPrivate::hasNext() const
+{
+ return next.isValid() && (next.hasMatch() || next.hasPartialMatch());
+}
+
+// PUBLIC API
+
+/*!
+ Constructs a QRegularExpression object with an empty pattern and no pattern
+ options.
+
+ \sa setPattern(), setPatternOptions()
+*/
+QRegularExpression::QRegularExpression()
+ : d(new QRegularExpressionPrivate)
+{
+}
+
+/*!
+ Constructs a QRegularExpression object using the given \a pattern as
+ pattern and the \a options as the pattern options.
+
+ \sa setPattern(), setPatternOptions()
+*/
+QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions options)
+ : d(new QRegularExpressionPrivate)
+{
+ d->pattern = pattern;
+ d->patternOptions = options;
+}
+
+/*!
+ Constructs a QRegularExpression object as a copy of \a re.
+
+ \sa operator=()
+*/
+QRegularExpression::QRegularExpression(const QRegularExpression &re)
+ : d(re.d)
+{
+}
+
+/*!
+ Destroys the QRegularExpression object.
+*/
+QRegularExpression::~QRegularExpression()
+{
+}
+
+/*!
+ Assigns the regular expression \a re to this object, and returns a reference
+ to the copy. Both the pattern and the pattern options are copied.
+*/
+QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re)
+{
+ d = re.d;
+ return *this;
+}
+
+/*!
+ \fn void QRegularExpression::swap(QRegularExpression &other)
+
+ Swaps the regular expression \a other with this regular expression. This
+ operation is very fast and never fails.
+*/
+
+/*!
+ Returns the pattern string of the regular expression.
+
+ \sa setPattern(), patternOptions()
+*/
+QString QRegularExpression::pattern() const
+{
+ return d->pattern;
+}
+
+/*!
+ Sets the pattern string of the regular expression to \a pattern. The
+ pattern options are left unchanged.
+
+ \sa pattern(), setPatternOptions()
+*/
+void QRegularExpression::setPattern(const QString &pattern)
+{
+ d.detach();
+ d->isDirty = true;
+ d->pattern = pattern;
+}
+
+/*!
+ Returns the pattern options for the regular expression.
+
+ \sa setPatternOptions(), pattern()
+*/
+QRegularExpression::PatternOptions QRegularExpression::patternOptions() const
+{
+ return d->patternOptions;
+}
+
+/*!
+ Sets the given \a options as the pattern options of the regular expression.
+ The pattern string is left unchanged.
+
+ \sa patternOptions(), setPattern()
+*/
+void QRegularExpression::setPatternOptions(PatternOptions options)
+{
+ d.detach();
+ d->isDirty = true;
+ d->patternOptions = options;
+}
+
+/*!
+ Returns the number of capturing groups inside the pattern string,
+ or -1 if the regular expression is not valid.
+
+ \sa isValid()
+*/
+int QRegularExpression::captureCount() const
+{
+ if (!isValid()) // will compile the pattern
+ return -1;
+ return d->capturingCount;
+}
+
+/*!
+ Returns true if the regular expression is a valid regular expression (that
+ is, it contains no syntax errors, etc.), or false otherwise. Use
+ errorString() to obtain a textual description of the error.
+
+ \sa errorString(), patternErrorOffset()
+*/
+bool QRegularExpression::isValid() const
+{
+ d.data()->compilePattern();
+ return d->compiledPattern;
+}
+
+/*!
+ Returns a textual description of the error found when checking the validity
+ of the regular expression, or "no error" if no error was found.
+
+ \sa isValid(), patternErrorOffset()
+*/
+QString QRegularExpression::errorString() const
+{
+ d.data()->compilePattern();
+ if (d->errorString)
+ return QCoreApplication::translate("QRegularExpression", d->errorString, 0, QCoreApplication::UnicodeUTF8);
+ return QCoreApplication::translate("QRegularExpression", "no error", 0, QCoreApplication::UnicodeUTF8);
+}
+
+/*!
+ Returns the offset, inside the pattern string, at which an error was found
+ when checking the validity of the regular expression. If no error was
+ found, then -1 is returned.
+
+ \sa pattern(), isValid(), errorString()
+*/
+int QRegularExpression::patternErrorOffset() const
+{
+ d.data()->compilePattern();
+ return d->errorOffset;
+}
+
+/*!
+ Attempts to match the regular expression against the given \a subject
+ string, starting at the position \a offset inside the subject, using a
+ match of type \a matchType and honoring the given \a matchOptions.
+
+ The returned QRegularExpressionMatch object contains the results of the
+ match.
+
+ \sa QRegularExpressionMatch, {normal matching}
+*/
+QRegularExpressionMatch QRegularExpression::match(const QString &subject,
+ int offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
+{
+ d.data()->compilePattern();
+
+ QRegularExpressionMatchPrivate *priv = d->doMatch(subject, offset, matchType, matchOptions);
+ return QRegularExpressionMatch(*priv);
+}
+
+/*!
+ Attempts to perform a global match of the regular expression against the
+ given \a subject string, starting at the position \a offset inside the
+ subject, using a match of type \a matchType and honoring the given \a
+ matchOptions.
+
+ The returned QRegularExpressionMatchIterator is positioned before the
+ first match result (if any).
+
+ \sa QRegularExpressionMatchIterator, {global matching}
+*/
+QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject,
+ int offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
+{
+ QRegularExpressionMatchIteratorPrivate *priv =
+ new QRegularExpressionMatchIteratorPrivate(*this,
+ matchType,
+ matchOptions,
+ match(subject, offset, matchType, matchOptions));
+
+ return QRegularExpressionMatchIterator(*priv);
+}
+
+/*!
+ Returns true if the regular expression is equal to \a re, or false
+ otherwise. Two QRegularExpression objects are equal if they have
+ the same pattern string and the same pattern options.
+
+ \sa operator!=()
+*/
+bool QRegularExpression::operator==(const QRegularExpression &re) const
+{
+ return (d == re.d) ||
+ (d->pattern == re.d->pattern && d->patternOptions == re.d->patternOptions);
+}
+
+/*!
+ \fn bool QRegularExpression::operator!=(const QRegularExpression &re) const
+
+ Returns true if the regular expression is different from \a re, or
+ false otherwise.
+
+ \sa operator==()
+*/
+
+/*!
+ Escapes all characters of \a str so that they no longer have any special
+ meaning when used as a regular expression pattern string, and returns
+ the escaped string. For instance:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 26
+
+ This is very convenient in order to build patterns from arbitrary strings:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 27
+
+ \note This function implements Perl's quotemeta algorithm and escapes with
+ a backslash all characters in \a str, except for the characters in the
+ \c{[A-Z]}, \c{[a-z]} and \c{[0-9]} ranges, as well as the underscore
+ (\c{_}) character. The only difference with Perl is that a literal NUL
+ inside \a str is escaped with the sequence \c{"\\\\0"} (backslash +
+ \c{'0'}), instead of \c{"\\\\\\0"} (backslash + \c{NUL}).
+*/
+QString QRegularExpression::escape(const QString &str)
+{
+ QString result;
+ const int count = str.size();
+ result.reserve(count * 2);
+
+ // everything but [a-zA-Z0-9_] gets escaped,
+ // cf. perldoc -f quotemeta
+ for (int i = 0; i < count; ++i) {
+ const QChar current = str.at(i);
+
+ if (current == QChar::Null) {
+ // unlike Perl, a literal NUL must be escaped with
+ // "\\0" (backslash + 0) and not "\\\0" (backslash + NUL),
+ // because pcre16_compile uses a NUL-terminated string
+ result.append(QLatin1Char('\\'));
+ result.append(QLatin1Char('0'));
+ } else if ( (current < QLatin1Char('a') || current > QLatin1Char('z')) &&
+ (current < QLatin1Char('A') || current > QLatin1Char('Z')) &&
+ (current < QLatin1Char('0') || current > QLatin1Char('9')) &&
+ current != QLatin1Char('_') )
+ {
+ result.append(QLatin1Char('\\'));
+ result.append(current);
+ if (current.isHighSurrogate() && i < (count - 1))
+ result.append(str.at(++i));
+ } else {
+ result.append(current);
+ }
+ }
+
+ result.squeeze();
+ return result;
+}
+
+/*!
+ Destroys the match result.
+*/
+QRegularExpressionMatch::~QRegularExpressionMatch()
+{
+}
+
+/*!
+ Constructs a match result by copying the result of the given \a match.
+
+ \sa operator=()
+*/
+QRegularExpressionMatch::QRegularExpressionMatch(const QRegularExpressionMatch &match)
+ : d(match.d)
+{
+}
+
+/*!
+ Assigns the match result \a match to this object, and returns a reference
+ to the copy.
+*/
+QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpressionMatch &match)
+{
+ d = match.d;
+ return *this;
+}
+
+/*!
+ \fn void QRegularExpressionMatch::swap(QRegularExpressionMatch &other)
+
+ Swaps the match result \a other with this match result. This
+ operation is very fast and never fails.
+*/
+
+/*!
+ \internal
+*/
+QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd)
+ : d(&dd)
+{
+}
+
+/*!
+ Returns the QRegularExpression object whose match() function returned this
+ object.
+
+ \sa QRegularExpression::match(), matchType(), matchOptions()
+*/
+QRegularExpression QRegularExpressionMatch::regularExpression() const
+{
+ return d->regularExpression;
+}
+
+
+/*!
+ Returns the match type that was used to get this QRegularExpressionMatch
+ object, that is, the match type that was passed to
+ QRegularExpression::match() or QRegularExpression::globalMatch().
+
+ \sa QRegularExpression::match(), regularExpression(), matchOptions()
+*/
+QRegularExpression::MatchType QRegularExpressionMatch::matchType() const
+{
+ return d->matchType;
+}
+
+/*!
+ Returns the match options that were used to get this
+ QRegularExpressionMatch object, that is, the match options that were passed
+ to QRegularExpression::match() or QRegularExpression::globalMatch().
+
+ \sa QRegularExpression::match(), regularExpression(), matchType()
+*/
+QRegularExpression::MatchOptions QRegularExpressionMatch::matchOptions() const
+{
+ return d->matchOptions;
+}
+
+/*!
+ Returns the index of the last capturing group that captured something,
+ including the implicit capturing group 0. This can be used to extract all
+ the substrings that were captured:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 28
+
+ Note that some of the capturing groups with an index less than
+ lastCapturedIndex() could have not matched, and therefore captured nothing.
+
+ If the regular expression did not match, this function returns -1.
+
+ \sa captured(), capturedStart(), capturedEnd(), capturedLength()
+*/
+int QRegularExpressionMatch::lastCapturedIndex() const
+{
+ return d->capturedCount - 1;
+}
+
+/*!
+ Returns the substring captured by the \a nth capturing group. If the \a nth
+ capturing group did not capture a string or doesn't exist, returns a null
+ QString.
+
+ \sa capturedRef(), lastCapturedIndex(), capturedStart(), capturedEnd(),
+ capturedLength(), QString::isNull()
+*/
+QString QRegularExpressionMatch::captured(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return QString();
+
+ int start = capturedStart(nth);
+
+ if (start == -1) // didn't capture
+ return QString();
+
+ return d->subject.mid(start, capturedLength(nth));
+}
+
+/*!
+ Returns a reference to the substring captured by the \a nth capturing group.
+ If the \a nth capturing group did not capture a string or doesn't exist,
+ returns a null QStringRef.
+
+ \sa captured(), lastCapturedIndex(), capturedStart(), capturedEnd(),
+ capturedLength(), QStringRef::isNull()
+*/
+QStringRef QRegularExpressionMatch::capturedRef(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return QStringRef();
+
+ int start = capturedStart(nth);
+
+ if (start == -1) // didn't capture
+ return QStringRef();
+
+ return d->subject.midRef(start, capturedLength(nth));
+}
+
+/*!
+ Returns the substring captured by the capturing group named \a name. If the
+ capturing group named \a name did not capture a string or doesn't exist,
+ returns a null QString.
+
+ \sa capturedRef(), capturedStart(), capturedEnd(), capturedLength(),
+ QString::isNull()
+*/
+QString QRegularExpressionMatch::captured(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::captured: empty capturing group name passed");
+ return QString();
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return QString();
+ return captured(nth);
+}
+
+/*!
+ Returns a reference to the string captured by the capturing group named \a
+ name. If the capturing group named \a name did not capture a string or
+ doesn't exist, returns a null QStringRef.
+
+ \sa captured(), capturedStart(), capturedEnd(), capturedLength(),
+ QStringRef::isNull()
+*/
+QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::capturedRef: empty capturing group name passed");
+ return QStringRef();
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return QStringRef();
+ return capturedRef(nth);
+}
+
+/*!
+ Returns a list of all strings captured by capturing groups, in the order
+ the groups themselves appear in the pattern string.
+*/
+QStringList QRegularExpressionMatch::capturedTexts() const
+{
+ QStringList texts;
+ for (int i = 0; i <= lastCapturedIndex(); ++i)
+ texts << captured(i);
+ return texts;
+}
+
+/*!
+ Returns the offset inside the subject string corresponding to the
+ starting position of the substring captured by the \a nth capturing group.
+ If the \a nth capturing group did not capture a string or doesn't exist,
+ returns -1.
+
+ \sa capturedEnd(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedStart(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return -1;
+
+ return d->capturedOffsets.at(nth * 2);
+}
+
+/*!
+ Returns the length of the substring captured by the \a nth capturing group.
+
+ \note This function returns 0 if the \a nth capturing group did not capture
+ a string or doesn't exist.
+
+ \sa capturedStart(), capturedEnd(), captured()
+*/
+int QRegularExpressionMatch::capturedLength(int nth) const
+{
+ // bound checking performed by these two functions
+ return capturedEnd(nth) - capturedStart(nth);
+}
+
+/*!
+ Returns the offset inside the subject string immediately after the ending
+ position of the substring captured by the \a nth capturing group. If the \a
+ nth capturing group did not capture a string or doesn't exist, returns -1.
+
+ \sa capturedStart(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedEnd(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return -1;
+
+ return d->capturedOffsets.at(nth * 2 + 1);
+}
+
+/*!
+ Returns the offset inside the subject string corresponding to the starting
+ position of the substring captured by the capturing group named \a name.
+ If the capturing group named \a name did not capture a string or doesn't
+ exist, returns -1.
+
+ \sa capturedEnd(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedStart(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed");
+ return -1;
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return -1;
+ return capturedStart(nth);
+}
+
+/*!
+ Returns the offset inside the subject string corresponding to the starting
+ position of the substring captured by the capturing group named \a name.
+
+ \note This function returns 0 if the capturing group named \a name did not
+ capture a string or doesn't exist.
+
+ \sa capturedStart(), capturedEnd(), captured()
+*/
+int QRegularExpressionMatch::capturedLength(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed");
+ return 0;
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return 0;
+ return capturedLength(nth);
+}
+
+/*!
+ Returns the offset inside the subject string immediately after the ending
+ position of the substring captured by the capturing group named \a name. If
+ the capturing group named \a name did not capture a string or doesn't
+ exist, returns -1.
+
+ \sa capturedStart(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedEnd(const QString &name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed");
+ return -1;
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return -1;
+ return capturedEnd(nth);
+}
+
+/*!
+ Returns true if the regular expression matched against the subject string,
+ or false otherwise.
+
+ \sa QRegularExpression::match(), hasPartialMatch()
+*/
+bool QRegularExpressionMatch::hasMatch() const
+{
+ return d->hasMatch;
+}
+
+/*!
+ Returns true if the regular expression partially matched against the
+ subject string, or false otherwise.
+
+ \note Only a match that explicitely used the one of the partial match types
+ can yield a partial match. Still, if such a match succeeds totally, this
+ function will return false, while hasMatch() will return true.
+
+ \sa QRegularExpression::match(), QRegularExpression::MatchType, hasMatch()
+*/
+bool QRegularExpressionMatch::hasPartialMatch() const
+{
+ return d->hasPartialMatch;
+}
+
+/*!
+ Returns true if the match object was obtained as a result from the
+ QRegularExpression::match() function invoked on a valid QRegularExpression
+ object; returns false if the QRegularExpression was invalid.
+
+ \sa QRegularExpression::match(), QRegularExpression::isValid()
+*/
+bool QRegularExpressionMatch::isValid() const
+{
+ return d->isValid;
+}
+
+/*!
+ \internal
+*/
+QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd)
+ : d(&dd)
+{
+}
+
+/*!
+ Destroys the QRegularExpressionMatchIterator object.
+*/
+QRegularExpressionMatchIterator::~QRegularExpressionMatchIterator()
+{
+}
+
+/*!
+ Constructs a QRegularExpressionMatchIterator object as a copy of \a
+ iterator.
+
+ \sa operator=()
+*/
+QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator)
+ : d(iterator.d)
+{
+}
+
+/*!
+ Assigns the iterator \a iterator to this object, and returns a reference to
+ the copy.
+*/
+QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(const QRegularExpressionMatchIterator &iterator)
+{
+ d = iterator.d;
+ return *this;
+}
+
+/*!
+ \fn void QRegularExpressionMatchIterator::swap(QRegularExpressionMatchIterator &other)
+
+ Swaps the iterator \a other with this iterator object. This operation is
+ very fast and never fails.
+*/
+
+/*!
+ Returns true if the iterator object was obtained as a result from the
+ QRegularExpression::globalMatch() function invoked on a valid
+ QRegularExpression object; returns false if the QRegularExpression was
+ invalid.
+
+ \sa QRegularExpression::globalMatch(), QRegularExpression::isValid()
+*/
+bool QRegularExpressionMatchIterator::isValid() const
+{
+ return d->next.isValid();
+}
+
+/*!
+ Returns true if there is at least one match result ahead of the iterator;
+ otherwise it returns false.
+
+ \sa next()
+*/
+bool QRegularExpressionMatchIterator::hasNext() const
+{
+ return d->hasNext();
+}
+
+/*!
+ Returns the next match result without moving the iterator.
+
+ \note Calling this function when the iterator is at the end of the result
+ set leads to undefined results.
+*/
+QRegularExpressionMatch QRegularExpressionMatchIterator::peekNext() const
+{
+ if (!hasNext())
+ qWarning("QRegularExpressionMatchIterator::peekNext() called on an iterator already at end");
+
+ return d->next;
+}
+
+/*!
+ Returns the next match result and advances the iterator by one position.
+
+ \note Calling this function when the iterator is at the end of the result
+ set leads to undefined results.
+*/
+QRegularExpressionMatch QRegularExpressionMatchIterator::next()
+{
+ if (!hasNext()) {
+ qWarning("QRegularExpressionMatchIterator::next() called on an iterator already at end");
+ return d->next;
+ }
+
+ QRegularExpressionMatch current = d->next;
+ d->next = d->next.d.constData()->nextMatch();
+ return current;
+}
+
+/*!
+ Returns the QRegularExpression object whose globalMatch() function returned
+ this object.
+
+ \sa QRegularExpression::globalMatch(), matchType(), matchOptions()
+*/
+QRegularExpression QRegularExpressionMatchIterator::regularExpression() const
+{
+ return d->regularExpression;
+}
+
+/*!
+ Returns the match type that was used to get this
+ QRegularExpressionMatchIterator object, that is, the match type that was
+ passed to QRegularExpression::globalMatch().
+
+ \sa QRegularExpression::globalMatch(), regularExpression(), matchOptions()
+*/
+QRegularExpression::MatchType QRegularExpressionMatchIterator::matchType() const
+{
+ return d->matchType;
+}
+
+/*!
+ Returns the match options that were used to get this
+ QRegularExpressionMatchIterator object, that is, the match options that
+ were passed to QRegularExpression::globalMatch().
+
+ \sa QRegularExpression::globalMatch(), regularExpression(), matchType()
+*/
+QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions() const
+{
+ return d->matchOptions;
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QRegularExpression
+
+ Writes the regular expression \a re to stream \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator<<(QDataStream &out, const QRegularExpression &re)
+{
+ out << re.pattern() << quint32(re.patternOptions());
+ return out;
+}
+
+/*!
+ \relates QRegularExpression
+
+ Reads a regular expression from stream \a in into \a re.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator>>(QDataStream &in, QRegularExpression &re)
+{
+ QString pattern;
+ quint32 patternOptions;
+ in >> pattern >> patternOptions;
+ re.setPattern(pattern);
+ re.setPatternOptions(QRegularExpression::PatternOptions(patternOptions));
+ return in;
+}
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ \relates QRegularExpression
+
+ Writes the regular expression \a re into the debug object \a debug for
+ debugging purposes.
+
+ \sa {Debugging Techniques}
+*/
+QDebug operator<<(QDebug debug, const QRegularExpression &re)
+{
+ debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ")";
+ return debug.space();
+}
+
+/*!
+ \relates QRegularExpression
+
+ Writes the pattern options \a patternOptions into the debug object \a debug
+ for debugging purposes.
+
+ \sa {Debugging Techniques}
+*/
+QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions)
+{
+ QStringList flags;
+
+ if (patternOptions == QRegularExpression::NoPatternOption) {
+ flags << QLatin1String("NoPatternOption");
+ } else {
+ if (patternOptions & QRegularExpression::CaseInsensitiveOption)
+ flags << QLatin1String("CaseInsensitiveOption");
+ if (patternOptions & QRegularExpression::DotMatchesEverythingOption)
+ flags << QLatin1String("DotMatchesEverythingOption");
+ if (patternOptions & QRegularExpression::MultilineOption)
+ flags << QLatin1String("MultilineOption");
+ if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption)
+ flags << QLatin1String("ExtendedPatternSyntaxOption");
+ if (patternOptions & QRegularExpression::InvertedGreedinessOption)
+ flags << QLatin1String("InvertedGreedinessOption");
+ if (patternOptions & QRegularExpression::DontCaptureOption)
+ flags << QLatin1String("DontCaptureOption");
+ if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
+ flags << QLatin1String("UseUnicodePropertiesOption");
+ }
+
+ debug.nospace() << "QRegularExpression::PatternOptions("
+ << qPrintable(flags.join(QLatin1String("|")))
+ << ")";
+
+ return debug.space();
+}
+/*!
+ \relates QRegularExpressionMatch
+
+ Writes the match object \a match into the debug object \a debug for
+ debugging purposes.
+
+ \sa {Debugging Techniques}
+*/
+QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
+{
+ debug.nospace() << "QRegularExpressionMatch(";
+
+ if (!match.isValid()) {
+ debug << "Invalid)";
+ return debug.space();
+ }
+
+ debug << "Valid";
+
+ if (match.hasMatch()) {
+ debug << ", has match: ";
+ for (int i = 0; i <= match.lastCapturedIndex(); ++i) {
+ debug << i
+ << ":(" << match.capturedStart(i) << ", " << match.capturedEnd(i)
+ << ", " << match.captured(i) << ")";
+ if (i < match.lastCapturedIndex())
+ debug << ", ";
+ }
+ } else if (match.hasPartialMatch()) {
+ debug << ", has partial match: ("
+ << match.capturedStart(0) << ", "
+ << match.capturedEnd(0) << ", "
+ << match.captured(0) << ")";
+ } else {
+ debug << ", no match";
+ }
+
+ debug << ")";
+
+ return debug.space();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
new file mode 100644
index 0000000000..3ca83c9e27
--- /dev/null
+++ b/src/corelib/tools/qregularexpression.h
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREGULAREXPRESSION_H
+#define QREGULAREXPRESSION_H
+
+#ifndef QT_NO_REGEXP
+
+#include <QtCore/qstring.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QRegularExpressionMatch;
+class QRegularExpressionMatchIterator;
+struct QRegularExpressionPrivate;
+
+class Q_CORE_EXPORT QRegularExpression
+{
+public:
+ enum PatternOption {
+ NoPatternOption = 0x0000,
+ CaseInsensitiveOption = 0x0001,
+ DotMatchesEverythingOption = 0x0002,
+ MultilineOption = 0x0004,
+ ExtendedPatternSyntaxOption = 0x0008,
+ InvertedGreedinessOption = 0x0010,
+ DontCaptureOption = 0x0020,
+ UseUnicodePropertiesOption = 0x0040
+ };
+ Q_DECLARE_FLAGS(PatternOptions, PatternOption)
+
+ PatternOptions patternOptions() const;
+ void setPatternOptions(PatternOptions options);
+
+ QRegularExpression();
+ explicit QRegularExpression(const QString &pattern, PatternOptions options = NoPatternOption);
+ QRegularExpression(const QRegularExpression &re);
+ ~QRegularExpression();
+ QRegularExpression &operator=(const QRegularExpression &re);
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QRegularExpression &operator=(QRegularExpression &&re)
+ { d.swap(re.d); return *this; }
+#endif
+
+ inline void swap(QRegularExpression &re) { d.swap(re.d); }
+
+ QString pattern() const;
+ void setPattern(const QString &pattern);
+
+ bool isValid() const;
+ int patternErrorOffset() const;
+ QString errorString() const;
+
+ int captureCount() const;
+
+ enum MatchType {
+ NormalMatch = 0,
+ PartialPreferCompleteMatch,
+ PartialPreferFirstMatch
+ };
+
+ enum MatchOption {
+ NoMatchOption = 0x0000,
+ AnchoredMatchOption = 0x0001
+ };
+ Q_DECLARE_FLAGS(MatchOptions, MatchOption)
+
+ QRegularExpressionMatch match(const QString &subject,
+ int offset = 0,
+ MatchType matchType = NormalMatch,
+ MatchOptions matchOptions = NoMatchOption) const;
+
+ QRegularExpressionMatchIterator globalMatch(const QString &subject,
+ int offset = 0,
+ MatchType matchType = NormalMatch,
+ MatchOptions matchOptions = NoMatchOption) const;
+
+ static QString escape(const QString &str);
+
+ bool operator==(const QRegularExpression &re) const;
+ inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); }
+
+private:
+ friend struct QRegularExpressionPrivate;
+ friend class QRegularExpressionMatch;
+ friend struct QRegularExpressionMatchPrivate;
+ friend class QRegularExpressionMatchIterator;
+
+ QRegularExpression(QRegularExpressionPrivate &dd);
+ QExplicitlySharedDataPointer<QRegularExpressionPrivate> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::PatternOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::MatchOptions)
+Q_DECLARE_TYPEINFO(QRegularExpression, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegularExpression &re);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegularExpression &re);
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpression &re);
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions);
+#endif
+
+struct QRegularExpressionMatchPrivate;
+
+class Q_CORE_EXPORT QRegularExpressionMatch
+{
+public:
+ ~QRegularExpressionMatch();
+ QRegularExpressionMatch(const QRegularExpressionMatch &match);
+ QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match);
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match)
+ { d.swap(match.d); return *this; }
+#endif
+ inline void swap(QRegularExpressionMatch &match) { d.swap(match.d); }
+
+ QRegularExpression regularExpression() const;
+ QRegularExpression::MatchType matchType() const;
+ QRegularExpression::MatchOptions matchOptions() const;
+
+ bool hasMatch() const;
+ bool hasPartialMatch() const;
+
+ bool isValid() const;
+
+ int lastCapturedIndex() const;
+
+ QString captured(int nth = 0) const;
+ QStringRef capturedRef(int nth = 0) const;
+
+ QString captured(const QString &name) const;
+ QStringRef capturedRef(const QString &name) const;
+
+ QStringList capturedTexts() const;
+
+ int capturedStart(int nth = 0) const;
+ int capturedLength(int nth = 0) const;
+ int capturedEnd(int nth = 0) const;
+
+ int capturedStart(const QString &name) const;
+ int capturedLength(const QString &name) const;
+ int capturedEnd(const QString &name) const;
+
+private:
+ friend class QRegularExpression;
+ friend struct QRegularExpressionMatchPrivate;
+ friend class QRegularExpressionMatchIterator;
+
+ QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd);
+ QSharedDataPointer<QRegularExpressionMatchPrivate> d;
+};
+
+Q_DECLARE_TYPEINFO(QRegularExpressionMatch, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match);
+#endif
+
+struct QRegularExpressionMatchIteratorPrivate;
+
+class Q_CORE_EXPORT QRegularExpressionMatchIterator
+{
+public:
+ ~QRegularExpressionMatchIterator();
+ QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator);
+ QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator)
+ { d.swap(iterator.d); return *this; }
+#endif
+ void swap(QRegularExpressionMatchIterator &iterator) { d.swap(iterator.d); }
+
+ bool isValid() const;
+
+ bool hasNext() const;
+ QRegularExpressionMatch next();
+ QRegularExpressionMatch peekNext() const;
+
+ QRegularExpression regularExpression() const;
+ QRegularExpression::MatchType matchType() const;
+ QRegularExpression::MatchOptions matchOptions() const;
+
+private:
+ friend class QRegularExpression;
+
+ QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd);
+ QSharedDataPointer<QRegularExpressionMatchIteratorPrivate> d;
+};
+
+Q_DECLARE_TYPEINFO(QRegularExpressionMatchIterator, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QRegularExpression)
+
+QT_END_HEADER
+
+#endif // QT_NO_REGEXP
+
+#endif // QREGULAREXPRESSION_H
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 6fc86fc04b..4d02fbe66d 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -98,7 +98,9 @@ template<int N> struct QConstStringData
#define QT_UNICODE_LITERAL_II(str) u"" str
-#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)
+#elif defined(Q_OS_WIN) \
+ || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) \
+ || (!defined(__SIZEOF_WCHAR_T__) && defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536))
// wchar_t is 2 bytes
template<int N> struct QConstStringData
{
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 3740975b12..250789a969 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -30,6 +30,7 @@ HEADERS += \
tools/qqueue.h \
tools/qrect.h \
tools/qregexp.h \
+ tools/qregularexpression.h \
tools/qringbuffer_p.h \
tools/qrefcount.h \
tools/qscopedpointer.h \
@@ -75,6 +76,7 @@ SOURCES += \
tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
+ tools/qregularexpression.cpp \
tools/qrefcount.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
@@ -105,6 +107,12 @@ contains(QT_CONFIG,icu) {
DEFINES += QT_USE_ICU
}
+pcre {
+ include($$PWD/../../3rdparty/pcre.pri)
+} else {
+ LIBS_PRIVATE += -lpcre16
+}
+
DEFINES += HB_EXPORT=Q_CORE_EXPORT
INCLUDEPATH += ../3rdparty/harfbuzz/src
HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index aa47616161..e5b290ae1f 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -571,10 +571,6 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
if (!object)
return 0;
- QEvent e(QEvent::AccessibilityPrepare);
-
- QCoreApplication::sendEvent(object, &e);
-
const QMetaObject *mo = object->metaObject();
while (mo) {
const QLatin1String cn(mo->className());
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index f16e5c85de..95b2b4a28e 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -185,10 +185,10 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QPoint QCursor::pos()
+ \fn QPoint QCursor::pos(const QScreen *screen)
- Returns the position of the cursor (hot spot) in global screen
- coordinates.
+ Returns the position of the cursor (hot spot) of the \a screen
+ in global screen coordinates.
You can call QWidget::mapFromGlobal() to translate it to widget
coordinates.
@@ -197,10 +197,23 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QCursor::setPos(int x, int y)
+ \fn QPoint QCursor::pos()
+
+ Returns the position of the cursor (hot spot) of
+ the primary screen in global screen coordinates.
+
+ You can call QWidget::mapFromGlobal() to translate it to widget
+ coordinates.
+
+ \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
+*/
- Moves the cursor (hot spot) to the global screen position (\a x,
- \a y).
+
+/*!
+ \fn void QCursor::setPos(QScreen *screen, int x, int y)
+
+ Moves the cursor (hot spot) of the \a screen to the global
+ screen position (\a x, \a y).
You can call QWidget::mapToGlobal() to translate widget
coordinates to global screen coordinates.
@@ -209,6 +222,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn void QCursor::setPos(int x, int y)
+
+ Moves the cursor (hot spot) of the primary screen
+ to the global screen position (\a x, \a y).
+
+ You can call QWidget::mapToGlobal() to translate widget
+ coordinates to global screen coordinates.
+
+ \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
+*/
+
+/*!
\fn void QCursor::setPos (const QPoint &p)
\overload
@@ -217,6 +242,15 @@ QT_BEGIN_NAMESPACE
\a p.
*/
+/*!
+ \fn void QCursor::setPos (QScreen *screen,const QPoint &p)
+
+ \overload
+
+ Moves the cursor (hot spot) to the global screen position of the
+ \a screen at point \a p.
+*/
+
/*****************************************************************************
QCursor stream functions
*****************************************************************************/
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index 00b709b308..4820bcee9b 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
class QVariant;
+class QScreen;
/*
### The fake cursor has to go first with old qdoc.
@@ -101,8 +102,11 @@ public:
QPoint hotSpot() const;
static QPoint pos();
+ static QPoint pos(const QScreen *screen);
static void setPos(int x, int y);
+ static void setPos(QScreen *screen, int x, int y);
inline static void setPos(const QPoint &p) { setPos(p.x(), p.y()); }
+ inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); }
#ifdef qdoc
HCURSOR_or_HANDLE handle() const;
diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp
index 7ba2e1c580..1c719c839e 100644
--- a/src/gui/kernel/qcursor_qpa.cpp
+++ b/src/gui/kernel/qcursor_qpa.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <qcursor.h>
+#include <qscreen.h>
#include <private/qcursor_p.h>
#include <qplatformcursor_qpa.h>
#include <private/qguiapplication_p.h>
@@ -110,27 +111,34 @@ void QCursorData::update()
QPoint QCursor::pos()
{
+ return QCursor::pos(QGuiApplication::primaryScreen());
+}
+
+QPoint QCursor::pos(const QScreen *screen)
+{
+ if (screen)
+ if (const QPlatformCursor *cursor = screen->handle()->cursor())
+ return cursor->pos();
return QGuiApplicationPrivate::lastCursorPosition.toPoint();
}
-void QCursor::setPos(int x, int y)
+void QCursor::setPos(QScreen *screen, int x, int y)
{
- QPoint target(x, y);
-
- // Need to check, since some X servers generate null mouse move
- // events, causing looping in applications which call setPos() on
- // every mouse move event.
- //
- if (pos() == target)
- return;
-
- QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
- int cursorCount = cursors.count();
- for (int i = 0; i < cursorCount; ++i) {
- const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
- if (cursor)
- cursor.data()->setPos(target);
+ if (screen) {
+ if (QPlatformCursor *cursor = screen->handle()->cursor()) {
+ const QPoint pos = QPoint(x, y);
+ // Need to check, since some X servers generate null mouse move
+ // events, causing looping in applications which call setPos() on
+ // every mouse move event.
+ if (pos != cursor->pos())
+ cursor->setPos(pos);
+ }
}
}
+void QCursor::setPos(int x, int y)
+{
+ QCursor::setPos(QGuiApplication::primaryScreen(), x, y);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index f1bf07635c..7b84f4a982 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3863,11 +3863,16 @@ QTouchEvent::TouchPoint::InfoFlags QTouchEvent::TouchPoint::flags() const
}
/*!
- Returns the raw, unfiltered positions for the touch point. The positions are in screen coordinates.
+ Returns the raw, unfiltered positions for the touch point. The positions are in native screen coordinates.
To get local coordinates you can use mapFromGlobal() of the QWindow returned by QTouchEvent::window().
\note Returns an empty list if the touch device's capabilities do not include QTouchDevice::RawPositions.
+ \note Native screen coordinates refer to the native orientation of the screen which, in case of
+ mobile devices, is typically portrait. This means that on systems capable of screen orientation
+ changes the positions in this list will not reflect the current orientation (unlike pos(),
+ screenPos(), etc.) and will always be reported in the native orientation.
+
\sa QTouchDevice::capabilities(), device(), window()
*/
QList<QPointF> QTouchEvent::TouchPoint::rawScreenPositions() const
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index be82005a54..42ce3745de 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -172,6 +172,11 @@ static inline void clearPalette()
static void initFontUnlocked()
{
+ if (!QGuiApplicationPrivate::app_font) {
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ if (const QFont *font = theme->font(QPlatformTheme::SystemFont))
+ QGuiApplicationPrivate::app_font = new QFont(*font);
+ }
if (!QGuiApplicationPrivate::app_font)
QGuiApplicationPrivate::app_font =
new QFont(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont());
@@ -933,6 +938,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
QPointF globalPoint = e->globalPos;
Qt::MouseButton button = Qt::NoButton;
+ bool doubleClick = false;
if (QGuiApplicationPrivate::lastCursorPosition != globalPoint) {
type = QEvent::MouseMove;
@@ -940,8 +946,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance||
qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance)
mousePressButton = Qt::NoButton;
- }
- else { // Check to see if a new button has been pressed/released.
+ } else { // Check to see if a new button has been pressed/released.
for (int check = Qt::LeftButton;
check <= int(Qt::MaxMouseButton);
check = check << 1) {
@@ -956,33 +961,26 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
}
buttons = e->buttons;
if (button & e->buttons) {
- if ((e->timestamp - mousePressTime) < static_cast<ulong>(qApp->styleHints()->mouseDoubleClickInterval()) &&
- button == mousePressButton) {
- type = QEvent::MouseButtonDblClick;
- mousePressButton = Qt::NoButton;
- }
- else {
- type = QEvent::MouseButtonPress;
- mousePressTime = e->timestamp;
- mousePressButton = button;
- const QPoint point = QGuiApplicationPrivate::lastCursorPosition.toPoint();
- mousePressX = point.x();
- mousePressY = point.y();
- }
- }
- else
+ ulong doubleClickInterval = static_cast<ulong>(qApp->styleHints()->mouseDoubleClickInterval());
+ doubleClick = e->timestamp - mousePressTime < doubleClickInterval && button == mousePressButton;
+ type = QEvent::MouseButtonPress;
+ mousePressTime = e->timestamp;
+ mousePressButton = button;
+ const QPoint point = QGuiApplicationPrivate::lastCursorPosition.toPoint();
+ mousePressX = point.x();
+ mousePressY = point.y();
+ } else {
type = QEvent::MouseButtonRelease;
+ }
}
-
if (window) {
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers);
ev.setTimestamp(e->timestamp);
#ifndef QT_NO_CURSOR
- QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
- for (int i = 0; i < cursors.count(); ++i)
- if (cursors.at(i))
- cursors.at(i).data()->pointerEvent(ev);
+ if (const QScreen *screen = window->screen())
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ cursor->pointerEvent(ev);
#endif
QGuiApplication::sendSpontaneousEvent(window, &ev);
if (!e->synthetic && !ev.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) {
@@ -1017,12 +1015,16 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
fake.synthetic = true;
processTouchEvent(&fake);
}
+ if (doubleClick) {
+ mousePressButton = Qt::NoButton;
+ QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, localPoint, localPoint, globalPoint,
+ button, buttons, e->modifiers);
+ dblClickEvent.setTimestamp(e->timestamp);
+ QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent);
+ }
}
}
-
-//### there's a lot of duplicated logic here -- refactoring required!
-
void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e)
{
if (!e->window)
@@ -1041,8 +1043,6 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
}
}
-
-
// Remember, Qt convention is: keyboard state is state *before*
void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e)
@@ -1813,16 +1813,11 @@ void QGuiApplication::changeOverrideCursor(const QCursor &cursor)
#ifndef QT_NO_CURSOR
-static void applyCursor(QWindow *w, const QCursor &c)
-{
- QCursor cc = c;
- QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
- int cursorCount = cursors.count();
- for (int i = 0; i < cursorCount; ++i) {
- const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
- if (cursor)
- cursor.data()->changeCursor(&cc, w);
- }
+static inline void applyCursor(QWindow *w, QCursor c)
+{
+ if (const QScreen *screen = w->screen())
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ cursor->changeCursor(&c, w);
}
static inline void applyCursor(const QList<QWindow *> &l, const QCursor &c)
diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp
index fd7bcdcf18..a4e998ddbc 100644
--- a/src/gui/kernel/qplatformcursor_qpa.cpp
+++ b/src/gui/kernel/qplatformcursor_qpa.cpp
@@ -43,13 +43,22 @@
#include <QPainter>
#include <QBitmap>
#include <QGuiApplication>
+#include <QScreen>
+#include <QPlatformScreen>
#include <private/qguiapplication_p.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
-QList <QWeakPointer<QPlatformCursor> > QPlatformCursorPrivate::instances;
+QList<QPlatformCursor *> QPlatformCursorPrivate::getInstances()
+{
+ QList<QPlatformCursor *> result;
+ foreach (const QScreen *screen, QGuiApplicationPrivate::screen_list)
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ result.push_back(cursor);
+ return result;
+}
/*!
\class QPlatformCursor
@@ -93,10 +102,8 @@ QList <QWeakPointer<QPlatformCursor> > QPlatformCursorPrivate::instances;
Constructs a QPlatformCursor for the given \a screen.
*/
-QPlatformCursor::QPlatformCursor(QPlatformScreen *scr )
- : screen(scr)
+QPlatformCursor::QPlatformCursor()
{
- QPlatformCursorPrivate::instances.append(this);
}
QPoint QPlatformCursor::pos() const
diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h
index a8cbb282fa..e29cf87d03 100644
--- a/src/gui/kernel/qplatformcursor_qpa.h
+++ b/src/gui/kernel/qplatformcursor_qpa.h
@@ -74,13 +74,12 @@ class QPlatformCursor;
class Q_GUI_EXPORT QPlatformCursorPrivate {
public:
- static QList<QWeakPointer<QPlatformCursor> > getInstances() { return instances; }
- static QList<QWeakPointer<QPlatformCursor> > instances;
+ static QList<QPlatformCursor *> getInstances();
};
class Q_GUI_EXPORT QPlatformCursor : public QObject {
public:
- QPlatformCursor(QPlatformScreen *);
+ QPlatformCursor();
// input methods
virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); }
@@ -88,11 +87,8 @@ public:
virtual QPoint pos() const;
virtual void setPos(const QPoint &pos);
-protected:
- QPlatformScreen* screen; // Where to request an update
-
private:
- Q_DECLARE_PRIVATE(QPlatformCursor);
+ Q_DECLARE_PRIVATE(QPlatformCursor)
friend void qt_qpa_set_cursor(QWidget * w, bool force);
friend class QApplicationPrivate;
};
diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp
index c832d853f4..022f198073 100644
--- a/src/gui/kernel/qplatformscreen_qpa.cpp
+++ b/src/gui/kernel/qplatformscreen_qpa.cpp
@@ -41,6 +41,7 @@
#include "qplatformscreen_qpa.h"
#include <QtGui/qguiapplication.h>
+#include <QtGui/qplatformcursor_qpa.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qplatformscreen_qpa_p.h>
#include <QtGui/qplatformintegration_qpa.h>
@@ -250,4 +251,14 @@ QPlatformScreenPageFlipper *QPlatformScreen::pageFlipper() const
return 0;
}
+/*!
+ Reimplement this function in subclass to return the cursor of the screen.
+
+ The default implementation returns 0.
+*/
+QPlatformCursor *QPlatformScreen::cursor() const
+{
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h
index 7d74698074..b6eb91f9b2 100644
--- a/src/gui/kernel/qplatformscreen_qpa.h
+++ b/src/gui/kernel/qplatformscreen_qpa.h
@@ -63,6 +63,7 @@ class QPlatformBackingStore;
class QPlatformOpenGLContext;
class QPlatformScreenPrivate;
class QPlatformWindow;
+class QPlatformCursor;
class QPlatformScreenPageFlipper;
class QScreen;
class QSurfaceFormat;
@@ -103,6 +104,7 @@ public:
virtual QString name() const { return QString(); }
virtual QPlatformScreenPageFlipper *pageFlipper() const;
+ virtual QPlatformCursor *cursor() const;
protected:
QScopedPointer<QPlatformScreenPrivate> d_ptr;
diff --git a/src/gui/kernel/qplatformtheme_qpa.cpp b/src/gui/kernel/qplatformtheme_qpa.cpp
index 3fdece70ea..c6314825d7 100644
--- a/src/gui/kernel/qplatformtheme_qpa.cpp
+++ b/src/gui/kernel/qplatformtheme_qpa.cpp
@@ -137,6 +137,12 @@ const QPalette *QPlatformTheme::palette(Palette type) const
return 0;
}
+const QFont *QPlatformTheme::font(Font type) const
+{
+ Q_UNUSED(type)
+ return 0;
+}
+
QVariant QPlatformTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
diff --git a/src/gui/kernel/qplatformtheme_qpa.h b/src/gui/kernel/qplatformtheme_qpa.h
index 3610a3c1c8..6ac6a0f573 100644
--- a/src/gui/kernel/qplatformtheme_qpa.h
+++ b/src/gui/kernel/qplatformtheme_qpa.h
@@ -55,6 +55,7 @@ class QPlatformMenuBar;
class QPlatformDialogHelper;
class QVariant;
class QPalette;
+class QFont;
class Q_GUI_EXPORT QPlatformTheme
{
@@ -86,9 +87,47 @@ public:
enum Palette {
SystemPalette,
ToolTipPalette,
+ ToolButtonPalette,
+ ButtonPalette,
+ HeaderPalette,
+ ComboBoxPalette,
+ ItemViewPalette,
+ MessageBoxLabelPelette,
+ TabBarPalette,
+ LabelPalette,
+ GroupBoxPalette,
+ MenuPalette,
+ MenuBarPalette,
+ TextEditPalette,
+ TextLineEditPalette,
NPalettes
};
+ enum Font {
+ SystemFont,
+ MenuFont,
+ MenuBarFont,
+ MenuItemFont,
+ MessageBoxFont,
+ LabelFont,
+ TipLabelFont,
+ StatusBarFont,
+ TitleBarFont,
+ MdiSubWindowTitleFont,
+ DockWidgetTitleFont,
+ PushButtonFont,
+ ToolButtonFont,
+ ItemViewFont,
+ ListViewFont,
+ HeaderViewFont,
+ ListBoxFont,
+ ComboMenuItemFont,
+ ComboLineEditFont,
+ SmallFont,
+ MiniFont,
+ NFonts
+ };
+
enum KeyboardSchemes
{
WindowsKeyboardScheme,
@@ -109,6 +148,8 @@ public:
virtual const QPalette *palette(Palette type = SystemPalette) const;
+ virtual const QFont *font(Font type = SystemFont) const;
+
virtual QVariant themeHint(ThemeHint hint) const;
};
diff --git a/src/gui/painting/qplatformbackingstore_qpa.cpp b/src/gui/painting/qplatformbackingstore_qpa.cpp
index 485190d301..ff7d91ccea 100644
--- a/src/gui/painting/qplatformbackingstore_qpa.cpp
+++ b/src/gui/painting/qplatformbackingstore_qpa.cpp
@@ -114,6 +114,9 @@ QWindow* QPlatformBackingStore::window() const
This function is called before painting onto the surface begins,
with the \a region in which the painting will occur.
+ \note A platform providing a backing store with an alpha channel
+ needs to properly initialize the region to be painted.
+
\sa endPaint(), paintDevice()
*/
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 4bceb28ef7..142d627100 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -227,6 +227,15 @@ HB_Face QFontEngine::harfbuzzFace() const
return hbFace;
}
+HB_Face QFontEngine::initializedHarfbuzzFace() const
+{
+ HB_Face face = harfbuzzFace();
+ if (face != 0 && face->font_for_init != 0)
+ face = qHBLoadFace(face);
+
+ return face;
+}
+
glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix)
{
glyph_metrics_t metrics = boundingBox(glyph);
@@ -1364,15 +1373,13 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) {
QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos);
for (int x=1; x < engines.size(); ++x) {
- if (!shouldLoadFontEngineForCharacter(x, ucs4))
+ if (engines.at(x) == 0 && !shouldLoadFontEngineForCharacter(x, ucs4))
continue;
QFontEngine *engine = engines.at(x);
- bool deleteThisEngine = false;
if (!engine) {
const_cast<QFontEngineMulti *>(this)->loadEngine(x);
engine = engines.at(x);
- deleteThisEngine = true;
}
Q_ASSERT(engine != 0);
if (engine->type() == Box)
@@ -1388,8 +1395,6 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
// set the high byte to indicate which engine the glyph came from
glyphs->glyphs[glyph_pos] |= (x << 24);
break;
- } else if (deleteThisEngine) {
- const_cast<QFontEngineMulti *>(this)->unloadEngine(x);
}
}
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 44464ee788..660e3be459 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -235,6 +235,7 @@ public:
HB_Font harfbuzzFont() const;
HB_Face harfbuzzFace() const;
+ HB_Face initializedHarfbuzzFace() const;
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp
index 8fcf421330..47a9fe5ab1 100644
--- a/src/gui/text/qplatformfontdatabase_qpa.cpp
+++ b/src/gui/text/qplatformfontdatabase_qpa.cpp
@@ -375,18 +375,6 @@ QFont QPlatformFontDatabase::defaultFont() const
}
/*!
- Returns fonts for class names.
-
- \sa QGuiApplication::font()
- \since 5.0
-*/
-
-QHash<QByteArray, QFont> QPlatformFontDatabase::defaultFonts() const
-{
- return QHash<QByteArray, QFont>();
-}
-
-/*!
Resolve alias to actual font family names.
\since 5.0
diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h
index 6a58a3106c..5a5a8f321f 100644
--- a/src/gui/text/qplatformfontdatabase_qpa.h
+++ b/src/gui/text/qplatformfontdatabase_qpa.h
@@ -100,7 +100,7 @@ public:
virtual QString fontDir() const;
virtual QFont defaultFont() const;
- virtual QHash<QByteArray, QFont> defaultFonts() const;
+
virtual QString resolveFontFamilyAlias(const QString &family) const;
//callback
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 0460db14d5..dae02def07 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1112,7 +1112,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
si.leading = qMax(actualFontEngine->leading(), si.leading);
shaper_item.font = actualFontEngine->harfbuzzFont();
- shaper_item.face = actualFontEngine->harfbuzzFace();
+ shaper_item.face = actualFontEngine->initializedHarfbuzzFace();
shaper_item.glyphIndicesPresent = true;
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 6aa3a5a5f4..890072eb7e 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -123,8 +123,8 @@ void QHttpNetworkConnectionPrivate::init()
//push session down to channels
channels[i].networkSession = networkSession;
#endif
- channels[i].init();
}
+
delayedConnectionTimer.setSingleShot(true);
QObject::connect(&delayedConnectionTimer, SIGNAL(timeout()), q, SLOT(_q_connectDelayedChannel()));
}
@@ -135,12 +135,14 @@ void QHttpNetworkConnectionPrivate::pauseConnection()
// Disable all socket notifiers
for (int i = 0; i < channelCount; i++) {
+ if (channels[i].socket) {
#ifndef QT_NO_SSL
- if (encrypt)
- QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
- else
+ if (encrypt)
+ QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ else
#endif
- QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+ QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+ }
}
}
@@ -149,16 +151,18 @@ void QHttpNetworkConnectionPrivate::resumeConnection()
state = RunningState;
// Enable all socket notifiers
for (int i = 0; i < channelCount; i++) {
+ if (channels[i].socket) {
#ifndef QT_NO_SSL
- if (encrypt)
- QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
- else
+ if (encrypt)
+ QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ else
#endif
- QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
+ QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
- // Resume pending upload if needed
- if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
- QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
+ // Resume pending upload if needed
+ if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
+ QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
+ }
}
// queue _q_startNextRequest
@@ -346,11 +350,15 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
QNetworkReply::NetworkError errorCode)
{
Q_Q(QHttpNetworkConnection);
- if (socket && reply) {
+
+ int i = 0;
+ if (socket)
+ i = indexOf(socket);
+
+ if (reply) {
// this error matters only to this reply
reply->d_func()->errorString = errorDetail(errorCode, socket);
emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
- int i = indexOf(socket);
// remove the corrupt data if any
reply->d_func()->eraseData();
@@ -358,7 +366,8 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
channels[i].close();
channels[i].reply = 0;
channels[i].request = QHttpNetworkRequest();
- channels[i].requeueCurrentlyPipelinedRequests();
+ if (socket)
+ channels[i].requeueCurrentlyPipelinedRequests();
// send the next request
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
@@ -582,9 +591,9 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
{
- Q_ASSERT(socket);
-
- int i = indexOf(socket);
+ int i = 0;
+ if (socket)
+ i = indexOf(socket);
if (!highPriorityQueue.isEmpty()) {
// remove from queue before sendRequest! else we might pipeline the same request again
@@ -740,15 +749,15 @@ bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue,
}
-QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket,
- const QString &extraDetail)
+QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket, const QString &extraDetail)
{
- Q_ASSERT(socket);
-
QString errorString;
switch (errorCode) {
case QNetworkReply::HostNotFoundError:
- errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName());
+ if (socket)
+ errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName());
+ else
+ errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(hostName);
break;
case QNetworkReply::ConnectionRefusedError:
errorString = QCoreApplication::translate("QHttp", "Connection refused");
@@ -891,9 +900,11 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
return;
// try to get a free AND connected socket
for (int i = 0; i < channelCount; ++i) {
- if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
- if (dequeueRequest(channels[i].socket))
- channels[i].sendRequest();
+ if (channels[i].socket) {
+ if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
+ if (dequeueRequest(channels[i].socket))
+ channels[i].sendRequest();
+ }
}
}
@@ -908,7 +919,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
return;
for (int i = 0; i < channelCount; i++)
- if (channels[i].socket->state() == QAbstractSocket::ConnectedState)
+ if (channels[i].socket && channels[i].socket->state() == QAbstractSocket::ConnectedState)
fillPipeline(channels[i].socket);
// If there is not already any connected channels we need to connect a new one.
@@ -916,11 +927,19 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
// connected or not. This is to reuse connected channels before we connect new once.
int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count();
for (int i = 0; i < channelCount; ++i) {
- if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState))
- queuedRequest--;
- if ( queuedRequest <=0 )
- break;
- if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) {
+ bool connectChannel = false;
+ if (channels[i].socket) {
+ if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState))
+ queuedRequest--;
+ if ( queuedRequest <=0 )
+ break;
+ if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState))
+ connectChannel = true;
+ } else { // not previously used channel
+ connectChannel = true;
+ }
+
+ if (connectChannel) {
if (networkLayerState == IPv4)
channels[i].networkLayerPreference = QAbstractSocket::IPv4Protocol;
else if (networkLayerState == IPv6)
@@ -928,6 +947,9 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
channels[i].ensureConnection();
queuedRequest--;
}
+
+ if ( queuedRequest <=0 )
+ break;
}
}
@@ -958,8 +980,8 @@ void QHttpNetworkConnectionPrivate::startHostInfoLookup()
#ifndef QT_NO_NETWORKPROXY
if (networkProxy.capabilities() & QNetworkProxy::HostNameLookupCapability) {
lookupHost = networkProxy.hostName();
- } else if (channels[0].socket->proxy().capabilities() & QNetworkProxy::HostNameLookupCapability) {
- lookupHost = channels[0].socket->proxy().hostName();
+ } else if (channels[0].proxy.capabilities() & QNetworkProxy::HostNameLookupCapability) {
+ lookupHost = channels[0].proxy.hostName();
}
#endif
QHostAddress temp;
@@ -1169,7 +1191,7 @@ void QHttpNetworkConnection::setTransparentProxy(const QNetworkProxy &networkPro
{
Q_D(QHttpNetworkConnection);
for (int i = 0; i < d->channelCount; ++i)
- d->channels[i].socket->setProxy(networkProxy);
+ d->channels[i].setProxy(networkProxy);
}
QNetworkProxy QHttpNetworkConnection::transparentProxy() const
@@ -1190,7 +1212,7 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config
// set the config on all channels
for (int i = 0; i < d->channelCount; ++i)
- static_cast<QSslSocket *>(d->channels[i].socket)->setSslConfiguration(config);
+ d->channels[i].setSslConfiguration(config);
}
void QHttpNetworkConnection::ignoreSslErrors(int channel)
@@ -1201,13 +1223,11 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel)
if (channel == -1) { // ignore for all channels
for (int i = 0; i < d->channelCount; ++i) {
- static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors();
- d->channels[i].ignoreAllSslErrors = true;
+ d->channels[i].ignoreSslErrors();
}
} else {
- static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors();
- d->channels[channel].ignoreAllSslErrors = true;
+ d->channels[channel].ignoreSslErrors();
}
}
@@ -1219,13 +1239,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int
if (channel == -1) { // ignore for all channels
for (int i = 0; i < d->channelCount; ++i) {
- static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors);
- d->channels[i].ignoreSslErrorsList = errors;
+ d->channels[i].ignoreSslErrors(errors);
}
} else {
- static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors);
- d->channels[channel].ignoreSslErrorsList = errors;
+ d->channels[channel].ignoreSslErrors(errors);
}
}
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 3991bffa47..a009222bd5 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE
QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
: socket(0)
, ssl(false)
+ , isInitialized(false)
, state(IdleState)
, reply(0)
, written(0)
@@ -152,19 +153,38 @@ void QHttpNetworkConnectionChannel::init()
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
Qt::DirectConnection);
+
+ if (ignoreAllSslErrors)
+ sslSocket->ignoreSslErrors();
+
+ if (!ignoreSslErrorsList.isEmpty())
+ sslSocket->ignoreSslErrors(ignoreSslErrorsList);
+
+ if (!sslConfiguration.isNull())
+ sslSocket->setSslConfiguration(sslConfiguration);
}
+
#endif
+
+#ifndef QT_NO_NETWORKPROXY
+ if (proxy.type() != QNetworkProxy::NoProxy)
+ socket->setProxy(proxy);
+#endif
+ isInitialized = true;
}
void QHttpNetworkConnectionChannel::close()
{
- if (socket->state() == QAbstractSocket::UnconnectedState)
+ if (!socket)
+ state = QHttpNetworkConnectionChannel::IdleState;
+ else if (socket->state() == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
- socket->close();
+ if (socket)
+ socket->close();
}
@@ -527,6 +547,9 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF()
bool QHttpNetworkConnectionChannel::ensureConnection()
{
+ if (!isInitialized)
+ init();
+
QAbstractSocket::SocketState socketState = socket->state();
// resend this request after we receive the disconnected signal
@@ -835,6 +858,46 @@ bool QHttpNetworkConnectionChannel::resetUploadData()
}
}
+#ifndef QT_NO_NETWORKPROXY
+
+void QHttpNetworkConnectionChannel::setProxy(const QNetworkProxy &networkProxy)
+{
+ if (socket)
+ socket->setProxy(networkProxy);
+
+ proxy = networkProxy;
+}
+
+#endif
+
+#ifndef QT_NO_SSL
+
+void QHttpNetworkConnectionChannel::ignoreSslErrors()
+{
+ if (socket)
+ static_cast<QSslSocket *>(socket)->ignoreSslErrors();
+
+ ignoreAllSslErrors = true;
+}
+
+
+void QHttpNetworkConnectionChannel::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ if (socket)
+ static_cast<QSslSocket *>(socket)->ignoreSslErrors(errors);
+
+ ignoreSslErrorsList = errors;
+}
+
+void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration &config)
+{
+ if (socket)
+ static_cast<QSslSocket *>(socket)->setSslConfiguration(config);
+
+ sslConfiguration = config;
+}
+
+#endif
void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair)
{
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 7da9b514d6..2648cba2a5 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -72,6 +72,7 @@
#ifndef QT_NO_SSL
# include <QtNetwork/qsslsocket.h>
# include <QtNetwork/qsslerror.h>
+# include <QtNetwork/qsslconfiguration.h>
#else
# include <QtNetwork/qtcpsocket.h>
#endif
@@ -100,6 +101,7 @@ public:
};
QAbstractSocket *socket;
bool ssl;
+ bool isInitialized;
ChannelState state;
QHttpNetworkRequest request; // current request
QHttpNetworkReply *reply; // current reply for this request
@@ -118,6 +120,10 @@ public:
#ifndef QT_NO_SSL
bool ignoreAllSslErrors;
QList<QSslError> ignoreSslErrorsList;
+ QSslConfiguration sslConfiguration;
+ void ignoreSslErrors();
+ void ignoreSslErrors(const QList<QSslError> &errors);
+ void setSslConfiguration(const QSslConfiguration &config);
#endif
#ifndef QT_NO_BEARERMANAGEMENT
QSharedPointer<QNetworkSession> networkSession;
@@ -144,6 +150,11 @@ public:
void setConnection(QHttpNetworkConnection *c);
QPointer<QHttpNetworkConnection> connection;
+#ifndef QT_NO_NETWORKPROXY
+ QNetworkProxy proxy;
+ void setProxy(const QNetworkProxy &networkProxy);
+#endif
+
void init();
void close();
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 60c28274c6..c65edb6673 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1089,15 +1089,16 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
QNetworkReply *reply,
bool synchronous,
QUrl &url,
- QUrl *urlForLastAuthentication)
+ QUrl *urlForLastAuthentication,
+ bool allowAuthenticationReuse)
{
Q_Q(QNetworkAccessManager);
// don't try the cache for the same URL twice in a row
// being called twice for the same URL means the authentication failed
// also called when last URL is empty, e.g. on first call
- if (urlForLastAuthentication->isEmpty()
- || url != *urlForLastAuthentication) {
+ if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
+ || url != *urlForLastAuthentication)) {
// if credentials are included in the url, then use them
if (!url.userName().isEmpty()
&& !url.password().isEmpty()) {
@@ -1124,7 +1125,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
*urlForLastAuthentication = url;
emit q->authenticationRequired(reply, authenticator);
- authenticationManager->cacheCredentials(url, authenticator);
+ if (allowAuthenticationReuse)
+ authenticationManager->cacheCredentials(url, authenticator);
}
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 0733756be4..b0bcaabacc 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -98,7 +98,8 @@ public:
QNetworkReply *reply,
bool synchronous,
QUrl &url,
- QUrl *urlForLastAuthentication);
+ QUrl *urlForLastAuthentication,
+ bool allowAuthenticationReuse = true);
void cacheCredentials(const QUrl &url, const QAuthenticator *auth);
QNetworkAuthenticationCredential *fetchCachedCredentials(const QUrl &url,
const QAuthenticator *auth = 0);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 2124395de3..1f456746ae 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -1179,10 +1179,10 @@ void QNetworkReplyHttpImplPrivate::replyDownloadProgressSlot(qint64 bytesReceive
emit q->downloadProgress(bytesDownloaded, bytesTotal);
}
-void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetworkRequest &,
+void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetworkRequest &request,
QAuthenticator *auth)
{
- managerPrivate->authenticationRequired(auth, q_func(), synchronous, url, &urlForLastAuthentication);
+ managerPrivate->authenticationRequired(auth, q_func(), synchronous, url, &urlForLastAuthentication, request.withCredentials());
}
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index 6969a9effd..33ae4a6a14 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -256,7 +256,7 @@ public:
Q_GLOBAL_STATIC(QWindowsSystemProxy, systemProxy)
QWindowsSystemProxy::QWindowsSystemProxy()
- : initialized(false), functional(false), isAutoConfig(false)
+ : hHttpSession(0), initialized(false), functional(false), isAutoConfig(false)
{
defaultResult << QNetworkProxy::NoProxy;
}
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 966497be2e..a9573bf1d8 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -123,6 +123,7 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qmap.h>
#include <QtCore/qmutex.h>
+#include <QtCore/private/qmutexpool_p.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qvarlengtharray.h>
@@ -263,6 +264,7 @@ void QSslCertificate::clear()
*/
QByteArray QSslCertificate::version() const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
if (d->versionString.isEmpty() && d->x509)
d->versionString =
QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
@@ -275,6 +277,7 @@ QByteArray QSslCertificate::version() const
*/
QByteArray QSslCertificate::serialNumber() const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
if (d->serialNumberString.isEmpty() && d->x509) {
ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
QByteArray hexString;
@@ -327,6 +330,7 @@ static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
*/
QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
@@ -344,6 +348,7 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
*/
QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
@@ -363,6 +368,7 @@ QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
*/
QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -379,6 +385,7 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
*/
QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -398,6 +405,7 @@ QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
*/
QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -417,6 +425,7 @@ QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
*/
QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
{
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
index 5cfbc6cb4f..ebe73bff16 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
@@ -229,7 +229,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTab
delete engine;
engine = 0;
} else if (scriptRequiresOpenType(script)) {
- HB_Face hbFace = engine->harfbuzzFace();
+ HB_Face hbFace = engine->initializedHarfbuzzFace();
if (!hbFace || !hbFace->supported_scripts[script]) {
delete engine;
engine = 0;
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index 8a9670118f..69ec3ba08a 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -575,7 +575,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::
delete engine;
engine = 0;
} else if (scriptRequiresOpenType(script)) {
- HB_Face hbFace = engine->harfbuzzFace();
+ HB_Face hbFace = engine->initializedHarfbuzzFace();
if (!hbFace || !hbFace->supported_scripts[script]) {
delete engine;
engine = 0;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index bfa2841158..d32f05022e 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE
class QRawFontPrivate;
class QCoreTextFontEngine : public QFontEngine
{
+ Q_OBJECT
public:
QCoreTextFontEngine(CTFontRef font, const QFontDef &def);
QCoreTextFontEngine(CGFontRef font, const QFontDef &def);
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 257fe9156f..602dd6264a 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -43,6 +43,7 @@
#include "../../services/genericunix/qgenericunixservices_p.h"
#include <QtGui/QPalette>
+#include <QtGui/QFont>
#include <QtGui/QGuiApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
@@ -54,6 +55,20 @@
QT_BEGIN_NAMESPACE
+ResourceHelper::ResourceHelper()
+{
+ qFill(palettes, palettes + QPlatformTheme::NPalettes, static_cast<QPalette *>(0));
+ qFill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(0));
+}
+
+void ResourceHelper::clear()
+{
+ qDeleteAll(palettes, palettes + QPlatformTheme::NPalettes);
+ qDeleteAll(fonts, fonts + QPlatformTheme::NFonts);
+ qFill(palettes, palettes + QPlatformTheme::NPalettes, static_cast<QPalette *>(0));
+ qFill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(0));
+}
+
/*!
\class QGenericX11ThemeQKdeTheme
\brief QGenericX11Theme is a generic theme implementation for X11.
@@ -148,19 +163,40 @@ QKdeTheme::QKdeTheme(const QString &kdeHome, int kdeVersion) :
m_kdeHome(kdeHome), m_kdeVersion(kdeVersion),
m_toolButtonStyle(Qt::ToolButtonTextBesideIcon), m_toolBarIconSize(0)
{
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
-void QKdeTheme::clearPalettes()
+static inline QFont *readKdeFontSetting(const QSettings &settings, const QString &key)
{
- qDeleteAll(m_palettes, m_palettes + NPalettes);
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+ const QVariant fontValue = settings.value(key);
+ if (fontValue.isValid()) {
+ // Read font value: Might be a QStringList as KDE stores fonts without quotes.
+ // Also retrieve the family for the constructor since we cannot use the
+ // default constructor of QFont, which accesses QGuiApplication::systemFont()
+ // causing recursion.
+ QString fontDescription;
+ QString fontFamily;
+ if (fontValue.type() == QVariant::StringList) {
+ const QStringList list = fontValue.toStringList();
+ if (!list.isEmpty()) {
+ fontFamily = list.first();
+ fontDescription = list.join(QStringLiteral(","));
+ }
+ } else {
+ fontDescription = fontFamily = fontValue.toString();
+ }
+ if (!fontDescription.isEmpty()) {
+ QFont font(fontFamily);
+ if (font.fromString(fontDescription))
+ return new QFont(font);
+ }
+ }
+ return 0;
}
void QKdeTheme::refresh()
{
- clearPalettes();
+ m_resources.clear();
m_toolButtonStyle = Qt::ToolButtonTextBesideIcon;
m_toolBarIconSize = 0;
@@ -177,7 +213,7 @@ void QKdeTheme::refresh()
QPalette systemPalette;
if (readKdeSystemPalette(kdeSettings, &systemPalette))
- m_palettes[SystemPalette] = new QPalette(systemPalette);
+ m_resources.palettes[SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
const QVariant styleValue = kdeSettings.value(QStringLiteral("widgetStyle"));
@@ -205,6 +241,9 @@ void QKdeTheme::refresh()
else if (toolBarStyle == QStringLiteral("TextUnderIcon"))
m_toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
+
+ // Read system font, ignore 'fixed' 'smallestReadableFont'
+ m_resources.fonts[SystemFont] = readKdeFontSetting(kdeSettings, QStringLiteral("font"));
}
QString QKdeTheme::globalSettingsFile() const
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
index 12937a205f..a9db29e8cd 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
@@ -50,6 +50,18 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
+class ResourceHelper
+{
+public:
+ ResourceHelper();
+ ~ResourceHelper() { clear(); }
+
+ void clear();
+
+ QPalette *palettes[QPlatformTheme::NPalettes];
+ QFont *fonts[QPlatformTheme::NFonts];
+};
+
class QGenericUnixTheme : public QPlatformTheme
{
public:
@@ -66,21 +78,24 @@ class QKdeTheme : public QPlatformTheme
{
QKdeTheme(const QString &kdeHome, int kdeVersion);
public:
- ~QKdeTheme() { clearPalettes(); }
static QPlatformTheme *createKdeTheme();
virtual QVariant themeHint(ThemeHint hint) const;
+
virtual const QPalette *palette(Palette type = SystemPalette) const
- { return m_palettes[type]; }
+ { return m_resources.palettes[type]; }
+
+ virtual const QFont *font(Font type) const
+ { return m_resources.fonts[type]; }
private:
QString globalSettingsFile() const;
- void clearPalettes();
void refresh();
const QString m_kdeHome;
const int m_kdeVersion;
- QPalette *m_palettes[NPalettes];
+
+ ResourceHelper m_resources;
QString m_iconThemeName;
QString m_iconFallbackThemeName;
QStringList m_styleNames;
diff --git a/src/platformsupport/udev/udev.pri b/src/platformsupport/udev/udev.pri
index 21c71d5f5b..c99d4b6810 100644
--- a/src/platformsupport/udev/udev.pri
+++ b/src/platformsupport/udev/udev.pri
@@ -1,4 +1,6 @@
contains(QT_CONFIG, libudev) {
HEADERS += $$PWD/qudevhelper_p.h $$PWD/qudevicehelper_p.h
SOURCES += $$PWD/qudevhelper.cpp $$PWD/qudevicehelper.cpp
+
+ INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
}
diff --git a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
index 82edf170a8..21e4bf63ee 100644
--- a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
+++ b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
@@ -12,11 +12,11 @@ HEADERS = \
QT += core-private platformsupport-private
-LIBS += -ludev
-
SOURCES = main.cpp \
qevdevkeyboardhandler.cpp \
qevdevkeyboardmanager.cpp
OTHER_FILES += \
evdevkeyboard.json
+
+LIBS += $$QMAKE_LIBS_LIBUDEV
diff --git a/src/plugins/generic/evdevmouse/evdevmouse.pro b/src/plugins/generic/evdevmouse/evdevmouse.pro
index c5d162fb2f..781d901f28 100644
--- a/src/plugins/generic/evdevmouse/evdevmouse.pro
+++ b/src/plugins/generic/evdevmouse/evdevmouse.pro
@@ -14,3 +14,5 @@ SOURCES = main.cpp \
OTHER_FILES += \
evdevmouse.json
+
+LIBS += $$QMAKE_LIBS_LIBUDEV
diff --git a/src/plugins/generic/evdevtouch/evdevtouch.pro b/src/plugins/generic/evdevtouch/evdevtouch.pro
index f9fb4a61d8..192a87c2a3 100644
--- a/src/plugins/generic/evdevtouch/evdevtouch.pro
+++ b/src/plugins/generic/evdevtouch/evdevtouch.pro
@@ -16,6 +16,8 @@ QT += core-private platformsupport-private
OTHER_FILES += \
evdevtouch.json
+LIBS += $$QMAKE_LIBS_LIBUDEV
+
# DEFINES += USE_MTDEV
contains(DEFINES, USE_MTDEV): LIBS += -lmtdev
diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
index 73f253ae96..9e6347457d 100644
--- a/src/plugins/generic/evdevtouch/qevdevtouch.cpp
+++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
@@ -134,7 +134,7 @@ void QTouchScreenData::registerDevice()
static inline bool testBit(long bit, const long *array)
{
- return array[bit / LONG_BITS] & (1 << (bit & (LONG_BITS - 1)));
+ return (array[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
}
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index ce87de2574..b953210720 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -27,6 +27,9 @@ OBJECTIVE_SOURCES += main.mm \
qcocoafiledialoghelper.mm \
qcocoafontdialoghelper.mm \
qcocoacursor.mm \
+ qcocoadrag.mm \
+ qmacclipboard.mm \
+ qmacmime.mm \
qcocoasystemsettings.mm \
HEADERS += qcocoaintegration.h \
@@ -52,6 +55,9 @@ HEADERS += qcocoaintegration.h \
qcocoafiledialoghelper.h \
qcocoafontdialoghelper.h \
qcocoacursor.h \
+ qcocoadrag.h \
+ qmacclipboard.h \
+ qmacmime.h \
qcocoasystemsettings.h \
FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index bccaa1e06b..85892ee820 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QCocoaCursor : public QPlatformCursor
{
public:
- explicit QCocoaCursor(QPlatformScreen *);
+ QCocoaCursor();
virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
virtual QPoint pos() const;
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index bddfaa752e..56f0dcf72e 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -47,8 +47,7 @@
QT_BEGIN_NAMESPACE
-QCocoaCursor::QCocoaCursor(QPlatformScreen *s) :
- QPlatformCursor(s)
+QCocoaCursor::QCocoaCursor()
{
// release cursors
QHash<Qt::CursorShape, NSCursor *>::const_iterator i = m_cursors.constBegin();
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
new file mode 100644
index 0000000000..17df54f748
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOADRAG_H
+#define QCOCOADRAG_H
+
+#include <Cocoa/Cocoa.h>
+#include <QtGui>
+#include <qplatformdrag_qpa.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
+
+#include <QtGui/private/qdnd_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaDrag : public QSimpleDrag
+{
+public:
+private:
+};
+
+class QCocoaDropData : public QInternalMimeData
+{
+public:
+ QCocoaDropData(NSPasteboard *pasteboard);
+ ~QCocoaDropData();
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+public:
+ CFStringRef dropPasteboard;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
new file mode 100644
index 0000000000..c596e3fdbb
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcocoadrag.h"
+#include "qmacmime.h"
+#include "qmacclipboard.h"
+
+QT_BEGIN_NAMESPACE
+
+QCocoaDropData::QCocoaDropData(NSPasteboard *pasteboard)
+{
+ dropPasteboard = reinterpret_cast<CFStringRef>(const_cast<const NSString *>([pasteboard name]));
+ CFRetain(dropPasteboard);
+}
+
+QCocoaDropData::~QCocoaDropData()
+{
+ CFRelease(dropPasteboard);
+}
+
+QStringList QCocoaDropData::formats_sys() const
+{
+ QStringList formats;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return formats;
+ }
+ formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats();
+ return formats;
+}
+
+QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant data;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return data;
+ }
+ data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type);
+ CFRelease(board);
+ return data;
+}
+
+bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const
+{
+ bool has = false;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return has;
+ }
+ has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType);
+ CFRelease(board);
+ return has;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 7b1247b739..3e3e8fa507 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -77,6 +77,11 @@ NSSize qt_mac_toNSSize(const QSize &qtSize);
QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
+NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
+NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
+Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
+Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
+
// Misc
void qt_mac_transformProccessToForegroundApplication();
QString qt_mac_removeMnemonics(const QString &original);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 29c505e1ab..ec4399b66c 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -270,6 +270,64 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
return i->qtKey;
}
+struct dndenum_mapper
+{
+ NSDragOperation mac_code;
+ Qt::DropAction qt_code;
+ bool Qt2Mac;
+};
+
+static dndenum_mapper dnd_enums[] = {
+ { NSDragOperationLink, Qt::LinkAction, true },
+ { NSDragOperationMove, Qt::MoveAction, true },
+ { NSDragOperationCopy, Qt::CopyAction, true },
+ { NSDragOperationGeneric, Qt::CopyAction, false },
+ { NSDragOperationEvery, Qt::ActionMask, false },
+ { NSDragOperationNone, Qt::IgnoreAction, false }
+};
+
+NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
+{
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
+ return dnd_enums[i].mac_code;
+ }
+ }
+ return NSDragOperationNone;
+}
+
+NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
+{
+ NSDragOperation nsActions = NSDragOperationNone;
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
+ nsActions |= dnd_enums[i].mac_code;
+ }
+ return nsActions;
+}
+
+Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
+{
+ Qt::DropAction action = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ return dnd_enums[i].qt_code;
+ }
+ return action;
+}
+
+Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ actions |= dnd_enums[i].qt_code;
+ }
+ return actions;
+}
+
+
+
//
// Misc
//
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 5493b21c34..bf54915365 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -46,6 +46,7 @@
#include "qcocoaautoreleasepool.h"
#include "qcocoacursor.h"
+#include "qcocoadrag.h"
#include <QtCore/QScopedPointer>
#include <QtGui/QPlatformIntegration>
@@ -62,6 +63,7 @@ public:
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
+ QPlatformCursor *cursor() const { return m_cursor; }
public:
NSScreen *m_screen;
@@ -88,6 +90,7 @@ public:
QPlatformNativeInterface *nativeInterface() const;
QPlatformAccessibility *accessibility() const;
+ QPlatformDrag *drag() const;
QPlatformTheme *platformTheme() const;
private:
@@ -98,6 +101,7 @@ private:
QScopedPointer<QPlatformAccessibility> mAccessibility;
QScopedPointer<QPlatformTheme> mPlatformTheme;
QList<QCocoaScreen *> mScreens;
+ QScopedPointer<QCocoaDrag> mCocoaDrag;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 626a7fe0f9..8411a795c1 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -52,6 +52,7 @@
#include "qmenu_mac.h"
#include "qcocoafiledialoghelper.h"
#include "qcocoatheme.h"
+#include "qmacmime.h"
#include <QtGui/qplatformaccessibility_qpa.h>
#include <QtCore/qcoreapplication.h>
@@ -78,7 +79,7 @@ QCocoaScreen::QCocoaScreen(int screenIndex)
const qreal inch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) * inch / dpi;
- m_cursor = new QCocoaCursor(this);
+ m_cursor = new QCocoaCursor;
};
QCocoaScreen::~QCocoaScreen()
@@ -91,7 +92,7 @@ QCocoaIntegration::QCocoaIntegration()
, mEventDispatcher(new QCocoaEventDispatcher())
, mAccessibility(new QPlatformAccessibility)
, mPlatformTheme(new QCocoaTheme)
-
+ , mCocoaDrag(new QCocoaDrag)
{
QCocoaAutoReleasePool pool;
@@ -138,6 +139,7 @@ QCocoaIntegration::QCocoaIntegration()
screenAdded(screen);
}
+ QMacPasteboardMime::initialize();
}
QCocoaIntegration::~QCocoaIntegration()
@@ -198,6 +200,11 @@ QPlatformAccessibility *QCocoaIntegration::accessibility() const
return mAccessibility.data();
}
+QPlatformDrag *QCocoaIntegration::drag() const
+{
+ return mCocoaDrag.data();
+}
+
QPlatformTheme *QCocoaIntegration::platformTheme() const
{
return mPlatformTheme.data();
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.h b/src/plugins/platforms/cocoa/qcocoasystemsettings.h
index 84a66d7193..10cac27dcd 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.h
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.h
@@ -42,12 +42,15 @@
#ifndef QCOCOASYSTEMSETTINGS_H
#define QCOCOASYSTEMSETTINGS_H
-#include <QtCore/qglobal.h>
+#include <QtCore/qhash.h>
#include <QtGui/qpalette.h>
+#include <QtGui/qplatformtheme_qpa.h>
QT_BEGIN_NAMESPACE
QPalette * qt_mac_createSystemPalette();
+QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes();
+QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts();
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 5170c0bc8a..c2f5df4d38 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -41,8 +41,12 @@
#include "qcocoasystemsettings.h"
-#include <Carbon/Carbon.h>
#include <QtCore/private/qcore_mac_p.h>
+#include <QtGui/qfont.h>
+
+#include <Carbon/Carbon.h>
+
+QT_BEGIN_NAMESPACE
QColor qt_mac_colorFromCGColor(CGColorRef cgcolor)
{
@@ -143,3 +147,126 @@ QPalette * qt_mac_createSystemPalette()
return palette;
}
+struct QMacPaletteMap {
+ inline QMacPaletteMap(QPlatformTheme::Palette p, ThemeBrush a, ThemeBrush i) :
+ paletteRole(p), active(a), inactive(i) { }
+
+ QPlatformTheme::Palette paletteRole;
+ ThemeBrush active, inactive;
+};
+
+static QMacPaletteMap mac_widget_colors[] = {
+// TODO (msorvig): Fix/match palette behavior with Qt 4 and enable.
+//
+// QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+// QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive),
+// QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
+// QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
+// QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+// QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+// QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive),
+// ### TODO: The zeros below gives white-on-black text.
+// QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0),
+// QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0),
+ QMacPaletteMap(QPlatformTheme::NPalettes, 0, 0) };
+
+QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
+{
+ QHash<QPlatformTheme::Palette, QPalette*> palettes;
+ QColor qc;
+ for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) {
+ QPalette pal;
+ if (mac_widget_colors[i].active != 0) {
+ qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active);
+ pal.setColor(QPalette::Active, QPalette::Text, qc);
+ pal.setColor(QPalette::Active, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
+ qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].inactive);
+ pal.setColor(QPalette::Inactive, QPalette::Text, qc);
+ pal.setColor(QPalette::Disabled, QPalette::Text, qc);
+ pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
+ }
+ if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette) {
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive);
+ pal.setBrush(QPalette::ButtonText, qc);
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::HighlightedText, qc);
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemDisabled);
+ pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
+ } else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette)
+ || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)) {
+ pal.setColor(QPalette::Disabled, QPalette::ButtonText,
+ pal.color(QPalette::Disabled, QPalette::Text));
+ pal.setColor(QPalette::Inactive, QPalette::ButtonText,
+ pal.color(QPalette::Inactive, QPalette::Text));
+ pal.setColor(QPalette::Active, QPalette::ButtonText,
+ pal.color(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
+ pal.setBrush(QPalette::Active, QPalette::Highlight,
+ qt_mac_colorForTheme(kThemeBrushAlternatePrimaryHighlightColor));
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc);
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) {
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette) {
+ pal.setBrush(QPalette::Disabled, QPalette::Base,
+ pal.brush(QPalette::Active, QPalette::Base));
+ }
+ palettes.insert(mac_widget_colors[i].paletteRole, new QPalette(pal));
+ }
+ return palettes;
+}
+
+QFont *qt_mac_qfontForThemeFont(ThemeFontID themeID)
+{
+ CTFontUIFontType ctID = HIThemeGetUIFontType(themeID);
+ QCFType<CTFontRef> ctfont = CTFontCreateUIFontForLanguage(ctID, 0, 0);
+ QString familyName = QCFString(CTFontCopyFamilyName(ctfont));
+ QCFType<CFDictionaryRef> dict = CTFontCopyTraits(ctfont);
+ CFNumberRef num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontWeightTrait));
+ float fW;
+ CFNumberGetValue(num, kCFNumberFloat32Type, &fW);
+ QFont::Weight wght = fW > 0. ? QFont::Bold : QFont::Normal;
+ num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontSlantTrait));
+ CFNumberGetValue(num, kCFNumberFloatType, &fW);
+ bool italic = (fW != 0.0);
+ return new QFont(familyName, CTFontGetSize(ctfont), wght, italic);
+}
+
+QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts()
+{
+ QHash<QPlatformTheme::Font, QFont *> fonts;
+
+ fonts.insert(QPlatformTheme::SystemFont, qt_mac_qfontForThemeFont(kThemeApplicationFont));
+ fonts.insert(QPlatformTheme::PushButtonFont, qt_mac_qfontForThemeFont(kThemePushButtonFont));
+ fonts.insert(QPlatformTheme::ListViewFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::ListBoxFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::TitleBarFont, qt_mac_qfontForThemeFont(kThemeWindowTitleFont));
+ fonts.insert(QPlatformTheme::MenuFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont));
+ fonts.insert(QPlatformTheme::ComboMenuItemFont, qt_mac_qfontForThemeFont(kThemeSystemFont));
+ fonts.insert(QPlatformTheme::HeaderViewFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::TipLabelFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::LabelFont, qt_mac_qfontForThemeFont(kThemeSystemFont));
+ fonts.insert(QPlatformTheme::ToolButtonFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::MenuItemFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont));
+ fonts.insert(QPlatformTheme::ComboLineEditFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::SmallFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::MiniFont, qt_mac_qfontForThemeFont(kThemeMiniSystemFont));
+
+ return fonts;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index fa235b6be0..030db1822c 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -42,8 +42,7 @@
#ifndef QPLATFORMTHEME_COCOA_H
#define QPLATFORMTHEME_COCOA_H
-#include <Cocoa/Cocoa.h>
-
+#include <QtCore/QHash>
#include <QtGui/QPlatformTheme>
QT_BEGIN_NAMESPACE
@@ -62,10 +61,13 @@ public:
QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const;
const QPalette *palette(Palette type = SystemPalette) const;
+ const QFont *font(Font type = SystemFont) const;
QVariant themeHint(ThemeHint hint) const;
private:
mutable QPalette *m_systemPalette;
+ mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes;
+ mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 6b0e04acf8..8ec6e3801e 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -109,12 +109,23 @@ const QPalette *QCocoaTheme::palette(Palette type) const
if (type == SystemPalette) {
if (!m_systemPalette)
m_systemPalette = qt_mac_createSystemPalette();
-
return m_systemPalette;
+ } else {
+ if (m_palettes.isEmpty())
+ m_palettes = qt_mac_createRolePalettes();
+ return m_palettes.value(type, 0);
}
return 0;
}
+const QFont *QCocoaTheme::font(Font type) const
+{
+ if (m_fonts.isEmpty()) {
+ m_fonts = qt_mac_createRoleFonts();
+ }
+ return m_fonts.value(type, 0);
+}
+
QVariant QCocoaTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index b2e93470c9..3f566ccb44 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -201,7 +201,7 @@ void QCocoaWindow::propagateSizeHints()
[m_nsWindow setResizeIncrements : qt_mac_toNSSize(window()->sizeIncrement())];
QSize baseSize = window()->baseSize();
- if (!baseSize.isNull()) {
+ if (!baseSize.isNull() && baseSize.isValid()) {
[m_nsWindow setFrameSize : NSMakeSize(baseSize.width(), baseSize.height()) display : YES];
}
}
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h
new file mode 100644
index 0000000000..9371aca459
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacclipboard.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMACCLIPBOARD_H
+#define QMACCLIPBOARD_H
+
+#include <QtGui>
+#include "qmacmime.h"
+
+#undef slots
+
+#import <Cocoa/Cocoa.h>
+
+class QMacPasteboard
+{
+ struct Promise {
+ Promise() : itemId(0), convertor(0) { }
+ Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
+ int itemId, offset;
+ QMacPasteboardMime *convertor;
+ QString mime;
+ QVariant data;
+ };
+ QList<Promise> promises;
+
+ PasteboardRef paste;
+ uchar mime_type;
+ mutable QPointer<QMimeData> mime;
+ mutable bool mac_mime_source;
+ static OSStatus promiseKeeper(PasteboardRef, PasteboardItemID, CFStringRef, void *);
+ void clear_helper();
+public:
+ QMacPasteboard(PasteboardRef p, uchar mime_type=0);
+ QMacPasteboard(uchar mime_type);
+ QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
+ ~QMacPasteboard();
+
+ bool hasFlavor(QString flavor) const;
+ bool hasOSType(int c_flavor) const;
+
+ PasteboardRef pasteBoard() const;
+ QMimeData *mimeData() const;
+ void setMimeData(QMimeData *mime);
+
+ QStringList formats() const;
+ bool hasFormat(const QString &format) const;
+ QVariant retrieveData(const QString &format, QVariant::Type) const;
+
+ void clear();
+ bool sync() const;
+};
+
+QString qt_mac_get_pasteboardString(PasteboardRef paste);
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
new file mode 100644
index 0000000000..d5af6de69c
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacclipboard.h"
+#include "qclipboard.h"
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qdebug.h"
+#include "qguiapplication.h"
+#include "qevent.h"
+#include "qurl.h"
+#include <stdlib.h>
+#include <string.h>
+#include "qcocoahelpers.h"
+#include "qmacmime.h"
+#include "qcocoaautoreleasepool.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+/*****************************************************************************
+ QClipboard debug facilities
+ *****************************************************************************/
+//#define DEBUG_PASTEBOARD
+
+#ifndef QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QClipboard member functions for mac.
+ *****************************************************************************/
+
+static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0};
+
+static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode)
+{
+ Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer);
+ if (mode == QClipboard::Clipboard)
+ return qt_mac_pasteboards[0];
+ else
+ return qt_mac_pasteboards[1];
+}
+
+static void qt_mac_cleanupPasteboard() {
+ delete qt_mac_pasteboards[0];
+ delete qt_mac_pasteboards[1];
+ qt_mac_pasteboards[0] = 0;
+ qt_mac_pasteboards[1] = 0;
+}
+
+static bool qt_mac_updateScrap(QClipboard::Mode mode)
+{
+ if (!qt_mac_pasteboards[0]) {
+ qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP);
+ qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP);
+ qAddPostRoutine(qt_mac_cleanupPasteboard);
+ return true;
+ }
+ return qt_mac_pasteboard(mode)->sync();
+}
+
+void QClipboard::clear(Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->clear();
+ setMimeData(0, mode);
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+
+void QClipboard::connectNotify(const char *signal)
+{
+ Q_UNUSED(signal);
+}
+
+bool QClipboard::event(QEvent *e)
+{
+ if (e->type() != QEvent::Clipboard)
+ return QObject::event(e);
+
+ if (qt_mac_updateScrap(QClipboard::Clipboard)) {
+ emitChanged(QClipboard::Clipboard);
+ }
+
+ if (qt_mac_updateScrap(QClipboard::FindBuffer)) {
+ emitChanged(QClipboard::FindBuffer);
+ }
+
+ return QObject::event(e);
+}
+
+const QMimeData *QClipboard::mimeData(Mode mode) const
+{
+ if (!supportsMode(mode))
+ return 0;
+ qt_mac_updateScrap(mode);
+ return qt_mac_pasteboard(mode)->mimeData();
+}
+
+void QClipboard::setMimeData(QMimeData *src, Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->setMimeData(src);
+ emitChanged(mode);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard || mode == FindBuffer);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+#endif // QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QMacPasteboard code
+*****************************************************************************/
+
+QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = p;
+ CFRetain(paste);
+}
+
+QMacPasteboard::QMacPasteboard(uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(0, &paste);
+ if (err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
+ }
+}
+
+QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(name, &paste);
+ if (err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
+ }
+}
+
+QMacPasteboard::~QMacPasteboard()
+{
+ // commit all promises for paste after exit close
+ for (int i = 0; i < promises.count(); ++i) {
+ const Promise &promise = promises.at(i);
+ QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
+ promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this);
+ }
+
+ if (paste)
+ CFRelease(paste);
+}
+
+PasteboardRef
+QMacPasteboard::pasteBoard() const
+{
+ return paste;
+}
+
+OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste)
+{
+ QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste;
+ const long promise_id = (long)id;
+
+ // Find the kept promise
+ const QString flavorAsQString = QCFString::toQString(flavor);
+ QMacPasteboard::Promise promise;
+ for (int i = 0; i < qpaste->promises.size(); i++){
+ QMacPasteboard::Promise tmp = qpaste->promises[i];
+ if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){
+ promise = tmp;
+ break;
+ }
+ }
+
+ if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) {
+ // we have promised this data, but wont be able to convert, so return null data.
+ // This helps in making the application/x-qt-mime-type-name hidden from normal use.
+ QByteArray ba;
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+ }
+
+ if (!promise.itemId) {
+ // There was no promise that could deliver data for the
+ // given id and flavor. This should not happend.
+ qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString));
+ return cantGetFlavorErr;
+ }
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id,
+ qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
+#endif
+
+ QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
+ if (md.size() <= promise.offset)
+ return cantGetFlavorErr;
+ const QByteArray &ba = md[promise.offset];
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+}
+
+bool
+QMacPasteboard::hasOSType(int c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF,
+ (c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF);
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ return false;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i);
+ const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType));
+ if (os_flavor == c_flavor) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+bool
+QMacPasteboard::hasFlavor(QString c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor));
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ PasteboardFlavorFlags flags;
+ if (PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+class QMacPasteboardMimeSource : public QMimeData {
+ const QMacPasteboard *paste;
+public:
+ QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { }
+ ~QMacPasteboardMimeSource() { }
+ virtual QStringList formats() const { return paste->formats(); }
+ virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); }
+};
+
+QMimeData
+*QMacPasteboard::mimeData() const
+{
+ if (!mime) {
+ mac_mime_source = true;
+ mime = new QMacPasteboardMimeSource(this);
+
+ }
+ return mime;
+}
+
+class QMacMimeData : public QMimeData
+{
+public:
+ QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
+private:
+ QMacMimeData();
+};
+
+void
+QMacPasteboard::setMimeData(QMimeData *mime_src)
+{
+ if (!paste)
+ return;
+
+ if (mime == mime_src || (!mime_src && mime && mac_mime_source))
+ return;
+ mac_mime_source = false;
+ delete mime;
+ mime = mime_src;
+
+ QList<QMacPasteboardMime*> availableConverters = QMacPasteboardMime::all(mime_type);
+ if (mime != 0) {
+ clear_helper();
+ QStringList formats = mime_src->formats();
+
+ // QMimeData sub classes reimplementing the formats() might not expose the
+ // temporary "application/x-qt-mime-type-name" mimetype. So check the existence
+ // of this mime type while doing drag and drop.
+ QString dummyMimeType(QLatin1String("application/x-qt-mime-type-name"));
+ if (!formats.contains(dummyMimeType)) {
+ QByteArray dummyType = mime_src->data(dummyMimeType);
+ if (!dummyType.isEmpty()) {
+ formats.append(dummyMimeType);
+ }
+ }
+ for (int f = 0; f < formats.size(); ++f) {
+ QString mimeType = formats.at(f);
+ for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) {
+ QMacPasteboardMime *c = (*it);
+ QString flavor(c->flavorFor(mimeType));
+ if (!flavor.isEmpty()) {
+ QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
+#if 0
+ //### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam
+ const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size();
+#else
+ int numItems = 1; //this is a hack but it is much faster than allowing conversion above
+ if (c->convertorName() == QLatin1String("FileURL"))
+ numItems = mime_src->urls().count();
+#endif
+ for (int item = 0; item < numItems; ++item) {
+ const int itemID = item+1; //id starts at 1
+ promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
+ PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags);
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - adding %d %s [%s] <%s> [%d]",
+ itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item);
+#endif
+ }
+ }
+ }
+ }
+ }
+}
+
+QStringList
+QMacPasteboard::formats() const
+{
+ if (!paste)
+ return QStringList();
+
+ sync();
+
+ QStringList ret;
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return ret;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Formats [%d]", (int)cnt);
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s", qPrintable(QString(flavor)));
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+ if (!mimeType.isEmpty() && !ret.contains(mimeType)) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor)));
+#endif
+ ret << mimeType;
+ }
+ }
+ }
+ return ret;
+}
+
+bool
+QMacPasteboard::hasFormat(const QString &format) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFormat [%s]", qPrintable(format));
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type);
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+#ifdef DEBUG_PASTEBOARD
+ if (!mimeType.isEmpty())
+ qDebug(" - %s", qPrintable(mimeType));
+#endif
+ if (mimeType == format)
+ return true;
+ }
+ }
+ return false;
+}
+
+QVariant
+QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
+{
+ if (!paste)
+ return QVariant();
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return QByteArray();
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("Pasteboard: retrieveData [%s]", qPrintable(format));
+#endif
+ const QList<QMacPasteboardMime *> mimes = QMacPasteboardMime::all(mime_type);
+ for (int mime = 0; mime < mimes.size(); ++mime) {
+ QMacPasteboardMime *c = mimes.at(mime);
+ QString c_flavor = c->flavorFor(format);
+ if (!c_flavor.isEmpty()) {
+ // Handle text/plain a little differently. Try handling Unicode first.
+ bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
+ || c_flavor == QLatin1String("public.utf8-plain-text"));
+ if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
+ // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
+ // correctly (as '\n') in this data. The 'public.utf16-plain-text' type
+ // usually maps newlines to '\r' instead.
+ QString str = qt_mac_get_pasteboardString(paste);
+ if (!str.isEmpty())
+ return str;
+ }
+ if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
+ c_flavor = QLatin1String("public.utf16-plain-text");
+
+ QVariant ret;
+ QList<QByteArray> retList;
+ for (uint index = 1; index <= cnt; ++index) {
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = static_cast<CFStringRef>(CFArrayGetValueAtIndex(types, i));
+ if (c_flavor == QCFString::toQString(flavor)) {
+ QCFType<CFDataRef> macBuffer;
+ if (PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) {
+ QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer));
+ if (!buffer.isEmpty()) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ buffer.detach(); //detach since we release the macBuffer
+ retList.append(buffer);
+ break; //skip to next element
+ }
+ }
+ } else {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ }
+ }
+ }
+
+ if (!retList.isEmpty()) {
+ ret = c->convertToMime(format, retList, c_flavor);
+ return ret;
+ }
+ }
+ }
+ return QVariant();
+}
+
+void QMacPasteboard::clear_helper()
+{
+ if (paste)
+ PasteboardClear(paste);
+ promises.clear();
+}
+
+void
+QMacPasteboard::clear()
+{
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: clear!");
+#endif
+ clear_helper();
+}
+
+bool
+QMacPasteboard::sync() const
+{
+ if (!paste)
+ return false;
+ const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified;
+
+ if (fromGlobal)
+ const_cast<QMacPasteboard *>(this)->setMimeData(0);
+
+#ifdef DEBUG_PASTEBOARD
+ if (fromGlobal)
+ qDebug("Pasteboard: Synchronize!");
+#endif
+ return fromGlobal;
+}
+
+
+QString qt_mac_get_pasteboardString(PasteboardRef paste)
+{
+ QCocoaAutoReleasePool pool;
+ NSPasteboard *pb = nil;
+ CFStringRef pbname;
+ if (PasteboardCopyName(paste, &pbname) == noErr) {
+ pb = [NSPasteboard pasteboardWithName:const_cast<NSString *>(reinterpret_cast<const NSString *>(pbname))];
+ CFRelease(pbname);
+ } else {
+ pb = [NSPasteboard generalPasteboard];
+ }
+ if (pb) {
+ NSString *text = [pb stringForType:NSStringPboardType];
+ if (text)
+ return QCFString::toQString(text);
+ }
+ return QString();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qmacmime.h b/src/plugins/platforms/cocoa/qmacmime.h
new file mode 100644
index 0000000000..842caa5f2f
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacmime.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMACMIME_H
+#define QMACMIME_H
+
+#include <QtCore>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+class Q_GUI_EXPORT QMacPasteboardMime {
+ char type;
+public:
+ enum QMacPasteboardMimeType { MIME_DND=0x01,
+ MIME_CLIP=0x02,
+ MIME_QT_CONVERTOR=0x04,
+ MIME_QT3_CONVERTOR=0x08,
+ MIME_ALL=MIME_DND|MIME_CLIP
+ };
+ explicit QMacPasteboardMime(char);
+ virtual ~QMacPasteboardMime();
+
+ static void initialize();
+
+ static QList<QMacPasteboardMime*> all(uchar);
+ static QMacPasteboardMime *convertor(uchar, const QString &mime, QString flav);
+ static QString flavorToMime(uchar, QString flav);
+
+ virtual QString convertorName() = 0;
+
+ virtual bool canConvert(const QString &mime, QString flav) = 0;
+ virtual QString mimeFor(QString flav) = 0;
+ virtual QString flavorFor(const QString &mime) = 0;
+ virtual QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) = 0;
+ virtual QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) = 0;
+};
+
+#endif
+
diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm
new file mode 100644
index 0000000000..db86deb91c
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacmime.mm
@@ -0,0 +1,938 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacmime.h"
+#include "qcocoahelpers.h"
+#include "qmacclipboard.h"
+
+#include "qdebug.h"
+#include "qpixmap.h"
+#include "qimagewriter.h"
+#include "qimagereader.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qdatetime.h"
+#include "qguiapplication.h"
+#include "qtextcodec.h"
+#include "qregexp.h"
+#include "qurl.h"
+#include "qmap.h"
+
+#include <Cocoa/Cocoa.h>
+
+QT_BEGIN_NAMESPACE
+
+extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp
+
+typedef QList<QMacPasteboardMime*> MimeList;
+Q_GLOBAL_STATIC(MimeList, globalMimeList)
+
+static void cleanup_mimes()
+{
+ MimeList *mimes = globalMimeList();
+ while (!mimes->isEmpty())
+ delete mimes->takeFirst();
+}
+
+Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
+
+/*!
+ \fn void qRegisterDraggedTypes(const QStringList &types)
+ \relates QMacPasteboardMime
+
+ Registers the given \a types as custom pasteboard types.
+
+ This function should be called to enable the Drag and Drop events
+ for custom pasteboard types on Cocoa implementations. This is required
+ in addition to a QMacPasteboardMime subclass implementation. By default
+ drag and drop is enabled for all standard pasteboard types.
+
+ \sa QMacPasteboardMime
+*/
+Q_WIDGETS_EXPORT void qRegisterDraggedTypes(const QStringList &types)
+{
+ (*globalDraggedTypesList()) += types;
+}
+
+const QStringList& qEnabledDraggedTypes()
+{
+ return (*globalDraggedTypesList());
+}
+
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_MIME_MAPS
+
+//functions
+extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
+extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp
+
+ScrapFlavorType qt_mac_mime_type = 'CUTE';
+CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
+
+/*!
+ \class QMacPasteboardMime
+ \brief The QMacPasteboardMime class converts between a MIME type and a
+ \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
+ Type Identifier (UTI)} format.
+ \since 4.2
+
+ \ingroup draganddrop
+ \inmodule QtWidgets
+
+ Qt's drag and drop and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol. On
+ Mac, although some applications use MIME to describe clipboard
+ contents, it is more common to use Apple's UTI format.
+
+ QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
+ By subclasses this class, one can extend Qt's drag and drop
+ and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
+
+ A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
+
+ Qt has predefined support for the following UTIs:
+ \list
+ \i public.utf8-plain-text - converts to "text/plain"
+ \i public.utf16-plain-text - converts to "text/plain"
+ \i public.html - converts to "text/html"
+ \i public.url - converts to "text/uri-list"
+ \i public.file-url - converts to "text/uri-list"
+ \i public.tiff - converts to "application/x-qt-image"
+ \i public.vcard - converts to "text/plain"
+ \i com.apple.traditional-mac-plain-text - converts to "text/plain"
+ \i com.apple.pict - converts to "application/x-qt-image"
+ \endlist
+
+ When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
+ find an instance that can convert to, or from, a specific MIME type. It will do this by calling
+ canConvert() on each instance, starting with (and choosing) the last created instance first.
+ The actual conversions will be done by using convertToMime() and convertFromMime().
+
+ \note The API uses the term "flavor" in some cases. This is for backwards
+ compatibility reasons, and should now be understood as UTIs.
+*/
+
+/*! \enum QMacPasteboardMime::QMacPasteboardMimeType
+ \internal
+*/
+
+/*!
+ Constructs a new conversion object of type \a t, adding it to the
+ globally accessed list of available convertors.
+*/
+QMacPasteboardMime::QMacPasteboardMime(char t) : type(t)
+{
+ globalMimeList()->append(this);
+}
+
+/*!
+ Destroys a conversion object, removing it from the global
+ list of available convertors.
+*/
+QMacPasteboardMime::~QMacPasteboardMime()
+{
+ if (!QGuiApplication::closingDown())
+ globalMimeList()->removeAll(this);
+}
+
+class QMacPasteboardMimeAny : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeAny() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeAny::convertorName()
+{
+ return QLatin1String("Any-Mime");
+}
+
+QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
+{
+ // do not handle the mime type name in the drag pasteboard
+ if (mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QString();
+ QString ret = QLatin1String("com.trolltech.anymime.") + mime;
+ return ret.replace(QLatin1Char('/'), QLatin1String("--"));
+}
+
+QString QMacPasteboardMimeAny::mimeFor(QString flav)
+{
+ const QString any_prefix = QLatin1String("com.trolltech.anymime.");
+ if (flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
+ return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
+ return QString();
+}
+
+bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
+ QVariant ret;
+ if (mime == QLatin1String("text/plain"))
+ ret = QString::fromUtf8(data.first());
+ else
+ ret = data.first();
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ else
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacPasteboardMimeTypeName : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeTypeName() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTypeName::convertorName()
+{
+ return QLatin1String("Qt-Mime-Type");
+}
+
+QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QLatin1String("com.trolltech.qt.MimeTypeName");
+ return QString();
+}
+
+QString QMacPasteboardMimeTypeName::mimeFor(QString)
+{
+ return QString();
+}
+
+bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
+{
+ return false;
+}
+
+QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
+{
+ QVariant ret;
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
+{
+ QList<QByteArray> ret;
+ ret.append(QString("x-qt-mime-type-name").toUtf8());
+ return ret;
+}
+
+class QMacPasteboardMimePlainText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimePlainText::convertorName()
+{
+ return QLatin1String("PlainText");
+}
+
+QString QMacPasteboardMimePlainText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("com.apple.traditional-mac-plain-text");
+ return QString();
+}
+
+QString QMacPasteboardMimePlainText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("com.apple.traditional-mac-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ QVariant ret;
+ if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text")))
+ ret.append(string.toLatin1());
+ return ret;
+}
+
+class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUnicodeText::convertorName()
+{
+ return QLatin1String("UnicodeText");
+}
+
+QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("public.utf16-plain-text");
+ int i = mime.indexOf(QLatin1String("charset="));
+ if (i >= 0) {
+ QString cs(mime.mid(i+8).toLower());
+ i = cs.indexOf(QLatin1Char(';'));
+ if (i>=0)
+ cs = cs.left(i);
+ if (cs == QLatin1String("system"))
+ return QLatin1String("public.utf8-plain-text");
+ else if (cs == QLatin1String("iso-10646-ucs-2")
+ || cs == QLatin1String("utf16"))
+ return QLatin1String("public.utf16-plain-text");
+ }
+ return QString();
+}
+
+QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ // I can only handle two types (system and unicode) so deal with them that way
+ QVariant ret;
+ if (flavor == QLatin1String("public.utf8-plain-text")) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else if (flavor == QLatin1String("public.utf16-plain-text")) {
+ ret = QString(reinterpret_cast<const QChar *>(firstData.constData()),
+ firstData.size() / sizeof(QChar));
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (flavor == QLatin1String("public.utf8-plain-text"))
+ ret.append(string.toUtf8());
+ else if (flavor == QLatin1String("public.utf16-plain-text"))
+ ret.append(QByteArray((char*)string.utf16(), string.length()*2));
+ return ret;
+}
+
+class QMacPasteboardMimeHTMLText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeHTMLText::convertorName()
+{
+ return QLatin1String("HTML");
+}
+
+QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/html"))
+ return QLatin1String("public.html");
+ return QString();
+}
+
+QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.html"))
+ return QLatin1String("text/html");
+ return QString();
+}
+
+bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
+{
+ if (!canConvert(mimeType, flavor))
+ return QVariant();
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
+ return data.first();
+}
+
+QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flavor))
+ return ret;
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacPasteboardMimeTiff : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTiff::convertorName()
+{
+ return QLatin1String("Tiff");
+}
+
+QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("application/x-qt-image")))
+ return QLatin1String("public.tiff");
+ return QString();
+}
+
+QString QMacPasteboardMimeTiff::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.tiff"))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
+}
+
+QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
+ QVariant ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ const QByteArray &a = data.first();
+ QCFType<CGImageRef> image;
+ QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
+ reinterpret_cast<const UInt8 *>(a.constData()),
+ a.size(), kCFAllocatorNull);
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
+ image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
+
+ // ### TODO (msorvig) QPixmap conversion
+ //if (image != 0)
+ // ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QImage img = qvariant_cast<QImage>(variant);
+ QCFType<CGImageRef> cgimage = qt_mac_image_to_cgimage(img);
+
+ QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
+ QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
+ if (imageDestination != 0) {
+ CFTypeRef keys[2];
+ QCFType<CFTypeRef> values[2];
+ QCFType<CFDictionaryRef> options;
+ keys[0] = kCGImagePropertyPixelWidth;
+ keys[1] = kCGImagePropertyPixelHeight;
+ int width = img.width();
+ int height = img.height();
+ values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
+ values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
+ options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
+ reinterpret_cast<const void **>(values), 2,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CGImageDestinationAddImage(imageDestination, cgimage, options);
+ CGImageDestinationFinalize(imageDestination);
+ }
+ QByteArray ar(CFDataGetLength(data), 0);
+ CFDataGetBytes(data,
+ CFRangeMake(0, ar.size()),
+ reinterpret_cast<UInt8 *>(ar.data()));
+ ret.append(ar);
+ return ret;
+}
+
+
+class QMacPasteboardMimeFileUri : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeFileUri::convertorName()
+{
+ return QLatin1String("FileURL");
+}
+
+QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/uri-list"))
+ return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+ return QString();
+}
+
+QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
+{
+ if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
+{
+ return mime == QLatin1String("text/uri-list")
+ && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+}
+
+QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (!canConvert(mime, flav))
+ return QVariant();
+ QList<QVariant> ret;
+ for (int i = 0; i < data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ QList<QVariant> urls = data.toList();
+ for (int i = 0; i < urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+class QMacPasteboardMimeUrl : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUrl::convertorName()
+{
+ return QLatin1String("URL");
+}
+
+QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("text/uri-list")))
+ return QLatin1String("public.url");
+ return QString();
+}
+
+QString QMacPasteboardMimeUrl::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.url"))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.url")
+ && mime == QLatin1String("text/uri-list");
+}
+
+QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (!canConvert(mime, flav))
+ return QVariant();
+
+ QList<QVariant> ret;
+ for (int i=0; i<data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QList<QVariant> urls = data.toList();
+ for (int i=0; i<urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+class QMacPasteboardMimeVCard : public QMacPasteboardMime
+{
+public:
+ QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeVCard::convertorName()
+{
+ return QString("VCard");
+}
+
+bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("text/plain")))
+ return QLatin1String("public.vcard");
+ return QString();
+}
+
+QString QMacPasteboardMimeVCard::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.vcard"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ QByteArray cards;
+ if (mime == QLatin1String("text/plain")) {
+ for (int i=0; i<data.size(); ++i)
+ cards += data[i];
+ }
+ return QVariant(cards);
+}
+
+QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ return ret;
+}
+
+
+/*!
+ \internal
+
+ This is an internal function.
+*/
+void QMacPasteboardMime::initialize()
+{
+ if (globalMimeList()->isEmpty()) {
+ qAddPostRoutine(cleanup_mimes);
+
+ //standard types that we wrap
+ new QMacPasteboardMimeTiff;
+ new QMacPasteboardMimeUnicodeText;
+ new QMacPasteboardMimePlainText;
+ new QMacPasteboardMimeHTMLText;
+ new QMacPasteboardMimeFileUri;
+ new QMacPasteboardMimeUrl;
+ new QMacPasteboardMimeTypeName;
+ new QMacPasteboardMimeVCard;
+ //make sure our "non-standard" types are always last! --Sam
+ new QMacPasteboardMimeAny;
+ }
+}
+
+/*!
+ Returns the most-recently created QMacPasteboardMime of type \a t that can convert
+ between the \a mime and \a flav formats. Returns 0 if no such convertor
+ exists.
+*/
+QMacPasteboardMime*
+QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, mime.toLatin1().constData(),
+ flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->canConvert(mime,flav));
+ for (int i = 0; i < (*it)->countFlavors(); ++i) {
+ int f = (*it)->flavor(i);
+ qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
+ (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
+ (*it)->convertorName().toLatin1().constData());
+ }
+#endif
+ if (((*it)->type & t) && (*it)->canConvert(mime, flav))
+ return (*it);
+ }
+ return 0;
+}
+/*!
+ Returns a MIME type of type \a t for \a flav, or 0 if none exists.
+*/
+QString QMacPasteboardMime::flavorToMime(uchar t, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->mimeFor(flav).toLatin1().constData());
+
+#endif
+ if ((*it)->type & t) {
+ QString mimeType = (*it)->mimeFor(flav);
+ if (!mimeType.isNull())
+ return mimeType;
+ }
+ }
+ return QString();
+}
+
+/*!
+ Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
+*/
+QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t)
+{
+ MimeList ret;
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+ if ((*it)->type & t)
+ ret.append((*it));
+ }
+ return ret;
+}
+
+
+/*!
+ \fn QString QMacPasteboardMime::convertorName()
+
+ Returns a name for the convertor.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
+
+ Returns true if the convertor can convert (both ways) between
+ \a mime and \a flav; otherwise returns false.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::mimeFor(QString flav)
+
+ Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
+ convertor does not support \a flav.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
+
+ Returns the Mac UTI used for MIME type \a mime, or 0 if this
+ convertor does not support \a mime.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+
+ Returns \a data converted from Mac UTI \a flav to MIME type \a
+ mime.
+
+ Note that Mac flavors must all be self-terminating. The input \a
+ data may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
+
+ Returns \a data converted from MIME type \a mime
+ to Mac UTI \a flav.
+
+ Note that Mac flavors must all be self-terminating. The return
+ value may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index c61ff2bd02..1a1a1cd3b9 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -57,6 +57,7 @@ QT_END_NAMESPACE
QCocoaWindow *m_platformWindow;
Qt::MouseButtons m_buttons;
QAccessibleInterface *m_accessibleRoot;
+ QStringList *currentCustomDragTypes;
}
- (id)init;
@@ -91,6 +92,9 @@ QT_END_NAMESPACE
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
+- (void)registerDragTypes;
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender;
+
@end
#endif //QNSVIEW_H
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a43b3fe893..9ed3332ba5 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -46,7 +46,9 @@
#include "qnsview.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include "qcocoaautoreleasepool.h"
#include "qmultitouch_mac_p.h"
+#include "qcocoadrag.h"
#include <QtGui/QWindowSystemInterface>
#include <QtCore/QDebug>
@@ -72,6 +74,7 @@ static QTouchDevice *touchDevice = 0;
m_cgImage = 0;
m_window = 0;
m_buttons = Qt::NoButton;
+ currentCustomDragTypes = 0;
if (!touchDevice) {
touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchPad);
@@ -109,6 +112,7 @@ static QTouchDevice *touchDevice = 0;
m_accessibleRoot = window->accessibleRoot();
#endif
+ [self registerDragTypes];
[self setPostsFrameChangedNotifications : YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateGeometry)
@@ -471,4 +475,74 @@ static QTouchDevice *touchDevice = 0;
[self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)];
}
+-(void)registerDragTypes
+{
+ QCocoaAutoReleasePool pool;
+ // ### Custom types disabled.
+ QStringList customTypes; // = qEnabledDraggedTypes();
+ if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
+ if (currentCustomDragTypes == 0)
+ currentCustomDragTypes = new QStringList();
+ *currentCustomDragTypes = customTypes;
+ const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
+ NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
+ // Add custom types supported by the application.
+ for (int i = 0; i < customTypes.size(); i++) {
+ [supportedTypes addObject:QCFString::toNSString(customTypes[i])];
+ }
+ [self registerForDraggedTypes:supportedTypes];
+ }
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ return [self handleDrag : sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+ return [self handleDrag : sender];
+}
+
+// Sends drag update to Qt, return the action
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_window, &mimeData, qt_windowPoint, qtAllowed);
+ return qt_mac_mapDropAction(response.acceptedAction());
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+
+ // Send 0 mime data to indicate drag exit
+ QWindowSystemInterface::handleDrag(m_window, 0 ,qt_windowPoint, Qt::IgnoreAction);
+}
+
+// called on drop, send the drop to Qt and return if it was accepted.
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_window, &mimeData, qt_windowPoint, qtAllowed);
+ return response.isAccepted();
+}
+
@end
diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h
index 8e94880c5a..b75e6e2bcb 100644
--- a/src/plugins/platforms/cocoa/qt_mac_p.h
+++ b/src/plugins/platforms/cocoa/qt_mac_p.h
@@ -196,44 +196,6 @@ public:
class QMacPasteboardMime;
class QMimeData;
-class QMacPasteboard
-{
- struct Promise {
- Promise() : itemId(0), convertor(0) { }
- Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
- int itemId, offset;
- QMacPasteboardMime *convertor;
- QString mime;
- QVariant data;
- };
- QList<Promise> promises;
-
- OSPasteboardRef paste;
- uchar mime_type;
- mutable QPointer<QMimeData> mime;
- mutable bool mac_mime_source;
- static OSStatus promiseKeeper(OSPasteboardRef, PasteboardItemID, CFStringRef, void *);
- void clear_helper();
-public:
- QMacPasteboard(OSPasteboardRef p, uchar mime_type=0);
- QMacPasteboard(uchar mime_type);
- QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
- ~QMacPasteboard();
-
- bool hasFlavor(QString flavor) const;
- bool hasOSType(int c_flavor) const;
-
- OSPasteboardRef pasteBoard() const;
- QMimeData *mimeData() const;
- void setMimeData(QMimeData *mime);
-
- QStringList formats() const;
- bool hasFormat(const QString &format) const;
- QVariant retrieveData(const QString &format, QVariant::Type) const;
-
- void clear();
- bool sync() const;
-};
extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp
diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
index e1660a998a..a63bc48133 100644
--- a/src/plugins/platforms/directfb/qdirectfbcursor.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
QDirectFBCursor::QDirectFBCursor(QPlatformScreen *screen)
- : QPlatformCursor(screen)
+ : m_screen(screen)
{
m_image.reset(new QPlatformCursorImage(0, 0, 0, 0, 0, 0));
}
@@ -70,7 +70,7 @@ void QDirectFBCursor::changeCursor(QCursor *cursor, QWindow *)
}
DFBResult res;
- IDirectFBDisplayLayer *layer = toDfbLayer(screen);
+ IDirectFBDisplayLayer *layer = toDfbLayer(m_screen);
IDirectFBSurface* surface(QDirectFbConvenience::dfbSurfaceForPlatformPixmap(map.handle()));
res = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.h b/src/plugins/platforms/directfb/qdirectfbcursor.h
index 3cc2825b28..f28e225dc7 100644
--- a/src/plugins/platforms/directfb/qdirectfbcursor.h
+++ b/src/plugins/platforms/directfb/qdirectfbcursor.h
@@ -60,6 +60,7 @@ public:
private:
QScopedPointer<QPlatformCursorImage> m_image;
+ QPlatformScreen *m_screen;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/directfb/qdirectfbscreen.h b/src/plugins/platforms/directfb/qdirectfbscreen.h
index ad80576c8f..8535239088 100644
--- a/src/plugins/platforms/directfb/qdirectfbscreen.h
+++ b/src/plugins/platforms/directfb/qdirectfbscreen.h
@@ -61,6 +61,7 @@ public:
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
+ QPlatformCursor *cursor() const { return m_cursor.data(); }
// DirectFb helpers
IDirectFBDisplayLayer *dfbLayer() const;
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
index a38f66bd02..37817af39d 100644
--- a/src/plugins/platforms/kms/qkmscursor.cpp
+++ b/src/plugins/platforms/kms/qkmscursor.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
QKmsCursor::QKmsCursor(QKmsScreen *screen)
- : QPlatformCursor(screen), m_screen(screen),
+ : m_screen(screen),
m_graphicsBufferManager(screen->device()->gbmDevice())
{
gbm_bo *bo = gbm_bo_create(m_graphicsBufferManager, 64, 64,
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index f1b9baf120..76b9bce28f 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -96,6 +96,11 @@ QSizeF QKmsScreen::physicalSize() const
return m_physicalSize;
}
+QPlatformCursor *QKmsScreen::cursor() const
+{
+ return m_cursor;
+}
+
GLuint QKmsScreen::framebufferObject() const
{
return m_bufferManager.framebufferObject();
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
index 4cb547b424..058314a515 100644
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ b/src/plugins/platforms/kms/qkmsscreen.h
@@ -61,6 +61,7 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const;
+ QPlatformCursor *cursor() const;
GLuint framebufferObject() const;
quint32 crtcId() const { return m_crtcId; }
diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h
index d82240255e..ac768e2dab 100644
--- a/src/plugins/platforms/windows/qtwindows_additional.h
+++ b/src/plugins/platforms/windows/qtwindows_additional.h
@@ -61,7 +61,8 @@
# define FE_FONTSMOOTHINGCLEARTYPE 0x0002
# define CLEARTYPE_QUALITY 5
# define SPI_GETDROPSHADOW 0x1024
-
+# define COLOR_MENUHILIGHT 29
+# define COLOR_MENUBAR 30
# define CF_DIBV5 17
#define CO_E_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80004021L)
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
index 1a8f593609..134b1c81ce 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
@@ -844,14 +844,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry);
if (ref.first) {
acc = QAccessible::queryAccessibleInterface(ref.first);
- if (acc && ref.second) {
- if (ref.second) {
- QAccessibleInterface *res = acc->child(ref.second - 1);
- delete acc;
- if (!res)
- return E_INVALIDARG;
- acc = res;
- }
+ if (acc && ref.second >= 0) {
+ QAccessibleInterface *res = acc->child(ref.second);
+ delete acc;
+ if (!res)
+ return E_INVALIDARG;
+ acc = res;
}
}
} else {
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index f75cbeb078..337ba9ab27 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -72,11 +72,6 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
\sa QWindowsWindowCursor
*/
-QWindowsCursor::QWindowsCursor(QPlatformScreen *s) :
- QPlatformCursor(s)
-{
-}
-
HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY)
{
HCURSOR cur = 0;
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index a03c77a3b6..61c43dc4d2 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -70,7 +70,7 @@ private:
class QWindowsCursor : public QPlatformCursor
{
public:
- explicit QWindowsCursor(QPlatformScreen *);
+ QWindowsCursor() {}
virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
virtual QPoint pos() const { return mousePosition(); }
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index fba7794a12..5094ad9dc3 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qwindowsfontdatabase.h"
+#include "qwindowsfontdatabase_ft.h" // for default font
#include "qwindowscontext.h"
#include "qwindowsfontengine.h"
#include "qwindowsfontenginedirectwrite.h"
@@ -1066,53 +1067,7 @@ static inline int verticalDPI()
QFont QWindowsFontDatabase::defaultFont() const
{
- LOGFONT lf;
- GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
- QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf);
- // "MS Shell Dlg 2" is the correct system font >= Win2k
- if (systemFont.family() == QStringLiteral("MS Shell Dlg"))
- systemFont.setFamily(QStringLiteral("MS Shell Dlg 2"));
- if (QWindowsContext::verboseFonts)
- qDebug() << __FUNCTION__ << systemFont;
- return systemFont;
-}
-
-QHash<QByteArray, QFont> QWindowsFontDatabase::defaultFonts() const
-{
- QHash<QByteArray, QFont> result;
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
-
- const int verticalRes = verticalDPI();
-
- const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes);
- const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes);
- const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes);
- const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes);
-
- LOGFONT lfIconTitleFont;
- SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes);
-
- result.insert(QByteArray("QMenu"), menuFont);
- result.insert(QByteArray("QMenuBar"), menuFont);
- result.insert(QByteArray("QMessageBox"), messageFont);
- result.insert(QByteArray("QTipLabel"), statusFont);
- result.insert(QByteArray("QStatusBar"), statusFont);
- result.insert(QByteArray("Q3TitleBar"), titleFont);
- result.insert(QByteArray("QWorkspaceTitleBar"), titleFont);
- result.insert(QByteArray("QAbstractItemView"), iconTitleFont);
- result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont);
- if (QWindowsContext::verboseFonts) {
- typedef QHash<QByteArray, QFont>::const_iterator CIT;
- QDebug nsp = qDebug().nospace();
- nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n";
- const CIT cend = result.constEnd();
- for (CIT it = result.constBegin(); it != cend; ++it)
- nsp << it.key() << ' ' << it.value() << '\n';
- }
- return result;
+ return QWindowsFontDatabaseFT::systemDefaultFont();
}
QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index b08b682991..04d6ccdd91 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -86,7 +86,6 @@ public:
virtual QString fontDir() const;
virtual QFont defaultFont() const;
- virtual QHash<QByteArray, QFont> defaultFonts() const;
static QFontEngine *createEngine(int script, const QFontDef &request,
HDC fontHdc, int dpi, bool rawMode,
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index e972ae23ee..fcce87d0bd 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -460,7 +460,7 @@ static inline int verticalDPI()
return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY);
}
-QFont QWindowsFontDatabaseFT::defaultFont() const
+QFont QWindowsFontDatabaseFT::systemDefaultFont()
{
LOGFONT lf;
GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
@@ -473,44 +473,6 @@ QFont QWindowsFontDatabaseFT::defaultFont() const
return systemFont;
}
-QHash<QByteArray, QFont> QWindowsFontDatabaseFT::defaultFonts() const
-{
- QHash<QByteArray, QFont> result;
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
-
- const int verticalRes = verticalDPI();
-
- const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes);
- const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes);
- const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes);
- const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes);
-
- LOGFONT lfIconTitleFont;
- SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes);
-
- result.insert(QByteArray("QMenu"), menuFont);
- result.insert(QByteArray("QMenuBar"), menuFont);
- result.insert(QByteArray("QMessageBox"), messageFont);
- result.insert(QByteArray("QTipLabel"), statusFont);
- result.insert(QByteArray("QStatusBar"), statusFont);
- result.insert(QByteArray("Q3TitleBar"), titleFont);
- result.insert(QByteArray("QWorkspaceTitleBar"), titleFont);
- result.insert(QByteArray("QAbstractItemView"), iconTitleFont);
- result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont);
- if (QWindowsContext::verboseFonts) {
- typedef QHash<QByteArray, QFont>::const_iterator CIT;
- QDebug nsp = qDebug().nospace();
- nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n";
- const CIT cend = result.constEnd();
- for (CIT it = result.constBegin(); it != cend; ++it)
- nsp << it.key() << ' ' << it.value() << '\n';
- }
- return result;
-}
-
QFont QWindowsFontDatabaseFT::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In)
{
if (verticalDPI_In <= 0)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 5a0c4c6377..4136b75dd8 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -59,8 +59,9 @@ public:
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual QString fontDir() const;
- virtual QFont defaultFont() const;
- virtual QHash<QByteArray, QFont> defaultFonts() const;
+ virtual QFont defaultFont() const { return systemDefaultFont(); }
+ static QFont systemDefaultFont();
+
static HFONT systemFont();
static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0);
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 1dc5175515..2476e15169 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -147,6 +147,14 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
return dbg;
}
+// Return the cursor to be shared by all screens (virtual desktop).
+static inline QSharedPointer<QWindowsCursor> sharedCursor()
+{
+ if (const QScreen *primaryScreen = QGuiApplication::primaryScreen())
+ return static_cast<const QWindowsScreen *>(primaryScreen->handle())->windowsCursor();
+ return QSharedPointer<QWindowsCursor>(new QWindowsCursor);
+}
+
/*!
\class QWindowsScreen
\brief Windows screen.
@@ -155,7 +163,7 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
*/
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
- m_data(data), m_cursor(this)
+ m_data(data), m_cursor(sharedCursor())
{
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 77a327a62a..5b9a50b2ab 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -46,6 +46,7 @@
#include <QtCore/QList>
#include <QtCore/QPair>
+#include <QtCore/QSharedPointer>
#include <QtGui/QPlatformScreen>
QT_BEGIN_NAMESPACE
@@ -74,6 +75,8 @@ struct QWindowsScreenData
class QWindowsScreen : public QPlatformScreen
{
public:
+ typedef QSharedPointer<QWindowsCursor> WindowsCursorPtr;
+
explicit QWindowsScreen(const QWindowsScreenData &data);
static QWindowsScreen *screenOf(const QWindow *w = 0);
@@ -98,14 +101,14 @@ public:
inline void handleChanges(const QWindowsScreenData &newData);
- const QWindowsCursor &cursor() const { return m_cursor; }
- QWindowsCursor &cursor() { return m_cursor; }
+ QPlatformCursor *cursor() const { return m_cursor.data(); }
+ const WindowsCursorPtr &windowsCursor() const { return m_cursor; }
const QWindowsScreenData &data() const { return m_data; }
private:
QWindowsScreenData m_data;
- QWindowsCursor m_cursor;
+ const WindowsCursorPtr m_cursor;
};
class QWindowsScreenManager
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 5350b3ca3f..10b4682ad8 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -44,6 +44,7 @@
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qt_windows.h"
+#include "qwindowsfontdatabase_ft.h"
#include <QtCore/QVariant>
#include <QtCore/QCoreApplication>
@@ -76,6 +77,22 @@ static inline QString paletteToString(const QPalette &palette)
return result;
}
+static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
+{
+ BOOL result;
+ if (SystemParametersInfo(what, 0, &result, 0))
+ return result ? true : false;
+ return defaultValue;
+}
+
+static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
+{
+ DWORD result;
+ if (SystemParametersInfo(what, 0, &result, 0))
+ return result;
+ return defaultValue;
+}
+
static inline QColor mixColors(const QColor &c1, const QColor &c2)
{
return QColor ((c1.red() + c2.red()) / 2,
@@ -138,7 +155,7 @@ static inline QPalette systemPalette()
return result;
}
-QPalette toolTipPalette(const QPalette &systemPalette)
+static inline QPalette toolTipPalette(const QPalette &systemPalette)
{
QPalette result(systemPalette);
const QColor tipBgColor(getSysColor(COLOR_INFOBK));
@@ -163,24 +180,58 @@ QPalette toolTipPalette(const QPalette &systemPalette)
return result;
}
-static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
+static inline QPalette menuPalette(const QPalette &systemPalette)
{
- BOOL result;
- if (SystemParametersInfo(what, 0, &result, 0))
- return result ? true : false;
- return defaultValue;
+ QPalette result(systemPalette);
+ const QColor menuColor(getSysColor(COLOR_INFOBK));
+ const QColor menuTextColor(getSysColor(COLOR_MENUTEXT));
+ const QColor disabled(getSysColor(COLOR_GRAYTEXT));
+ const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false);
+ // we might need a special color group for the result.
+ result.setColor(QPalette::Active, QPalette::Button, menuColor);
+ result.setColor(QPalette::Active, QPalette::Text, menuTextColor);
+ result.setColor(QPalette::Active, QPalette::WindowText, menuTextColor);
+ result.setColor(QPalette::Active, QPalette::ButtonText, menuTextColor);
+ result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Highlight,
+ getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT));
+ result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Button,
+ result.color(QPalette::Active, QPalette::Button));
+ result.setColor(QPalette::Inactive, QPalette::Button,
+ result.color(QPalette::Active, QPalette::Button));
+ result.setColor(QPalette::Inactive, QPalette::Text,
+ result.color(QPalette::Active, QPalette::Text));
+ result.setColor(QPalette::Inactive, QPalette::WindowText,
+ result.color(QPalette::Active, QPalette::WindowText));
+ result.setColor(QPalette::Inactive, QPalette::ButtonText,
+ result.color(QPalette::Active, QPalette::ButtonText));
+ result.setColor(QPalette::Inactive, QPalette::Highlight,
+ result.color(QPalette::Active, QPalette::Highlight));
+ result.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ result.color(QPalette::Active, QPalette::HighlightedText));
+ result.setColor(QPalette::Inactive, QPalette::ButtonText,
+ systemPalette.color(QPalette::Inactive, QPalette::Dark));
+ return result;
}
-static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
+static inline QPalette *menuBarPalette(const QPalette &menuPalette)
{
- DWORD result;
- if (SystemParametersInfo(what, 0, &result, 0))
- return result;
- return defaultValue;
+ QPalette *result = 0;
+ if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) {
+ result = new QPalette(menuPalette);
+ const QColor menubar(getSysColor(COLOR_MENUBAR));
+ result->setColor(QPalette::Active, QPalette::Button, menubar);
+ result->setColor(QPalette::Disabled, QPalette::Button, menubar);
+ result->setColor(QPalette::Inactive, QPalette::Button, menubar);
+ }
+ return result;
}
QWindowsTheme::QWindowsTheme()
{
+ qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
@@ -188,12 +239,7 @@ QWindowsTheme::QWindowsTheme()
QWindowsTheme::~QWindowsTheme()
{
clearPalettes();
-}
-
-void QWindowsTheme::clearPalettes()
-{
- qDeleteAll(m_palettes, m_palettes + NPalettes);
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+ clearFonts();
}
QWindowsTheme *QWindowsTheme::instance()
@@ -243,17 +289,65 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QPlatformTheme::themeHint(hint);
}
-void QWindowsTheme::refresh()
+void QWindowsTheme::clearPalettes()
{
- clearPalettes();
- if (QGuiApplication::desktopSettingsAware()) {
- m_palettes[SystemPalette] = new QPalette(systemPalette());
- m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
- if (QWindowsContext::verboseTheming)
- qDebug() << __FUNCTION__ << '\n'
- << " system=" << paletteToString(*m_palettes[SystemPalette])
- << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
- }
+ qDeleteAll(m_palettes, m_palettes + NPalettes);
+ qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+}
+
+void QWindowsTheme::refreshPalettes()
+{
+
+ if (!QGuiApplication::desktopSettingsAware())
+ return;
+ m_palettes[SystemPalette] = new QPalette(systemPalette());
+ m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
+ m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette]));
+ m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]);
+ if (QWindowsContext::verboseTheming)
+ qDebug() << __FUNCTION__ << '\n'
+ << " system=" << paletteToString(*m_palettes[SystemPalette])
+ << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
+}
+
+void QWindowsTheme::clearFonts()
+{
+ qDeleteAll(m_fonts, m_fonts + NFonts);
+ qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
+}
+
+void QWindowsTheme::refreshFonts()
+{
+ clearFonts();
+ if (!QGuiApplication::desktopSettingsAware())
+ return;
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+
+ const QFont menuFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMenuFont);
+ const QFont messageBoxFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMessageFont);
+ const QFont statusFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfStatusFont);
+ const QFont titleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfCaptionFont);
+
+ LOGFONT lfIconTitleFont;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
+ const QFont iconTitleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(lfIconTitleFont);
+
+ m_fonts[SystemFont] = new QFont(QWindowsFontDatabaseFT::systemDefaultFont());
+ m_fonts[MenuFont] = new QFont(menuFont);
+ m_fonts[MenuBarFont] = new QFont(menuFont);
+ m_fonts[MessageBoxFont] = new QFont(messageBoxFont);
+ m_fonts[TipLabelFont] = new QFont(statusFont);
+ m_fonts[StatusBarFont] = new QFont(statusFont);
+ m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont);
+ m_fonts[DockWidgetTitleFont] = new QFont(titleFont);
+ m_fonts[ItemViewFont] = new QFont(iconTitleFont);
+
+ if (QWindowsContext::verboseTheming)
+ qDebug() << __FUNCTION__ << '\n'
+ << " menuFont=" << menuFont
+ << " messageBox=" << MessageBoxFont;
}
bool QWindowsTheme::usePlatformNativeDialog(DialogType type) const
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 950c380737..37346eed3a 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -64,14 +64,20 @@ public:
virtual QVariant themeHint(ThemeHint) const;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
+ virtual const QFont *font(Font type = SystemFont) const
+ { return m_fonts[type]; }
void windowsThemeChanged(QWindow *window);
private:
- void refresh();
+ void refresh() { refreshPalettes(); refreshFonts(); }
void clearPalettes();
+ void refreshPalettes();
+ void clearFonts();
+ void refreshFonts();
QPalette *m_palettes[NPalettes];
+ QFont *m_fonts[NFonts];
};
static inline COLORREF qColorToCOLORREF(const QColor &color)
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index b2ebe06a58..1edb243f4e 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -618,7 +618,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
m_windowState(aWindow->windowState()),
m_opacity(1.0),
m_mouseGrab(false),
- m_cursor(QWindowsScreen::screenOf(aWindow)->cursor().standardWindowCursor()),
+ m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
m_dropTarget(0),
m_savedStyle(0)
{
@@ -1309,16 +1309,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
}
/*!
- \brief Applies to cursor property set on the window to the global cursor
- unless there is an override cursor.
+ \brief Applies to cursor property set on the window to the global cursor.
\sa QWindowsCursor
*/
void QWindowsWindow::applyCursor()
{
- if (!QGuiApplication::overrideCursor())
- SetCursor(m_cursor.handle());
+ SetCursor(m_cursor.handle());
}
void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index ed7c22b1e6..7e1b66829a 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -261,7 +261,7 @@ static const char * const cursorNames[] = {
};
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), QPlatformCursor(screen), m_screen(screen)
+ : QXcbObject(conn), m_screen(screen)
{
if (cursorCount++)
return;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 15ffc5b8ff..8b66ef4603 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -237,6 +237,11 @@ QSizeF QXcbScreen::physicalSize() const
return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
}
+QPlatformCursor *QXcbScreen::cursor() const
+{
+ return m_cursor;
+}
+
int QXcbScreen::screenNumber() const
{
return m_number;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 870d4d5662..ac4ecb1c8d 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -68,6 +68,7 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const;
+ QPlatformCursor *cursor() const;
int screenNumber() const;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 739426a92a..542d7ab69f 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -548,6 +548,8 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ updateNetWmUserTime(connection()->time());
+
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
xcb_flush(xcb_connection());
diff --git a/src/plugins/platforms/xlib/qxlibcursor.cpp b/src/plugins/platforms/xlib/qxlibcursor.cpp
index 8ab40e31ef..a714f82371 100644
--- a/src/plugins/platforms/xlib/qxlibcursor.cpp
+++ b/src/plugins/platforms/xlib/qxlibcursor.cpp
@@ -52,8 +52,7 @@
QT_BEGIN_NAMESPACE
-QXlibCursor::QXlibCursor(QXlibScreen *screen)
- : QPlatformCursor(screen)
+QXlibCursor::QXlibCursor(QXlibScreen *screen) : m_screen(screen)
{
}
@@ -191,9 +190,4 @@ Cursor QXlibCursor::createCursorShape(int cshape)
return cursor;
}
-QXlibScreen * QXlibCursor::testLiteScreen() const
-{
- return static_cast<QXlibScreen *>(screen);
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibcursor.h b/src/plugins/platforms/xlib/qxlibcursor.h
index 92e42ac7a1..0056aa9554 100644
--- a/src/plugins/platforms/xlib/qxlibcursor.h
+++ b/src/plugins/platforms/xlib/qxlibcursor.h
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-class QXlibCursor : QPlatformCursor
+class QXlibCursor : public QPlatformCursor
{
public:
QXlibCursor(QXlibScreen *screen);
@@ -59,8 +59,9 @@ private:
Cursor createCursorBitmap(QCursor * cursor);
Cursor createCursorShape(int cshape);
- QXlibScreen *testLiteScreen() const;
+ QXlibScreen *testLiteScreen() const { return m_screen; }
QMap<int, Cursor> cursorMap;
+ QXlibScreen *m_screen;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp
index fc903708b3..62c80b6ad4 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.cpp
+++ b/src/plugins/platforms/xlib/qxlibscreen.cpp
@@ -241,6 +241,11 @@ QXlibScreen::~QXlibScreen()
delete mDisplay;
}
+QPlatformCursor *QXlibScreen::cursor() const
+{
+ return mCursor;
+}
+
Window QXlibScreen::rootWindow()
{
return RootWindow(mDisplay->nativeDisplay(), mScreen);
diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h
index c6672c3540..5bb6cc7735 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.h
+++ b/src/plugins/platforms/xlib/qxlibscreen.h
@@ -63,6 +63,7 @@ public:
int depth() const { return mDepth; }
QImage::Format format() const { return mFormat; }
QSizeF physicalSize() const { return mPhysicalSize; }
+ QPlatformCursor *cursor() const;
Window rootWindow();
unsigned long blackPixel();
diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp
index c7b450786d..ce2362b4fe 100644
--- a/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -271,7 +271,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QWidget *pageEdit = new QWidget(toolbar);
QVBoxLayout *vboxLayout = new QVBoxLayout;
vboxLayout->setContentsMargins(0, 0, 0, 0);
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
// We query the widgets about their size and then we fix the size.
// This should do the trick for the laying out part...
QSize pageNumEditSize, pageNumLabelSize;
@@ -281,7 +281,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
pageNumLabel->resize(pageNumLabelSize);
#endif
QFormLayout *formLayout = new QFormLayout;
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
// We have to change the growth policy in Mac.
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
#endif
@@ -560,7 +560,7 @@ void QPrintPreviewDialogPrivate::_q_print()
{
Q_Q(QPrintPreviewDialog);
-#if defined(Q_OS_WIN) || defined(Q_WS_MAC)
+#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
if (printer->outputFormat() != QPrinter::NativeFormat) {
QString title;
QString suffix;
diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.cpp b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp
index aeb4599955..b6f65ee893 100644
--- a/src/printsupport/kernel/qplatformprintersupport_qpa.cpp
+++ b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp
@@ -124,6 +124,26 @@ void QPlatformPrinterSupport::setPrinterInfoCupsPrinterIndex(QPrinterInfo *p, in
#endif
}
+/*
+ Converts QSizeF in millimeters to a predefined PaperSize (returns Custom if
+ the size isn't a standard size)
+*/
+QPrinter::PaperSize QPlatformPrinterSupport::convertQSizeFToPaperSize(const QSizeF &sizef)
+{
+ extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF &);
+ return qSizeFTopaperSize(sizef);
+}
+
+/*
+ Converts a predefined PaperSize to a QSizeF in millimeters (returns
+ QSizeF(0.0, 0.0) if PaperSize is Custom)
+*/
+QSizeF QPlatformPrinterSupport::convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize)
+{
+ extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size);
+ return qt_paperSizeToQSizeF(paperSize);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_PRINTER
diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.h b/src/printsupport/kernel/qplatformprintersupport_qpa.h
index 53f5900cce..5dba56579c 100644
--- a/src/printsupport/kernel/qplatformprintersupport_qpa.h
+++ b/src/printsupport/kernel/qplatformprintersupport_qpa.h
@@ -66,6 +66,9 @@ public:
virtual QList<QPrinterInfo> availablePrinters();
virtual QPrinterInfo defaultPrinter();
+ static QPrinter::PaperSize convertQSizeFToPaperSize(const QSizeF &sizef);
+ static QSizeF convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize);
+
protected:
static QPrinterInfo printerInfo(const QString &printerName, bool isDefault = false);
static void setPrinterInfoDefault(QPrinterInfo *p, bool isDefault);
diff --git a/src/printsupport/kernel/qplatformprintplugin.cpp b/src/printsupport/kernel/qplatformprintplugin.cpp
index 409de3eb4a..2c87fcc5e6 100644
--- a/src/printsupport/kernel/qplatformprintplugin.cpp
+++ b/src/printsupport/kernel/qplatformprintplugin.cpp
@@ -58,15 +58,27 @@ QPlatformPrinterSupportPlugin::~QPlatformPrinterSupportPlugin()
{
}
+/*!
+ \internal
+
+ Returns a lazily-initialized singleton. Ownership is granted to the
+ QPlatformPrinterSupportPlugin, which is never unloaded or destroyed until
+ application exit, i.e. you can expect this pointer to always be valid and
+ multiple calls to this function will always return the same pointer.
+*/
QPlatformPrinterSupport *QPlatformPrinterSupportPlugin::get()
{
- QStringList k = loader()->keys();
- if (k.isEmpty())
- return 0;
- QPlatformPrinterSupportPlugin *plugin = qobject_cast<QPlatformPrinterSupportPlugin *>(loader()->instance(k.first()));
- if (!plugin)
- return 0;
- return plugin->create(k.first());
+ static QPlatformPrinterSupport *singleton = 0;
+ if (!singleton) {
+ QStringList k = loader()->keys();
+ if (k.isEmpty())
+ return 0;
+ QPlatformPrinterSupportPlugin *plugin = qobject_cast<QPlatformPrinterSupportPlugin *>(loader()->instance(k.first()));
+ if (!plugin)
+ return 0;
+ singleton = plugin->create(k.first());
+ }
+ return singleton;
}
QT_END_NAMESPACE
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 447c535420..f56d34975d 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -58,8 +58,6 @@
#if defined (Q_WS_WIN)
#include <private/qprintengine_win_p.h>
-#elif defined (Q_WS_MAC)
-#include <private/qprintengine_mac_p.h>
#elif defined (QTOPIA_PRINTENGINE)
#include <private/qprintengine_qws_p.h>
#endif
@@ -176,11 +174,6 @@ void QPrinterPrivate::createDefaultEngines()
paintEngine = pdfEngine;
printEngine = pdfEngine;
}
-#if defined (Q_WS_MAC)
- QMacPrintEngine *macEngine = new QMacPrintEngine(printerMode);
- paintEngine = macEngine;
- printEngine = macEngine;
-#endif
}
break;
case QPrinter::PdfFormat: {
diff --git a/src/printsupport/widgets/qprintpreviewwidget.cpp b/src/printsupport/widgets/qprintpreviewwidget.cpp
index 16aea238b1..abed05292e 100644
--- a/src/printsupport/widgets/qprintpreviewwidget.cpp
+++ b/src/printsupport/widgets/qprintpreviewwidget.cpp
@@ -152,7 +152,7 @@ public:
GraphicsView(QWidget* parent = 0)
: QGraphicsView(parent)
{
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
setFrameStyle(QFrame::NoFrame);
#endif
}
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index d2dc5af070..b2a55252ac 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -174,12 +174,37 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset)
// must use typeName for resolving the type to match QSqliteDriver::record
QString typeName = QString(reinterpret_cast<const QChar *>(
sqlite3_column_decltype16(stmt, i)));
-
- int dotIdx = colName.lastIndexOf(QLatin1Char('.'));
- QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName));
-
// sqlite3_column_type is documented to have undefined behavior if the result set is empty
int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);
+
+ QVariant::Type fieldType;
+
+ if (!typeName.isEmpty()) {
+ fieldType = qGetColumnType(typeName);
+ } else {
+ // Get the proper type for the field based on stp value
+ switch (stp) {
+ case SQLITE_INTEGER:
+ fieldType = QVariant::Int;
+ break;
+ case SQLITE_FLOAT:
+ fieldType = QVariant::Double;
+ break;
+ case SQLITE_BLOB:
+ fieldType = QVariant::ByteArray;
+ break;
+ case SQLITE_TEXT:
+ fieldType = QVariant::String;
+ break;
+ case SQLITE_NULL:
+ default:
+ fieldType = QVariant::Invalid;
+ break;
+ }
+ }
+
+ int dotIdx = colName.lastIndexOf(QLatin1Char('.'));
+ QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), fieldType);
fld.setSqlType(stp);
rInf.append(fld);
}
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 571c28f515..d39df1d710 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -87,7 +87,7 @@ int QSqlTableModelPrivate::insertCount(int maxRow) const
for (;
i != e && (maxRow < 0 || i.key() <= maxRow);
++i) {
- if (i.value().op() == Insert)
+ if (i.value().insert())
++cnt;
}
@@ -122,19 +122,17 @@ void QSqlTableModelPrivate::revertCachedRow(int row)
Q_Q(QSqlTableModel);
ModifiedRow r = cache.value(row);
- // cannot revert a committed change
- if (r.submitted())
- return;
-
switch (r.op()) {
case QSqlTableModelPrivate::None:
Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map");
return;
case QSqlTableModelPrivate::Update:
case QSqlTableModelPrivate::Delete:
- cache.remove(row);
- emit q->dataChanged(q->createIndex(row, 0),
- q->createIndex(row, q->columnCount() - 1));
+ if (!r.submitted()) {
+ cache[row].revert();
+ emit q->dataChanged(q->createIndex(row, 0),
+ q->createIndex(row, q->columnCount() - 1));
+ }
break;
case QSqlTableModelPrivate::Insert: {
QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row);
@@ -201,16 +199,7 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
QSqlRecord QSqlTableModelPrivate::primaryValues(int row) const
{
- Q_Q(const QSqlTableModel);
- if (cache.value(row).op() == Insert)
- return QSqlRecord();
-
- QSqlRecord values(primaryIndex.isEmpty() ? rec : primaryIndex);
-
- for (int i = 0; i < values.count(); ++i)
- values.setValue(i, q->QSqlQueryModel::data(createIndex(row, rec.indexOf(values.fieldName(i))), Qt::EditRole));
-
- return values;
+ return cache.value(row).primaryValues(primaryIndex.isEmpty() ? rec : primaryIndex);
}
/*!
@@ -382,7 +371,7 @@ bool QSqlTableModel::select()
while (it != d->cache.constBegin()) {
--it;
// rows must be accounted for
- if (it.value().op() == QSqlTableModelPrivate::Insert) {
+ if (it.value().insert()) {
beginRemoveRows(QModelIndex(), it.key(), it.key());
it = d->cache.erase(it);
endRemoveRows();
@@ -403,6 +392,51 @@ bool QSqlTableModel::select()
}
/*!
+ \since 5.0
+
+ Refreshes \a row in the model with values from the database table row matching
+ on primary key values. Without a primary key, all column values must match. If
+ no matching row is found, the model will show an empty row.
+
+ Returns true if successful; otherwise returns false.
+
+ \sa select()
+*/
+bool QSqlTableModel::selectRow(int row)
+{
+ Q_D(QSqlTableModel);
+
+ if (row < 0 || row >= rowCount())
+ return false;
+
+ const int table_sort_col = d->sortColumn;
+ d->sortColumn = -1;
+ const QString table_filter = d->filter;
+ d->filter = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement,
+ d->tableName,
+ d->primaryValues(row),
+ false);
+ if (d->filter.startsWith(QLatin1String("WHERE "), Qt::CaseInsensitive))
+ d->filter.remove(0, 6);
+ const QString stmt = selectStatement();
+ d->sortColumn = table_sort_col;
+ d->filter = table_filter;
+
+ QSqlQuery q(d->db);
+ q.setForwardOnly(true);
+ if (!q.exec(stmt))
+ return false;
+
+ bool exists = q.next();
+ d->cache[row].refresh(exists, q.record());
+
+ emit headerDataChanged(Qt::Vertical, row, row);
+ emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1));
+
+ return true;
+}
+
+/*!
\reimp
*/
QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
@@ -411,29 +445,9 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole))
return QVariant();
- if (d->cache.contains(index.row())) {
- const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
-
- switch (d->strategy) {
- case OnFieldChange:
- case OnRowChange:
- if (row.op() == QSqlTableModelPrivate::Insert) {
- if (index.column() < 0 || index.column() >= row.rec().count())
- return QVariant();
- return row.rec().value(index.column());
- } else if (row.op() == QSqlTableModelPrivate::Update) {
- if (row.rec().isGenerated(index.column()))
- return row.rec().value(index.column());
- }
- break;
- case OnManualSubmit:
- if (row.op() == QSqlTableModelPrivate::Insert
- || (row.op() != QSqlTableModelPrivate::None
- && row.rec().isGenerated(index.column())))
- return row.rec().value(index.column());
- break;
- }
- }
+ const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(index.row());
+ if (mrow.op() != QSqlTableModelPrivate::None)
+ return mrow.rec().value(index.column());
return QSqlQueryModel::data(index, role);
}
@@ -499,18 +513,21 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in
if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
return false;
+ if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete)
+ return false;
+
if (d->strategy == OnFieldChange && d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert) {
- d->cache.clear();
+ revertAll();
} else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(index.row())) {
submit();
- d->cache.clear();
+ revertAll();
}
QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
if (row.op() == QSqlTableModelPrivate::None)
row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
- d->rec);
+ record(index.row()));
row.setValue(index.column(), value);
emit dataChanged(index, index);
@@ -648,8 +665,8 @@ bool QSqlTableModel::deleteRowFromTable(int row)
Returns false on error, detailed error information can be
obtained with lastError().
- On success the model will be repopulated. Any views
- presenting it will lose their selections.
+ In OnManualSubmit, on success the model will be repopulated.
+ Any views presenting it will lose their selections.
Note: In OnManualSubmit mode, already submitted changes won't
be cleared from the cache when submitAll() fails. This allows
@@ -662,6 +679,8 @@ bool QSqlTableModel::submitAll()
{
Q_D(QSqlTableModel);
+ bool success = true;
+
for (QSqlTableModelPrivate::CacheMap::Iterator it = d->cache.begin();
it != d->cache.constEnd(); ++it) {
if (it.value().submitted())
@@ -669,25 +688,35 @@ bool QSqlTableModel::submitAll()
switch (it.value().op()) {
case QSqlTableModelPrivate::Insert:
- if (!insertRowIntoTable(it.value().rec()))
- return false;
+ success = insertRowIntoTable(it.value().rec());
break;
case QSqlTableModelPrivate::Update:
- if (!updateRowInTable(it.key(), it.value().rec()))
- return false;
+ success = updateRowInTable(it.key(), it.value().rec());
break;
case QSqlTableModelPrivate::Delete:
- if (!deleteRowFromTable(it.key()))
- return false;
+ success = deleteRowFromTable(it.key());
break;
case QSqlTableModelPrivate::None:
Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
break;
}
- it.value().setSubmitted(true);
+
+ if (success) {
+ it.value().setSubmitted();
+ if (d->strategy != OnManualSubmit)
+ success = selectRow(it.key());
+ }
+
+ if (!success)
+ break;
+ }
+
+ if (success) {
+ if (d->strategy == OnManualSubmit)
+ success = select();
}
- return select();
+ return success;
}
/*!
@@ -704,8 +733,8 @@ bool QSqlTableModel::submitAll()
Returns true on success; otherwise returns false. Use lastError()
to query detailed error information.
- On success the model will be repopulated. Any views
- presenting it will lose their selections.
+ Does not automatically repopulate the model. Submitted rows are
+ refreshed from the database on success.
\sa revert(), revertRow(), submitAll(), revertAll(), lastError()
*/
@@ -788,8 +817,10 @@ void QSqlTableModel::revertAll()
{
Q_D(QSqlTableModel);
- while (!d->cache.isEmpty())
- revertRow(d->cache.constBegin().key());
+ const QList<int> rows(d->cache.keys());
+ for (int i = rows.size() - 1; i >= 0; --i) {
+ revertRow(rows.value(i));
+ }
}
/*!
@@ -996,15 +1027,17 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
else if (!count)
return true;
- for (int i = 0; i < count; ++i) {
- int idx = row + i;
- if (d->cache.value(idx).op() == QSqlTableModelPrivate::Insert) {
+ // Iterate backwards so we don't have to worry about removed rows causing
+ // higher cache entries to shift downwards.
+ for (int idx = row + count - 1; idx >= row; --idx) {
+ QSqlTableModelPrivate::ModifiedRow& mrow = d->cache[idx];
+ if (mrow.op() == QSqlTableModelPrivate::Insert) {
revertRow(idx);
- // Reverting a row means all the other cache entries have been adjusted downwards
- // so fake this by adjusting row
- --row;
} else {
- d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete);
+ if (mrow.op() == QSqlTableModelPrivate::None)
+ mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx));
+ else
+ mrow.setOp(QSqlTableModelPrivate::Delete);
if (d->strategy == OnManualSubmit)
emit headerDataChanged(Qt::Vertical, idx, idx);
}
@@ -1187,6 +1220,8 @@ Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
return 0;
if (d->rec.field(index.column()).isReadOnly())
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete)
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
}
@@ -1215,8 +1250,11 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values)
if (row >= rowCount())
return false;
+ if (d->cache.value(row).op() == QSqlTableModelPrivate::Delete)
+ return false;
+
if (d->strategy == OnFieldChange && d->cache.value(row).op() != QSqlTableModelPrivate::Insert)
- d->cache.clear();
+ revertAll();
else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(row))
submit();
@@ -1235,7 +1273,7 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values)
QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row];
if (mrow.op() == QSqlTableModelPrivate::None)
mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
- d->rec);
+ record(row));
Map::const_iterator i = map.constBegin();
const Map::const_iterator e = map.constEnd();
diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h
index 38e92200c7..13316bc4ed 100644
--- a/src/sql/models/qsqltablemodel.h
+++ b/src/sql/models/qsqltablemodel.h
@@ -67,6 +67,7 @@ public:
virtual ~QSqlTableModel();
virtual bool select();
+ virtual bool selectRow(int row);
virtual void setTable(const QString &tableName);
QString tableName() const;
diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h
index 0ae6b53742..323964afe8 100644
--- a/src/sql/models/qsqltablemodel_p.h
+++ b/src/sql/models/qsqltablemodel_p.h
@@ -101,25 +101,88 @@ public:
{
public:
inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord())
- : m_op(o), m_rec(r), m_submitted(false)
+ : m_op(None), m_db_values(r), m_insert(o == Insert)
+ { setOp(o); }
+ inline Op op() const { return m_op; }
+ inline void setOp(Op o)
{
- for (int i = m_rec.count() - 1; i >= 0; --i)
- m_rec.setGenerated(i, false);
+ if (o == m_op)
+ return;
+ m_submitted = (o != Insert && o != Delete);
+ m_op = o;
+ m_rec = m_db_values;
+ setGenerated(m_rec, m_op == Delete);
}
- inline Op op() const { return m_op; }
inline QSqlRecord rec() const { return m_rec; }
inline QSqlRecord& recRef() { return m_rec; }
inline void setValue(int c, const QVariant &v)
{
+ m_submitted = false;
m_rec.setValue(c, v);
m_rec.setGenerated(c, true);
}
inline bool submitted() const { return m_submitted; }
- inline void setSubmitted(bool b) { m_submitted = b; }
+ inline void setSubmitted()
+ {
+ m_submitted = true;
+ setGenerated(m_rec, false);
+ if (m_op == Delete) {
+ m_rec.clearValues();
+ }
+ else {
+ m_op = Update;
+ m_db_values = m_rec;
+ setGenerated(m_db_values, true);
+ }
+ }
+ inline void refresh(bool exists, const QSqlRecord& newvals)
+ {
+ m_submitted = true;
+ if (exists) {
+ m_op = Update;
+ m_db_values = newvals;
+ m_rec = newvals;
+ setGenerated(m_rec, false);
+ } else {
+ m_op = Delete;
+ m_rec.clear();
+ m_db_values.clear();
+ }
+ }
+ inline bool insert() const { return m_insert; }
+ inline void revert()
+ {
+ if (m_submitted)
+ return;
+ if (m_op == Delete)
+ m_op = Update;
+ m_rec = m_db_values;
+ setGenerated(m_rec, false);
+ m_submitted = true;
+ }
+ inline QSqlRecord primaryValues(const QSqlRecord& pi) const
+ {
+ if (m_op == None || m_op == Insert)
+ return QSqlRecord();
+
+ QSqlRecord values(pi);
+
+ for (int i = values.count() - 1; i >= 0; --i)
+ values.setValue(i, m_db_values.value(values.fieldName(i)));
+
+ return values;
+ }
private:
+ inline static void setGenerated(QSqlRecord& r, bool g)
+ {
+ for (int i = r.count() - 1; i >= 0; --i)
+ r.setGenerated(i, g);
+ }
Op m_op;
QSqlRecord m_rec;
+ QSqlRecord m_db_values;
bool m_submitted;
+ bool m_insert;
};
typedef QMap<int, ModifiedRow> CacheMap;
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index 897c732f45..5625bd606c 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -192,18 +192,20 @@ namespace QTest
if (!widget)
widget = QWidget::keyboardGrabber();
if (!widget) {
+ // Popup widgets stealthily steal the keyboard grab
+ if (QWidget *apw = QApplication::activePopupWidget())
+ widget = apw->focusWidget() ? apw->focusWidget() : apw;
+ }
+ if (!widget) {
QWindow *window = QGuiApplication::focusWindow();
if (window) {
sendKeyEvent(action, window, code, text, modifier, delay);
return;
}
-
- if (QWidget *apw = QApplication::activePopupWidget())
- widget = apw->focusWidget() ? apw->focusWidget() : apw;
- else
- widget = QApplication::focusWidget();
}
if (!widget)
+ widget = QApplication::focusWidget();
+ if (!widget)
widget = QApplication::activeWindow();
QTEST_ASSERT(widget);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 095b58eeaf..90b64db579 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -131,8 +131,11 @@ QApplicationPrivate *QApplicationPrivate::self = 0;
static void initSystemPalette()
{
if (!QApplicationPrivate::sys_pal)
- if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette())
+ if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette()) {
QApplicationPrivate::setSystemPalette(*themePalette);
+ QApplicationPrivate::initializeWidgetPaletteHash();
+ }
+
if (!QApplicationPrivate::sys_pal && QApplicationPrivate::app_style)
QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
}
@@ -428,11 +431,6 @@ PaletteHash *qt_app_palettes_hash()
return app_palettes();
}
-FontHash::FontHash()
-{
- QHash<QByteArray, QFont>::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts());
-}
-
Q_GLOBAL_STATIC(FontHash, app_fonts)
FontHash *qt_app_fonts_hash()
{
@@ -3124,7 +3122,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
case QEvent::ChildRemoved:
case QEvent::UpdateRequest:
case QEvent::UpdateLater:
- case QEvent::AccessibilityPrepare:
case QEvent::LocaleChange:
case QEvent::Style:
case QEvent::IconDrag:
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index ae4f0c2044..2d639172e2 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -157,10 +157,7 @@ QMacTabletHash *qt_mac_tablet_hash();
# endif
#endif
-struct FontHash : public QHash<QByteArray, QFont>
-{
- FontHash();
-};
+typedef QHash<QByteArray, QFont> FontHash;
FontHash *qt_app_fonts_hash();
typedef QHash<QByteArray, QPalette> PaletteHash;
@@ -292,6 +289,7 @@ public:
static void setSystemPalette(const QPalette &pal);
static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash);
static void initializeWidgetPaletteHash();
+ static void initializeWidgetFontHash();
static void setSystemFont(const QFont &font);
#if defined(Q_WS_X11)
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index 54c5c39396..97fc794252 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -289,8 +289,85 @@ void QApplicationPrivate::cleanupMultitouch_sys()
{
}
+static void setPossiblePalette(const QPalette *palette, const char *className)
+{
+ if (palette == 0)
+ return;
+ QApplicationPrivate::setPalette_helper(*palette, className, false);
+}
+
+
void QApplicationPrivate::initializeWidgetPaletteHash()
{
+ QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
+ if (!platformTheme)
+ return;
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "Q3Header");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPelette), "QMessageBoxLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
+ setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
+}
+
+void QApplicationPrivate::initializeWidgetFontHash()
+{
+ const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+ if (!theme)
+ return;
+ FontHash *fontHash = qt_app_fonts_hash();
+ if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
+ fontHash->insert(QByteArrayLiteral("QMenu"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
+ fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
+ fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
+ fontHash->insert(QByteArrayLiteral("QLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
+ fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
+ fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
+ fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont)) {
+ fontHash->insert(QByteArrayLiteral("QWorkspaceTitleBar"), *font);
+ fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
+ }
+ if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
+ fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
+ fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
+ fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
+ fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
+ fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont)) {
+ fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
+ fontHash->insert(QByteArrayLiteral("Q3Header"), *font);
+ }
+ if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
+ fontHash->insert(QByteArrayLiteral("QListBox"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
+ fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
+ fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
+ fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
+ if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
+ fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
}
#ifndef QT_NO_WHEELEVENT
@@ -391,6 +468,7 @@ QPlatformNativeInterface *QApplication::platformNativeInterface()
void qt_init(QApplicationPrivate *priv, int type)
{
+ Q_UNUSED(priv);
Q_UNUSED(type);
qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
@@ -398,6 +476,7 @@ void qt_init(QApplicationPrivate *priv, int type)
if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
QToolTip::setPalette(*toolTipPalette);
+ QApplicationPrivate::initializeWidgetFontHash();
qApp->setObjectName(appName);
}
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 5eee5752cc..bf864503a4 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -8390,7 +8390,6 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event)
void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
- mousePressEvent(event); // try mouse press event
}
#ifndef QT_NO_WHEELEVENT
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index a37de8547a..3d23b04ddf 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -905,16 +905,12 @@ void QWidgetPrivate::setModal_sys()
}
#ifndef QT_NO_CURSOR
-static void applyCursor(QWidget *w, const QCursor &c)
+static inline void applyCursor(QWidget *w, QCursor c)
{
- QCursor cc = c;
- QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
- int cursorCount = cursors.count();
- for (int i = 0; i < cursorCount; ++i) {
- const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
- if (cursor)
- cursor.data()->changeCursor(&cc, w->window()->windowHandle());
- }
+ if (QWindow *window = w->windowHandle())
+ if (const QScreen *screen = window->screen())
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ cursor->changeCursor(&c, window);
}
void qt_qpa_set_cursor(QWidget *w, bool force)
diff --git a/src/widgets/statemachine/qguistatemachine.cpp b/src/widgets/statemachine/qguistatemachine.cpp
index 465da1e2ba..7c8de05466 100644
--- a/src/widgets/statemachine/qguistatemachine.cpp
+++ b/src/widgets/statemachine/qguistatemachine.cpp
@@ -181,8 +181,6 @@ static QEvent *cloneEvent(QEvent *e)
#endif
case QEvent::InputMethod:
return new QInputMethodEvent(*static_cast<QInputMethodEvent*>(e));
- case QEvent::AccessibilityPrepare:
- return new QEvent(*e);
case QEvent::LocaleChange:
return new QEvent(*e);
case QEvent::LanguageChange:
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index a07ab73ad0..5adb2f1c95 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -2631,8 +2631,6 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
- fallbackToSizeHints = false;
-
if (_ver_struct_list != 0) {
QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
ver_struct_list.resize(3);
diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h
index 17078f3709..10eb0da651 100644
--- a/src/widgets/widgets/qdockarealayout_p.h
+++ b/src/widgets/widgets/qdockarealayout_p.h
@@ -232,7 +232,7 @@ public:
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
int sep; // separator extent
- bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the central widget is set)
+ bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the separator is moved by user)
mutable QVector<QWidget*> separatorWidgets;
bool isValid() const;
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index c67881e652..ff05503540 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1351,6 +1351,8 @@ bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
if (movingSeparator.isEmpty())
return false;
+ layoutState.dockAreaLayout.fallbackToSizeHints = false;
+
savedState = layoutState;
movingSeparatorPos = movingSeparatorOrigin = pos;
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index b42fedf0be..af75d6b8aa 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -2260,7 +2260,7 @@ QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags)
d->updateGeometryConstraints();
setAttribute(Qt::WA_Resized, false);
d->titleBarPalette = d->desktopPalette();
- d->font = QApplication::font("QWorkspaceTitleBar");
+ d->font = QApplication::font("QMdiSubWindowTitleBar");
// We don't want the menu icon by default on mac.
#ifndef Q_WS_MAC
if (windowIcon().isNull())
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 3fb2a6122c..fd030a5383 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1075,7 +1075,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
if (action_e == QAction::Hover) {
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
- int actionIndex = indexOf(action) + 1;
+ int actionIndex = indexOf(action);
QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, q, actionIndex));
QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, q, actionIndex));
}
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 11f6592cc9..0efa6caebc 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -531,7 +531,6 @@ void QMenuBarPrivate::_q_actionHovered()
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
int actionIndex = actions.indexOf(action);
- ++actionIndex;
QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, q, actionIndex));
QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, q, actionIndex));
}
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index ca94854d11..ce25a22847 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -1183,8 +1183,8 @@ void QTabBar::setCurrentIndex(int index)
d->layoutTab(index);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
- QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, index + 1));
- QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, this, index + 1));
+ QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, index));
+ QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, this, index));
}
#endif
emit currentChanged(index);
diff --git a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp
index 534dec8160..05d1569988 100644
--- a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp
+++ b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp
@@ -123,6 +123,7 @@ private slots:
void deletedInUpdateCurrentTime();
void totalDuration();
void zeroLoopCount();
+ void recursiveAnimations();
};
void tst_QPropertyAnimation::initTestCase()
@@ -1237,5 +1238,49 @@ void tst_QPropertyAnimation::zeroLoopCount()
QCOMPARE(finishedSpy.count(), 0);
}
+
+class RecursiveObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+public:
+ RecursiveObject() : m_x(0), m_y(0) {
+ animation.setTargetObject(this);
+ animation.setPropertyName("y");
+ animation.setDuration(30);
+ }
+ qreal x() const { return m_x; }
+ void setX(qreal x) {
+ m_x = x;
+ animation.setEndValue(x);
+ animation.start();
+ }
+ qreal y() const { return m_y; }
+ void setY(qreal y) { m_y = y; }
+
+ qreal m_x;
+ qreal m_y;
+ QPropertyAnimation animation;
+};
+
+
+void tst_QPropertyAnimation::recursiveAnimations()
+{
+ RecursiveObject o;
+ QPropertyAnimation anim;
+ anim.setTargetObject(&o);
+ anim.setPropertyName("x");
+ anim.setDuration(30);
+
+ anim.setEndValue(4000);
+ anim.start();
+ QTest::qWait(anim.duration() + o.animation.duration());
+ QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped);
+ QTRY_COMPARE(o.animation.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(o.y(), qreal(4000));
+}
+
+
QTEST_MAIN(tst_QPropertyAnimation)
#include "tst_qpropertyanimation.moc"
diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro
index 9de476fe13..1772f4b65f 100644
--- a/tests/auto/corelib/io/qsettings/qsettings.pro
+++ b/tests/auto/corelib/io/qsettings/qsettings.pro
@@ -5,5 +5,3 @@ SOURCES = tst_qsettings.cpp
RESOURCES += qsettings.qrc
win32-msvc*:LIBS += advapi32.lib
-
-win32: CONFIG += insignificant_test # QTBUG-24145
diff --git a/tests/auto/corelib/json/test.bjson b/tests/auto/corelib/json/test.bjson
index aa412eec67..9a0515f3ef 100644
--- a/tests/auto/corelib/json/test.bjson
+++ b/tests/auto/corelib/json/test.bjson
Binary files differ
diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp
index f5b4f17732..f35831c900 100644
--- a/tests/auto/corelib/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/json/tst_qtjson.cpp
@@ -115,6 +115,8 @@ private Q_SLOTS:
void testCompaction();
void testDebugStream();
void testCompactionError();
+
+ void parseUnicodeEscapes();
private:
QString testDataDir;
};
@@ -1758,5 +1760,19 @@ void TestQtJson::testCompactionError()
}
}
+void TestQtJson::parseUnicodeEscapes()
+{
+ const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]";
+
+ QJsonDocument doc = QJsonDocument::fromJson(json);
+ QJsonArray array = doc.array();
+
+ QString result = QLatin1String("A");
+ result += QChar(0xe4);
+ result += QChar(0xc4);
+
+ QCOMPARE(array.first().toString(), result);
+}
+
QTEST_MAIN(TestQtJson)
#include "tst_qtjson.moc"
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index 63adcadb86..9076f37c7c 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -207,6 +207,7 @@ void tst_QMimeDatabase::mimeTypeForFileName_data()
QTest::newRow("directory") << "/" << "inode/directory";
QTest::newRow("doesn't exist, no extension") << "IDontExist" << "application/octet-stream";
QTest::newRow("doesn't exist but has known extension") << "IDontExist.txt" << "text/plain";
+ QTest::newRow("empty") << "" << "application/octet-stream";
}
static inline QByteArray msgMimeTypeForFileNameFailed(const QList<QMimeType> &actual,
diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/tools/qregularexpression/.gitignore
new file mode 100644
index 0000000000..c9249e090e
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/.gitignore
@@ -0,0 +1,2 @@
+tst_qregularexpression_alwaysoptimize
+tst_qregularexpression_defaultoptimize
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
new file mode 100644
index 0000000000..f48b1ee96a
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qregularexpression_alwaysoptimize
+QT = core testlib
+HEADERS = ../tst_qregularexpression.h
+SOURCES = \
+ tst_qregularexpression_alwaysoptimize.cpp \
+ ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp
new file mode 100644
index 0000000000..9190f183a1
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include "../tst_qregularexpression.h"
+
+class tst_QRegularExpression_AlwaysOptimize : public tst_QRegularExpression
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+};
+
+QT_BEGIN_NAMESPACE
+extern Q_CORE_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count; // from qregularexpression.cpp
+QT_END_NAMESPACE
+
+void tst_QRegularExpression_AlwaysOptimize::initTestCase()
+{
+ qt_qregularexpression_optimize_after_use_count = 1;
+}
+
+QTEST_APPLESS_MAIN(tst_QRegularExpression_AlwaysOptimize)
+
+#include "tst_qregularexpression_alwaysoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
new file mode 100644
index 0000000000..dd1a90cfbc
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qregularexpression_defaultoptimize
+QT = core testlib
+HEADERS = ../tst_qregularexpression.h
+SOURCES = \
+ tst_qregularexpression_defaultoptimize.cpp \
+ ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp
new file mode 100644
index 0000000000..d0b5bee4b7
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include "../tst_qregularexpression.h"
+
+class tst_QRegularExpression_DefaultOptimize : public tst_QRegularExpression
+{
+ Q_OBJECT
+};
+
+QTEST_APPLESS_MAIN(tst_QRegularExpression_DefaultOptimize)
+
+#include "tst_qregularexpression_defaultoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
new file mode 100644
index 0000000000..0cae10112f
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = defaultoptimize
+contains(QT_CONFIG,private_tests):SUBDIRS += alwaysoptimize
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
new file mode 100644
index 0000000000..72157c0536
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
@@ -0,0 +1,1198 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qstring.h>
+#include <qlist.h>
+#include <qstringlist.h>
+#include <qhash.h>
+
+#include "tst_qregularexpression.h"
+
+struct Match
+{
+ Match()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ isValid = false;
+ hasMatch = false;
+ hasPartialMatch = false;
+ captured.clear();
+ namedCaptured.clear();
+ }
+
+ bool isValid;
+ bool hasMatch;
+ bool hasPartialMatch;
+ QStringList captured;
+ QHash<QString, QString> namedCaptured;
+};
+
+Q_DECLARE_METATYPE(Match)
+Q_DECLARE_METATYPE(QList<Match>)
+
+bool operator==(const QRegularExpressionMatch &rem, const Match &m)
+{
+ if (rem.isValid() != m.isValid)
+ return false;
+ if (!rem.isValid())
+ return true;
+ if ((rem.hasMatch() != m.hasMatch) || (rem.hasPartialMatch() != m.hasPartialMatch))
+ return false;
+ if (rem.hasMatch() || rem.hasPartialMatch()) {
+ if (rem.lastCapturedIndex() != (m.captured.size() - 1))
+ return false;
+ for (int i = 0; i <= rem.lastCapturedIndex(); ++i) {
+ QString remCaptured = rem.captured(i);
+ QString mCaptured = m.captured.at(i);
+ if (remCaptured != mCaptured
+ || remCaptured.isNull() != mCaptured.isNull()
+ || remCaptured.isEmpty() != mCaptured.isEmpty()) {
+ return false;
+ }
+ }
+
+ Q_FOREACH (const QString &name, m.namedCaptured.keys()) {
+ if (rem.captured(name) != m.namedCaptured.value(name))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool operator==(const Match &m, const QRegularExpressionMatch &rem)
+{
+ return operator==(rem, m);
+}
+
+bool operator!=(const QRegularExpressionMatch &rem, const Match &m)
+{
+ return !operator==(rem, m);
+}
+
+bool operator!=(const Match &m, const QRegularExpressionMatch &rem)
+{
+ return !operator==(m, rem);
+}
+
+
+bool operator==(const QRegularExpressionMatchIterator &iterator, const QList<Match> &expectedMatchList)
+{
+ QRegularExpressionMatchIterator i = iterator;
+ if (i.isValid() != (!expectedMatchList.isEmpty()))
+ return false;
+
+ foreach (const Match &expectedMatch, expectedMatchList)
+ {
+ if (!i.hasNext())
+ return false;
+
+ QRegularExpressionMatch match = i.next();
+ if (match != expectedMatch)
+ return false;
+ }
+
+ if (i.hasNext())
+ return false;
+
+ return true;
+}
+
+bool operator==(const QList<Match> &expectedMatchList, const QRegularExpressionMatchIterator &iterator)
+{
+ return operator==(iterator, expectedMatchList);
+}
+
+bool operator!=(const QRegularExpressionMatchIterator &iterator, const QList<Match> &expectedMatchList)
+{
+ return !operator==(iterator, expectedMatchList);
+}
+
+bool operator!=(const QList<Match> &expectedMatchList, const QRegularExpressionMatchIterator &iterator)
+{
+ return !operator==(expectedMatchList, iterator);
+}
+
+void consistencyCheck(const QRegularExpressionMatch &match)
+{
+ if (match.isValid()) {
+ QVERIFY(match.regularExpression().isValid());
+ QVERIFY(!(match.hasMatch() && match.hasPartialMatch()));
+
+ if (match.hasMatch() || match.hasPartialMatch()) {
+ QVERIFY(match.lastCapturedIndex() >= 0);
+ if (match.hasPartialMatch())
+ QVERIFY(match.lastCapturedIndex() == 0);
+
+ for (int i = 0; i <= match.lastCapturedIndex(); ++i) {
+ int startPos = match.capturedStart(i);
+ int endPos = match.capturedEnd(i);
+ int length = match.capturedLength(i);
+ QString captured = match.captured(i);
+ QStringRef capturedRef = match.capturedRef(i);
+
+ if (!captured.isNull()) {
+ QVERIFY(startPos >= 0);
+ QVERIFY(endPos >= 0);
+ QVERIFY(length >= 0);
+ QVERIFY(endPos >= startPos);
+ QVERIFY((endPos - startPos) == length);
+ QVERIFY(captured == capturedRef);
+ } else {
+ QVERIFY(startPos == -1);
+ QVERIFY(endPos == -1);
+ QVERIFY((endPos - startPos) == length);
+ QVERIFY(capturedRef.isNull());
+ }
+ }
+ }
+ } else {
+ QVERIFY(!match.hasMatch());
+ QVERIFY(!match.hasPartialMatch());
+ QVERIFY(match.captured(0).isNull());
+ QVERIFY(match.capturedStart(0) == -1);
+ QVERIFY(match.capturedEnd(0) == -1);
+ QVERIFY(match.capturedLength(0) == 0);
+ }
+}
+
+void consistencyCheck(const QRegularExpressionMatchIterator &iterator)
+{
+ QRegularExpressionMatchIterator i(iterator); // make a copy, we modify it
+ if (i.isValid()) {
+ while (i.hasNext()) {
+ QRegularExpressionMatch peeked = i.peekNext();
+ QRegularExpressionMatch match = i.next();
+ consistencyCheck(peeked);
+ consistencyCheck(match);
+ QVERIFY(match.isValid());
+ QVERIFY(match.hasMatch() || match.hasPartialMatch());
+ QCOMPARE(i.regularExpression(), match.regularExpression());
+ QCOMPARE(i.matchOptions(), match.matchOptions());
+ QCOMPARE(i.matchType(), match.matchType());
+
+ QVERIFY(peeked.isValid() == match.isValid());
+ QVERIFY(peeked.hasMatch() == match.hasMatch());
+ QVERIFY(peeked.hasPartialMatch() == match.hasPartialMatch());
+ QVERIFY(peeked.lastCapturedIndex() == match.lastCapturedIndex());
+ for (int i = 0; i <= peeked.lastCapturedIndex(); ++i) {
+ QVERIFY(peeked.captured(i) == match.captured(i));
+ QVERIFY(peeked.capturedStart(i) == match.capturedStart(i));
+ QVERIFY(peeked.capturedEnd(i) == match.capturedEnd(i));
+ }
+ }
+ } else {
+ QVERIFY(!i.hasNext());
+ QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionMatchIterator::peekNext() called on an iterator already at end");
+ QRegularExpressionMatch peeked = i.peekNext();
+ QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionMatchIterator::next() called on an iterator already at end");
+ QRegularExpressionMatch match = i.next();
+ consistencyCheck(peeked);
+ consistencyCheck(match);
+ QVERIFY(!match.isValid());
+ QVERIFY(!peeked.isValid());
+ }
+
+}
+
+void tst_QRegularExpression::provideRegularExpressions()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QRegularExpression::PatternOptions>("patternOptions");
+
+ QTest::newRow("emptynull01") << QString()
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("emptynull02") << QString()
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption
+ | QRegularExpression::DotMatchesEverythingOption
+ | QRegularExpression::MultilineOption);
+ QTest::newRow("emptynull03") << ""
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("emptynull04") << ""
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption
+ | QRegularExpression::DotMatchesEverythingOption
+ | QRegularExpression::MultilineOption);
+
+ QTest::newRow("regexp01") << "a pattern"
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("regexp02") << "^a (.*) more complicated(?<P>pattern)$"
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("regexp03") << "(?:a) pAttErN"
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption);
+ QTest::newRow("regexp04") << "a\nmultiline\npattern"
+ << QRegularExpression::PatternOptions(QRegularExpression::MultilineOption);
+ QTest::newRow("regexp05") << "an extended # IGNOREME\npattern"
+ << QRegularExpression::PatternOptions(QRegularExpression::ExtendedPatternSyntaxOption);
+ QTest::newRow("regexp06") << "a [sS]ingleline .* match"
+ << QRegularExpression::PatternOptions(QRegularExpression::DotMatchesEverythingOption);
+ QTest::newRow("regexp07") << "multiple.*options"
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption
+ | QRegularExpression::DotMatchesEverythingOption
+ | QRegularExpression::MultilineOption
+ | QRegularExpression::DontCaptureOption
+ | QRegularExpression::InvertedGreedinessOption);
+
+ QTest::newRow("unicode01") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$")
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("unicode02") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$")
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption
+ | QRegularExpression::DotMatchesEverythingOption
+ | QRegularExpression::InvertedGreedinessOption);
+ QTest::newRow("unicode03") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f")
+ << QRegularExpression::PatternOptions(0);
+ QTest::newRow("unicode04") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f")
+ << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption
+ | QRegularExpression::DotMatchesEverythingOption
+ | QRegularExpression::InvertedGreedinessOption);
+}
+
+void tst_QRegularExpression::gettersSetters_data()
+{
+ provideRegularExpressions();
+}
+
+void tst_QRegularExpression::gettersSetters()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QRegularExpression::PatternOptions, patternOptions);
+ {
+ QRegularExpression re;
+ re.setPattern(pattern);
+ QCOMPARE(re.pattern(), pattern);
+ QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
+ }
+ {
+ QRegularExpression re;
+ re.setPatternOptions(patternOptions);
+ QCOMPARE(re.pattern(), QString());
+ QCOMPARE(re.patternOptions(), patternOptions);
+ }
+ {
+ QRegularExpression re(pattern);
+ QCOMPARE(re.pattern(), pattern);
+ QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
+ }
+ {
+ QRegularExpression re(pattern, patternOptions);
+ QCOMPARE(re.pattern(), pattern);
+ QCOMPARE(re.patternOptions(), patternOptions);
+ }
+}
+
+void tst_QRegularExpression::escape_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<QString>("escaped");
+ QTest::newRow("escape01") << "a normal pattern"
+ << "a\\ normal\\ pattern";
+
+ QTest::newRow("escape02") << "abcdefghijklmnopqrstuvzABCDEFGHIJKLMNOPQRSTUVZ1234567890_"
+ << "abcdefghijklmnopqrstuvzABCDEFGHIJKLMNOPQRSTUVZ1234567890_";
+
+ QTest::newRow("escape03") << "^\\ba\\b.*(?<NAME>reg|exp)$"
+ << "\\^\\\\ba\\\\b\\.\\*\\(\\?\\<NAME\\>reg\\|exp\\)\\$";
+
+ QString nulString("abcXabcXXabc");
+ nulString[3] = nulString[7] = nulString[8] = QChar(0, 0);
+ QTest::newRow("NUL") << nulString
+ << "abc\\0abc\\0\\0abc";
+
+ QTest::newRow("unicode01") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$")
+ << QString::fromUtf8("\\^s\\[ome\\]\\ latin\\-1\\ \\\xc3\x80\\\xc3\x88\\\xc3\x8c\\\xc3\x92\\\xc3\x99\\ chars\\$");
+ QTest::newRow("unicode02") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f")
+ << QString::fromUtf8("Unicode\\ \\\xf0\x9d\x85\x9d\\ \\\xf0\x9d\x85\x9e\\\xf0\x9d\x85\x9f");
+
+ QString unicodeAndNulString = QString::fromUtf8("^\xc3\x80\xc3\x88\xc3\x8cN\xc3\x92NN\xc3\x99 chars$");
+ unicodeAndNulString[4] = unicodeAndNulString[6] = unicodeAndNulString[7] = QChar(0, 0);
+ QTest::newRow("unicode03") << unicodeAndNulString
+ << QString::fromUtf8("\\^\\\xc3\x80\\\xc3\x88\\\xc3\x8c\\0\\\xc3\x92\\0\\0\\\xc3\x99\\ chars\\$");
+}
+
+void tst_QRegularExpression::escape()
+{
+ QFETCH(QString, string);
+ QFETCH(QString, escaped);
+ QCOMPARE(QRegularExpression::escape(string), escaped);
+ QRegularExpression re(escaped);
+ QCOMPARE(re.isValid(), true);
+}
+
+void tst_QRegularExpression::validity_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<bool>("validity");
+
+ QTest::newRow("valid01") << "a pattern" << true;
+ QTest::newRow("valid02") << "(a|pattern)" << true;
+ QTest::newRow("valid03") << "a [pP]attern" << true;
+ QTest::newRow("valid04") << "^(?<article>a).*(?<noun>pattern)$" << true;
+ QTest::newRow("valid05") << "a \\P{Ll}attern" << true;
+
+ QTest::newRow("invalid01") << "a pattern\\" << false;
+ QTest::newRow("invalid02") << "(a|pattern" << false;
+ QTest::newRow("invalid03") << "a \\P{BLAH}attern" << false;
+
+ QString pattern;
+ // 0xD800 (high surrogate) not followed by a low surrogate
+ pattern = "abcdef";
+ pattern[3] = QChar(0x00, 0xD8);
+ QTest::newRow("invalidUnicode01") << pattern << false;
+}
+
+void tst_QRegularExpression::validity()
+{
+ QFETCH(QString, pattern);
+ QFETCH(bool, validity);
+ QRegularExpression re(pattern);
+ QCOMPARE(re.isValid(), validity);
+ if (!validity)
+ QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
+ QRegularExpressionMatch match = re.match("a pattern");
+ QCOMPARE(match.isValid(), validity);
+ consistencyCheck(match);
+
+ if (!validity)
+ QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
+ QRegularExpressionMatchIterator iterator = re.globalMatch("a pattern");
+ QCOMPARE(iterator.isValid(), validity);
+}
+
+void tst_QRegularExpression::patternOptions_data()
+{
+ QTest::addColumn<QRegularExpression>("regexp");
+ QTest::addColumn<QString>("subject");
+ QTest::addColumn<Match>("match");
+
+ // none of these would successfully match if the respective
+ // pattern option is not set
+
+ Match m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << QString::fromUtf8("AbC\xc3\xa0");
+ QTest::newRow("/i") << QRegularExpression(QString::fromUtf8("abc\xc3\x80"), QRegularExpression::CaseInsensitiveOption)
+ << QString::fromUtf8("AbC\xc3\xa0")
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "abc123\n678def";
+ QTest::newRow("/s") << QRegularExpression("\\Aabc.*def\\z", QRegularExpression::DotMatchesEverythingOption)
+ << "abc123\n678def"
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "jumped over";
+ QTest::newRow("/m") << QRegularExpression("^\\w+ \\w+$", QRegularExpression::MultilineOption)
+ << "the quick fox\njumped over\nthe lazy\ndog"
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "abc 123456";
+ QTest::newRow("/x") << QRegularExpression("\\w+ # a word\n"
+ "\\ # a space\n"
+ "\\w+ # another word",
+ QRegularExpression::ExtendedPatternSyntaxOption)
+ << "abc 123456 def"
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "the quick fox" << "the" << "quick fox";
+ QTest::newRow("/U") << QRegularExpression("(.+) (.+?)", QRegularExpression::InvertedGreedinessOption)
+ << "the quick fox"
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "the quick fox" << "quick";
+ m.namedCaptured["named"] = "quick";
+ QTest::newRow("no cap") << QRegularExpression("(\\w+) (?<named>\\w+) (\\w+)", QRegularExpression::DontCaptureOption)
+ << "the quick fox"
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << QString::fromUtf8("abc\xc3\x80\xc3\xa0 12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98")
+ << QString::fromUtf8("abc\xc3\x80\xc3\xa0")
+ << QString::fromUtf8("12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98");
+ QTest::newRow("unicode properties") << QRegularExpression("(\\w+) (\\d+)", QRegularExpression::UseUnicodePropertiesOption)
+ << QString::fromUtf8("abc\xc3\x80\xc3\xa0 12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98")
+ << m;
+}
+
+void tst_QRegularExpression::patternOptions()
+{
+ QFETCH(QRegularExpression, regexp);
+ QFETCH(QString, subject);
+ QFETCH(Match, match);
+
+ QRegularExpressionMatch m = regexp.match(subject);
+ consistencyCheck(m);
+ QVERIFY(m == match);
+}
+
+void tst_QRegularExpression::normalMatch_data()
+{
+ QTest::addColumn<QRegularExpression>("regexp");
+ QTest::addColumn<QString>("subject");
+ QTest::addColumn<int>("offset");
+ QTest::addColumn<QRegularExpression::MatchOptions>("matchOptions");
+ QTest::addColumn<Match>("match");
+
+ Match m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "string" << "string";
+ QTest::newRow("match01") << QRegularExpression("(\\bstring\\b)")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "a string" << "a" << "string";
+ QTest::newRow("match02") << QRegularExpression("(\\w+) (\\w+)")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "a string" << "a" << "string";
+ m.namedCaptured["article"] = "a";
+ m.namedCaptured["noun"] = "string";
+ QTest::newRow("match03") << QRegularExpression("(?<article>\\w+) (?<noun>\\w+)")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << " string" << QString() << "string";
+ QTest::newRow("match04") << QRegularExpression("(\\w+)? (\\w+)")
+ << " string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << " string" << QString("") << "string";
+ QTest::newRow("match05") << QRegularExpression("(\\w*) (\\w+)")
+ << " string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "c123def" << "c12" << "3" << "def";
+ QTest::newRow("match06") << QRegularExpression("(\\w*)(\\d+)(\\w*)")
+ << "abc123def"
+ << 2
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << QString("");
+ QTest::newRow("match07") << QRegularExpression("\\w*")
+ << "abc123def"
+ << 9
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << QString("a string") << QString("a string") << QString("");
+ QTest::newRow("match08") << QRegularExpression("(.*)(.*)")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << QString("a string") << QString("") << QString("a string");
+ QTest::newRow("match09") << QRegularExpression("(.*?)(.*)")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ // ***
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch01") << QRegularExpression("\\d+")
+ << "a string"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch02") << QRegularExpression("(\\w+) (\\w+)")
+ << "a string"
+ << 1
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch03") << QRegularExpression("\\w+")
+ << "abc123def"
+ << 9
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ // ***
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("anchoredmatch01") << QRegularExpression("\\d+")
+ << "abc123def"
+ << 0
+ << QRegularExpression::MatchOptions(QRegularExpression::AnchoredMatchOption)
+ << m;
+}
+
+
+void tst_QRegularExpression::normalMatch()
+{
+ QFETCH(QRegularExpression, regexp);
+ QFETCH(QString, subject);
+ QFETCH(int, offset);
+ QFETCH(QRegularExpression::MatchOptions, matchOptions);
+ QFETCH(Match, match);
+
+ QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NormalMatch, matchOptions);
+ consistencyCheck(m);
+ QVERIFY(m == match);
+}
+
+
+void tst_QRegularExpression::partialMatch_data()
+{
+ QTest::addColumn<QRegularExpression>("regexp");
+ QTest::addColumn<QString>("subject");
+ QTest::addColumn<int>("offset");
+ QTest::addColumn<QRegularExpression::MatchType>("matchType");
+ QTest::addColumn<QRegularExpression::MatchOptions>("matchOptions");
+ QTest::addColumn<Match>("match");
+
+ Match m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "str";
+ QTest::newRow("softmatch01") << QRegularExpression("string")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << " str";
+ QTest::newRow("softmatch02") << QRegularExpression("\\bstring\\b")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << " str";
+ QTest::newRow("softmatch03") << QRegularExpression("(\\bstring\\b)")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "8 Dec 19";
+ QTest::newRow("softmatch04") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$")
+ << "8 Dec 19"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "8 Dec 1985" << "8" << "Dec" << "1985";
+ QTest::newRow("softmatch05") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$")
+ << "8 Dec 1985"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured << "def";
+ QTest::newRow("softmatch06") << QRegularExpression("abc\\w+X|def")
+ << "abcdef"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "abcdef";
+ QTest::newRow("softmatch07") << QRegularExpression("abc\\w+X|defY")
+ << "abcdef"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "def";
+ QTest::newRow("softmatch08") << QRegularExpression("abc\\w+X|defY")
+ << "abcdef"
+ << 1
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ // ***
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "str";
+ QTest::newRow("hardmatch01") << QRegularExpression("string")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << " str";
+ QTest::newRow("hardmatch02") << QRegularExpression("\\bstring\\b")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << " str";
+ QTest::newRow("hardmatch03") << QRegularExpression("(\\bstring\\b)")
+ << "a str"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "8 Dec 19";
+ QTest::newRow("hardmatch04") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$")
+ << "8 Dec 19"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "8 Dec 1985";
+ QTest::newRow("hardmatch05") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$")
+ << "8 Dec 1985"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "abcdef";
+ QTest::newRow("hardmatch06") << QRegularExpression("abc\\w+X|def")
+ << "abcdef"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "abcdef";
+ QTest::newRow("hardmatch07") << QRegularExpression("abc\\w+X|defY")
+ << "abcdef"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "def";
+ QTest::newRow("hardmatch08") << QRegularExpression("abc\\w+X|defY")
+ << "abcdef"
+ << 1
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "ab";
+ QTest::newRow("hardmatch09") << QRegularExpression("abc|ab")
+ << "ab"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "abc";
+ QTest::newRow("hardmatch10") << QRegularExpression("abc(def)?")
+ << "abc"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true; m.hasPartialMatch = true;
+ m.captured << "abc";
+ QTest::newRow("hardmatch11") << QRegularExpression("(abc)*")
+ << "abc"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+
+ // ***
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch01") << QRegularExpression("abc\\w+X|defY")
+ << "123456"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch02") << QRegularExpression("abc\\w+X|defY")
+ << "123456"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch03") << QRegularExpression("abc\\w+X|defY")
+ << "ab123"
+ << 0
+ << QRegularExpression::PartialPreferCompleteMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+ m.clear();
+ m.isValid = true;
+ QTest::newRow("nomatch04") << QRegularExpression("abc\\w+X|defY")
+ << "ab123"
+ << 0
+ << QRegularExpression::PartialPreferFirstMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << m;
+
+}
+
+void tst_QRegularExpression::partialMatch()
+{
+ QFETCH(QRegularExpression, regexp);
+ QFETCH(QString, subject);
+ QFETCH(int, offset);
+ QFETCH(QRegularExpression::MatchType, matchType);
+ QFETCH(QRegularExpression::MatchOptions, matchOptions);
+ QFETCH(Match, match);
+
+ QRegularExpressionMatch m = regexp.match(subject, offset, matchType, matchOptions);
+ consistencyCheck(m);
+ QVERIFY(m == match);
+}
+
+void tst_QRegularExpression::globalMatch_data()
+{
+ QTest::addColumn<QRegularExpression>("regexp");
+ QTest::addColumn<QString>("subject");
+ QTest::addColumn<int>("offset");
+ QTest::addColumn<QRegularExpression::MatchType>("matchType");
+ QTest::addColumn<QRegularExpression::MatchOptions>("matchOptions");
+ QTest::addColumn<QList<Match> >("matchList");
+
+ QList<Match> matchList;
+ Match m;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ QTest::newRow("globalmatch01") << QRegularExpression("\\w+")
+ << "the quick fox"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the" << "t" << "he";
+ matchList << m;
+ m.captured = QStringList() << "quick" << "q" << "uick";
+ matchList << m;
+ m.captured = QStringList() << "fox" << "f" << "ox";
+ matchList << m;
+ QTest::newRow("globalmatch02") << QRegularExpression("(\\w+?)(\\w+)")
+ << "the quick fox"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "c";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "c";
+ matchList << m;
+ m.captured = QStringList() << "aabb";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures01") << QRegularExpression("a*b*|c")
+ << "ccaabbd"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures02") << QRegularExpression(".*")
+ << "the\nquick\nfox"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures03") << QRegularExpression(".*")
+ << "the\nquick\nfox\n"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures04") << QRegularExpression("(*CRLF).*")
+ << "the\r\nquick\r\nfox"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures05") << QRegularExpression("(*CRLF).*")
+ << "the\r\nquick\r\nfox\r\n"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+
+ matchList.clear();
+ m.clear();
+ m.isValid = true; m.hasMatch = true;
+ m.captured = QStringList() << "the";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "quick";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "fox";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+ m.captured = QStringList() << "jumped";
+ matchList << m;
+ m.captured = QStringList() << "";
+ matchList << m;
+
+ QTest::newRow("globalmatch_emptycaptures06") << QRegularExpression("(*ANYCRLF).*")
+ << "the\r\nquick\nfox\rjumped"
+ << 0
+ << QRegularExpression::NormalMatch
+ << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption)
+ << matchList;
+}
+
+void tst_QRegularExpression::globalMatch()
+{
+ QFETCH(QRegularExpression, regexp);
+ QFETCH(QString, subject);
+ QFETCH(int, offset);
+ QFETCH(QRegularExpression::MatchType, matchType);
+ QFETCH(QRegularExpression::MatchOptions, matchOptions);
+ QFETCH(QList<Match>, matchList);
+
+ QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, matchType, matchOptions);
+ consistencyCheck(iterator);
+ QVERIFY(iterator == matchList);
+}
+
+void tst_QRegularExpression::serialize_data()
+{
+ provideRegularExpressions();
+}
+
+void tst_QRegularExpression::serialize()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QRegularExpression::PatternOptions, patternOptions);
+ QRegularExpression outRe(pattern, patternOptions);
+ QByteArray buffer;
+ {
+ QDataStream out(&buffer, QIODevice::WriteOnly);
+ out << outRe;
+ }
+ QRegularExpression inRe;
+ {
+ QDataStream in(&buffer, QIODevice::ReadOnly);
+ in >> inRe;
+ }
+ QCOMPARE(inRe, outRe);
+}
+
+static void verifyEquality(const QRegularExpression &re1, const QRegularExpression &re2)
+{
+ QVERIFY(re1 == re2);
+ QVERIFY(re2 == re1);
+ QVERIFY(!(re1 != re2));
+ QVERIFY(!(re2 != re1));
+
+ QRegularExpression re3(re1);
+
+ QVERIFY(re1 == re3);
+ QVERIFY(re3 == re1);
+ QVERIFY(!(re1 != re3));
+ QVERIFY(!(re3 != re1));
+
+ QVERIFY(re2 == re3);
+ QVERIFY(re3 == re2);
+ QVERIFY(!(re2 != re3));
+ QVERIFY(!(re3 != re2));
+
+ re3 = re2;
+ QVERIFY(re1 == re3);
+ QVERIFY(re3 == re1);
+ QVERIFY(!(re1 != re3));
+ QVERIFY(!(re3 != re1));
+
+ QVERIFY(re2 == re3);
+ QVERIFY(re3 == re2);
+ QVERIFY(!(re2 != re3));
+ QVERIFY(!(re3 != re2));
+}
+
+void tst_QRegularExpression::operatoreq_data()
+{
+ provideRegularExpressions();
+}
+
+void tst_QRegularExpression::operatoreq()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QRegularExpression::PatternOptions, patternOptions);
+ {
+ QRegularExpression re1(pattern);
+ QRegularExpression re2(pattern);
+ verifyEquality(re1, re2);
+ }
+ {
+ QRegularExpression re1(QString(), patternOptions);
+ QRegularExpression re2(QString(), patternOptions);
+ verifyEquality(re1, re2);
+ }
+ {
+ QRegularExpression re1(pattern, patternOptions);
+ QRegularExpression re2(pattern, patternOptions);
+ verifyEquality(re1, re2);
+ }
+}
+
+void tst_QRegularExpression::captureCount_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<int>("captureCount");
+ QTest::newRow("captureCount01") << "a pattern" << 0;
+ QTest::newRow("captureCount02") << "a.*pattern" << 0;
+ QTest::newRow("captureCount03") << "(a) pattern" << 1;
+ QTest::newRow("captureCount04") << "(a).*(pattern)" << 2;
+ QTest::newRow("captureCount05") << "^(?<article>\\w+) (?<noun>\\w+)$" << 2;
+ QTest::newRow("captureCount06") << "^(\\w+) (?<word>\\w+) (.)$" << 3;
+ QTest::newRow("captureCount07") << "(?:non capturing) (capturing) (?<n>named) (?:non (capturing))" << 3;
+ QTest::newRow("captureCount08") << "(?|(a)(b)|(c)(d))" << 2;
+ QTest::newRow("captureCount09") << "(?|(a)(b)|(c)(d)(?:e))" << 2;
+ QTest::newRow("captureCount10") << "(?|(a)(b)|(c)(d)(e)) (f)(g)" << 5;
+ QTest::newRow("captureCount11") << "(?|(a)(b)|(c)(d)(e)) (f)(?:g)" << 4;
+ QTest::newRow("captureCount_invalid01") << "(.*" << -1;
+ QTest::newRow("captureCount_invalid02") << "\\" << -1;
+ QTest::newRow("captureCount_invalid03") << "(?<noun)" << -1;
+}
+
+void tst_QRegularExpression::captureCount()
+{
+ QFETCH(QString, pattern);
+ QRegularExpression re(pattern);
+ QTEST(re.captureCount(), "captureCount");
+ if (!re.isValid())
+ QCOMPARE(re.captureCount(), -1);
+}
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
new file mode 100644
index 0000000000..1a703a8f92
--- /dev/null
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qobject.h>
+#include <qregularexpression.h>
+
+Q_DECLARE_METATYPE(QRegularExpression::PatternOptions)
+Q_DECLARE_METATYPE(QRegularExpression::MatchType)
+Q_DECLARE_METATYPE(QRegularExpression::MatchOptions)
+
+class tst_QRegularExpression : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void gettersSetters_data();
+ void gettersSetters();
+ void escape_data();
+ void escape();
+ void validity_data();
+ void validity();
+ void patternOptions_data();
+ void patternOptions();
+ void normalMatch_data();
+ void normalMatch();
+ void partialMatch_data();
+ void partialMatch();
+ void globalMatch_data();
+ void globalMatch();
+ void serialize_data();
+ void serialize();
+ void operatoreq_data();
+ void operatoreq();
+ void captureCount_data();
+ void captureCount();
+
+private:
+ void provideRegularExpressions();
+};
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index 89bb3bc416..d8961559e5 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -25,6 +25,7 @@ SUBDIRS=\
qqueue \
qrect \
qregexp \
+ qregularexpression \
qringbuffer \
qscopedpointer \
qscopedvaluerollback \
diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp
index 97c749e5ba..61efb6e3f3 100644
--- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp
+++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp
@@ -151,14 +151,9 @@ protected:
Result ambigResult;
};
-QT_BEGIN_NAMESPACE
-template<> struct QMetaTypeId<tst_QShortcut::Widget> : public QMetaTypeId<int>
-{ static inline int qt_metatype_id() { return QMetaType::Int; } };
-template<> struct QMetaTypeId<tst_QShortcut::Result> : public QMetaTypeId<int>
-{ static inline int qt_metatype_id() { return QMetaType::Int; } };
-template<> struct QMetaTypeId<tst_QShortcut::Action> : public QMetaTypeId<int>
-{ static inline int qt_metatype_id() { return QMetaType::Int; } };
-QT_END_NAMESPACE
+Q_DECLARE_METATYPE(tst_QShortcut::Widget);
+Q_DECLARE_METATYPE(tst_QShortcut::Result);
+Q_DECLARE_METATYPE(tst_QShortcut::Action);
class TestEdit : public QTextEdit
{
@@ -221,9 +216,7 @@ void tst_QShortcut::initTestCase()
mainW->setFixedSize( 100, 100 );
mainW->setCentralWidget( edit );
mainW->show();
-#ifdef Q_WS_X11
- qt_x11_wait_for_window_manager(mainW);
-#endif
+ QTest::qWaitForWindowShown(mainW);
mainW->activateWindow();
QTest::qWait(100);
connect( mainW->statusBar(), SIGNAL(messageChanged(const QString&)),
@@ -251,8 +244,8 @@ Qt::KeyboardModifiers tst_QShortcut::toButtons( int key )
void tst_QShortcut::defElements()
{
- QTest::addColumn<int>("action");
- QTest::addColumn<int>("testWidget");
+ QTest::addColumn<tst_QShortcut::Action>("action");
+ QTest::addColumn<tst_QShortcut::Widget>("testWidget");
QTest::addColumn<QString>("txt");
QTest::addColumn<int>("k1");
QTest::addColumn<int>("c1");
@@ -262,7 +255,7 @@ void tst_QShortcut::defElements()
QTest::addColumn<int>("c3");
QTest::addColumn<int>("k4");
QTest::addColumn<int>("c4");
- QTest::addColumn<int>("result");
+ QTest::addColumn<tst_QShortcut::Result>("result");
}
void tst_QShortcut::number()
@@ -287,7 +280,7 @@ void tst_QShortcut::number_data()
defElements();
// Clear all
- QTest::newRow("N00 - clear") << ClearAll <<0<<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<0;
+ QTest::newRow("N00 - clear") << ClearAll << NoWidget <<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<NoResult;
//===========================================
// [Shift + key] on non-shift shortcuts testing
@@ -307,7 +300,7 @@ void tst_QShortcut::number_data()
//commented out because the behaviour changed, those tests should be updated
//QTest::newRow("N001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("N001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N001 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N001 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_M on Shift + Qt::Key_M
@@ -321,7 +314,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("N002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N002 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N002 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Qt::Key_F1
@@ -331,7 +324,7 @@ void tst_QShortcut::number_data()
//commented out because the behaviour changed, those tests should be updated
//QTest::newRow("N003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N003 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N003 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Shift + Qt::Key_F1
Qt::Key_F1 on Shift + Qt::Key_F1
@@ -340,7 +333,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N004:Shift+F1 - [Shift+F1]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N004 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N004 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Qt::Key_Tab
@@ -355,7 +348,7 @@ void tst_QShortcut::number_data()
// (Shift+)BackTab != Tab, but Shift+BackTab == Shift+Tab
QTest::newRow("N005a:Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005a - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N005a - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Shift + Qt::Key_Tab
@@ -368,7 +361,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N005b:BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N005b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N005b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Qt::Key_Backtab
@@ -384,7 +377,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N006a:BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
//commented out because the behaviour changed, those tests should be updated
//QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N006a - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N006a - clear") << ClearAll << NoWidget<< QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Shift + Qt::Key_Backtab
@@ -397,7 +390,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N006b:BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
- QTest::newRow("N006b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N006b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
//===========================================
// [Shift + key] and [key] on shortcuts with
@@ -412,7 +405,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N007 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N007 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_M
@@ -434,7 +427,7 @@ void tst_QShortcut::number_data()
*/
QTest::newRow("N05 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("N:Qt::Key_M on slot") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
- QTest::newRow("N05 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N05 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Specialkeys
Qt::Key_aring
@@ -450,7 +443,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("N:Qt::UNICODE_ACCEL + Qt::Key_K") << TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N09 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N09 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Multiple Sequences
Qt::Key_M
@@ -464,7 +457,7 @@ void tst_QShortcut::number_data()
QTest::newRow("N:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("N:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N13 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("N13 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
}
// ------------------------------------------------------------------
@@ -474,7 +467,7 @@ void tst_QShortcut::text_data()
{
defElements();
// Clear all
- QTest::newRow("T00 - clear") << ClearAll <<0<<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<0;
+ QTest::newRow("T00 - clear") << ClearAll << NoWidget <<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<< NoResult;
//===========================================
// [Shift + key] on non-shift shortcuts testing
@@ -494,7 +487,7 @@ void tst_QShortcut::text_data()
//commented out because the behaviour changed, those tests should be updated
//QTest::newRow("T001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("T001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T001 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T001 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_M on Shift + Qt::Key_M
@@ -510,7 +503,7 @@ void tst_QShortcut::text_data()
QTest::newRow("T002 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("T002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T002 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus
@@ -522,7 +515,7 @@ void tst_QShortcut::text_data()
//QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T002b:+ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002b - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T002b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Qt::Key_F1
@@ -532,7 +525,7 @@ void tst_QShortcut::text_data()
//commented out because the behaviour changed, those tests should be updated
//QTest::newRow("T003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T003 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T003 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Shift + Qt::Key_F1
@@ -541,7 +534,7 @@ void tst_QShortcut::text_data()
QTest::newRow("T004 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T004:Shift+F1 - [Shift+F1]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T004 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T004 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
//===========================================
// [Shift + key] and [key] on shortcuts with
@@ -556,7 +549,7 @@ void tst_QShortcut::text_data()
QTest::newRow("T007 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T007 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T007 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_M
@@ -579,7 +572,7 @@ void tst_QShortcut::text_data()
*/
QTest::newRow("T05 - slot2") << SetupAccel << TriggerSlot2 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T:Qt::Key_M on TriggerSlot2") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
- QTest::newRow("T06 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T06 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Specialkeys
Qt::Key_aring
@@ -595,7 +588,7 @@ void tst_QShortcut::text_data()
QTest::newRow("T:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("T:Qt::UNICODE_ACCEL + Qt::Key_K") << TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T09 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T09 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Multiple Sequences
Qt::Key_M
@@ -608,7 +601,7 @@ void tst_QShortcut::text_data()
QTest::newRow("T:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T13 - clear") << ClearAll << 0 << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; // Clear all
+ QTest::newRow("T13 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
}
// ------------------------------------------------------------------
@@ -1239,8 +1232,8 @@ void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2
void tst_QShortcut::testElement()
{
currentResult = NoResult;
- QFETCH(int, action);
- QFETCH(int, testWidget);
+ QFETCH(tst_QShortcut::Action, action);
+ QFETCH(tst_QShortcut::Widget, testWidget);
QFETCH(QString, txt);
QFETCH(int, k1);
QFETCH(int, c1);
@@ -1250,15 +1243,15 @@ void tst_QShortcut::testElement()
QFETCH(int, c3);
QFETCH(int, k4);
QFETCH(int, c4);
- QFETCH(int, result);
+ QFETCH(tst_QShortcut::Result, result);
if (action == ClearAll) {
clearAllShortcuts();
} else if (action == SetupAccel) {
setupShortcut(testWidget, txt, k1, k2, k3, k4);
} else {
- sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4);
- QCOMPARE(int(currentResult), result);
+ sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4);
+ QCOMPARE(currentResult, result);
}
}
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index d8f9bf32ad..8685546a5f 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -3385,6 +3385,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data()
<< QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=0"); // isn't used in cache loading
content.first.setRawHeaders(rawHeaders);
content.first.setLastModified(past);
+ content.first.setExpirationDate(past);
QTest::newRow("expired,200,prefer-network")
<< reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true;
@@ -6334,29 +6335,52 @@ void tst_QNetworkReply::qtbug13431replyThrottling()
void tst_QNetworkReply::httpWithNoCredentialUsage()
{
- QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
- // Do not use credentials
- request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);
QNetworkAccessManager manager;
- QNetworkReplyPtr reply = manager.get(request);
- qRegisterMetaType<QNetworkReply*>("QNetworkReply*");
- qRegisterMetaType<QAuthenticator*>("QAuthenticator*");
QSignalSpy authSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)));
QSignalSpy finishedSpy(&manager, SIGNAL(finished(QNetworkReply*)));
- qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
- QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError)));
- connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
+ // Get with credentials, to preload authentication cache
+ {
+ QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ QNetworkReplyPtr reply = manager.get(request);
+ QVERIFY(waitForFinish(reply) == Success);
+ // credentials in URL, so don't expect authentication signal
+ QCOMPARE(authSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 1);
+ finishedSpy.clear();
+ }
- // We check if authenticationRequired was emitted, however we do not anything in it so it should be 401
- QCOMPARE(authSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 1);
- QCOMPARE(errorSpy.count(), 1);
+ // Get with cached credentials (normal usage)
+ {
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ QNetworkReplyPtr reply = manager.get(request);
+ QVERIFY(waitForFinish(reply) == Success);
+ // credentials in cache, so don't expect authentication signal
+ QCOMPARE(authSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 1);
+ finishedSpy.clear();
+ }
- QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
+ // Do not use cached credentials (webkit cross origin usage)
+ {
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);
+ QNetworkReplyPtr reply = manager.get(request);
+
+ QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError)));
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // We check if authenticationRequired was emitted, however we do not anything in it so it should be 401
+ QCOMPARE(authSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(errorSpy.count(), 1);
+
+ QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
+ }
}
void tst_QNetworkReply::qtbug15311doubleContentLength()
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index 5da9ff0476..93299c26c6 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -109,6 +109,7 @@ private slots:
void subjectAndIssuerAttributes();
void verify();
void extensions();
+ void threadSafeConstMethods();
// helper for verbose test failure messages
QString toString(const QList<QSslError>&);
@@ -1059,6 +1060,77 @@ void tst_QSslCertificate::extensions()
}
+class TestThread : public QThread
+{
+public:
+ void run()
+ {
+ effectiveDate = cert.effectiveDate();
+ expiryDate = cert.expiryDate();
+ extensions = cert.extensions();
+ isBlacklisted = cert.isBlacklisted();
+ issuerInfo = cert.issuerInfo(QSslCertificate::CommonName);
+ issuerInfoAttributes = cert.issuerInfoAttributes();
+ publicKey = cert.publicKey();
+ serialNumber = cert.serialNumber();
+ subjectInfo = cert.subjectInfo(QSslCertificate::CommonName);
+ subjectInfoAttributes = cert.subjectInfoAttributes();
+ toDer = cert.toDer();
+ toPem = cert.toPem();
+ toText = cert.toText();
+ version = cert.version();
+ }
+ QSslCertificate cert;
+ QDateTime effectiveDate;
+ QDateTime expiryDate;
+ QList<QSslCertificateExtension> extensions;
+ bool isBlacklisted;
+ QStringList issuerInfo;
+ QList<QByteArray> issuerInfoAttributes;
+ QSslKey publicKey;
+ QByteArray serialNumber;
+ QStringList subjectInfo;
+ QList<QByteArray> subjectInfoAttributes;
+ QByteArray toDer;
+ QByteArray toPem;
+ QByteArray toText;
+ QByteArray version;
+};
+
+void tst_QSslCertificate::threadSafeConstMethods()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QByteArray encoded = readFile(testDataDir + "/certificates/cert.pem");
+ QSslCertificate certificate(encoded);
+ QVERIFY(!certificate.isNull());
+
+ TestThread t1;
+ t1.cert = certificate; //shallow copy
+ TestThread t2;
+ t2.cert = certificate; //shallow copy
+ t1.start();
+ t2.start();
+ QVERIFY(t1.wait(5000));
+ QVERIFY(t2.wait(5000));
+ QVERIFY(t1.cert == t2.cert);
+ QVERIFY(t1.effectiveDate == t2.effectiveDate);
+ QVERIFY(t1.expiryDate == t2.expiryDate);
+ //QVERIFY(t1.extensions == t2.extensions); // no equality operator, so not tested
+ QVERIFY(t1.isBlacklisted == t2.isBlacklisted);
+ QVERIFY(t1.issuerInfo == t2.issuerInfo);
+ QVERIFY(t1.issuerInfoAttributes == t2.issuerInfoAttributes);
+ QVERIFY(t1.publicKey == t2.publicKey);
+ QVERIFY(t1.serialNumber == t2.serialNumber);
+ QVERIFY(t1.subjectInfo == t2.subjectInfo);
+ QVERIFY(t1.subjectInfoAttributes == t2.subjectInfoAttributes);
+ QVERIFY(t1.toDer == t2.toDer);
+ QVERIFY(t1.toPem == t2.toPem);
+ QVERIFY(t1.toText == t2.toText);
+ QVERIFY(t1.version == t2.version);
+
+}
#endif // QT_NO_SSL
diff --git a/tests/auto/other/headersclean/headersclean.pri b/tests/auto/other/headersclean/headersclean.pri
new file mode 100644
index 0000000000..163ef6d409
--- /dev/null
+++ b/tests/auto/other/headersclean/headersclean.pri
@@ -0,0 +1,38 @@
+# The headersclean test attempts to ensure all public Qt headers
+# abide by various rules.
+#
+# To reuse this test outside of the qtbase module,
+# include this .pri and create a qt_headersclean_headers.h which includes
+# the headers you'd like to test.
+
+*-g++*: QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror
+
+# The flags here come from http://wiki.qt-project.org/Coding_Conventions#Conventions_for_public_header_files
+# -Wold-style-cast cannot be used, /usr/include/bits/byteswap.h defines the macro bswap_16 using C style casts :(
+# -Wfloat-equal cannot be used, qrect.h and qvector2d.h do exact comparisons in isNull and operator==. Would need #pragmas.
+*-g++*: QMAKE_CXXFLAGS += -Woverloaded-virtual -Wshadow -Wundef
+
+# Other nice flags
+*-g++*: QMAKE_CXXFLAGS += -Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wpointer-arith -Wformat-security
+
+# Enable pedantic mode, but accept variadic macros and 'long long' usage.
+*-g++*: QMAKE_CXXFLAGS += -Wno-long-long -Wno-variadic-macros -pedantic-errors
+
+# There are outstanding alignment issues on ARM in some container classes.
+contains(QT_ARCH,arm):*-g++*:QMAKE_CXXFLAGS -= -Wcast-align
+
+QMAKE_CXXFLAGS += -DQT_NO_CAST_TO_ASCII \
+ -DQT_NO_CAST_FROM_ASCII \
+ -DQT_STRICT_ITERATORS \
+ -DQT_NO_URL_CAST_FROM_STRING \
+ -DQT_NO_CAST_FROM_BYTEARRAY \
+ -DQT_NO_KEYWORDS \
+ -DQT_USE_FAST_CONCATENATION \
+ -DQT_USE_FAST_OPERATOR_PLUS
+
+TARGET = tst_headersclean
+SOURCES += $$PWD/tst_headersclean.cpp
+HEADERS += $$PWD/tst_headersclean.h
+
+# qt_headersclean_headers.h should be alongside the .pro file
+INCLUDEPATH += $$_PRO_FILE_PWD_
diff --git a/tests/auto/other/headersclean/headersclean.pro b/tests/auto/other/headersclean/headersclean.pro
index 5444bebfb9..9bfadca08c 100644
--- a/tests/auto/other/headersclean/headersclean.pro
+++ b/tests/auto/other/headersclean/headersclean.pro
@@ -1,28 +1,2 @@
-CONFIG += testcase
-TARGET = tst_headersclean
-SOURCES += tst_headersclean.cpp
-
-# No need to link to all modules, only those actually used
QT = core testlib gui widgets
-
-*-g++*: QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror
-
-# The flags here come from http://wiki.qt-project.org/Coding_Conventions#Conventions_for_public_header_files
-# -Wold-style-cast cannot be used, /usr/include/bits/byteswap.h defines the macro bswap_16 using C style casts :(
-# -Wfloat-equal cannot be used, qrect.h and qvector2d.h do exact comparisons in isNull and operator==. Would need #pragmas.
-*-g++*: QMAKE_CXXFLAGS += -Woverloaded-virtual -Wshadow -Wundef
-
-# Other nice flags
-*-g++*: QMAKE_CXXFLAGS += -Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wpointer-arith -Wformat-security
-
-# Enable pedantic mode, but accept variadic macros and 'long long' usage.
-*-g++*: QMAKE_CXXFLAGS += -Wno-long-long -Wno-variadic-macros -pedantic-errors
-
-QMAKE_CXXFLAGS += -DQT_NO_CAST_TO_ASCII \
- -DQT_NO_CAST_FROM_ASCII \
- -DQT_STRICT_ITERATORS \
- -DQT_NO_URL_CAST_FROM_STRING \
- -DQT_NO_CAST_FROM_BYTEARRAY \
- -DQT_NO_KEYWORDS \
- -DQT_USE_FAST_CONCATENATION \
- -DQT_USE_FAST_OPERATOR_PLUS
+include(headersclean.pri)
diff --git a/tests/auto/other/headersclean/qt_headersclean_headers.h b/tests/auto/other/headersclean/qt_headersclean_headers.h
new file mode 100644
index 0000000000..c9b4e3f399
--- /dev/null
+++ b/tests/auto/other/headersclean/qt_headersclean_headers.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_HEADERSCLEAN_HEADERS
+#define QT_HEADERSCLEAN_HEADERS
+
+/*
+ This file should include all the headers to be tested by the headersclean
+ test. It may be copied and customized for each module.
+*/
+
+#include <QtCore/QtCore>
+#include <QtConcurrent/QtConcurrent>
+#include <QtTest/QtTest>
+
+#include <QtNetwork/QtNetwork>
+#include <QtXml/QtXml>
+#include <QtSql/QtSql>
+#include <QtGui/QtGui>
+#include <QtWidgets/QtWidgets>
+#include <QtPrintSupport/QtPrintSupport>
+#include <QtPlatformSupport/QtPlatformSupport>
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/QtOpenGL>
+#endif
+
+#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
+#include <QtDBus/QtDBus>
+#endif
+
+#endif
diff --git a/tests/auto/other/headersclean/tst_headersclean.cpp b/tests/auto/other/headersclean/tst_headersclean.cpp
index 81d0aa3a4a..d442ad39d3 100644
--- a/tests/auto/other/headersclean/tst_headersclean.cpp
+++ b/tests/auto/other/headersclean/tst_headersclean.cpp
@@ -39,38 +39,12 @@
**
****************************************************************************/
-#define signals int
-#define slots int
-#define emit public:;
-#define foreach public:;
-#define forever public:;
+#include "tst_headersclean.h"
+#include <QTest>
-#include <QtCore/QtCore>
-#include <QtConcurrent/QtConcurrent>
-#include <QtTest/QtTest>
-
-#include <QtNetwork/QtNetwork>
-#include <QtXml/QtXml>
-#include <QtSql/QtSql>
-#include <QtGui/QtGui>
-#include <QtWidgets/QtWidgets>
-#include <QtPrintSupport/QtPrintSupport>
-#include <QtPlatformSupport/QtPlatformSupport>
-
-#ifndef QT_NO_OPENGL
-#include <QtOpenGL/QtOpenGL>
-#endif
-
-#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
-#include <QtDBus/QtDBus>
-#endif
-
-class tst_HeadersClean: public QObject
+void tst_HeadersClean::initTestCase()
{
- Q_OBJECT
-public:
- tst_HeadersClean() {}
-};
+ QWARN("This is a compile test only");
+}
QTEST_MAIN(tst_HeadersClean)
-#include "tst_headersclean.moc"
diff --git a/tests/auto/other/headersclean/tst_headersclean.h b/tests/auto/other/headersclean/tst_headersclean.h
new file mode 100644
index 0000000000..7479e061dc
--- /dev/null
+++ b/tests/auto/other/headersclean/tst_headersclean.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_HEADERSCLEAN_H
+#define TST_HEADERSCLEAN_H
+
+#define signals int
+#define slots int
+#define emit public:;
+#define foreach public:;
+#define forever public:;
+
+#include <qt_headersclean_headers.h>
+#include <QObject>
+
+class tst_HeadersClean: public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase();
+};
+
+#endif
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index 9ec5ea8e34..6c708baa6b 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -30,8 +30,7 @@ testcocoon: SUBDIRS -= headersclean
cross_compile: SUBDIRS -= \
atwrapper \
- compiler \
- headersclean \
+ compiler
wince*|!contains(QT_CONFIG, accessibility):SUBDIRS -= qaccessibility
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index b2a4b1cca2..4c370bebc7 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -777,6 +777,7 @@ void tst_QAccessibility::actionTest()
{
QPushButton *button = new QPushButton;
button->show();
+ QTest::qWaitForWindowShown(button);
button->clearFocus();
QCOMPARE(button->hasFocus(), false);
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index b22e876c3c..584fcb045a 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -222,6 +222,8 @@ private slots:
void sqlite_real_data() { generic_data("QSQLITE"); }
void sqlite_real();
+ void aggregateFunctionTypes_data() { generic_data(); }
+ void aggregateFunctionTypes();
private:
// returns all database connections
void generic_data(const QString &engine=QString());
@@ -3339,5 +3341,121 @@ void tst_QSqlQuery::sqlite_real()
QCOMPARE(q.value(0).toDouble(), 5.6);
}
+void tst_QSqlQuery::aggregateFunctionTypes()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ {
+ const QString tableName(qTableName("numericFunctionsWithIntValues", __FILE__));
+ tst_Databases::safeDropTable( db, tableName );
+
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id INTEGER)"));
+
+ // First test without any entries
+ QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.record().field(0).type(), QVariant::Invalid);
+
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (1)"));
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (2)"));
+
+ QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), 3);
+ QCOMPARE(q.record().field(0).type(), QVariant::Int);
+
+ QVERIFY_SQL(q, exec("SELECT AVG(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 1.5);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT COUNT(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), 2);
+ QCOMPARE(q.record().field(0).type(), QVariant::Int);
+
+ QVERIFY_SQL(q, exec("SELECT MIN(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), 1);
+ QCOMPARE(q.record().field(0).type(), QVariant::Int);
+
+ QVERIFY_SQL(q, exec("SELECT MAX(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), 2);
+ QCOMPARE(q.record().field(0).type(), QVariant::Int);
+ }
+ {
+ const QString tableName(qTableName("numericFunctionsWithDoubleValues", __FILE__));
+ tst_Databases::safeDropTable( db, tableName );
+
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id DOUBLE)"));
+
+ // First test without any entries
+ QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.record().field(0).type(), QVariant::Invalid);
+
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (1.5)"));
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (2.5)"));
+
+ QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 4.0);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT AVG(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 2.0);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT COUNT(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), 2);
+ QCOMPARE(q.record().field(0).type(), QVariant::Int);
+
+ QVERIFY_SQL(q, exec("SELECT MIN(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 1.5);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT MAX(id) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 2.5);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT ROUND(id, 1) FROM " + tableName + " WHERE id=1.5"));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 1.5);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+
+ QVERIFY_SQL(q, exec("SELECT ROUND(id, 0) FROM " + tableName + " WHERE id=2.5"));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toDouble(), 3.0);
+ QCOMPARE(q.record().field(0).type(), QVariant::Double);
+ }
+ {
+ const QString tableName(qTableName("stringFunctions", __FILE__));
+ tst_Databases::safeDropTable( db, tableName );
+
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id INTEGER, txt VARCHAR(50))"));
+
+ QVERIFY_SQL(q, exec("SELECT MAX(txt) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.record().field(0).type(), QVariant::Invalid);
+
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, txt) VALUES (1, 'lower')"));
+ QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, txt) VALUES (2, 'upper')"));
+
+ QVERIFY_SQL(q, exec("SELECT MAX(txt) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toString(), QLatin1String("upper"));
+ QCOMPARE(q.record().field(0).type(), QVariant::String);
+ }
+}
+
QTEST_MAIN( tst_QSqlQuery )
#include "tst_qsqlquery.moc"
diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
index ddafeea427..ce0d8db1fd 100644
--- a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
+++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
@@ -542,6 +542,13 @@ void tst_QSqlRelationalTableModel::setRecord()
model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, submit());
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit) {
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("tester"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("herr"));
+ QVERIFY_SQL(model, select());
+ }
+
QCOMPARE(model.data(model.index(3, 0)).toInt(), 7);
QCOMPARE(model.data(model.index(3, 1)).toString(), QString("tester"));
QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
@@ -599,6 +606,8 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
QVERIFY_SQL(model, submitAll());
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ // The changes were submitted, but there was no automatic select to resort
+ QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0,0)).toInt(), 1);
QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry"));
@@ -1401,6 +1410,8 @@ void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers()
QVERIFY_SQL(model, insertRecord(-1, rec));
model.submitAll();
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit)
+ QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 3);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Washington"));
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
index 270de8292b..448111cd9f 100644
--- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -411,8 +411,11 @@ void tst_QSqlTableModel::setRecord()
} else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1)
model.submit();
else {
- // dataChanged() is not emitted when submitAll() is called
- QCOMPARE(spy.count(), 1);
+ // dataChanged() emitted by selectRow() as well as setRecord()
+ if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnFieldChange)
+ QCOMPARE(spy.count(), 2);
+ else
+ QCOMPARE(spy.count(), 1);
QCOMPARE(spy.at(0).count(), 2);
QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(0)), model.index(i, 0));
QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(1)), model.index(i, rec.count() - 1));
@@ -471,8 +474,7 @@ void tst_QSqlTableModel::insertRow()
rec.setValue(0, 42);
rec.setValue(1, QString("francis"));
- // FieldChange updates immediately and resorts
- // Row/Manual submit does not resort
+ // Setting record does not cause resort
QVERIFY(model.setRecord(2, rec));
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
@@ -482,8 +484,23 @@ void tst_QSqlTableModel::insertRow()
QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
- // See comment above setRecord
- if (submitpolicy == QSqlTableModel::OnFieldChange) {
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 3);
+
+ QVERIFY(model.submitAll());
+
+ if (submitpolicy == QSqlTableModel::OnManualSubmit) {
+ // After the submit we should have the resorted view
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
@@ -491,6 +508,13 @@ void tst_QSqlTableModel::insertRow()
QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis"));
QCOMPARE(model.data(model.index(3, 2)).toInt(), 2);
} else {
+ // Submit does not select, therefore not resorted
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
QCOMPARE(model.data(model.index(2, 0)).toInt(), 42);
QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis"));
QCOMPARE(model.data(model.index(2, 2)).toInt(), 2);
@@ -499,9 +523,8 @@ void tst_QSqlTableModel::insertRow()
QCOMPARE(model.data(model.index(3, 2)).toInt(), 3);
}
- QVERIFY(model.submitAll());
-
- // After the submit we should have the resorted view
+ QVERIFY(model.select());
+ // After the select we should have the resorted view in all strategies
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
@@ -514,7 +537,6 @@ void tst_QSqlTableModel::insertRow()
QCOMPARE(model.data(model.index(3, 0)).toInt(), 42);
QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis"));
QCOMPARE(model.data(model.index(3, 2)).toInt(), 2);
-
}
void tst_QSqlTableModel::insertRecord()
@@ -647,8 +669,7 @@ void tst_QSqlTableModel::removeRow()
QVERIFY_SQL(model, select());
QCOMPARE(model.rowCount(), 3);
- // headerDataChanged must be emitted by the model when the edit strategy is OnManualSubmit,
- // when OnFieldChange or OnRowChange it's not needed because the model will re-select.
+ // headerDataChanged must be emitted by the model since the row won't vanish until select
qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
@@ -673,7 +694,10 @@ void tst_QSqlTableModel::removeRow()
headerDataChangedSpy.clear();
QVERIFY(model.removeRow(1));
- QCOMPARE(headerDataChangedSpy.count(), 0);
+ QCOMPARE(headerDataChangedSpy.count(), 1);
+ QCOMPARE(model.rowCount(), 3);
+
+ QVERIFY_SQL(model, select());
QCOMPARE(model.rowCount(), 2);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
@@ -706,6 +730,11 @@ void tst_QSqlTableModel::removeRows()
QCOMPARE(beforeDeleteSpy.count(), 2);
QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 0);
QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 1);
+ // deleted rows shown as empty until select
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString(""));
+ QVERIFY(model.select());
+ // deleted rows are gone
QCOMPARE(model.rowCount(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi"));
model.clear();
@@ -730,10 +759,10 @@ void tst_QSqlTableModel::removeRows()
QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
QVERIFY(model.removeRows(0, 2, QModelIndex()));
QCOMPARE(headerDataChangedSpy.count(), 2);
- QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 0);
- QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 0);
- QCOMPARE(headerDataChangedSpy.at(1).at(1).toInt(), 1);
- QCOMPARE(headerDataChangedSpy.at(1).at(2).toInt(), 1);
+ QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(headerDataChangedSpy.at(1).at(1).toInt(), 0);
+ QCOMPARE(headerDataChangedSpy.at(1).at(2).toInt(), 0);
QCOMPARE(model.rowCount(), 3);
QVERIFY(beforeDeleteSpy.count() == 0);
QVERIFY(model.submitAll());
@@ -778,6 +807,14 @@ void tst_QSqlTableModel::removeInsertedRow()
model.submitAll();
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit) {
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 55);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("null columns"));
+ QCOMPARE(model.data(model.index(1, 2)).isNull(), true);
+ QVERIFY(model.select());
+ }
+
QCOMPARE(model.rowCount(), 4);
QCOMPARE(model.data(model.index(3, 0)).toInt(), 55);
QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns"));
@@ -785,8 +822,17 @@ void tst_QSqlTableModel::removeInsertedRow()
QVERIFY(model.removeRow(3));
model.submitAll();
- QCOMPARE(model.rowCount(), 3);
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit) {
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString(""));
+ QVERIFY(model.select());
+ }
+
+ QCOMPARE(model.rowCount(), 3);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
@@ -1129,6 +1175,11 @@ void tst_QSqlTableModel::insertRecordBeforeSelect()
buffer.setValue("title", 0);
QVERIFY_SQL(model, insertRecord(1, buffer));
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit) {
+ QCOMPARE(model.rowCount(), 2);
+ QVERIFY_SQL(model, select());
+ }
+
int rowCount = model.rowCount();
model.clear();
QCOMPARE(model.rowCount(), 0);
diff --git a/tests/auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri b/tests/auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri
index cbd2d0f7d0..ea58ef076e 100644
--- a/tests/auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri
+++ b/tests/auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri
@@ -1 +1,2 @@
+load(default_pre)
setVar(BAR)
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index af76b1c3c1..ee7ec7ba57 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -4338,9 +4338,16 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
QPointF newMouseScenePos = view.mapToScene(mouseViewPos);
qreal slack = 1;
- QEXPECT_FAIL("", "QTBUG-22455", Abort);
- QVERIFY(qAbs(newMouseScenePos.x() - mouseScenePos.x()) < slack);
- QVERIFY(qAbs(newMouseScenePos.y() - mouseScenePos.y()) < slack);
+
+ const qreal dx = qAbs(newMouseScenePos.x() - mouseScenePos.x());
+ const qreal dy = qAbs(newMouseScenePos.y() - mouseScenePos.y());
+ const QByteArray message = QString::fromLatin1("QTBUG-22455, distance: dx=%1, dy=%2 slack=%3 (%4).").
+ arg(dx).arg(dy).arg(slack).arg(qApp->style()->metaObject()->className()).toLocal8Bit();
+ // This is highly unstable (observed to pass on Windows and some Linux configurations).
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL("", message.constData(), Abort);
+#endif
+ QVERIFY2(dx < slack && dy < slack, message.constData());
#endif
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index 0a2d0cd2f8..c6b2b49d98 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -1158,9 +1158,6 @@ void tst_QGraphicsWidget::initStyleOption()
QCOMPARE(hasFocus, focus);
bool isUnderMouse = option.state & QStyle::State_MouseOver;
#ifndef Q_OS_WINCE
-# if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
- QEXPECT_FAIL("all", "QTBUG-22457", Abort);
-# endif
QCOMPARE(isUnderMouse, underMouse);
#endif
// if (layoutDirection != Qt::LeftToRight)
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index f139eac275..9bb08edcce 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -1830,10 +1830,11 @@ void tst_QListView::taskQTBUG_2233_scrollHiddenItems()
QStringListModel model(&view);
QStringList list;
for (int i = 0; i < rowCount; ++i)
- list << QString::fromAscii("Item %1").arg(i);
+ list << QString::number(i);
model.setStringList(list);
view.setModel(&model);
+ view.setUniformItemSizes(true);
view.setViewMode(QListView::ListMode);
for (int i = 0; i < rowCount / 2; ++i)
view.setRowHidden(2 * i, true);
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index caf0f1f80d..dab9dd7690 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -5693,7 +5693,6 @@ private:
void tst_QWidget::childEvents()
{
EventRecorder::EventList expected;
- bool accessibilityEnabled = false;
// Move away the cursor; otherwise it might result in an enter event if it's
// inside the widget when the widget is shown.
@@ -5735,8 +5734,6 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show);
- if (accessibilityEnabled)
- expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
expected << qMakePair(&widget, QEvent::ShowToParent);
QCOMPARE(spy.eventList(), expected);
spy.clear();
@@ -5820,8 +5817,6 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show);
- if (accessibilityEnabled)
- expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
expected << qMakePair(&widget, QEvent::ShowToParent);
QCOMPARE(spy.eventList(), expected);
spy.clear();
@@ -5908,8 +5903,6 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show);
- if (accessibilityEnabled)
- expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
expected << qMakePair(&widget, QEvent::ShowToParent);
QCOMPARE(spy.eventList(), expected);
spy.clear();
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 1201b0f1da..544923a1c3 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -555,11 +555,11 @@ void tst_QStyleSheetStyle::layoutSpacing()
void tst_QStyleSheetStyle::qproperty()
{
QPushButton pb;
- pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: true; qproperty-checked: 1}");
+ pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: 1; qproperty-checked: false}");
pb.ensurePolished();
QCOMPARE(pb.text(), QString("hello"));
QCOMPARE(pb.isCheckable(), true);
- QCOMPARE(pb.isChecked(), true);
+ QCOMPARE(pb.isChecked(), false);
}
namespace ns {
@@ -781,10 +781,6 @@ void tst_QStyleSheetStyle::focusColors()
+ " did not contain background color #e8ff66, using style "
+ QString::fromLatin1(qApp->style()->metaObject()->className()))
.toLocal8Bit().constData());
-#ifdef Q_OS_MAC
- if (widget == widgets.first())
- QEXPECT_FAIL("", "Failure only for first widget, the QPushButton, see QTBUG-23686", Continue);
-#endif
QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain text color #ff0084, using style "
@@ -882,8 +878,7 @@ void tst_QStyleSheetStyle::hoverColors()
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain background color #e8ff66").toLocal8Bit().constData());
#ifdef Q_OS_MAC
- if (qobject_cast<QPushButton *>(widget)
- || qobject_cast<QComboBox *>(widget))
+ if (qobject_cast<QComboBox *>(widget))
QEXPECT_FAIL("", "Failure only for QPushButton and QComboBox, see QTBUG-23686", Continue);
#endif
QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro
index 127d78596a..f16110cbd1 100644
--- a/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro
+++ b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro
@@ -2,6 +2,3 @@ CONFIG += testcase
TARGET = tst_qcalendarwidget
QT += widgets testlib
SOURCES += tst_qcalendarwidget.cpp
-
-# QTBUG-23615 - unstable test
-linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = oneiric ]"):CONFIG += insignificant_test
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
index 4f95f80525..4857900dc8 100644
--- a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
+++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
@@ -175,6 +175,8 @@ void tst_QCalendarWidget::buttonClickCheck()
QSize size = object.sizeHint();
object.setGeometry(0,0,size.width(), size.height());
object.show();
+ QTest::qWaitForWindowShown(&object);
+ object.activateWindow();
QDate selectedDate(2005, 1, 1);
//click on the month buttons
diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
index 0f07546559..c6a039cb37 100644
--- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
+++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
@@ -1435,6 +1435,11 @@ void MoveSeparator::apply(QMainWindow *mw) const
}
QVERIFY(!path.isEmpty());
+ // For QTBUG-15689:
+ // Following commands is used to simulate user move action. A better way should
+ // use QMainWindowLayout::startSeparatorMove/separatorMove/endSeparatorMove,
+ // but then we will need real start/end position coordinates.
+ l->layoutState.dockAreaLayout.fallbackToSizeHints = false;
l->layoutState.dockAreaLayout.separatorMove(path, QPoint(0, 0), QPoint(delta, delta));
}
#endif
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index 4fffd74491..473c5e05ec 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -562,9 +562,6 @@ void tst_QMenu::tearOff()
QTest::mouseClick(menu, Qt::LeftButton, 0, QPoint(3, 3), 10);
QTest::qWait(100);
-#ifndef Q_OS_MAC
- QEXPECT_FAIL("", "QTBUG-22565", Abort);
-#endif
QVERIFY(menu->isTearOffMenuVisible());
QPointer<QMenu> torn = 0;
foreach (QWidget *w, QApplication::allWidgets()) {
@@ -783,9 +780,6 @@ void tst_QMenu::task258920_mouseBorder()
#ifdef Q_OS_WINCE_WM
QSKIP("Mouse move related signals for Windows Mobile unavailable");
#endif
- // ### fixme: Check platforms
- QSKIP("QTBUG-20753 QCursor::setPos() / QTest::mouseMove() doesn't work on qpa");
-
Menu258920 menu;
// For styles which inherit from QWindowsStyle, styleHint(QStyle::SH_Menu_MouseTracking) is true.
menu.setMouseTracking(true);
diff --git a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
index a3cdd38e56..c80a946366 100644
--- a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -77,6 +77,9 @@ private slots:
void constructCoreTypeCopy_data();
void constructCoreTypeCopy();
+ void constructCustomType_data();
+ void constructCustomType();
+
void constructInPlace_data();
void constructInPlace();
void constructInPlaceCopy_data();
@@ -309,6 +312,24 @@ void tst_QMetaType::constructCoreTypeCopy()
}
}
+void tst_QMetaType::constructCustomType_data()
+{
+ QTest::addColumn<int>("typeId");
+
+ QTest::newRow("BigClass") << qMetaTypeId<BigClass>();
+}
+
+void tst_QMetaType::constructCustomType()
+{
+ QFETCH(int, typeId);
+ QBENCHMARK {
+ for (int i = 0; i < 100000; ++i) {
+ void *data = QMetaType::create(typeId, (void *)0);
+ QMetaType::destroy(typeId, data);
+ }
+ }
+}
+
void tst_QMetaType::constructInPlace_data()
{
constructCoreType_data();
diff --git a/tests/manual/qcursor/allcursors/allcursors.pro b/tests/manual/qcursor/allcursors/allcursors.pro
index 8e7da30752..b9f6a0c98d 100644
--- a/tests/manual/qcursor/allcursors/allcursors.pro
+++ b/tests/manual/qcursor/allcursors/allcursors.pro
@@ -6,7 +6,7 @@
TARGET = tst_allcursors
TEMPLATE = app
-
+QT = core gui widgets
SOURCES += main.cpp\
mainwindow.cpp
diff --git a/tests/manual/qcursor/allcursors/main.cpp b/tests/manual/qcursor/allcursors/main.cpp
index 8872481e88..fab9a7d3d7 100644
--- a/tests/manual/qcursor/allcursors/main.cpp
+++ b/tests/manual/qcursor/allcursors/main.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include <QtGui/QApplication>
+#include <QtWidgets/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
diff --git a/tests/manual/qcursor/allcursors/mainwindow.h b/tests/manual/qcursor/allcursors/mainwindow.h
index 938f744862..5908d26e17 100644
--- a/tests/manual/qcursor/allcursors/mainwindow.h
+++ b/tests/manual/qcursor/allcursors/mainwindow.h
@@ -42,7 +42,7 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QtGui/QMainWindow>
+#include <QtWidgets/QMainWindow>
class QTimer;
diff --git a/tests/manual/qcursor/grab_override/grab_override.pro b/tests/manual/qcursor/grab_override/grab_override.pro
index c0f69be5ad..d84e2ee2b8 100644
--- a/tests/manual/qcursor/grab_override/grab_override.pro
+++ b/tests/manual/qcursor/grab_override/grab_override.pro
@@ -6,7 +6,7 @@
TARGET = t_cursors
TEMPLATE = app
-
+QT = core gui widgets
SOURCES += main.cpp\
mainwindow.cpp
diff --git a/tests/manual/qcursor/grab_override/main.cpp b/tests/manual/qcursor/grab_override/main.cpp
index 8872481e88..fab9a7d3d7 100644
--- a/tests/manual/qcursor/grab_override/main.cpp
+++ b/tests/manual/qcursor/grab_override/main.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include <QtGui/QApplication>
+#include <QtWidgets/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
diff --git a/tests/manual/qcursor/grab_override/mainwindow.h b/tests/manual/qcursor/grab_override/mainwindow.h
index c231e9583d..3eb7e26fd7 100644
--- a/tests/manual/qcursor/grab_override/mainwindow.h
+++ b/tests/manual/qcursor/grab_override/mainwindow.h
@@ -42,7 +42,7 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QtGui/QMainWindow>
+#include <QtWidgets/QMainWindow>
class QTimer;