summaryrefslogtreecommitdiffstats
path: root/src
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 /src
parent3d19422ef16a230bb11dbbfe4a8cc9667f39bf15 (diff)
parent6c612c933803ef57ea45e907d0181b40659148ac (diff)
Merge remote-tracking branch 'origin/master' into api_changes
Diffstat (limited to 'src')
-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
144 files changed, 5738 insertions, 686 deletions
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);