diff options
61 files changed, 1462 insertions, 310 deletions
@@ -4309,8 +4309,7 @@ fi # detect neon support if [ "$CFG_ARCH" = "arm" ] && [ "${CFG_NEON}" = "auto" ]; then - # The iOS toolchain has trouble building the pixman NEON draw-helpers - if [ "$XPLATFORM_IOS" != "yes" ] && compileTest unix/neon "neon"; then + if compileTest unix/neon "neon"; then CFG_NEON=yes else CFG_NEON=no @@ -6405,12 +6404,13 @@ fi cat >>"$QTCONFIG.tmp" <<EOF #configuration CONFIG += $QTCONFIG_CONFIG -QT_ARCH = $CFG_ARCH -QT_HOST_ARCH = $CFG_HOST_ARCH -QT_CPU_FEATURES = $CFG_CPUFEATURES -QT_HOST_CPU_FEATURES = $CFG_HOST_CPUFEATURES -QMAKE_DEFAULT_LIBDIRS = `echo "$DEFAULT_LIBDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '` -QMAKE_DEFAULT_INCDIRS = `echo "$DEFAULT_INCDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '` +host_build { + QT_ARCH = $CFG_HOST_ARCH +} else { + QT_ARCH = $CFG_ARCH + QMAKE_DEFAULT_LIBDIRS = `echo "$DEFAULT_LIBDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '` + QMAKE_DEFAULT_INCDIRS = `echo "$DEFAULT_INCDIRS" | sed 's,^,",;s,$,",' | tr '\n' ' '` +} QT_EDITION = $Edition QT_CONFIG += $QT_CONFIG @@ -6492,6 +6492,14 @@ if [ -n "$CFG_SKIP_MODULES" ]; then echo "QT_SKIP_MODULES += $CFG_SKIP_MODULES" >> "$QTMODULE.tmp" fi +cat >>"$QTMODULE.tmp" <<EOF +host_build { + QT_CPU_FEATURES = $CFG_HOST_CPUFEATURES +} else { + QT_CPU_FEATURES = $CFG_CPUFEATURES +} +EOF + if [ -n "$QT_CFLAGS_PSQL" ]; then echo "QT_CFLAGS_PSQL = $QT_CFLAGS_PSQL" >> "$QTMODULE.tmp" fi diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index 3ce04b679e..c94ee40934 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -20,13 +20,3 @@ QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_LFLAGS_CXX11 = - -QMAKE_CFLAGS_SSE2 += -msse2 -QMAKE_CFLAGS_SSE3 += -msse3 -QMAKE_CFLAGS_SSSE3 += -mssse3 -QMAKE_CFLAGS_SSE4_1 += -msse4.1 -QMAKE_CFLAGS_SSE4_2 += -msse4.2 -QMAKE_CFLAGS_AVX += -mavx -QMAKE_CFLAGS_AVX2 += -mavx2 -QMAKE_CFLAGS_IWMMXT += -mcpu=iwmmxt -QMAKE_CFLAGS_NEON += -mfpu=neon diff --git a/mkspecs/common/ios/qmake.conf b/mkspecs/common/ios/qmake.conf index 39465aa765..3c477438a3 100644 --- a/mkspecs/common/ios/qmake.conf +++ b/mkspecs/common/ios/qmake.conf @@ -15,9 +15,6 @@ QMAKE_RANLIB = ranlib -s QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX -# Basic iOS frameworks needed for any GUI app -QMAKE_LFLAGS += -framework Foundation -framework UIKit -framework QuartzCore -lz - # No OpenGL ES1 QMAKE_INCDIR_OPENGL_ES1 = QMAKE_LIBDIR_OPENGL_ES1 = diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 58c4256aa5..c50235767a 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.1.0" +#define QT_VERSION_STR "5.2.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050100 +#define QT_VERSION 0x050200 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index ae9b667b58..484dcbf22e 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -251,7 +251,7 @@ QT_BEGIN_NAMESPACE return retVal; enum { - DefaultStreamVersion = QDataStream::Qt_5_1 + DefaultStreamVersion = QDataStream::Qt_5_2 }; /*! @@ -538,8 +538,9 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_4_7 Same as Qt_4_6. \value Qt_4_8 Same as Qt_4_6. \value Qt_4_9 Same as Qt_4_6. - \value Qt_5_0 Version 13 (Qt 5.0) + \value Qt_5_0 Version 13 (Qt 5.0, Qt 5.1, Qt 5.2) \value Qt_5_1 Same as Qt_5_0. + \value Qt_5_2 Same as Qt_5_0. \sa setVersion(), version() */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 6017ba5e7d..f893e6a503 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -86,8 +86,9 @@ public: Qt_4_8 = Qt_4_7, Qt_4_9 = Qt_4_8, Qt_5_0 = 13, - Qt_5_1 = Qt_5_0 -#if QT_VERSION >= 0x050200 + Qt_5_1 = Qt_5_0, + Qt_5_2 = Qt_5_1 +#if QT_VERSION >= 0x050300 #error Add the datastream version for this Qt version #endif }; diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index 6a57ccaca8..a0ac33e8a8 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -110,6 +110,11 @@ public: inline bool operator!=(const QPersistentModelIndex &other) const { return !operator==(other); } QPersistentModelIndex &operator=(const QPersistentModelIndex &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPersistentModelIndex(QPersistentModelIndex &&other) : d(other.d) { other.d = 0; } + inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) + { qSwap(d, other.d); return *this; } +#endif inline void swap(QPersistentModelIndex &other) { qSwap(d, other.d); } bool operator==(const QModelIndex &other) const; bool operator!=(const QModelIndex &other) const; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index aed998f2e2..4add02f805 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -52,6 +52,10 @@ #endif #include <new> +#include <vector> +#include <list> +#include <map> + #ifdef Bool #error qmetatype.h must be included before any header file that defines Bool #endif @@ -183,6 +187,19 @@ QT_BEGIN_NAMESPACE #define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \ TypeName = Id, +#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ + F(QList) \ + F(QVector) \ + F(QQueue) \ + F(QStack) \ + F(QSet) \ + F(QLinkedList) + +#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \ + F(QHash, class) \ + F(QMap, class) \ + F(QPair, struct) + class QDataStream; class QMetaTypeInterface; struct QMetaObject; @@ -846,19 +863,6 @@ struct QMetaTypeId< SMART_POINTER<T> > : public QMetaTypeId_ ## SMART_POINTER ## { \ }; -#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ - F(QList) \ - F(QVector) \ - F(QQueue) \ - F(QStack) \ - F(QSet) \ - F(QLinkedList) - -#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \ - F(QHash, class) \ - F(QMap, class) \ - F(QPair, struct) - #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \ F(QSharedPointer) \ F(QWeakPointer) \ @@ -872,6 +876,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER) #undef Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER +Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::vector) +Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::list) + #define Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \ template <class T1, class T2> CPPTYPE TEMPLATENAME; \ Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME) @@ -880,6 +887,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER) #undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER +Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair) +Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::map) + #define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \ Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME) diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index e0c7f171c3..6c88ed4531 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -181,17 +181,16 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent) : QObject(*new QSocketNotifierPrivate, parent) { Q_D(QSocketNotifier); - if (socket < 0) - qWarning("QSocketNotifier: Invalid socket specified"); d->sockfd = socket; d->sntype = type; d->snenabled = true; - if (!d->threadData->eventDispatcher.load()) { + if (socket < 0) + qWarning("QSocketNotifier: Invalid socket specified"); + else if (!d->threadData->eventDispatcher.load()) qWarning("QSocketNotifier: Can only be used with threads started with QThread"); - } else { + else d->threadData->eventDispatcher.load()->registerSocketNotifier(this); - } } /*! diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index e3b76886f1..fecb9120eb 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -516,6 +516,60 @@ Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator } //namespace QAlgorithmsPrivate +Q_DECL_CONSTEXPR inline uint qPopulationCount(quint32 v) +{ +#ifdef Q_CC_GNU + return __builtin_popcount(v); +#else + // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + return + (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 24) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; +#endif +} + +Q_DECL_CONSTEXPR inline uint qPopulationCount(quint8 v) +{ +#ifdef Q_CC_GNU + return __builtin_popcount(v); +#else + return + (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; +#endif +} + +Q_DECL_CONSTEXPR inline uint qPopulationCount(quint16 v) +{ +#ifdef Q_CC_GNU + return __builtin_popcount(v); +#else + return + (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; +#endif +} + +Q_DECL_CONSTEXPR inline uint qPopulationCount(quint64 v) +{ +#ifdef Q_CC_GNU + return __builtin_popcountll(v); +#else + return + (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 24) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 36) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 48) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f + + (((v >> 60) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; +#endif +} + +Q_DECL_CONSTEXPR inline uint qPopulationCount(long unsigned int v) +{ + return qPopulationCount(static_cast<quint64>(v)); +} + QT_END_NAMESPACE #endif // QALGORITHMS_H diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index cc544af868..7c3aa1a3b2 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -635,3 +635,34 @@ of \a value in the variable passed as a reference in argument \a n. \sa {qLess()}{qLess<T>()} */ + + +/*! + \fn uint qPopulationCount(quint8 v) + \relates <QtAlgorithms> + \since 5.2 + + Returns the number of bits set in \a v. This number also called + the Hamming Weight of \a v. + */ + +/*! + \fn uint qPopulationCount(quint16 v) + \relates <QtAlgorithms> + \since 5.2 + \overload + */ + +/*! + \fn uint qPopulationCount(quint32 v) + \relates <QtAlgorithms> + \since 5.2 + \overload + */ + +/*! + \fn uint qPopulationCount(quint64 v) + \relates <QtAlgorithms> + \since 5.2 + \overload + */ diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 2b459b2b1b..4949476f25 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qbitarray.h" +#include <qalgorithms.h> #include <qdatastream.h> #include <qdebug.h> #include <string.h> @@ -159,24 +160,18 @@ int QBitArray::count(bool on) const for (int i = 0; i < len; ++i) numBits += testBit(i); #else - // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1; while (len >= 32) { quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24); - quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; - c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; - c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; len -= 32; bits += 4; - numBits += int(c); + numBits += int(qPopulationCount(v)); } while (len >= 24) { quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16); - quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; - c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; len -= 24; bits += 3; - numBits += int(c); + numBits += int(qPopulationCount(v)); } while (len >= 0) { if (bits[len / 8] & (1 << ((len - 1) & 7))) diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 1103712627..eaf9b2ff25 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -61,6 +61,7 @@ public: QBitArray(const QBitArray &other) : d(other.d) {} inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } #ifdef Q_COMPILER_RVALUE_REFS + inline QBitArray(QBitArray &&other) : d(std::move(other.d)) {} inline QBitArray &operator=(QBitArray &&other) { qSwap(d, other.d); return *this; } #endif diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h index 27ddb44e91..1471fd5712 100644 --- a/src/corelib/tools/qharfbuzz_p.h +++ b/src/corelib/tools/qharfbuzz_p.h @@ -140,20 +140,6 @@ typedef enum { HB_ScriptCount = HB_Script_Inherited } HB_Script; -typedef enum { - HB_NoJustification= 0, /* Justification can't be applied after this glyph */ - HB_Arabic_Space = 1, /* This glyph represents a space inside arabic text */ - HB_Character = 2, /* Inter-character justification point follows this glyph */ - HB_Space = 4, /* This glyph represents a blank outside an Arabic run */ - HB_Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */ - HB_Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */ - HB_Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */ - HB_Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */ - HB_Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */ - HB_Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */ - HB_Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */ -} HB_JustificationClass; - #ifdef __xlC__ typedef unsigned hb_bitfield; #else diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index d5c3637293..1390c67c80 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -70,6 +70,7 @@ public: inline QSet<T> &operator=(const QSet<T> &other) { q_hash = other.q_hash; return *this; } #ifdef Q_COMPILER_RVALUE_REFS + inline QSet(QSet &&other) : q_hash(qMove(other.q_hash)) {} inline QSet<T> &operator=(QSet<T> &&other) { qSwap(q_hash, other.q_hash); return *this; } #endif diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index e81bea69d6..f1a78b508c 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -62,6 +62,10 @@ public: QIcon(); QIcon(const QPixmap &pixmap); QIcon(const QIcon &other); +#ifdef Q_COMPILER_RVALUE_REFS + QIcon(QIcon &&other) + :d(0) { qSwap(d, other.d); } +#endif explicit QIcon(const QString &fileName); // file or resource name explicit QIcon(QIconEngine *engine); ~QIcon(); diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 50d4bc7666..a4aaf049f0 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -139,6 +139,11 @@ public: explicit QImage(const QString &fileName, const char *format = 0); QImage(const QImage &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QImage(QImage &&other) + : QPaintDevice(), d(0) + { qSwap(d, other.d); } +#endif ~QImage(); QImage &operator=(const QImage &); diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 47ba27d72a..aadcc0f686 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -91,9 +91,12 @@ SSE2_SOURCES += painting/qdrawhelper_sse2.cpp SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp AVX_SOURCES += painting/qdrawhelper_avx.cpp -NEON_SOURCES += painting/qdrawhelper_neon.cpp -NEON_HEADERS += painting/qdrawhelper_neon_p.h -NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S + +!ios { + NEON_SOURCES += painting/qdrawhelper_neon.cpp + NEON_HEADERS += painting/qdrawhelper_neon_p.h + NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S +} MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 628d12d881..651949192b 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6162,7 +6162,7 @@ void qInitDrawhelperAsm() } #endif // IWMMXT -#if defined(QT_COMPILER_SUPPORTS_NEON) +#if defined(QT_COMPILER_SUPPORTS_NEON) && !defined(Q_OS_IOS) if (features & NEON) { qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 2fa7f0232d..229db80186 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -59,9 +59,9 @@ #include <algorithm> #include <stdlib.h> +#ifndef QT_NO_RAWFONT #include "qfontengine_qpa_p.h" - -#include <private/qharfbuzz_p.h> +#endif QT_BEGIN_NAMESPACE @@ -838,21 +838,6 @@ void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrd #endif } -// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item. -static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine) -{ - int nGlyphs = item->num_glyphs; - - QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly); - if (item->item.bidiLevel % 2) - shaperFlags |= QFontEngine::RightToLeft; - - bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags); - item->num_glyphs = nGlyphs; - glyphs->numGlyphs = nGlyphs; - return result; -} - // shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line. void QTextEngine::shapeLine(const QScriptLine &line) { @@ -892,19 +877,48 @@ void QTextEngine::shapeText(int item) const if (si.num_glyphs) return; - shapeTextWithHarfbuzz(item); - si.width = 0; + si.glyph_data_offset = layoutData->used; - if (!si.num_glyphs) - return; - QGlyphLayout glyphs = shapedGlyphs(&si); + const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.constData()) + si.position; + const int itemLength = length(item); + + if (!ensureSpace(itemLength)) + return; // ### report OOM error somehow + + QString casedString; + if (si.analysis.flags && si.analysis.flags <= QScriptAnalysis::SmallCaps) { + casedString.resize(itemLength); + ushort *uc = reinterpret_cast<ushort *>(casedString.data()); + for (int i = 0; i < itemLength; ++i) { + uint ucs4 = string[i]; + if (QChar::isHighSurrogate(ucs4) && i + 1 < itemLength) { + uint low = string[i + 1]; + if (QChar::isLowSurrogate(low)) { + ++i; + ucs4 = QChar::surrogateToUcs4(ucs4, low); + ucs4 = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4) + : QChar::toUpper(ucs4); + // high part never changes in simple casing + uc[i] = QChar::lowSurrogate(ucs4); + } + } else { + uc[i] = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4) + : QChar::toUpper(ucs4); + } + } + string = reinterpret_cast<const ushort *>(casedString.constData()); + } + QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading); + + bool kerningEnabled; bool letterSpacingIsAbsolute; QFixed letterSpacing, wordSpacing; #ifndef QT_NO_RAWFONT if (useRawFont) { QTextCharFormat f = format(&si); + kerningEnabled = f.fontKerning(); wordSpacing = QFixed::fromReal(f.fontWordSpacing()); letterSpacing = QFixed::fromReal(f.fontLetterSpacing()); letterSpacingIsAbsolute = true; @@ -912,6 +926,7 @@ void QTextEngine::shapeText(int item) const #endif { QFont font = this->font(si); + kerningEnabled = font.d->kerning; letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute; letterSpacing = font.d->letterSpacing; wordSpacing = font.d->wordSpacing; @@ -920,6 +935,13 @@ void QTextEngine::shapeText(int item) const letterSpacing *= font.d->dpi / qt_defaultDpiY(); } + si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, kerningEnabled); + if (!si.num_glyphs) + return; // ### report shaping errors somehow + layoutData->used += si.num_glyphs; + + QGlyphLayout glyphs = shapedGlyphs(&si); + if (letterSpacing != 0) { for (int i = 1; i < si.num_glyphs; ++i) { if (glyphs.attributes[i].clusterStart) { @@ -940,12 +962,12 @@ void QTextEngine::shapeText(int item) const } if (wordSpacing != 0) { for (int i = 0; i < si.num_glyphs; ++i) { - if (glyphs.attributes[i].justification == HB_Space - || glyphs.attributes[i].justification == HB_Arabic_Space) { + if (glyphs.attributes[i].justification == QGlyphAttributes::Space + || glyphs.attributes[i].justification == QGlyphAttributes::Arabic_Space) { // word spacing only gets added once to a consecutive run of spaces (see CSS spec) if (i + 1 == si.num_glyphs - ||(glyphs.attributes[i+1].justification != HB_Space - && glyphs.attributes[i+1].justification != HB_Arabic_Space)) + ||(glyphs.attributes[i+1].justification != QGlyphAttributes::Space + && glyphs.attributes[i+1].justification != QGlyphAttributes::Arabic_Space)) glyphs.advances_x[i] += wordSpacing; } } @@ -955,14 +977,6 @@ void QTextEngine::shapeText(int item) const si.width += glyphs.advances_x[i] * !glyphs.attributes[i].dontPrint; } -static inline bool hasCaseChange(const QScriptItem &si) -{ - return si.analysis.flags == QScriptAnalysis::SmallCaps || - si.analysis.flags == QScriptAnalysis::Uppercase || - si.analysis.flags == QScriptAnalysis::Lowercase; -} - - static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num) { if (num > 0 && destination.glyphs != source.glyphs) { @@ -973,84 +987,60 @@ static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLa } } +QT_BEGIN_INCLUDE_NAMESPACE + +#include <private/qharfbuzz_p.h> + +QT_END_INCLUDE_NAMESPACE + Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t)); Q_STATIC_ASSERT(sizeof(HB_GlyphAttributes) == sizeof(QGlyphAttributes)); Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed)); Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint)); -/// take the item from layoutData->items and -void QTextEngine::shapeTextWithHarfbuzz(int item) const +// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item. +static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine) { - QScriptItem &si = layoutData->items[item]; - - si.glyph_data_offset = layoutData->used; + int nGlyphs = item->num_glyphs; - QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); + QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly); + if (item->item.bidiLevel % 2) + shaperFlags |= QFontEngine::RightToLeft; - bool kerningEnabled; -#ifndef QT_NO_RAWFONT - if (useRawFont) { - QTextCharFormat f = format(&si); - kerningEnabled = f.fontKerning(); - } else -#endif - kerningEnabled = this->font(si).d->kerning; + bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags); + item->num_glyphs = nGlyphs; + glyphs->numGlyphs = nGlyphs; + return result; +} +int QTextEngine::shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const +{ HB_ShaperItem entire_shaper_item; memset(&entire_shaper_item, 0, sizeof(entire_shaper_item)); - entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData()); - entire_shaper_item.stringLength = layoutData->string.length(); + entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(string); + entire_shaper_item.stringLength = itemLength; entire_shaper_item.item.script = script_to_hbscript(si.analysis.script); - entire_shaper_item.item.pos = si.position; - entire_shaper_item.item.length = length(item); + entire_shaper_item.item.pos = 0; + entire_shaper_item.item.length = itemLength; entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel; - QVarLengthArray<HB_UChar16, 256> casedString; - if (hasCaseChange(si)) { - if (casedString.size() < static_cast<int>(entire_shaper_item.item.length)) - casedString.resize(entire_shaper_item.item.length); - HB_UChar16 *uc = casedString.data(); - for (uint i = 0; i < entire_shaper_item.item.length; ++i) { - uint ucs4 = entire_shaper_item.string[si.position + i]; - if (QChar::isHighSurrogate(ucs4)) { - uc[i] = ucs4; // high part never changes in simple casing - if (i + 1 < entire_shaper_item.item.length) { - ushort low = entire_shaper_item.string[si.position + i + 1]; - if (QChar::isLowSurrogate(low)) { - ucs4 = QChar::surrogateToUcs4(ucs4, low); - ucs4 = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4) - : QChar::toUpper(ucs4); - uc[++i] = QChar::lowSurrogate(ucs4); - } - } - } else { - uc[i] = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4) - : QChar::toUpper(ucs4); - } - } - entire_shaper_item.item.pos = 0; - entire_shaper_item.string = uc; - entire_shaper_item.stringLength = entire_shaper_item.item.length; - } - entire_shaper_item.shaperFlags = 0; if (!kerningEnabled) entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning; if (option.useDesignMetrics()) entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics; - entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length)); - if (!ensureSpace(entire_shaper_item.num_glyphs)) - return; + entire_shaper_item.num_glyphs = itemLength; + QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); - if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { + if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) { if (!ensureSpace(entire_shaper_item.num_glyphs)) - return; + return 0; initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); - if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { + if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, fontEngine)) { // ############ if this happens there's a bug in the fontengine - return; + return 0; } } @@ -1060,7 +1050,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const itemBoundaries[0] = entire_shaper_item.item.pos; itemBoundaries[1] = 0; - if (font->type() == QFontEngine::Multi) { + if (fontEngine->type() == QFontEngine::Multi) { uint lastEngine = 0; int charIdx = entire_shaper_item.item.pos; const int stringEnd = charIdx + entire_shaper_item.item.length; @@ -1099,18 +1089,17 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const if (shaper_item.num_glyphs < shaper_item.item.length) shaper_item.num_glyphs = shaper_item.item.length; - QFontEngine *actualFontEngine = font; + QFontEngine *actualFontEngine = fontEngine; uint engineIdx = 0; - if (font->type() == QFontEngine::Multi) { + if (fontEngine->type() == QFontEngine::Multi) { engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24); - actualFontEngine = static_cast<QFontEngineMulti *>(font)->engine(engineIdx); + actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); + si.ascent = qMax(actualFontEngine->ascent(), si.ascent); + si.descent = qMax(actualFontEngine->descent(), si.descent); + si.leading = qMax(actualFontEngine->leading(), si.leading); } - si.ascent = qMax(actualFontEngine->ascent(), si.ascent); - si.descent = qMax(actualFontEngine->descent(), si.descent); - si.leading = qMax(actualFontEngine->leading(), si.leading); - shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont(); shaper_item.face = (HB_Face)actualFontEngine->harfbuzzFace(); @@ -1120,7 +1109,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const do { if (!ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) - return; + return 0; const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); if (shaper_item.num_glyphs > shaper_item.item.length) @@ -1137,8 +1126,6 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const } shaper_item.log_clusters = logClusters(&si) + shaper_item.item.pos - entire_shaper_item.item.pos; - -// qDebug(" .. num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs); } while (!qShapeItem(&shaper_item)); // this does the actual shaping via harfbuzz. QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs); @@ -1158,10 +1145,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const glyph_pos += shaper_item.num_glyphs; } -// qDebug(" -> item: script=%d num_glyphs=%d", shaper_item.script, shaper_item.num_glyphs); - si.num_glyphs = glyph_pos; - - layoutData->used += si.num_glyphs; + return glyph_pos; } void QTextEngine::init(QTextEngine *e) @@ -1821,7 +1805,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph, point->type = type; point->glyph = glyph; - if (type >= HB_Arabic_Normal) { + if (type >= QGlyphAttributes::Arabic_Normal) { QChar ch(0x640); // Kashida character QGlyphLayoutArray<8> glyphs; int nglyphs = 7; @@ -1829,7 +1813,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph, if (glyphs.glyphs[0] && glyphs.advances_x[0] != 0) { point->kashidaWidth = glyphs.advances_x[0]; } else { - point->type = HB_NoJustification; + point->type = QGlyphAttributes::NoJustification; point->kashidaWidth = 0; } } @@ -1897,7 +1881,7 @@ void QTextEngine::justify(const QScriptLine &line) for (int i = 0; i < nItems; ++i) { QScriptItem &si = layoutData->items[firstItem + i]; - int kashida_type = HB_Arabic_Normal; + int kashida_type = QGlyphAttributes::Arabic_Normal; int kashida_pos = -1; int start = qMax(line.from - si.position, 0); @@ -1921,11 +1905,11 @@ void QTextEngine::justify(const QScriptLine &line) int justification = g.attributes[i].justification; switch(justification) { - case HB_NoJustification: + case QGlyphAttributes::NoJustification: break; - case HB_Space : + case QGlyphAttributes::Space : // fall through - case HB_Arabic_Space : + case QGlyphAttributes::Arabic_Space : if (kashida_pos >= 0) { // qDebug("kashida position at %d in word", kashida_pos); set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si)); @@ -1936,19 +1920,19 @@ void QTextEngine::justify(const QScriptLine &line) } } kashida_pos = -1; - kashida_type = HB_Arabic_Normal; + kashida_type = QGlyphAttributes::Arabic_Normal; // fall through - case HB_Character : + case QGlyphAttributes::Character : set(&justificationPoints[nPoints++], justification, g.mid(i), fontEngine(si)); maxJustify = qMax(maxJustify, justification); break; - case HB_Arabic_Normal : - case HB_Arabic_Waw : - case HB_Arabic_BaRa : - case HB_Arabic_Alef : - case HB_Arabic_HaaDal : - case HB_Arabic_Seen : - case HB_Arabic_Kashida : + case QGlyphAttributes::Arabic_Normal : + case QGlyphAttributes::Arabic_Waw : + case QGlyphAttributes::Arabic_BaRa : + case QGlyphAttributes::Arabic_Alef : + case QGlyphAttributes::Arabic_HaaDal : + case QGlyphAttributes::Arabic_Seen : + case QGlyphAttributes::Arabic_Kashida : if (justification >= kashida_type) { kashida_pos = i; kashida_type = justification; @@ -1977,9 +1961,9 @@ void QTextEngine::justify(const QScriptLine &line) // qDebug(" minKashida=%f, need=%f", minKashida.toReal(), need.toReal()); // distribute in priority order - if (maxJustify >= HB_Arabic_Normal) { + if (maxJustify >= QGlyphAttributes::Arabic_Normal) { while (need >= minKashida) { - for (int type = maxJustify; need >= minKashida && type >= HB_Arabic_Normal; --type) { + for (int type = maxJustify; need >= minKashida && type >= QGlyphAttributes::Arabic_Normal; --type) { for (int i = 0; need >= minKashida && i < nPoints; ++i) { if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) { justificationPoints[i].glyph.justifications->nKashidas++; @@ -1996,7 +1980,7 @@ void QTextEngine::justify(const QScriptLine &line) if (!need) goto end; - maxJustify = qMin(maxJustify, (int)HB_Space); + maxJustify = qMin(maxJustify, int(QGlyphAttributes::Space)); for (int type = maxJustify; need != 0 && type > 0; --type) { int n = 0; for (int i = 0; i < nPoints; ++i) { @@ -2438,12 +2422,13 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int const int end = si.position + length(&si); for (int i = si.position; i < end - 1; ++i) { - if (layoutData->string.at(i) == QLatin1Char('&')) { + if (layoutData->string.at(i) == QLatin1Char('&') + && !attributes[i + 1].whiteSpace && attributes[i + 1].graphemeBoundary) { const int gp = logClusters[i - si.position]; glyphs.attributes[gp].dontPrint = true; - attributes[i + 1].graphemeBoundary = false; - attributes[i + 1].lineBreak = false; - attributes[i + 1].whiteSpace = false; + // emulate grapheme cluster + attributes[i] = attributes[i + 1]; + memset(attributes + i + 1, 0, sizeof(QCharAttributes)); if (layoutData->string.at(i + 1) == QLatin1Char('&')) ++i; } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index ec7f7407b2..6d46231c67 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -96,6 +96,20 @@ typedef quint8 q_hb_bitfield; #endif typedef struct { + typedef enum { + NoJustification= 0, /* Justification can't be applied after this glyph */ + Arabic_Space = 1, /* This glyph represents a space inside arabic text */ + Character = 2, /* Inter-character justification point follows this glyph */ + Space = 4, /* This glyph represents a blank outside an Arabic run */ + Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */ + Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */ + Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */ + Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */ + Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */ + Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */ + Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */ + } JustificationClass; + q_hb_bitfield justification :4; /* Justification class */ q_hb_bitfield clusterStart :1; /* First glyph of representation of cluster */ q_hb_bitfield mark :1; /* needs to be positioned around base char */ @@ -685,7 +699,7 @@ private: void setBoundary(int strPos) const; void addRequiredBoundaries() const; void shapeText(int item) const; - void shapeTextWithHarfbuzz(int item) const; + int shapeTextWithHarfbuzz(QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, bool kerningEnabled) const; void splitItem(int item, int pos) const; int endOfLine(int lineNum); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 83cb729589..8c671a8c99 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -431,6 +431,7 @@ static void ensureInitialized() QNetworkAccessManager::QNetworkAccessManager(QObject *parent) : QObject(*new QNetworkAccessManagerPrivate, parent) { + Q_D(QNetworkAccessManager); ensureInitialized(); qRegisterMetaType<QNetworkReply::NetworkError>(); @@ -447,6 +448,19 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) #endif qRegisterMetaType<QNetworkReply::NetworkError>(); qRegisterMetaType<QSharedPointer<char> >(); + +#ifndef QT_NO_BEARERMANAGEMENT + if (!d->networkSessionRequired) { + // if a session is required, we track online state through + // the QNetworkSession's signals + connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); + // we would need all active configurations to check for + // d->networkConfigurationManager.isOnline(), which is asynchronous + // and potentially expensive. We can just check the configuration here + d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); + } +#endif } /*! @@ -833,6 +847,11 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ To restore the default network configuration set the network configuration to the value returned from QNetworkConfigurationManager::defaultConfiguration(). + Setting a network configuration means that the QNetworkAccessManager instance will only + be using the specified one. In particular, if the default network configuration changes + (upon e.g. Wifi being available), this new configuration needs to be enabled + manually if desired. + \snippet code/src_network_access_qnetworkaccessmanager.cpp 2 If an invalid network configuration is set, a network session will not be created. In this @@ -844,7 +863,10 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ */ void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config) { - d_func()->createSession(config); + Q_D(QNetworkAccessManager); + d->networkConfiguration = config; + d->customNetworkConfiguration = true; + d->createSession(config); } /*! @@ -926,16 +948,23 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess { Q_D(const QNetworkAccessManager); - QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); - if (networkSession) { - // d->online holds online/offline state of this network session. + if (d->networkSessionRequired) { + QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); + if (networkSession) { + // d->online holds online/offline state of this network session. + if (d->online) + return d->networkAccessible; + else + return NotAccessible; + } else { + // Network accessibility is either disabled or unknown. + return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility; + } + } else { if (d->online) return d->networkAccessible; else return NotAccessible; - } else { - // Network accessibility is either disabled or unknown. - return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility; } } @@ -1050,10 +1079,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera return new QDisabledNetworkReply(this, req, op); } - if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.isEmpty())) { + if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { QNetworkConfigurationManager manager; - if (!d->networkConfiguration.isEmpty()) { - d->createSession(manager.configurationFromIdentifier(d->networkConfiguration)); + if (!d->networkConfiguration.identifier().isEmpty()) { + d->createSession(d->networkConfiguration); } else { if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) d->createSession(manager.defaultConfiguration()); @@ -1403,7 +1432,7 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() Q_Q(QNetworkAccessManager); QSharedPointer<QNetworkSession> networkSession(getNetworkSession()); if (networkSession) { - networkConfiguration = networkSession->configuration().identifier(); + networkConfiguration = networkSession->configuration(); //disconnect from old session QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); @@ -1437,6 +1466,18 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession } } } + +void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) +{ + // if the user set a config, we only care whether this one is active. + // Otherwise, this QNAM is online if there is an online config. + if (customNetworkConfiguration) { + online = (networkConfiguration.state() & QNetworkConfiguration::Active); + } else { + online = isOnline; + } +} + #endif // QT_NO_BEARERMANAGEMENT QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 826c8e47d7..ac8d58522b 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -165,6 +165,7 @@ private: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) + Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) #endif }; diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index cf756dad7b..ec4fb24371 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -60,6 +60,9 @@ #include "QtNetwork/qnetworkproxy.h" #include "QtNetwork/qnetworksession.h" #include "qnetworkaccessauthenticationmanager_p.h" +#ifndef QT_NO_BEARERMANAGEMENT +#include "QtNetwork/qnetworkconfigmanager.h" +#endif QT_BEGIN_NAMESPACE @@ -79,6 +82,10 @@ public: #endif #ifndef QT_NO_BEARERMANAGEMENT lastSessionState(QNetworkSession::Invalid), + networkConfiguration(networkConfigurationManager.defaultConfiguration()), + customNetworkConfiguration(false), + networkSessionRequired(networkConfigurationManager.capabilities() + & QNetworkConfigurationManager::NetworkSessionRequired), networkAccessible(QNetworkAccessManager::Accessible), activeReplyCount(0), online(false), @@ -127,6 +134,7 @@ public: void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); void _q_networkSessionStateChanged(QNetworkSession::State state); + void _q_onlineStateChanged(bool isOnline); #endif QNetworkRequest prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart); @@ -148,7 +156,12 @@ public: QSharedPointer<QNetworkSession> networkSessionStrongRef; QWeakPointer<QNetworkSession> networkSessionWeakRef; QNetworkSession::State lastSessionState; - QString networkConfiguration; + QNetworkConfigurationManager networkConfigurationManager; + QNetworkConfiguration networkConfiguration; + // we need to track whether the user set a config or not, + // because the default config might change + bool customNetworkConfiguration; + bool networkSessionRequired; QNetworkAccessManager::NetworkAccessibility networkAccessible; int activeReplyCount; bool online; diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp index 58f24c0a04..80453816fc 100644 --- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp +++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp @@ -41,17 +41,6 @@ #include "qxlibeglintegration_p.h" -static int countBits(unsigned long mask) -{ - int count = 0; - while (mask != 0) { - if (mask & 1) - ++count; - mask >>= 1; - } - return count; -} - VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config) { VisualID visualId = 0; @@ -92,9 +81,9 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay return visualId; } - int visualRedSize = countBits(chosenVisualInfo->red_mask); - int visualGreenSize = countBits(chosenVisualInfo->green_mask); - int visualBlueSize = countBits(chosenVisualInfo->blue_mask); + int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask); + int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask); + int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask); int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size bool visualMatchesConfig = false; diff --git a/src/plugins/platforms/ios/plugin.pro b/src/plugins/platforms/ios/plugin.pro index 591a0a67ed..5f46ea7ef5 100644 --- a/src/plugins/platforms/ios/plugin.pro +++ b/src/plugins/platforms/ios/plugin.pro @@ -4,7 +4,7 @@ PLUGIN_TYPE = platforms load(qt_plugin) QT += core-private gui-private platformsupport-private -LIBS += -framework UIKit -framework QuartzCore +LIBS += -framework Foundation -framework UIKit -framework QuartzCore OBJECTIVE_SOURCES = \ plugin.mm \ diff --git a/src/plugins/platforms/qnx/main.cpp b/src/plugins/platforms/qnx/main.cpp index ea50b12cb3..fb81928625 100644 --- a/src/plugins/platforms/qnx/main.cpp +++ b/src/plugins/platforms/qnx/main.cpp @@ -46,9 +46,8 @@ QT_BEGIN_NAMESPACE QPlatformIntegration *QQnxIntegrationPlugin::create(const QString& system, const QStringList& paramList) { - Q_UNUSED(paramList); if (system.toLower() == QLatin1String("qnx")) - return new QQnxIntegration; + return new QQnxIntegration(paramList); return 0; } diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 203cdebda9..50884ace66 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -11,11 +11,11 @@ QT += platformsupport platformsupport-private CONFIG(blackberry) { CONFIG += qqnx_pps - # Unomment this to enable screen event handling - # through a dedicated thread. - # DEFINES += QQNX_SCREENEVENTTHREAD + # Uncomment following line to enable screen event + # handling through a dedicated thread. + # CONFIG += qqnx_screeneventthread } else { - DEFINES += QQNX_SCREENEVENTTHREAD + CONFIG += qqnx_screeneventthread } # Uncomment these to enable debugging output for various aspects of the plugin @@ -40,11 +40,11 @@ CONFIG(blackberry) { #DEFINES += QQNXVIRTUALKEYBOARD_DEBUG #DEFINES += QQNXWINDOW_DEBUG #DEFINES += QQNXCURSOR_DEBUG +#DEFINES += QQNXFILEPICKER_DEBUG SOURCES = main.cpp \ qqnxbuffer.cpp \ - qqnxscreeneventthread.cpp \ qqnxintegration.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ @@ -60,7 +60,6 @@ SOURCES = main.cpp \ HEADERS = main.h \ qqnxbuffer.h \ - qqnxscreeneventthread.h \ qqnxkeytranslator.h \ qqnxintegration.h \ qqnxscreen.h \ @@ -75,6 +74,12 @@ HEADERS = main.h \ qqnxservices.h \ qqnxcursor.h +CONFIG(qqnx_screeneventthread) { + DEFINES += QQNX_SCREENEVENTTHREAD + SOURCES += qqnxscreeneventthread.cpp + HEADERS += qqnxscreeneventthread.h +} + LIBS += -lscreen contains(QT_CONFIG, opengles2) { @@ -91,8 +96,7 @@ CONFIG(blackberry) { qqnxbpseventfilter.cpp \ qqnxvirtualkeyboardbps.cpp \ qqnxtheme.cpp \ - qqnxsystemsettings.cpp \ - qqnxfiledialoghelper.cpp + qqnxsystemsettings.cpp HEADERS += qqnxnavigatorbps.h \ qqnxeventdispatcher_blackberry.h \ @@ -105,6 +109,17 @@ CONFIG(blackberry) { LIBS += -lbps } +CONFIG(blackberry-playbook) { + SOURCES += qqnxfiledialoghelper_playbook.cpp +} else { + CONFIG(blackberry) { + SOURCES += qqnxfiledialoghelper_bb10.cpp \ + qqnxfilepicker.cpp + + HEADERS += qqnxfilepicker.h + } +} + CONFIG(qqnx_pps) { DEFINES += QQNX_PPS diff --git a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp index d94d3c092a..133bf02fee 100644 --- a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp +++ b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp @@ -41,11 +41,12 @@ #include "qqnxbpseventfilter.h" #include "qqnxnavigatoreventhandler.h" -#include "qqnxfiledialoghelper.h" #include "qqnxscreen.h" #include "qqnxscreeneventhandler.h" #include "qqnxvirtualkeyboardbps.h" +#include "qqnxfiledialoghelper.h" +#include <QCoreApplication> #include <QAbstractEventDispatcher> #include <QDebug> @@ -126,6 +127,7 @@ void QQnxBpsEventFilter::unregisterForScreenEvents(QQnxScreen *screen) qWarning("QQNX: failed to unregister for screen events on screen %p", screen->nativeContext()); } +#if defined(Q_OS_BLACKBERRY_TABLET) void QQnxBpsEventFilter::registerForDialogEvents(QQnxFileDialogHelper *dialog) { if (dialog_request_events(0) != BPS_SUCCESS) @@ -141,6 +143,7 @@ void QQnxBpsEventFilter::unregisterForDialogEvents(QQnxFileDialogHelper *dialog) if (count == 0) qWarning("QQNX: attempting to unregister dialog that was not registered"); } +#endif // Q_OS_BLACKBERRY_TABLET bool QQnxBpsEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { @@ -160,12 +163,14 @@ bool QQnxBpsEventFilter::nativeEventFilter(const QByteArray &eventType, void *me return m_screenEventHandler->handleEvent(screenEvent); } +#if defined(Q_OS_BLACKBERRY_TABLET) if (eventDomain == dialog_get_domain()) { dialog_instance_t nativeDialog = dialog_event_get_dialog_instance(event); QQnxFileDialogHelper *dialog = m_dialogMapper.value(nativeDialog, 0); if (dialog) return dialog->handleEvent(event); } +#endif if (eventDomain == navigator_get_domain()) return handleNavigatorEvent(event); @@ -244,6 +249,11 @@ bool QQnxBpsEventFilter::handleNavigatorEvent(bps_event_t *event) break; } + case NAVIGATOR_LOW_MEMORY: + qWarning() << "QGuiApplication based process" << QCoreApplication::applicationPid() + << "received \"NAVIGATOR_LOW_MEMORY\" event"; + return false; + default: qBpsEventFilterDebug() << Q_FUNC_INFO << "Unhandled navigator event. code=" << bps_event_get_code(event); return false; diff --git a/src/plugins/platforms/qnx/qqnxbpseventfilter.h b/src/plugins/platforms/qnx/qqnxbpseventfilter.h index e897863efb..f8e36823d5 100644 --- a/src/plugins/platforms/qnx/qqnxbpseventfilter.h +++ b/src/plugins/platforms/qnx/qqnxbpseventfilter.h @@ -73,8 +73,10 @@ public: void registerForScreenEvents(QQnxScreen *screen); void unregisterForScreenEvents(QQnxScreen *screen); +#ifdef Q_OS_BLACKBERRY_TABLET void registerForDialogEvents(QQnxFileDialogHelper *dialog); void unregisterForDialogEvents(QQnxFileDialogHelper *dialog); +#endif private: bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h index e17ea80501..ad2483365b 100644 --- a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h +++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h @@ -44,12 +44,19 @@ #include <qpa/qplatformdialoghelper.h> -#include <bps/dialog.h> QT_BEGIN_NAMESPACE class QQnxIntegration; +#if defined(Q_OS_BLACKBERRY_TABLET) +#include <bps/dialog.h> +#define NativeDialogPtr dialog_instance_t +#else +class QQnxFilePicker; +#define NativeDialogPtr QQnxFilePicker * +#endif + class QQnxFileDialogHelper : public QPlatformFileDialogHelper { Q_OBJECT @@ -57,7 +64,9 @@ public: explicit QQnxFileDialogHelper(const QQnxIntegration *); ~QQnxFileDialogHelper(); +#if defined(Q_OS_BLACKBERRY_TABLET) bool handleEvent(bps_event_t *event); +#endif void exec(); @@ -73,21 +82,24 @@ public: void selectNameFilter(const QString &filter); QString selectedNameFilter() const; - dialog_instance_t nativeDialog() const { return m_dialog; } + NativeDialogPtr nativeDialog() const { return m_dialog; } Q_SIGNALS: void dialogClosed(); private: void setNameFilter(const QString &filter); + void setNameFilters(const QStringList &filters); const QQnxIntegration *m_integration; - dialog_instance_t m_dialog; + NativeDialogPtr m_dialog; QFileDialogOptions::AcceptMode m_acceptMode; QString m_selectedFilter; QPlatformDialogHelper::DialogCode m_result; +#if defined(Q_OS_BLACKBERRY_TABLET) QStringList m_paths; +#endif }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp b/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp new file mode 100644 index 0000000000..f4c48610a6 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp @@ -0,0 +1,209 @@ +/*************************************************************************** +** +** Copyright (C) 2013 Research In Motion +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqnxfiledialoghelper.h" + +#include "qqnxfilepicker.h" +#include "qqnxbpseventfilter.h" +#include "qqnxscreen.h" +#include "qqnxintegration.h" + +#include <QDebug> +#include <QEventLoop> +#include <QScreen> +#include <QTimer> +#include <QWindow> + +#ifdef QQNXFILEDIALOGHELPER_DEBUG +#define qFileDialogHelperDebug qDebug +#else +#define qFileDialogHelperDebug QT_NO_QDEBUG_MACRO +#endif + +QT_BEGIN_NAMESPACE + +QQnxFileDialogHelper::QQnxFileDialogHelper(const QQnxIntegration *integration) + : QPlatformFileDialogHelper(), + m_integration(integration), + m_dialog(new QQnxFilePicker), + m_acceptMode(QFileDialogOptions::AcceptOpen), + m_selectedFilter(), + m_result(QPlatformDialogHelper::Rejected) +{ +} + +QQnxFileDialogHelper::~QQnxFileDialogHelper() +{ + delete m_dialog; +} + +void QQnxFileDialogHelper::exec() +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + + // Clear any previous results + m_dialog->setDirectories(QStringList()); + + QEventLoop loop; + connect(m_dialog, SIGNAL(closed()), &loop, SLOT(quit())); + loop.exec(); + + if (m_dialog->selectedFiles().isEmpty()) + Q_EMIT reject(); + else + Q_EMIT accept(); +} + +bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) +{ + Q_UNUSED(flags); + Q_UNUSED(parent); + Q_UNUSED(modality); + + qFileDialogHelperDebug() << Q_FUNC_INFO; + + // Create dialog + const QSharedPointer<QFileDialogOptions> &opts = options(); + if (opts->acceptMode() == QFileDialogOptions::AcceptOpen) { + // Select one or many files? + const QQnxFilePicker::Mode mode = (opts->fileMode() == QFileDialogOptions::ExistingFiles) + ? QQnxFilePicker::PickerMultiple : QQnxFilePicker::Picker; + + m_dialog->setMode(mode); + + // Set the actual list of extensions + if (!opts->nameFilters().isEmpty()) + setNameFilters(opts->nameFilters()); + else + setNameFilter(tr("All files (*.*)")); + } else { + const QQnxFilePicker::Mode mode = (opts->initiallySelectedFiles().count() >= 2) + ? QQnxFilePicker::SaverMultiple : QQnxFilePicker::Saver; + + m_dialog->setMode(mode); + + if (!opts->initiallySelectedFiles().isEmpty()) + m_dialog->setDefaultSaveFileNames(opts->initiallySelectedFiles()); + } + + // Cache the accept mode so we know which functions to use to get the results back + m_acceptMode = opts->acceptMode(); + m_dialog->setTitle(opts->windowTitle()); + m_dialog->open(); + + return true; +} + +void QQnxFileDialogHelper::hide() +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + m_dialog->close(); +} + +bool QQnxFileDialogHelper::defaultNameFilterDisables() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + return false; +} + +void QQnxFileDialogHelper::setDirectory(const QString &directory) +{ + m_dialog->addDirectory(directory); +} + +QString QQnxFileDialogHelper::directory() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + if (!m_dialog->directories().isEmpty()) + return m_dialog->directories().first(); + + return QString(); +} + +void QQnxFileDialogHelper::selectFile(const QString &fileName) +{ + m_dialog->addDefaultSaveFileName(fileName); +} + +QStringList QQnxFileDialogHelper::selectedFiles() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + return m_dialog->selectedFiles(); +} + +void QQnxFileDialogHelper::setFilter() +{ + // No native api to support setting a filter from QDir::Filters + qFileDialogHelperDebug() << Q_FUNC_INFO; +} + +void QQnxFileDialogHelper::selectNameFilter(const QString &filter) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter; + setNameFilter(filter); +} + +QString QQnxFileDialogHelper::selectedNameFilter() const +{ + // For now there is no way for the user to change the selected filter + // so this just reflects what the developer has set programmatically. + qFileDialogHelperDebug() << Q_FUNC_INFO; + return m_selectedFilter; +} + +void QQnxFileDialogHelper::setNameFilter(const QString &filter) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter; + + setNameFilters(QPlatformFileDialogHelper::cleanFilterList(filter)); +} + +void QQnxFileDialogHelper::setNameFilters(const QStringList &filters) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filters =" << filters; + + Q_ASSERT(!filters.isEmpty()); + + m_dialog->setFilters(filters); + m_selectedFilter = filters.first(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp b/src/plugins/platforms/qnx/qqnxfiledialoghelper_playbook.cpp index 0325a33268..12e8d8afbf 100644 --- a/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp +++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper_playbook.cpp @@ -118,7 +118,7 @@ bool QQnxFileDialogHelper::handleEvent(bps_event_t *event) m_result = QPlatformDialogHelper::Rejected; } - emit dialogClosed(); + Q_EMIT dialogClosed(); return true; } @@ -135,9 +135,9 @@ void QQnxFileDialogHelper::exec() loop.exec(); if (m_result == QPlatformDialogHelper::Accepted) - emit accept(); + Q_EMIT accept(); else - emit reject(); + Q_EMIT reject(); } bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) @@ -291,9 +291,15 @@ QString QQnxFileDialogHelper::selectedNameFilter() const void QQnxFileDialogHelper::setNameFilter(const QString &filter) { qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter; + setNameFilters(QPlatformFileDialogHelper::cleanFilterList(filter)); +} + +void QQnxFileDialogHelper::setNameFilters(const QStringList &filters) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filters =" << filters; + + Q_ASSERT(!filters.isEmpty()); - // Extract the globbing expressions - QStringList filters = QPlatformFileDialogHelper::cleanFilterList(filter); char **globs = new char*[filters.size()]; for (int i = 0; i < filters.size(); ++i) { QByteArray glob = filters.at(i).toLocal8Bit(); @@ -303,7 +309,7 @@ void QQnxFileDialogHelper::setNameFilter(const QString &filter) // Set the filters dialog_set_filebrowse_filter(m_dialog, const_cast<const char**>(globs), filters.size()); - m_selectedFilter = filter; + m_selectedFilter = filters.first(); // Cleanup for (int i = 0; i < filters.size(); ++i) diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.cpp b/src/plugins/platforms/qnx/qqnxfilepicker.cpp new file mode 100644 index 0000000000..9326a23b98 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxfilepicker.cpp @@ -0,0 +1,287 @@ +/*************************************************************************** +** +** Copyright (C) 2013 Research In Motion +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqnxfilepicker.h" + +#include <QAbstractEventDispatcher> +#include <QCoreApplication> +#include <QDebug> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QJsonParseError> + +#include <bps/navigator.h> +#include <bps/navigator_invoke.h> + +#include <errno.h> + +#ifdef QQNXFILEPICKER_DEBUG +#define qFilePickerDebug qDebug +#else +#define qFilePickerDebug QT_NO_QDEBUG_MACRO +#endif + +static const char s_filePickerTarget[] = "sys.filepicker.target"; + +QQnxFilePicker::QQnxFilePicker(QObject *parent) + : QObject(parent) + , m_invocationHandle(0) + , m_mode(QQnxFilePicker::Picker) + , m_title(tr("Pick a file")) +{ + QCoreApplication::eventDispatcher()->installNativeEventFilter(this); +} + +QQnxFilePicker::~QQnxFilePicker() +{ + cleanup(); + + QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); +} + +void QQnxFilePicker::open() +{ + if (m_invocationHandle) + return; + + int errorCode = BPS_SUCCESS; + + errorCode = navigator_invoke_invocation_create(&m_invocationHandle); + if (errorCode != BPS_SUCCESS) { + qWarning() << "QQnxFilePicker: unable to create invocation:" << strerror(errno); + return; + } + + errorCode = navigator_invoke_invocation_set_target(m_invocationHandle, s_filePickerTarget); + + if (errorCode != BPS_SUCCESS) { + cleanup(); + qWarning() << "QQnxFilePicker: unable to set target:" << strerror(errno); + return; + } + + errorCode = navigator_invoke_invocation_set_action(m_invocationHandle, "bb.action.OPEN"); + if (errorCode != BPS_SUCCESS) { + cleanup(); + qWarning() << "QQnxFilePicker: unable to set action:" << strerror(errno); + return; + } + + errorCode = navigator_invoke_invocation_set_type(m_invocationHandle, "application/vnd.blackberry.file_picker"); + if (errorCode != BPS_SUCCESS) { + cleanup(); + qWarning() << "QQnxFilePicker: unable to set mime type:" << strerror(errno); + return; + } + + QVariantMap map; + map[QStringLiteral("Type")] = QStringLiteral("Other"); + map[QStringLiteral("Mode")] = modeToString(m_mode); + map[QStringLiteral("Title")] = m_title; + map[QStringLiteral("ViewMode")] = QStringLiteral("Default"); + map[QStringLiteral("SortBy")] = QStringLiteral("Default"); + map[QStringLiteral("SortOrder")] = QStringLiteral("Default"); + map[QStringLiteral("ImageCrop")] = false; + map[QStringLiteral("AllowOverwrite")] = false; + + if (!m_defaultSaveFileNames.isEmpty()) + map[QStringLiteral("DefaultFileNames")] = m_defaultSaveFileNames.join(","); + if (!m_filters.isEmpty()) + map[QStringLiteral("Filter")] = m_filters.join(";"); + + QJsonDocument document; + document.setObject(QJsonObject::fromVariantMap(map)); + const QByteArray jsonData = document.toJson(QJsonDocument::Compact); + + errorCode = navigator_invoke_invocation_set_data(m_invocationHandle, jsonData.constData(), jsonData.size()); + if (errorCode != BPS_SUCCESS) { + cleanup(); + qWarning() << "QQnxFilePicker: unable to set data:" << strerror(errno); + return; + } + + navigator_invoke_invocation_send(m_invocationHandle); +} + +void QQnxFilePicker::close() +{ + navigator_card_close_child(); + cleanup(); +} + +bool QQnxFilePicker::nativeEventFilter(const QByteArray&, void *message, long*) +{ + bps_event_t * const event = static_cast<bps_event_t*>(message); + if (!event) + return false; + + if (bps_event_get_code(event) == NAVIGATOR_INVOKE_TARGET_RESULT) { + const char *id = navigator_event_get_id(event); + const char *err = navigator_event_get_err(event); + qFilePickerDebug("received invocation response: id=%s err=%s", id, err); + } else if (bps_event_get_code(event) == NAVIGATOR_CHILD_CARD_CLOSED) { + const char *data = navigator_event_get_card_closed_data(event); + qFilePickerDebug("received data: data='%s'", data); + handleFilePickerResponse(data); + } + + return false; // do not drop the event +} + +void QQnxFilePicker::setMode(QQnxFilePicker::Mode mode) +{ + m_mode = mode; +} + +void QQnxFilePicker::setDefaultSaveFileNames(const QStringList &fileNames) +{ + m_defaultSaveFileNames = fileNames; +} + +void QQnxFilePicker::addDefaultSaveFileName(const QString &fileName) +{ + m_defaultSaveFileNames.append(fileName); +} + +void QQnxFilePicker::setDirectories(const QStringList &directories) +{ + m_directories = directories; +} + +void QQnxFilePicker::addDirectory(const QString &directory) +{ + m_directories.append(directory); +} + +void QQnxFilePicker::setFilters(const QStringList &filters) +{ + m_filters = filters; +} + +void QQnxFilePicker::setTitle(const QString &title) +{ + m_title = title; +} + +QQnxFilePicker::Mode QQnxFilePicker::mode() const +{ + return m_mode; +} + +QStringList QQnxFilePicker::defaultSaveFileNames() const +{ + return m_defaultSaveFileNames; +} + +QStringList QQnxFilePicker::directories() const +{ + return m_directories; +} + +QStringList QQnxFilePicker::filters() const +{ + return m_filters; +} + +QStringList QQnxFilePicker::selectedFiles() const +{ + return m_selectedFiles; +} + +QString QQnxFilePicker::title() const +{ + return m_title; +} + +void QQnxFilePicker::cleanup() +{ + if (m_invocationHandle) { + navigator_invoke_invocation_destroy(m_invocationHandle); + m_invocationHandle = 0; + } +} + +void QQnxFilePicker::handleFilePickerResponse(const char *data) +{ + QJsonParseError jsonError; + QJsonDocument document = QJsonDocument::fromJson(data, &jsonError); + + if (jsonError.error != QJsonParseError::NoError) { + qFilePickerDebug() << "Error parsing FilePicker response: " + << jsonError.errorString(); + Q_EMIT closed(); + cleanup(); + return; + } + + // The response is a list of Json objects. + const QVariantList array = document.array().toVariantList(); + + foreach (const QVariant &variant, array) { + const QJsonObject object = QJsonObject::fromVariantMap(variant.toMap()); + const QString uri = object.value(QStringLiteral("uri")).toString(); + + if (!uri.isEmpty()) + m_selectedFiles << uri; + + qFilePickerDebug() << "FilePicker uri response:" << uri; + } + + Q_EMIT closed(); + cleanup(); +} + +QString QQnxFilePicker::modeToString(QQnxFilePicker::Mode mode) const +{ + switch (mode) { + case Picker: + return QStringLiteral("Picker"); + case Saver: + return QStringLiteral("Saver"); + case PickerMultiple: + return QStringLiteral("PickerMultiple"); + case SaverMultiple: + return QStringLiteral("SaverMultiple"); + } + + return QStringLiteral("Picker"); +} diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.h b/src/plugins/platforms/qnx/qqnxfilepicker.h new file mode 100644 index 0000000000..5bb8f0969f --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxfilepicker.h @@ -0,0 +1,110 @@ +/*************************************************************************** +** +** Copyright (C) 2013 Research In Motion +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQNXFILEPICKER_H +#define QQNXFILEPICKER_H + +#include <QAbstractNativeEventFilter> +#include <QObject> +#include <QStringList> + +struct navigator_invoke_invocation_t; + +class QQnxFilePicker : public QObject, public QAbstractNativeEventFilter +{ + Q_OBJECT + +public: + explicit QQnxFilePicker(QObject *parent = 0); + ~QQnxFilePicker(); + + enum Mode { + Picker, + Saver, + PickerMultiple, + SaverMultiple + }; + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + + void setMode(Mode mode); + void setDefaultSaveFileNames(const QStringList &fileNames); + void addDefaultSaveFileName(const QString &fileName); + void setDirectories(const QStringList &directories); + void addDirectory(const QString &directory); + void setFilters(const QStringList &filters); + void setTitle(const QString &title); + + Mode mode() const; + + QStringList defaultSaveFileNames() const; + QStringList directories() const; + QStringList filters() const; + QStringList selectedFiles() const; + + QString title() const; + +Q_SIGNALS: + void closed(); + +public Q_SLOTS: + void open(); + void close(); + +private: + void cleanup(); + void handleFilePickerResponse(const char *data); + + QString modeToString(Mode mode) const; + + navigator_invoke_invocation_t *m_invocationHandle; + + Mode m_mode; + + QStringList m_defaultSaveFileNames; + QStringList m_directories; + QStringList m_filters; + QStringList m_selectedFiles; + + QString m_title; +}; + +#endif // QQNXFILEPICKER_H diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 4cbbfa4da8..2b10a26c88 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -40,7 +40,9 @@ ****************************************************************************/ #include "qqnxintegration.h" +#if defined(QQNXSCREENEVENTTHREAD) #include "qqnxscreeneventthread.h" +#endif #include "qqnxnativeinterface.h" #include "qqnxrasterbackingstore.h" #include "qqnxscreen.h" @@ -84,6 +86,8 @@ #include <qpa/qplatformwindow.h> #include <qpa/qwindowsysteminterface.h> +#include <QtGui/private/qguiapplication_p.h> + #if !defined(QT_NO_OPENGL) #include "qqnxglcontext.h" #include <QtGui/QOpenGLContext> @@ -107,9 +111,20 @@ QT_BEGIN_NAMESPACE QQnxWindowMapper QQnxIntegration::ms_windowMapper; QMutex QQnxIntegration::ms_windowMapperMutex; -QQnxIntegration::QQnxIntegration() +static inline QQnxIntegration::Options parseOptions(const QStringList ¶mList) +{ + QQnxIntegration::Options options = QQnxIntegration::NoOptions; + if (!paramList.contains(QLatin1String("no-fullscreen"))) { + options |= QQnxIntegration::FullScreenApplication; + } + return options; +} + +QQnxIntegration::QQnxIntegration(const QStringList ¶mList) : QPlatformIntegration() +#if defined(QQNX_SCREENEVENTTHREAD) , m_screenEventThread(0) +#endif , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) , m_virtualKeyboard(0) #if defined(QQNX_PPS) @@ -134,6 +149,7 @@ QQnxIntegration::QQnxIntegration() #if !defined(QT_NO_DRAGANDDROP) , m_drag(new QSimpleDrag()) #endif + , m_options(parseOptions(paramList)) { qIntegrationDebug() << Q_FUNC_INFO; // Open connection to QNX composition manager @@ -186,8 +202,13 @@ QQnxIntegration::QQnxIntegration() #if defined(Q_OS_BLACKBERRY) QQnxVirtualKeyboardBps* virtualKeyboardBps = new QQnxVirtualKeyboardBps; - m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler, - (m_screenEventThread ? 0 : m_screenEventHandler), virtualKeyboardBps); + +#if defined(QQNX_SCREENEVENTTHREAD) + m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler, 0, virtualKeyboardBps); +#else + m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler, m_screenEventHandler, virtualKeyboardBps); +#endif + m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher); m_virtualKeyboard = virtualKeyboardBps; @@ -385,7 +406,7 @@ QPlatformDrag *QQnxIntegration::drag() const QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const { qIntegrationDebug() << Q_FUNC_INFO; - if (hint == ShowIsFullScreen) + if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication)) return true; return QPlatformIntegration::styleHint(hint); @@ -530,6 +551,11 @@ QQnxScreen *QQnxIntegration::primaryDisplay() const return m_screens.first(); } +QQnxIntegration::Options QQnxIntegration::options() const +{ + return m_options; +} + bool QQnxIntegration::supportsNavigatorEvents() const { // If QQNX_PPS or Q_OS_BLACKBERRY is defined then we have navigator diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index e3eb9e06ba..5f9d709928 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -51,7 +51,9 @@ QT_BEGIN_NAMESPACE class QQnxBpsEventFilter; +#if defined(QQNX_SCREENEVENTTHREAD) class QQnxScreenEventThread; +#endif class QQnxFileDialogHelper; class QQnxNativeInterface; class QQnxWindow; @@ -80,7 +82,12 @@ typedef QHash<screen_window_t, QWindow *> QQnxWindowMapper; class QQnxIntegration : public QPlatformIntegration { public: - QQnxIntegration(); + enum Option { // Options to be passed on command line. + NoOptions = 0x0, + FullScreenApplication = 0x1 + }; + Q_DECLARE_FLAGS(Options, Option) + explicit QQnxIntegration(const QStringList ¶mList); ~QQnxIntegration(); bool hasCapability(QPlatformIntegration::Capability cap) const; @@ -129,6 +136,8 @@ public: void createDisplay(screen_display_t display, bool isPrimary); void removeDisplay(QQnxScreen *screen); QQnxScreen *primaryDisplay() const; + Options options() const; + private: void createDisplays(); void destroyDisplays(); @@ -137,7 +146,9 @@ private: static void removeWindow(screen_window_t qnxWindow); screen_context_t m_screenContext; +#if defined(QNX_SCREENEVENTTHREAD) QQnxScreenEventThread *m_screenEventThread; +#endif QQnxNavigatorEventHandler *m_navigatorEventHandler; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; #if defined(QQNX_PPS) @@ -164,6 +175,8 @@ private: static QQnxWindowMapper ms_windowMapper; static QMutex ms_windowMapperMutex; + const Options m_options; + friend class QQnxWindow; }; diff --git a/src/plugins/platforms/qnx/qqnxtheme.cpp b/src/plugins/platforms/qnx/qqnxtheme.cpp index 733b7223b6..37c1079441 100644 --- a/src/plugins/platforms/qnx/qqnxtheme.cpp +++ b/src/plugins/platforms/qnx/qqnxtheme.cpp @@ -58,10 +58,8 @@ QQnxTheme::~QQnxTheme() bool QQnxTheme::usePlatformNativeDialog(DialogType type) const { -#if defined(Q_OS_BLACKBERRY_TABLET) if (type == QPlatformTheme::FileDialog) return true; -#endif #if !defined(QT_NO_COLORDIALOG) if (type == QPlatformTheme::ColorDialog) return false; @@ -76,10 +74,8 @@ bool QQnxTheme::usePlatformNativeDialog(DialogType type) const QPlatformDialogHelper *QQnxTheme::createPlatformDialogHelper(DialogType type) const { switch (type) { -#if defined(Q_OS_BLACKBERRY_TABLET) case QPlatformTheme::FileDialog: return new QQnxFileDialogHelper(m_integration); -#endif #if !defined(QT_NO_COLORDIALOG) case QPlatformTheme::ColorDialog: #endif diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h index 521f1c12b8..e21998070a 100644 --- a/src/tools/qdoc/config.h +++ b/src/tools/qdoc/config.h @@ -198,6 +198,7 @@ private: #define CONFIG_OUTPUTFORMATS "outputformats" #define CONFIG_OUTPUTPREFIXES "outputprefixes" #define CONFIG_PROJECT "project" +#define CONFIG_REDIRECTDOCUMENTATIONTODEVNULL "redirectdocumentationtodevnull" #define CONFIG_QHP "qhp" #define CONFIG_QUOTINGINFORMATION "quotinginformation" #define CONFIG_SCRIPTDIRS "scriptdirs" diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 68edb1336a..db7c637b53 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -867,8 +867,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } } else if (command == COMMAND_REIMP) { - if (node->parent() && !node->parent()->isInternal()) { - if (node != 0 && node->type() == Node::Function) { + if (node != 0 && node->parent() && !node->parent()->isInternal()) { + if (node->type() == Node::Function) { FunctionNode *func = (FunctionNode *) node; const FunctionNode *from = func->reimplementedFrom(); if (from == 0) { diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 47ebded1b1..e2ee660dd1 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -96,6 +96,7 @@ QStringList Generator::styleDirs; QStringList Generator::styleFiles; bool Generator::debugging_ = false; bool Generator::noLinkErrors_ = false; +bool Generator::redirectDocumentationToDevNull_ = false; Generator::Passes Generator::qdocPass_ = Both; void Generator::setDebugSegfaultFlag(bool b) @@ -267,7 +268,8 @@ void Generator::beginSubPage(const InnerNode* node, const QString& fileName) path += fileName; Generator::debugSegfault("Writing: " + path); outFileNames.insert(fileName,fileName); - QFile* outFile = new QFile(path); + + QFile* outFile = new QFile(redirectDocumentationToDevNull_ ? QStringLiteral("/dev/null") : path); if (!outFile->open(QFile::WriteOnly)) node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName())); QTextStream* out = new QTextStream(outFile); @@ -1472,6 +1474,7 @@ QString Generator::indent(int level, const QString& markedCode) void Generator::initialize(const Config &config) { outputFormats = config.getOutputFormats(); + redirectDocumentationToDevNull_ = config.getBool(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL); if (!outputFormats.isEmpty()) { outDir_ = config.getOutputDir(); diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index e4bc85b2bc..ec1e49d2fb 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -200,6 +200,7 @@ private: static QStringList styleFiles; static bool debugging_; static bool noLinkErrors_; + static bool redirectDocumentationToDevNull_; static Passes qdocPass_; void appendFullName(Text& text, diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index 9c2dd4dcfc..a4e35c5f96 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -95,6 +95,7 @@ bool creationTimeBefore(const QFileInfo &fi1, const QFileInfo &fi2) static bool highlighting = false; static bool showInternal = false; +static bool redirectDocumentationToDevNull = false; static bool noLinkErrors = false; static bool obsoleteLinks = false; static QStringList defines; @@ -139,6 +140,8 @@ static void printHelp() "Run qdoc to read the index files and generate the docs\n" " -showinternal " "Include content marked internal\n" + " -redirect-documentation-to-dev-null " + "Save all documentation content to /dev/null. Useful if someone is interested in qdoc errors only.\n" " -version " "Display version of qdoc and exit\n") ); } @@ -257,6 +260,7 @@ static void processQdocconfFile(const QString &fileName) } config.setStringList(CONFIG_SYNTAXHIGHLIGHTING, QStringList(highlighting ? "true" : "false")); config.setStringList(CONFIG_SHOWINTERNAL, QStringList(showInternal ? "true" : "false")); + config.setStringList(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL, QStringList(redirectDocumentationToDevNull ? "true" : "false")); config.setStringList(CONFIG_NOLINKERRORS, QStringList(noLinkErrors ? "true" : "false")); config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false")); @@ -573,6 +577,9 @@ int main(int argc, char **argv) else if (opt == "-showinternal") { showInternal = true; } + else if (opt == "-redirect-documentation-to-dev-null") { + redirectDocumentationToDevNull = true; + } else if (opt == "-no-examples") { Config::generateExamples = false; } diff --git a/src/tools/qdoc/qmlvisitor.h b/src/tools/qdoc/qmlvisitor.h index 2c3ff341d6..b59fbb0cbb 100644 --- a/src/tools/qdoc/qmlvisitor.h +++ b/src/tools/qdoc/qmlvisitor.h @@ -45,7 +45,6 @@ #include <qstring.h> #include "qqmljsastvisitor_p.h" #include "node.h" -#include "tree.h" QT_BEGIN_NAMESPACE diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 213aefe5f5..0f12c2b80e 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -238,7 +238,7 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const #endif #ifdef Q_OS_WIN - if (m_resolveSymlinks && fileInfo.isSymLink()) { + if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) { QFileInfo resolvedInfo(fileInfo.symLinkTarget()); resolvedInfo = resolvedInfo.canonicalFilePath(); if (resolvedInfo.exists()) { diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 0c4e644e40..447ee78edc 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -108,7 +108,13 @@ public: return QExtendedInformation::System; } - bool isSymLink() const { + bool isSymLink(bool ignoreNtfsSymLinks = false) const + { + if (ignoreNtfsSymLinks) { +#ifdef Q_OS_WIN + return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive); +#endif + } return mFileInfo.isSymLink(); } diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 9556c0ed15..ee1c8ad0fd 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -800,7 +800,7 @@ QString QFileSystemModelPrivate::name(const QModelIndex &index) const if (!index.isValid()) return QString(); QFileSystemNode *dirNode = node(index); - if (fileInfoGatherer.resolveSymlinks() && !resolvedSymLinks.isEmpty() && dirNode->isSymLink()) { + if (fileInfoGatherer.resolveSymlinks() && !resolvedSymLinks.isEmpty() && dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) { QString fullPath = QDir::fromNativeSeparators(filePath(index)); if (resolvedSymLinks.contains(fullPath)) return resolvedSymLinks[fullPath]; diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index d61936d545..663be3d933 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -116,7 +116,7 @@ public: inline bool isFile() const { if (info) return info->isFile(); return true; } inline bool isSystem() const { if (info) return info->isSystem(); return true; } inline bool isHidden() const { if (info) return info->isHidden(); return false; } - inline bool isSymLink() const { if (info) return info->isSymLink(); return false; } + inline bool isSymLink(bool ignoreNtfsSymLinks = false) const { return info && info->isSymLink(ignoreNtfsSymLinks); } inline bool caseSensitive() const { if (info) return info->isCaseSensitive(); return false; } inline QIcon icon() const { if (info) return info->icon; return QIcon(); } diff --git a/src/widgets/graphicsview/qgridlayoutengine.cpp b/src/widgets/graphicsview/qgridlayoutengine.cpp index b80612bc47..8fc4b205d2 100644 --- a/src/widgets/graphicsview/qgridlayoutengine.cpp +++ b/src/widgets/graphicsview/qgridlayoutengine.cpp @@ -432,6 +432,8 @@ QGridLayoutBox QGridLayoutRowData::totalBox(int start, int end) const result.q_maximumSize = 0.0; qreal nextSpacing = 0.0; for (int i = start; i < end; ++i) { + if (ignore.testBit(i)) + continue; result.add(boxes.at(i), stretches.at(i), nextSpacing); nextSpacing = spacings.at(i); } @@ -1475,7 +1477,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt int effectiveRowSpan = 1; for (int i = 1; i < itemRowSpan; ++i) { - if (!rowData->ignore.testBit(i)) + if (!rowData->ignore.testBit(i + itemRow)) ++effectiveRowSpan; } @@ -1713,7 +1715,8 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, q_descents.resize(rowCount()); if (constraintOrientation() != Qt::Horizontal) { - //We might have items whose width depends on their height + // We might have items whose height depends on their width, + // or none of the items has a dynamic constraint. ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as //constraints to find the row heights @@ -1724,7 +1727,7 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]); } else { - //We have items whose height depends on their width + // We have items whose width depends on their height ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as //constraints to find the column widths diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index 8a0736ec70..b435639390 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -220,6 +220,22 @@ QIcon QFileIconProvider::icon(IconType type) const return QIcon(); } +static bool isCacheable(const QFileInfo &fi) +{ + if (!fi.isFile()) + return false; + +#ifdef Q_OS_WIN + // On windows it's faster to just look at the file extensions. QTBUG-13182 + const QString fileExtension = fi.suffix(); + return fileExtension.compare(QLatin1String("exe"), Qt::CaseInsensitive) && + fileExtension.compare(QLatin1String("lnk"), Qt::CaseInsensitive) && + fileExtension.compare(QLatin1String("ico"), Qt::CaseInsensitive); +#else + return !fi.isExecutable() && !fi.isSymLink(); +#endif +} + QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const { QIcon retIcon; @@ -234,7 +250,7 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const const QString fileExtension = fi.suffix().toUpper(); const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper(); - bool cacheable = fi.isFile() && !fi.isExecutable() && !fi.isSymLink() && fileExtension != QLatin1String("ICO"); + bool cacheable = isCacheable(fi); if (cacheable) { QPixmap pixmap; QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap); diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 38e4a0bf9b..573df1db6a 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -1755,13 +1755,13 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi visualRow = bottom; break; case MovePageUp: { - int newRow = rowAt(visualRect(current).top() - d->viewport->height()); + int newRow = rowAt(visualRect(current).bottom() - d->viewport->height()); if (newRow == -1) newRow = d->logicalRow(0); return d->model->index(newRow, current.column(), d->root); } case MovePageDown: { - int newRow = rowAt(visualRect(current).bottom() + d->viewport->height()); + int newRow = rowAt(visualRect(current).top() + d->viewport->height()); if (newRow == -1) newRow = d->logicalRow(bottom); return d->model->index(newRow, current.column(), d->root); diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp index 5f929caf03..0b0efa2bdf 100644 --- a/src/widgets/widgets/qfontcombobox.cpp +++ b/src/widgets/widgets/qfontcombobox.cpp @@ -54,6 +54,88 @@ QT_BEGIN_NAMESPACE +static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script) +{ + switch (script) { + case QLocale::ArabicScript: + return QFontDatabase::Arabic; + case QLocale::CyrillicScript: + return QFontDatabase::Cyrillic; + case QLocale::GurmukhiScript: + return QFontDatabase::Gurmukhi; + case QLocale::SimplifiedHanScript: + return QFontDatabase::SimplifiedChinese; + case QLocale::TraditionalHanScript: + return QFontDatabase::TraditionalChinese; + case QLocale::LatinScript: + return QFontDatabase::Latin; + case QLocale::ArmenianScript: + return QFontDatabase::Armenian; + case QLocale::BengaliScript: + return QFontDatabase::Bengali; + case QLocale::DevanagariScript: + return QFontDatabase::Devanagari; + case QLocale::GeorgianScript: + return QFontDatabase::Georgian; + case QLocale::GreekScript: + return QFontDatabase::Greek; + case QLocale::GujaratiScript: + return QFontDatabase::Gujarati; + case QLocale::HebrewScript: + return QFontDatabase::Hebrew; + case QLocale::JapaneseScript: + return QFontDatabase::Japanese; + case QLocale::KhmerScript: + return QFontDatabase::Khmer; + case QLocale::KannadaScript: + return QFontDatabase::Kannada; + case QLocale::KoreanScript: + return QFontDatabase::Korean; + case QLocale::LaoScript: + return QFontDatabase::Lao; + case QLocale::MalayalamScript: + return QFontDatabase::Malayalam; + case QLocale::MyanmarScript: + return QFontDatabase::Myanmar; + case QLocale::TamilScript: + return QFontDatabase::Tamil; + case QLocale::TeluguScript: + return QFontDatabase::Telugu; + case QLocale::ThaanaScript: + return QFontDatabase::Thaana; + case QLocale::ThaiScript: + return QFontDatabase::Thai; + case QLocale::TibetanScript: + return QFontDatabase::Tibetan; + case QLocale::SinhalaScript: + return QFontDatabase::Sinhala; + case QLocale::SyriacScript: + return QFontDatabase::Syriac; + case QLocale::OriyaScript: + return QFontDatabase::Oriya; + case QLocale::OghamScript: + return QFontDatabase::Ogham; + case QLocale::RunicScript: + return QFontDatabase::Runic; + case QLocale::NkoScript: + return QFontDatabase::Nko; + default: + return QFontDatabase::Any; + } +} + +static QFontDatabase::WritingSystem writingSystemFromLocale() +{ + QStringList uiLanguages = QLocale::system().uiLanguages(); + QLocale::Script script; + if (!uiLanguages.isEmpty()) + script = QLocale(uiLanguages.at(0)).script(); + else + script = QLocale::system().script(); + + return writingSystemFromScript(script); +} + static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin) { QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase().writingSystems(font.family()); @@ -66,7 +148,22 @@ static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool if (writingSystems.isEmpty()) return QFontDatabase::Any; - QFontDatabase::WritingSystem system = writingSystems.last(); + QFontDatabase::WritingSystem system = writingSystemFromLocale(); + + if (writingSystems.contains(system)) + return system; + + if (system == QFontDatabase::TraditionalChinese + && writingSystems.contains(QFontDatabase::SimplifiedChinese)) { + return QFontDatabase::SimplifiedChinese; + } + + if (system == QFontDatabase::SimplifiedChinese + && writingSystems.contains(QFontDatabase::TraditionalChinese)) { + return QFontDatabase::TraditionalChinese; + } + + system = writingSystems.last(); if (!*hasLatin) { // we need to show something diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 77ea39da53..f412ee2970 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1302,15 +1302,20 @@ Q_DECLARE_METATYPE(MyObjectPtr) void tst_QMetaType::automaticTemplateRegistration() { - { - QList<int> intList; - intList << 42; - QVERIFY(QVariant::fromValue(intList).value<QList<int> >().first() == 42); - QVector<QList<int> > vectorList; - vectorList << intList; - QVERIFY(QVariant::fromValue(vectorList).value<QVector<QList<int> > >().first().first() == 42); +#define TEST_SEQUENTIAL_CONTAINER(CONTAINER, VALUE_TYPE) \ + { \ + CONTAINER<VALUE_TYPE> innerContainer; \ + innerContainer.push_back(42); \ + QVERIFY(*QVariant::fromValue(innerContainer).value<CONTAINER<VALUE_TYPE> >().begin() == 42); \ + QVector<CONTAINER<VALUE_TYPE> > outerContainer; \ + outerContainer << innerContainer; \ + QVERIFY(*QVariant::fromValue(outerContainer).value<QVector<CONTAINER<VALUE_TYPE> > >().first().begin() == 42); \ } + TEST_SEQUENTIAL_CONTAINER(QList, int) + TEST_SEQUENTIAL_CONTAINER(std::vector, int) + TEST_SEQUENTIAL_CONTAINER(std::list, int) + { QList<QByteArray> bytearrayList; bytearrayList << QByteArray("foo"); @@ -1323,14 +1328,9 @@ void tst_QMetaType::automaticTemplateRegistration() QCOMPARE(::qMetaTypeId<QVariantList>(), (int)QMetaType::QVariantList); QCOMPARE(::qMetaTypeId<QList<QVariant> >(), (int)QMetaType::QVariantList); - { - QList<QVariant> variantList; - variantList << 42; - QVERIFY(QVariant::fromValue(variantList).value<QList<QVariant> >().first() == 42); - QVector<QList<QVariant> > vectorList; - vectorList << variantList; - QVERIFY(QVariant::fromValue(vectorList).value<QVector<QList<QVariant> > >().first().first() == 42); - } + TEST_SEQUENTIAL_CONTAINER(QList, QVariant) + TEST_SEQUENTIAL_CONTAINER(std::vector, QVariant) + TEST_SEQUENTIAL_CONTAINER(std::list, QVariant) { QList<QSharedPointer<QObject> > sharedPointerList; @@ -1395,6 +1395,31 @@ void tst_QMetaType::automaticTemplateRegistration() QCOMPARE(QVariant::fromValue(variantMap).value<QVariantMap>().value(QStringLiteral("4")), QVariant(2)); } { + typedef std::map<int, int> IntIntMap; + IntIntMap intIntMap; + intIntMap[4] = 2; + QCOMPARE(QVariant::fromValue(intIntMap).value<IntIntMap>()[4], 2); + } + { + typedef std::map<int, uint> StdIntUIntMap; + StdIntUIntMap intUIntMap; + intUIntMap[4] = 2; + QCOMPARE(QVariant::fromValue(intUIntMap).value<StdIntUIntMap>()[4], (uint)2); + } + { + typedef std::map<int, CustomObject*> StdMapIntCustomObject ; + StdMapIntCustomObject intComparableMap; + CustomObject *o = 0; + intComparableMap[4] = o; + QCOMPARE(QVariant::fromValue(intComparableMap).value<StdMapIntCustomObject >()[4], o); + } + { + typedef std::map<QString, QVariant> StdMapStringVariant; + StdMapStringVariant variantMap; + variantMap[QStringLiteral("4")] = 2; + QCOMPARE(QVariant::fromValue(variantMap).value<StdMapStringVariant>()[QStringLiteral("4")], QVariant(2)); + } + { typedef QPair<int, int> IntIntPair; IntIntPair intIntPair = qMakePair(4, 2); QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().first, 4); @@ -1412,6 +1437,25 @@ void tst_QMetaType::automaticTemplateRegistration() QCOMPARE(QVariant::fromValue(intComparablePair).value<IntComparablePair>().second, m); } { + typedef std::pair<int, int> IntIntPair; + IntIntPair intIntPair = std::make_pair(4, 2); + QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().first, 4); + QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().second, 2); + } + { + typedef std::pair<int, uint> StdIntUIntPair; + StdIntUIntPair intUIntPair = std::make_pair<int, uint>(4, 2); + QCOMPARE(QVariant::fromValue(intUIntPair).value<StdIntUIntPair>().first, 4); + QCOMPARE(QVariant::fromValue(intUIntPair).value<StdIntUIntPair>().second, (uint)2); + } + { + typedef std::pair<int, CustomQObject*> StdIntComparablePair; + CustomQObject* o = 0; + StdIntComparablePair intComparablePair = std::make_pair(4, o); + QCOMPARE(QVariant::fromValue(intComparablePair).value<StdIntComparablePair>().first, 4); + QCOMPARE(QVariant::fromValue(intComparablePair).value<StdIntComparablePair>().second, o); + } + { typedef QHash<int, UnregisteredType> IntUnregisteredTypeHash; QVERIFY(qRegisterMetaType<IntUnregisteredTypeHash>("IntUnregisteredTypeHash") > 0); } diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp index 72bf5c58ca..c18ba4d05c 100644 --- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp +++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp @@ -78,10 +78,22 @@ private slots: void qCountContainer() const; void binaryFindOnLargeContainer() const; -#if Q_TEST_PERFORMANCE + void popCount08_data() { popCount_data_impl(sizeof(quint8 )); } + void popCount16_data() { popCount_data_impl(sizeof(quint16)); } + void popCount32_data() { popCount_data_impl(sizeof(quint32)); } + void popCount64_data() { popCount_data_impl(sizeof(quint64)); } + void popCount08() { popCount_impl<quint8 >(); } + void popCount16() { popCount_impl<quint16>(); } + void popCount32() { popCount_impl<quint32>(); } + void popCount64() { popCount_impl<quint64>(); } + private: +#if Q_TEST_PERFORMANCE void performance(); #endif + void popCount_data_impl(size_t sizeof_T_Int); + template <typename T_Int> + void popCount_impl(); }; class TestInt @@ -1007,6 +1019,72 @@ void tst_QAlgorithms::binaryFindOnLargeContainer() const QCOMPARE(foundIt.pos(), 1073987655); } +// alternative implementation of qPopulationCount for comparison: +static const uint bitsSetInNibble[] = { + 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4, +}; +Q_STATIC_ASSERT(sizeof bitsSetInNibble / sizeof *bitsSetInNibble == 16); + +static Q_DECL_CONSTEXPR uint bitsSetInByte(quint8 byte) +{ + return bitsSetInNibble[byte & 0xF] + bitsSetInNibble[byte >> 4]; +} +static Q_DECL_CONSTEXPR uint bitsSetInShort(quint16 word) +{ + return bitsSetInByte(word & 0xFF) + bitsSetInByte(word >> 8); +} +static Q_DECL_CONSTEXPR uint bitsSetInInt(quint32 word) +{ + return bitsSetInShort(word & 0xFFFF) + bitsSetInShort(word >> 16); +} +static Q_DECL_CONSTEXPR uint bitsSetInInt64(quint64 word) +{ + return bitsSetInInt(word & 0xFFFFFFFF) + bitsSetInInt(word >> 32); +} + + +void tst_QAlgorithms::popCount_data_impl(size_t sizeof_T_Int) +{ + using namespace QTest; + addColumn<quint64>("input"); + addColumn<uint>("expected"); + + for (uint i = 0; i < UCHAR_MAX; ++i) { + const uchar byte = static_cast<uchar>(i); + const uint bits = bitsSetInByte(byte); + const quint64 value = static_cast<quint64>(byte); + const quint64 input = value << ((i % sizeof_T_Int) * 8U); + newRow(qPrintable(QString().sprintf("0x%016llx", input))) << input << bits; + } + + // and some random ones: + if (sizeof_T_Int >= 8) + for (size_t i = 0; i < 1000; ++i) { + const quint64 input = quint64(qrand()) << 32 | quint32(qrand()); + newRow(qPrintable(QString().sprintf("0x%016llx", input))) << input << bitsSetInInt64(input); + } + else if (sizeof_T_Int >= 2) + for (size_t i = 0; i < 1000 ; ++i) { + const quint32 input = qrand(); + if (sizeof_T_Int >= 4) + newRow(qPrintable(QString().sprintf("0x%08x", input))) << quint64(input) << bitsSetInInt(input); + else + newRow(qPrintable(QString().sprintf("0x%04x", quint16(input & 0xFFFF)))) << quint64(input & 0xFFFF) << bitsSetInShort(input & 0xFFFF); + } +} + +template <typename T_Int> +void tst_QAlgorithms::popCount_impl() +{ + QFETCH(quint64, input); + QFETCH(uint, expected); + + const T_Int value = static_cast<T_Int>(input); + + QCOMPARE(qPopulationCount(value), expected); +} + QTEST_APPLESS_MAIN(tst_QAlgorithms) #include "tst_qalgorithms.moc" diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp index 25301feee4..125eab2f8c 100644 --- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp +++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp @@ -77,30 +77,43 @@ void tst_QNetworkAccessManager::networkAccessible() QSignalSpy spy(&manager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility))); - QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility); + // if there is no session, we cannot know in which state we are in + QNetworkAccessManager::NetworkAccessibility initialAccessibility = + manager.networkAccessible(); + QCOMPARE(manager.networkAccessible(), initialAccessibility); manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); - QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), - QNetworkAccessManager::NotAccessible); + int expectedCount = (initialAccessibility == QNetworkAccessManager::Accessible) ? 1 : 0; + QCOMPARE(spy.count(), expectedCount); + if (expectedCount > 0) + QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), + QNetworkAccessManager::NotAccessible); QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); manager.setNetworkAccessible(QNetworkAccessManager::Accessible); - QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), - QNetworkAccessManager::UnknownAccessibility); - QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::UnknownAccessibility); + QCOMPARE(spy.count(), expectedCount); + if (expectedCount > 0) + QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), + initialAccessibility); + QCOMPARE(manager.networkAccessible(), initialAccessibility); QNetworkConfigurationManager configManager; + bool sessionRequired = (configManager.capabilities() + & QNetworkConfigurationManager::NetworkSessionRequired); QNetworkConfiguration defaultConfig = configManager.defaultConfiguration(); if (defaultConfig.isValid()) { manager.setConfiguration(defaultConfig); - QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), - QNetworkAccessManager::Accessible); + // the accessibility has not changed if no session is required + if (sessionRequired) { + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().at(0).value<QNetworkAccessManager::NetworkAccessibility>(), + QNetworkAccessManager::Accessible); + } else { + QCOMPARE(spy.count(), 0); + } QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible); manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 2b9dfc5081..ee5c7e42d8 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -513,7 +513,7 @@ void tst_QTcpSocket::bind() { QFETCH_GLOBAL(bool, setProxy); if (setProxy) - QSKIP("QTBUG-22964"); + return; // QTBUG-22964 for proxies, QTBUG-29972 for QSKIP QFETCH(QString, stringAddr); QFETCH(bool, successExpected); QFETCH(QString, stringExpectedLocalAddress); diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index 41e5ed466c..92caeb7803 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -126,6 +126,7 @@ private slots: void spanningItem2x3_data(); void spanningItem2x3(); void spanningItem(); + void spanAcrossEmptyRow(); void heightForWidth(); void widthForHeight(); void heightForWidthWithSpanning(); @@ -3180,23 +3181,19 @@ void tst_QGraphicsGridLayout::heightForWidthWithSpanning() QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(1, 1)); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(200, 100)); - QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30000, 30000)); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100)); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100)); - QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100)); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 10000)); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 10000)); - QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 10000)); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100)); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100)); - QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue); - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 10000)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100)); } Q_DECLARE_METATYPE(QSizePolicy::Policy) @@ -3352,6 +3349,37 @@ void tst_QGraphicsGridLayout::spanningItem() QCOMPARE(layout->maximumSize(), QSizeF(160,80)); } +void tst_QGraphicsGridLayout::spanAcrossEmptyRow() +{ + QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window); + QGraphicsGridLayout *layout = new QGraphicsGridLayout(form); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + RectWidget *w1 = new RectWidget; + RectWidget *w2 = new RectWidget; + RectWidget *w3 = new RectWidget; + + QSizeF size(10, 10); + for (int i = 0; i < 3; ++i) { + w1->setSizeHint((Qt::SizeHint)i, size); + w2->setSizeHint((Qt::SizeHint)i, size); + w3->setSizeHint((Qt::SizeHint)i, size); + size+=size; //[(10,10), (20,20), (40,40)] + } + layout->addItem(w1, 0, 0, 1, 1); + layout->addItem(w2, 0, 1, 1, 2); + layout->addItem(w3, 0, 99, 1, 1); + + form->resize(60,20); + QCOMPARE(w1->geometry(), QRectF( 0, 0, 20, 20)); + QCOMPARE(w2->geometry(), QRectF(20, 0, 20, 20)); + QCOMPARE(w3->geometry(), QRectF(40, 0, 20, 20)); + + QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize), QSizeF(30, 10)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 20)); + QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize), QSizeF(120, 40)); +} + void tst_QGraphicsGridLayout::stretchAndHeightForWidth() { QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window); diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index 13476a7ffa..3710645514 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -106,6 +106,8 @@ private slots: void moveCursorStrikesBack_data(); void moveCursorStrikesBack(); + void moveCursorBiggerJump(); + void hideRows_data(); void hideRows(); @@ -1353,6 +1355,34 @@ void tst_QTableView::moveCursorStrikesBack() QCOMPARE(newColumn, expectedColumn); } +void tst_QTableView::moveCursorBiggerJump() +{ + QtTestTableModel model(50, 7); + QTableView view; + view.setModel(&model); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + int height = view.horizontalHeader()->height(); + for (int i=0;i<8;i++) + height += view.verticalHeader()->sectionSize(i); + view.resize(view.width(), height); + view.setCurrentIndex(model.index(0,0)); + + QTest::keyClick(&view, Qt::Key_PageDown); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(1,0)); + QTest::keyClick(&view, Qt::Key_PageDown); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(8,0)); + QTest::keyClick(&view, Qt::Key_PageDown); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(15,0)); + QTest::keyClick(&view, Qt::Key_PageUp); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(14,0)); + QTest::keyClick(&view, Qt::Key_PageUp); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(7,0)); + QTest::keyClick(&view, Qt::Key_PageUp); + QCOMPARE(view.indexAt(QPoint(0,0)), model.index(0,0)); +} + void tst_QTableView::hideRows_data() { QTest::addColumn<int>("rowCount"); @@ -3761,8 +3791,6 @@ void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections() QTRY_COMPARE(tv.rowAt(0), tv.verticalHeader()->logicalIndex(0)); int newRow = tv.rowAt(tv.viewport()->height()); - if (newRow == tv.rowAt(tv.viewport()->height() - 1)) // Overlapping row - newRow++; QTest::keyClick(&tv, Qt::Key_PageDown); // Scroll down and check current QTRY_COMPARE(tv.currentIndex().row(), newRow); diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 9a7b7956d8..dcda9f7fd7 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -2017,6 +2017,8 @@ void tst_QTreeView::clicked() view.setModel(&model); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QModelIndex firstIndex = model.index(0, 0, QModelIndex()); QVERIFY(firstIndex.isValid()); int itemHeight = view.visualRect(firstIndex).height(); diff --git a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp index aec2479239..bb05570f18 100644 --- a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp +++ b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp @@ -49,7 +49,7 @@ public: setFlags(QGraphicsItem::ItemIsSelectable); } - void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option*/, QWidget * /*widget*/) + void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option*/, QWidget * /*widget*/) Q_DECL_OVERRIDE { if (isSelected()) painter->fillRect(rect(), QColor(255, 0, 0)); @@ -68,7 +68,7 @@ public: connect(this, SIGNAL(rubberBandChanged(QRect, QPointF, QPointF)), this, SLOT(updateRubberbandInfo(QRect, QPointF, QPointF))); } protected: - void mouseMoveEvent(QMouseEvent *event) + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE { QGraphicsView::mouseMoveEvent(event); diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index dc11c0d0a2..11cdc035b8 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2871,6 +2871,12 @@ void Configure::generateCachefile() moduleStream << "QT_SKIP_MODULES += " << skipModules.join(' ') << endl; moduleStream << endl; + moduleStream << "host_build {" << endl; + moduleStream << " QT_CPU_FEATURES = " << dictionary["QT_HOST_CPU_FEATURES"] << endl; + moduleStream << "} else {" << endl; + moduleStream << " QT_CPU_FEATURES = " << dictionary["QT_CPU_FEATURES"] << endl; + moduleStream << "}" << endl; + if (dictionary["QT_EDITION"] != "QT_EDITION_OPENSOURCE") moduleStream << "DEFINES *= QT_EDITION=QT_EDITION_DESKTOP" << endl; @@ -3149,15 +3155,16 @@ void Configure::generateQConfigPri() configStream << " qpa"; configStream << endl; - configStream << "QT_ARCH = " << dictionary["QT_ARCH"] << endl; - configStream << "QT_HOST_ARCH = " << dictionary["QT_HOST_ARCH"] << endl; - configStream << "QT_CPU_FEATURES = " << dictionary["QT_CPU_FEATURES"] << endl; - configStream << "QT_HOST_CPU_FEATURES = " << dictionary["QT_HOST_CPU_FEATURES"] << endl; + configStream << "host_build {" << endl; + configStream << " QT_ARCH = " << dictionary["QT_HOST_ARCH"] << endl; + configStream << "} else {" << endl; + configStream << " QT_ARCH = " << dictionary["QT_ARCH"] << endl; if (dictionary.contains("XQMAKESPEC") && !dictionary["XQMAKESPEC"].startsWith("wince")) { // FIXME: add detection - configStream << "QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib" << endl; - configStream << "QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include" << endl; + configStream << " QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib" << endl; + configStream << " QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include" << endl; } + configStream << "}" << endl; if (dictionary["QT_EDITION"].contains("OPENSOURCE")) configStream << "QT_EDITION = " << QLatin1String("OpenSource") << endl; else |