From 2d8b80bb9c623c246c3815c3fd32cbd6392dc27b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 12 Sep 2019 11:03:07 +0200 Subject: QList: make cast from ptrdiff_t to int explicit Amends ffc2d5722317fcab86865b11491d7bf7fef3e16d. Fixes: QTBUG-78235 Change-Id: Ie91d8d71c92bb62e3268847407b7b252c382d700 Reviewed-by: Marc Mutz --- src/corelib/tools/qlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 74b57f7ad4..a98a9147d6 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -1031,7 +1031,7 @@ int lastIndexOf(const QList &list, const U &u, int from) Node *n = reinterpret_cast(list.p.at(from + 1)); while (n-- != b) { if (n->t() == u) - return typename QList::difference_type(n - b); + return int(n - b); } } return -1; -- cgit v1.2.3 From e02293a76d21e7077f1952d4ed8af6c6d1970190 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 30 Sep 2019 08:26:36 +0200 Subject: Always update the pressed position when pressing on an item If there is an item already selected then the pressed position needs to be updated regardless when selecting a new one even if it is not made current as this will be used to determine the drag distance. Otherwise it will start a drag within one pixel of moving due to the fact it is doing it relative to the first item to be pressed rather than the last. Fixes: QTBUG-78797 Change-Id: I853041b278b2e92ccf20660f7ced945fef72527a Reviewed-by: Samuel Gaist Reviewed-by: Christian Ehrlicher --- src/widgets/itemviews/qabstractitemview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index cb99214d4e..7d5e014dd5 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1775,8 +1775,8 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid(); QPoint offset = d->offset(); + d->pressedPosition = pos + offset; if ((command & QItemSelectionModel::Current) == 0) { - d->pressedPosition = pos + offset; d->currentSelectionStartIndex = index; } else if (!d->currentSelectionStartIndex.isValid()) -- cgit v1.2.3 From 7d73d4b9a93b3132c1a24aa3ae77f0a307e821fd Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 20 Aug 2019 10:53:53 +0200 Subject: Remove the unregistered recognizer from the main list This amends 1320b2f64412f0d86bd09c66c22df845e13a94a1 to keep the behavior of removing from the main list but without re-introducing the memory leak. Fixes: QTBUG-77770 Change-Id: I91fa6cb71fab8d60baa35417fdb34322af11dbbb Reviewed-by: Friedemann Kleint Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qgesturemanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index cd27c9c5be..5d2adc1e1c 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -143,6 +143,7 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) { QList list = m_recognizers.values(type); + m_recognizers.remove(type); foreach (QGesture *g, m_gestureToRecognizer.keys()) { QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); if (list.contains(recognizer)) { -- cgit v1.2.3 From 5aa13ea144cff4dbadf12c08b7aa49646347e186 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 12 Sep 2019 15:22:24 +0200 Subject: QTreeWidget: Don't assume the selected indexes include the first column If the first column is hidden in a QTreeWidget then when doing a drag then the selected indexes will not include any that have a column of 0. Therefore it has to account for this use std::unique to ensure that there is only one instance of the selected items represented by the selected indexes. Fixes: QTBUG-35511 Change-Id: I39dff596959f30db7378ff946735ee2866778524 Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qtreewidget.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index d2dc91b18c..be7ddd8b30 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -748,11 +748,14 @@ QMimeData *QTreeModel::internalMimeData() const QMimeData *QTreeModel::mimeData(const QModelIndexList &indexes) const { - QList items; - for (const auto &index : indexes) { - if (index.column() == 0) // only one item per row - items << item(index); - } + QList items; + std::transform(indexes.begin(), indexes.end(), std::back_inserter(items), + [this](const QModelIndex &idx) -> QTreeWidgetItem * { return item(idx); }); + + // Ensure we only have one item as an item may have more than + // one index selected if there is more than one column + std::sort(items.begin(), items.end()); + items.erase(std::unique(items.begin(), items.end()), items.end()); // cachedIndexes is a little hack to avoid copying from QModelIndexList to // QList and back again in the view -- cgit v1.2.3 From d448f2ecb8bca7de1e69f9f6f10d0ffb8c3d1beb Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 23 Sep 2019 16:46:07 +0200 Subject: Correct handling of -qfloat16(0) It is finite and normal; it classifies as a zero; and it should not be > qfloat16(0). Added tests to match. Change-Id: I7874fb54f622b4cdf28b0894050ad3e75cf5d77c Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.cpp | 2 +- src/corelib/global/qfloat16.h | 4 ++-- tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp | 13 ++++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 2ba4c79374..6c21b7de5a 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -155,7 +155,7 @@ QT_BEGIN_NAMESPACE int qfloat16::fpClassify() const noexcept { return isInf() ? FP_INFINITE : isNaN() ? FP_NAN - : !b16 ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL; + : !(b16 & 0x7fff) ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL; } /*! \fn int qRound(qfloat16 value) diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 4d1aa91349..9a4f1800a4 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -94,7 +94,7 @@ public: static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); } // Signalling NaN is 0x7f00 inline constexpr bool isNormal() const noexcept - { return b16 == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); } + { return (b16 & 0x7fff) == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); } private: quint16 b16; constexpr inline explicit qfloat16(Wrap nibble) noexcept : b16(nibble.b16) {} @@ -296,7 +296,7 @@ class numeric_limits : public numeric_limits> 15 (sign) + uint S: 1; // b16 >> 15 (sign); can be set for zero uint E: 5; // (b16 >> 10) & 0x1f (offset exponent) uint M: 10; // b16 & 0x3ff (adjusted mantissa) diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index 01a1789188..94f0afa5ed 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -107,6 +107,7 @@ void tst_qfloat16::ltgt_data() QTest::addColumn("val2"); QTest::newRow("zero") << 0.0f << 0.0f; + QTest::newRow("-zero") << -0.0f << 0.0f; QTest::newRow("ten") << 10.0f << 10.0f; QTest::newRow("large") << 100000.0f << 100000.0f; QTest::newRow("small") << 0.0000001f << 0.0000001f; @@ -405,6 +406,7 @@ void tst_qfloat16::finite_data() QTest::addColumn("mode"); QTest::newRow("zero") << qfloat16(0) << FP_ZERO; + QTest::newRow("-zero") << -qfloat16(0) << FP_ZERO; QTest::newRow("one") << qfloat16(1) << FP_NORMAL; QTest::newRow("-one") << qfloat16(-1) << FP_NORMAL; QTest::newRow("ten") << qfloat16(10) << FP_NORMAL; @@ -459,6 +461,12 @@ void tst_qfloat16::limits() // See also: qNaN() and infinity() // A few useful values: const qfloat16 zero(0), one(1), ten(10); + // The specifics of minus zero: + // (IEEE 754 seems to want -zero < zero, but -0. == 0. and -0.f == 0.f in C++.) + QVERIFY(-zero <= zero); + QVERIFY(-zero == zero); + QVERIFY(!(-zero > zero)); + // digits in the mantissa, including the implicit 1 before the binary dot at its left: QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1))); QVERIFY(qfloat16(1 << Bounds::digits) + one == qfloat16(1 << Bounds::digits)); @@ -523,7 +531,10 @@ void tst_qfloat16::limits() // See also: qNaN() and infinity() QVERIFY(Bounds::denorm_min() > zero); if (overOptimized) QEXPECT_FAIL("", "Over-optimized on ARM", Continue); - QCOMPARE(Bounds::denorm_min() / rose, zero); + QVERIFY(Bounds::denorm_min() / rose == zero); + if (overOptimized) + QEXPECT_FAIL("", "Over-optimized on ARM", Continue); + QVERIFY(-Bounds::denorm_min() / rose == -zero); } QTEST_APPLESS_MAIN(tst_qfloat16) -- cgit v1.2.3 From dcecaeb7b95f673bfae55c4cee1056bfc6e903d9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 1 Oct 2019 11:32:55 +0200 Subject: Prospective fix to stabilize tst_qwindow::isActive() on Windows 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is conceivable that during the try-compare loop of processing windowing system events we loose and regain the focus. That would explain the occasional test failure where instead of the expected 3 focus in events, we have received four. Task-number: QTBUG-77769 Change-Id: I2221440d09a74d4d18a72f7786232b4491cf45a8 Reviewed-by: Tor Arne Vestbø (cherry picked from commit 56f084781e2b8891929eca0070212fd7a32b32fc) Reviewed-by: Edward Welbourne --- tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 4f26950192..60f89fcb4e 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -893,7 +893,13 @@ void tst_QWindow::isActive() QTRY_COMPARE(QGuiApplication::focusWindow(), &window); QCoreApplication::processEvents(); QTRY_COMPARE(dialog.received(QEvent::FocusOut), 1); - QTRY_COMPARE(window.received(QEvent::FocusIn), 3); + // We should be checking for exactly three, but since this is a try-compare _loop_, we might + // loose and regain focus multiple times in the event of a system popup. This has been observed + // to fail on Windows, see QTBUG-77769. + QTRY_VERIFY2(window.received(QEvent::FocusIn) >= 3, + qPrintable( + QStringLiteral("Expected more than three focus in events, received: %1") + .arg(window.received(QEvent::FocusIn)))); QVERIFY(window.isActive()); -- cgit v1.2.3 From 932805807123833bb8f5ae9abda7e946f48d9f0c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 2 Oct 2019 07:56:16 -0700 Subject: Fix crash when running QtCore: Stack is misaligned on x86-64 When our ELF entry point function is started by the kernel, the stack is aligned at 16 bytes. However, the stack is expected to be off by 8, due to a preceding CALL instruction which didn't exist. This cauases a crash further down as the compiler may generate aligned stack access. Change-Id: I1496b069cc534f1a838dfffd15c9dc4ef9e3869e Reviewed-by: Edward Welbourne --- src/corelib/global/qlibraryinfo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 5634d6e6c3..f2ada4ab30 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -709,10 +709,14 @@ QT_END_NAMESPACE #include "private/qcoreapplication_p.h" +QT_WARNING_DISABLE_GCC("-Wattributes") +QT_WARNING_DISABLE_CLANG("-Wattributes") +QT_WARNING_DISABLE_INTEL(2621) + extern const char qt_core_interpreter[] __attribute__((section(".interp"))) = ELF_INTERPRETER; -extern "C" void qt_core_boilerplate(); +extern "C" void qt_core_boilerplate() __attribute__((force_align_arg_pointer)); void qt_core_boilerplate() { printf("This is the QtCore library version " QT_BUILD_STR "\n" -- cgit v1.2.3 From 85f9fa7fab7b9a2d987be44a2a7a9d5ba57d6680 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 2 Oct 2019 22:28:06 +0200 Subject: Stop using QTime as a timer in QIBaseDriver::close() This is probably still the wrong thing to do here, though. Change-Id: I4ff76393dde0b9ad9eb4a5e0d35fb6125d141901 Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/ibase/qsql_ibase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp index ead08dbce8..0f39f6aa0d 100644 --- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp @@ -40,6 +40,7 @@ #include "qsql_ibase_p.h" #include #include +#include #include #include #include @@ -1570,10 +1571,9 @@ void QIBaseDriver::close() d->eventBuffers.clear(); #if defined(FB_API_VER) - // Workaround for Firebird crash - QTime timer; - timer.start(); - while (timer.elapsed() < 500) + // TODO check whether this workaround for Firebird crash is still needed + QDeadlineTimer timer(500); + while (!timer.hasExpired()) QCoreApplication::processEvents(); #endif } -- cgit v1.2.3 From ce5dc3193279cdbcc34b583151ba05464444dd5a Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 30 Sep 2019 10:51:59 +0200 Subject: Fix needless resolution of -l LIBS entries on Windows Do not resolve -l entries to absolute file paths for libraries in the default search paths. This restores behavior from 5.12.0 (commit 2327944d) for Windows system libraries. Fixes: QTBUG-78827 Change-Id: Ic2d4626df87308dd635afc1ab5c4b8191d3d2831 Reviewed-by: Oliver Wolff Reviewed-by: Kai Koehne --- qmake/generators/win32/winmakefile.cpp | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 27d2a7c0a5..86d10c213c 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -38,6 +38,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) @@ -73,16 +75,37 @@ Win32MakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg) return LibFlagFile; } +class LibrarySearchPath : public QMakeLocalFileName +{ +public: + LibrarySearchPath() = default; + + LibrarySearchPath(const QString &s) + : QMakeLocalFileName(s) + { + } + + LibrarySearchPath(QString &&s, bool isDefault = false) + : QMakeLocalFileName(std::move(s)), _default(isDefault) + { + } + + bool isDefault() const { return _default; } + +private: + bool _default = false; +}; + bool Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { ProStringList impexts = project->values("QMAKE_LIB_EXTENSIONS"); if (impexts.isEmpty()) impexts = project->values("QMAKE_EXTENSION_STATICLIB"); - QVector dirs; + QVector dirs; int libidx = 0; for (const ProString &dlib : project->values("QMAKE_DEFAULT_LIBDIRS")) - dirs.append(QMakeLocalFileName(dlib.toQString())); + dirs.append(LibrarySearchPath(dlib.toQString(), true)); static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE", "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr }; for (int i = 0; lflags[i]; i++) { @@ -92,12 +115,20 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) ProString arg; LibFlagType type = parseLibFlag(opt, &arg); if (type == LibFlagPath) { - QMakeLocalFileName lp(arg.toQString()); - int idx = dirs.indexOf(lp); + const QString argqstr = arg.toQString(); + auto dit = std::find_if(dirs.cbegin(), dirs.cend(), + [&argqstr](const LibrarySearchPath &p) + { + return p.real() == argqstr; + }); + int idx = dit == dirs.cend() + ? -1 + : std::distance(dirs.cbegin(), dit); if (idx >= 0 && idx < libidx) { it = l.erase(it); continue; } + const LibrarySearchPath lp(argqstr); dirs.insert(libidx++, lp); (*it) = "-L" + lp.real(); } else if (type == LibFlagLib) { @@ -114,7 +145,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) for (ProStringList::ConstIterator extit = impexts.cbegin(); extit != impexts.cend(); ++extit) { if (exists(libBase + '.' + *extit)) { - (*it) = cand + verovr + '.' + *extit; + *it = (dir_it->isDefault() ? lib : cand) + + verovr + '.' + *extit; goto found; } } -- cgit v1.2.3 From 5ab8efd66a1a3c56f04a393ed1fe558ec8c1ba5c Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 30 Sep 2019 14:23:55 +0200 Subject: Make conflicting targets check less strict People tend to "turn off debug and release builds" by just not building one of the variants. For example, Qt's own rcc is built in release only, however it is configured for debug_and_release with the same TARGET for both. Let qmake complain about conflicting TARGETs only we're about to build all of those conflicting targets, i.e. if build_all is set. Change-Id: I0448bf5cb421e2d801d3cc30e0d80353fba0d999 Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- qmake/generators/metamakefile.cpp | 4 ++++ .../tools/qmake/testdata/conflicting_targets/conflicting_targets.pro | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 22a72100f7..b8b93bc8cb 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -252,6 +252,10 @@ void BuildsMetaMakefileGenerator::checkForConflictingTargets() const // and the last entry in makefiles is the "glue" Build. return; } + if (!project->isActiveConfig("build_all")) { + // Only complain if we're about to build all configurations. + return; + } using TargetInfo = std::pair; QVector targets; const int last = makefiles.count() - 1; diff --git a/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro index c3e8034e35..bd0d4d824a 100644 --- a/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro +++ b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro @@ -1,5 +1,5 @@ TEMPLATE = app -CONFIG += debug_and_release +CONFIG += debug_and_release build_all TARGET = bah DESTDIR = shu SOURCES += main.cpp -- cgit v1.2.3 From 3afe4a402c18a0956cab31169d843018d1b7a6d3 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 3 Oct 2019 17:08:13 +0200 Subject: Convert a few sizeof(array)/sizeof(element0) fors to range fors Increases readability Change-Id: I81ea915517fd2cd6bc2780f37ba8d8097c63f44b Reviewed-by: Thiago Macieira Reviewed-by: Volker Hilsheimer --- src/corelib/io/qsettings.cpp | 7 +++---- src/dbus/qdbus_symbols.cpp | 12 ++++++------ src/gui/painting/qpagesize.cpp | 8 +++----- src/gui/rhi/qrhivulkan.cpp | 16 ++++++++-------- src/gui/vulkan/qvulkanwindow.cpp | 16 ++++++++-------- src/network/access/qhttp2protocolhandler.cpp | 15 ++++++--------- src/platformsupport/edid/qedidparser.cpp | 8 +++----- 7 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 4a119a1e2f..fc7122d904 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -746,7 +746,6 @@ bool QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, i { '\'', '\'' }, { '\\', '\\' } }; - static const int numEscapeCodes = sizeof(escapeCodes) / sizeof(escapeCodes[0]); bool isStringList = false; bool inQuotedString = false; @@ -770,9 +769,9 @@ StNormal: goto end; ch = str.at(i++); - for (int j = 0; j < numEscapeCodes; ++j) { - if (ch == escapeCodes[j][0]) { - stringResult += QLatin1Char(escapeCodes[j][1]); + for (const auto &escapeCode : escapeCodes) { + if (ch == escapeCode[0]) { + stringResult += QLatin1Char(escapeCode[1]); goto StNormal; } } diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index 284ba999c2..1e2cbf6da6 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -100,15 +100,15 @@ bool qdbus_loadLibDBus() }; lib->unload(); - for (uint i = 0; i < sizeof(majorversions) / sizeof(majorversions[0]); ++i) { - for (uint j = 0; j < sizeof(baseNames) / sizeof(baseNames[0]); ++j) { + for (const int majorversion : majorversions) { + for (const QString &baseName : baseNames) { #ifdef Q_OS_WIN QString suffix; - if (majorversions[i] != -1) - suffix = QString::number(- majorversions[i]); // negative so it prepends the dash - lib->setFileName(baseNames[j] + suffix); + if (majorversion != -1) + suffix = QString::number(- majorversion); // negative so it prepends the dash + lib->setFileName(baseName + suffix); #else - lib->setFileNameAndVersion(baseNames[j], majorversions[i]); + lib->setFileNameAndVersion(baseName, majorversion); #endif if (lib->load() && lib->resolve("dbus_connection_open_private")) return true; diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp index a1c9f6e417..c98ca8a1fb 100644 --- a/src/gui/painting/qpagesize.cpp +++ b/src/gui/painting/qpagesize.cpp @@ -222,8 +222,6 @@ static const int qt_windowsConversion[][2] = { {DMPAPER_PENV_10_ROTATED, DMPAPER_PENV_10} // Is = DMPAPER_LAST, use as loop terminator }; -static const int windowsConversionCount = int(sizeof(qt_windowsConversion) / sizeof(qt_windowsConversion[0])); - // Standard sizes data struct StandardPageSize { QPageSize::PageSizeId id; @@ -423,9 +421,9 @@ static QPageSize::PageSizeId qt_idForWindowsID(int windowsId, QSize *match = 0) if (windowsId <= DMPAPER_NONE || windowsId > DMPAPER_LAST) return QPageSize::Custom; // Check if one of the unsupported values, convert to valid value if is - for (int i = 0; i < windowsConversionCount; ++i) { - if (qt_windowsConversion[i][0] == windowsId) { - windowsId = qt_windowsConversion[i][1]; + for (const auto &it : qt_windowsConversion) { + if (it[0] == windowsId) { + windowsId = it[1]; break; } } diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index cb32aa08f3..36a6557e04 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -3241,12 +3241,12 @@ QVector QRhiVulkan::supportedSampleCounts() const VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts; QVector result; - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if ((color & qvk_sampleCounts[i].mask) - && (depth & qvk_sampleCounts[i].mask) - && (stencil & qvk_sampleCounts[i].mask)) + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if ((color & qvk_sampleCount.mask) + && (depth & qvk_sampleCount.mask) + && (stencil & qvk_sampleCount.mask)) { - result.append(qvk_sampleCounts[i].count); + result.append(qvk_sampleCount.count); } } @@ -3263,9 +3263,9 @@ VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount) return VK_SAMPLE_COUNT_1_BIT; } - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if (qvk_sampleCounts[i].count == sampleCount) - return qvk_sampleCounts[i].mask; + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if (qvk_sampleCount.count == sampleCount) + return qvk_sampleCount.mask; } Q_UNREACHABLE(); diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index 6d12377a60..4b5c2b56ee 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -498,12 +498,12 @@ QVector QVulkanWindow::supportedSampleCounts() VkSampleCountFlags depth = limits->framebufferDepthSampleCounts; VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts; - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if ((color & qvk_sampleCounts[i].mask) - && (depth & qvk_sampleCounts[i].mask) - && (stencil & qvk_sampleCounts[i].mask)) + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if ((color & qvk_sampleCount.mask) + && (depth & qvk_sampleCount.mask) + && (stencil & qvk_sampleCount.mask)) { - result.append(qvk_sampleCounts[i].count); + result.append(qvk_sampleCount.count); } } @@ -547,9 +547,9 @@ void QVulkanWindow::setSampleCount(int sampleCount) return; } - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if (qvk_sampleCounts[i].count == sampleCount) { - d->sampleCount = qvk_sampleCounts[i].mask; + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if (qvk_sampleCount.count == sampleCount) { + d->sampleCount = qvk_sampleCount.mask; return; } } diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 9bf5547f15..dce51d4fd5 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -1339,14 +1339,13 @@ void QHttp2ProtocolHandler::markAsReset(quint32 streamID) quint32 QHttp2ProtocolHandler::popStreamToResume() { quint32 streamID = connectionStreamID; - const int nQ = sizeof suspendedStreams / sizeof suspendedStreams[0]; using QNR = QHttpNetworkRequest; - const QNR::Priority ranks[nQ] = {QNR::HighPriority, - QNR::NormalPriority, - QNR::LowPriority}; + const QNR::Priority ranks[] = {QNR::HighPriority, + QNR::NormalPriority, + QNR::LowPriority}; - for (int i = 0; i < nQ; ++i) { - auto &queue = suspendedStreams[ranks[i]]; + for (const QNR::Priority rank : ranks) { + auto &queue = suspendedStreams[rank]; auto it = queue.begin(); for (; it != queue.end(); ++it) { if (!activeStreams.contains(*it)) @@ -1367,9 +1366,7 @@ quint32 QHttp2ProtocolHandler::popStreamToResume() void QHttp2ProtocolHandler::removeFromSuspended(quint32 streamID) { - const int nQ = sizeof suspendedStreams / sizeof suspendedStreams[0]; - for (int i = 0; i < nQ; ++i) { - auto &q = suspendedStreams[i]; + for (auto &q : suspendedStreams) { q.erase(std::remove(q.begin(), q.end(), streamID), q.end()); } } diff --git a/src/platformsupport/edid/qedidparser.cpp b/src/platformsupport/edid/qedidparser.cpp index 06c8852825..6bf1f1db96 100644 --- a/src/platformsupport/edid/qedidparser.cpp +++ b/src/platformsupport/edid/qedidparser.cpp @@ -42,8 +42,6 @@ #include "qedidparser_p.h" #include "qedidvendortable_p.h" -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - #define EDID_DESCRIPTOR_ALPHANUMERIC_STRING 0xfe #define EDID_DESCRIPTOR_PRODUCT_NAME 0xfc #define EDID_DESCRIPTOR_SERIAL_NUMBER 0xff @@ -139,9 +137,9 @@ bool QEdidParser::parse(const QByteArray &blob) manufacturer = m_vendorCache.value(pnpIdString); if (manufacturer.isEmpty()) { // Find the manufacturer from the vendor lookup table - for (size_t i = 0; i < ARRAY_LENGTH(q_edidVendorTable); i++) { - if (strncmp(q_edidVendorTable[i].id, pnpId, 3) == 0) { - manufacturer = QString::fromUtf8(q_edidVendorTable[i].name); + for (const auto &vendor : q_edidVendorTable) { + if (strncmp(vendor.id, pnpId, 3) == 0) { + manufacturer = QString::fromUtf8(vendor.name); break; } } -- cgit v1.2.3 From de182ea0be4dd5f9ca6552e4b81e80ab43b26be3 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Wed, 9 Jan 2019 14:17:35 +0100 Subject: Add libfuzzer test for QTextDocument::setMarkdown() Change-Id: I729d4a3bb276523011a6f17a800e72aa34540e47 Reviewed-by: Edward Welbourne Reviewed-by: Shawn Rutledge --- .../gui/text/qtextdocument/setMarkdown/main.cpp | 34 ++++++++++++++++++++++ .../text/qtextdocument/setMarkdown/setMarkdown.pro | 4 +++ 2 files changed, 38 insertions(+) create mode 100644 tests/libfuzzer/gui/text/qtextdocument/setMarkdown/main.cpp create mode 100644 tests/libfuzzer/gui/text/qtextdocument/setMarkdown/setMarkdown.pro diff --git a/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/main.cpp b/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/main.cpp new file mode 100644 index 0000000000..acdd91e06e --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/main.cpp @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + QTextDocument().setMarkdown(QByteArray(Data, Size)); + return 0; +} diff --git a/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/setMarkdown.pro b/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/setMarkdown.pro new file mode 100644 index 0000000000..4a2dfa51b9 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextdocument/setMarkdown/setMarkdown.pro @@ -0,0 +1,4 @@ +CONFIG += console +CONFIG -= app_bundle +SOURCES += main.cpp +LIBS += -fsanitize=fuzzer -- cgit v1.2.3 From 9a9bdebb92eda34939c8a7442f06d24ded82b799 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Tue, 1 Oct 2019 08:18:54 +0200 Subject: docs: Mark QPair and QLatin1Char as reentrant Change-Id: I7d37eb13809a6fa4d1c2c74fd8aea35bdf235996 Fixes: QTBUG-78552 Reviewed-by: Andy Shaw --- src/corelib/text/qchar.cpp | 1 + src/corelib/tools/qpair.qdoc | 1 + 2 files changed, 2 insertions(+) diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp index d959c55bb7..9b03a93278 100644 --- a/src/corelib/text/qchar.cpp +++ b/src/corelib/text/qchar.cpp @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE /*! \class QLatin1Char \inmodule QtCore + \reentrant \brief The QLatin1Char class provides an 8-bit ASCII/Latin-1 character. \ingroup string-processing diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc index 59e6931995..65576ef2e6 100644 --- a/src/corelib/tools/qpair.qdoc +++ b/src/corelib/tools/qpair.qdoc @@ -28,6 +28,7 @@ /*! \class QPair \inmodule QtCore + \reentrant \brief The QPair class is a template class that stores a pair of items. \ingroup tools -- cgit v1.2.3 From bb65ac80977c277b6cba1abee423ccfd5f1b1f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Oct 2019 13:59:06 +0200 Subject: Modernize QWindowSystemInterface::handleCloseEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The base WindowSystemEvent has had an eventAccepted flag since 2014. Change-Id: Ia0aa795083cd98ece83a4c1cc010d3a25e2489fd Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qguiapplication.cpp | 5 ++--- src/gui/kernel/qplatformwindow.cpp | 4 +--- src/gui/kernel/qwindowsysteminterface.cpp | 10 ++++------ src/gui/kernel/qwindowsysteminterface.h | 2 +- src/gui/kernel/qwindowsysteminterface_p.h | 5 ++--- src/plugins/platforms/cocoa/qcocoawindow.mm | 13 +++++-------- 6 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index fe73278c62..13de8af8b5 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2527,9 +2527,8 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl QCloseEvent event; QGuiApplication::sendSpontaneousEvent(e->window.data(), &event); - if (e->accepted) { - *(e->accepted) = event.isAccepted(); - } + + e->eventAccepted = event.isAccepted(); } void QGuiApplicationPrivate::processFileOpenEvent(QWindowSystemInterfacePrivate::FileOpenEvent *e) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 4e95751397..2a0cb1094c 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -348,9 +348,7 @@ void QPlatformWindow::setWindowIcon(const QIcon &icon) { Q_UNUSED(icon); } */ bool QPlatformWindow::close() { - bool accepted = false; - QWindowSystemInterface::handleCloseEvent(window(), &accepted); - return accepted; + return QWindowSystemInterface::handleCloseEvent(window()); } /*! diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 40a298226a..03be72ca30 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -340,13 +340,11 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QReg QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleCloseEvent, QWindow *window, bool *accepted) +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window) { - if (window) { - QWindowSystemInterfacePrivate::CloseEvent *e = - new QWindowSystemInterfacePrivate::CloseEvent(window, accepted); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); - } + Q_ASSERT(window); + auto *event = new QWindowSystemInterfacePrivate::CloseEvent(window); + return QWindowSystemInterfacePrivate::handleWindowSystemEvent(event); } /*! diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index fd70eda9ff..4a0bc858a9 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -194,7 +194,7 @@ public: static void handleExposeEvent(QWindow *window, const QRegion ®ion); template - static void handleCloseEvent(QWindow *window, bool *accepted = nullptr); + static bool handleCloseEvent(QWindow *window); template static void handleEnterEvent(QWindow *window, const QPointF &local = QPointF(), const QPointF& global = QPointF()); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index d6513f1836..540170f733 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -123,11 +123,10 @@ public: class CloseEvent : public WindowSystemEvent { public: - explicit CloseEvent(QWindow *w, bool *a = nullptr) - : WindowSystemEvent(Close), window(w), accepted(a) + explicit CloseEvent(QWindow *w) + : WindowSystemEvent(Close), window(w) { } QPointer window; - bool *accepted; }; class GeometryChangeEvent : public WindowSystemEvent { diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 35b7162346..a744a86695 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1275,14 +1275,11 @@ void QCocoaWindow::windowWillClose() bool QCocoaWindow::windowShouldClose() { qCDebug(lcQpaWindow) << "QCocoaWindow::windowShouldClose" << window(); - // This callback should technically only determine if the window - // should (be allowed to) close, but since our QPA API to determine - // that also involves actually closing the window we do both at the - // same time, instead of doing the latter in windowWillClose. - bool accepted = false; - QWindowSystemInterface::handleCloseEvent(window(), &accepted); - QWindowSystemInterface::flushWindowSystemEvents(); - return accepted; + // This callback should technically only determine if the window + // should (be allowed to) close, but since our QPA API to determine + // that also involves actually closing the window we do both at the + // same time, instead of doing the latter in windowWillClose. + return QWindowSystemInterface::handleCloseEvent(window()); } // ----------------------------- QPA forwarding ----------------------------- -- cgit v1.2.3 From 91a869671eaf16bb8502141f1eb00a38312aa3d5 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 27 Sep 2019 03:14:45 +0200 Subject: CMake: generate moc files for headers using Q_NAMESPACE_EXPORT too Commit f66c1db16c050c introduced Q_NAMESPACE_EXPORT and cmake automoc needs to be told to trigger moc creation for headers using that. The default value for this variable, from cmake's Modules/CMakeGenericSystem.cmake is set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_NAMESPACE") But it makes more sense to set this here than in upstream cmake, anyway, given that changes to this list happen here in qtbase. Change-Id: I07c85fd0bb5e03e98df7687a8663e28620e1fdb6 Reviewed-by: Simon Hausmann --- src/corelib/Qt5CoreConfigExtras.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index e0652fdcf9..659faac6a5 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -46,6 +46,8 @@ if (NOT TARGET Qt5::rcc) ) endif() +set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_NAMESPACE" "Q_NAMESPACE_EXPORT") + set(Qt5Core_QMAKE_EXECUTABLE Qt5::qmake) set(Qt5Core_MOC_EXECUTABLE Qt5::moc) set(Qt5Core_RCC_EXECUTABLE Qt5::rcc) -- cgit v1.2.3 From d3be61d965ea13d972e7b64c7fe6a2ef0cc8eeec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 27 Sep 2019 12:28:49 +0200 Subject: Fix unused function warning for prefixFromQtCoreLibraryHelper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iedbe0e9363b6bd97071b38aa1d4546777b34139d Reviewed-by: Simon Hausmann Reviewed-by: Tor Arne Vestbø --- src/corelib/global/qlibraryinfo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 52ad471e71..6476b7404a 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -495,6 +495,8 @@ static QString prefixFromAppDirHelper() #endif #if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) +#if !defined(QT_STATIC) && !(defined(Q_OS_DARWIN) && QT_CONFIG(framework)) \ + && (QT_CONFIG(dlopen) || defined(Q_OS_WIN)) static QString prefixFromQtCoreLibraryHelper(const QString &qtCoreLibraryPath) { const QString qtCoreLibrary = QDir::fromNativeSeparators(qtCoreLibraryPath); @@ -503,6 +505,7 @@ static QString prefixFromQtCoreLibraryHelper(const QString &qtCoreLibraryPath) + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH); return QDir::cleanPath(prefixDir); } +#endif #if defined(Q_OS_WIN) #if defined(Q_OS_WINRT) -- cgit v1.2.3 From 3018c48f32120b59a72120068f4f99a1f5647e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 27 Sep 2019 15:07:58 +0200 Subject: qmake: Parse -framework link lines the same way the linker does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][qmake] The syntax 'LIBS += -frameworkFoo', or 'LIBS += "-framework Foo"' is no longer supported. Use the canonical 'LIBS += -framework Foo' instead. Change-Id: I50fd02dbfa155a0b95859734486a92bd448e87c2 Reviewed-by: Edward Welbourne Reviewed-by: Alexandru Croitor Reviewed-by: Tor Arne Vestbø --- qmake/generators/unix/unixmake.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 71bf72100e..f4bc0e47ea 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -433,12 +433,9 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) QMakeLocalFileName f(opt.mid(2)); if (!frameworkdirs.contains(f)) frameworkdirs.insert(fwidx++, f); - } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { + } else if (target_mode == TARG_MAC_MODE && opt == "-framework") { if (linkPrl) { - if (opt.length() == 10) - opt = (*++it).toQString(); - else - opt = opt.mid(10).trimmed(); + opt = (*++it).toQString(); static const QChar suffixMarker = ','; const int suffixPosition = opt.indexOf(suffixMarker); const bool hasSuffix = suffixPosition >= 0; -- cgit v1.2.3 From d1a9815a438c87893a4d19f5e46f14315f74ad7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 Oct 2019 15:36:43 +0200 Subject: macOS: Add missing export of QDebug stream operator for QMacAutoReleasePool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id3e140bd91dcbf2683a41cd9ac36ff79b8f365b4 Reviewed-by: Thiago Macieira Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcore_mac_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 3266dc10a8..270b8fcf0f 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -168,7 +168,7 @@ Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); #endif #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool); +Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool); #endif Q_CORE_EXPORT bool qt_apple_isApplicationExtension(); -- cgit v1.2.3 From 191eb076a9b3f54b50d8c6d50039c59c03ae0483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 Oct 2019 15:37:59 +0200 Subject: Add explicit QDebug stream operator for QCFString Disambiguates between the QString and CFStringRef overloads. Change-Id: I55a7121cd7449b4adc081f6bb7e29736e7af4442 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_mac_objc.mm | 6 ++++++ src/corelib/kernel/qcore_mac_p.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 9e9e71c397..b1f3b74cd4 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -211,6 +211,12 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool) debug << "QMacAutoReleasePool(" << (const void *)pool << ')'; return debug; } + +QDebug operator<<(QDebug debug, const QCFString &string) +{ + debug << static_cast(string); + return debug; +} #endif // !QT_NO_DEBUG_STREAM #ifdef Q_OS_MACOS diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 270b8fcf0f..d03e2f3738 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -169,6 +169,7 @@ Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool); +Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string); #endif Q_CORE_EXPORT bool qt_apple_isApplicationExtension(); -- cgit v1.2.3 From f21ecb5657ee679f4c988de1bcd8d66b32952dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 Oct 2019 15:39:17 +0200 Subject: Simplify creating QCFTypes from CFTypeRefs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of forcing the user to cast: QCFType foo = (CFFooRef)CFFunctionReturningCFTypeRef()); We can do it for them, since we already know the expected type: auto foo = QCFType(CFFunctionReturningCFTypeRef)); Change-Id: I994d5d6530f220288b4bfd6ab16eae9f159ce3ef Reviewed-by: Thiago Macieira Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcore_mac_p.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index d03e2f3738..535d3579b2 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -137,8 +137,10 @@ private: template class QCFType : public QAppleRefCounted { + using Base = QAppleRefCounted; public: - using QAppleRefCounted::QAppleRefCounted; + using Base::Base; + explicit QCFType(CFTypeRef r) : Base(static_cast(r)) {} template X as() const { return reinterpret_cast(this->value); } static QCFType constructFromGet(const T &t) { @@ -151,6 +153,7 @@ public: class Q_CORE_EXPORT QCFString : public QCFType { public: + using QCFType::QCFType; inline QCFString(const QString &str) : QCFType(0), string(str) {} inline QCFString(const CFStringRef cfstr = 0) : QCFType(cfstr) {} inline QCFString(const QCFType &other) : QCFType(other) {} -- cgit v1.2.3 From 0768a28fbfe4c7227182b6b4b7cacbc6772c54f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 3 Oct 2019 12:36:56 +0200 Subject: Remove CFBundleGetInfoString from Info.plist templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Is't been deprecated since Mac OS X 10.5. Task-number: QTBUG-74872 Change-Id: I8b1ad7aca6448883cb164fd0c4b329592ca60548 Reviewed-by: Edward Welbourne Reviewed-by: Alexandru Croitor Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-clang/Info.plist.app | 2 -- mkspecs/macx-clang/Info.plist.lib | 2 -- mkspecs/macx-g++/Info.plist.app | 2 -- mkspecs/macx-g++/Info.plist.lib | 2 -- mkspecs/macx-icc/Info.plist.app | 2 -- mkspecs/macx-icc/Info.plist.lib | 2 -- mkspecs/macx-ios-clang/Info.plist.app | 2 -- mkspecs/macx-ios-clang/Info.plist.lib | 2 -- mkspecs/macx-tvos-clang/Info.plist.app | 2 -- mkspecs/macx-tvos-clang/Info.plist.lib | 2 -- mkspecs/macx-watchos-clang/Info.plist.app | 2 -- mkspecs/macx-watchos-clang/Info.plist.lib | 2 -- tests/auto/corelib/io/qdir/Info.plist | 2 -- tests/auto/other/macplist/tst_macplist.cpp | 10 ---------- 14 files changed, 36 deletions(-) diff --git a/mkspecs/macx-clang/Info.plist.app b/mkspecs/macx-clang/Info.plist.app index 4d64a77704..fa592af089 100644 --- a/mkspecs/macx-clang/Info.plist.app +++ b/mkspecs/macx-clang/Info.plist.app @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIconFile ${ASSETCATALOG_COMPILER_APPICON_NAME} CFBundleIdentifier diff --git a/mkspecs/macx-clang/Info.plist.lib b/mkspecs/macx-clang/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-clang/Info.plist.lib +++ b/mkspecs/macx-clang/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/mkspecs/macx-g++/Info.plist.app b/mkspecs/macx-g++/Info.plist.app index 4d64a77704..fa592af089 100644 --- a/mkspecs/macx-g++/Info.plist.app +++ b/mkspecs/macx-g++/Info.plist.app @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIconFile ${ASSETCATALOG_COMPILER_APPICON_NAME} CFBundleIdentifier diff --git a/mkspecs/macx-g++/Info.plist.lib b/mkspecs/macx-g++/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-g++/Info.plist.lib +++ b/mkspecs/macx-g++/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/mkspecs/macx-icc/Info.plist.app b/mkspecs/macx-icc/Info.plist.app index 4d64a77704..fa592af089 100644 --- a/mkspecs/macx-icc/Info.plist.app +++ b/mkspecs/macx-icc/Info.plist.app @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIconFile ${ASSETCATALOG_COMPILER_APPICON_NAME} CFBundleIdentifier diff --git a/mkspecs/macx-icc/Info.plist.lib b/mkspecs/macx-icc/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-icc/Info.plist.lib +++ b/mkspecs/macx-icc/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/mkspecs/macx-ios-clang/Info.plist.app b/mkspecs/macx-ios-clang/Info.plist.app index 1acbf9d768..03ba3e82b4 100644 --- a/mkspecs/macx-ios-clang/Info.plist.app +++ b/mkspecs/macx-ios-clang/Info.plist.app @@ -6,8 +6,6 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIconFile ${ASSETCATALOG_COMPILER_APPICON_NAME} CFBundleIdentifier diff --git a/mkspecs/macx-ios-clang/Info.plist.lib b/mkspecs/macx-ios-clang/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-ios-clang/Info.plist.lib +++ b/mkspecs/macx-ios-clang/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/mkspecs/macx-tvos-clang/Info.plist.app b/mkspecs/macx-tvos-clang/Info.plist.app index 04aef816c2..b9b67fe41e 100644 --- a/mkspecs/macx-tvos-clang/Info.plist.app +++ b/mkspecs/macx-tvos-clang/Info.plist.app @@ -8,8 +8,6 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIcons CFBundlePrimaryIcon diff --git a/mkspecs/macx-tvos-clang/Info.plist.lib b/mkspecs/macx-tvos-clang/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-tvos-clang/Info.plist.lib +++ b/mkspecs/macx-tvos-clang/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/mkspecs/macx-watchos-clang/Info.plist.app b/mkspecs/macx-watchos-clang/Info.plist.app index 47f5a58d5e..5ac0ef78a0 100644 --- a/mkspecs/macx-watchos-clang/Info.plist.app +++ b/mkspecs/macx-watchos-clang/Info.plist.app @@ -8,8 +8,6 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleName diff --git a/mkspecs/macx-watchos-clang/Info.plist.lib b/mkspecs/macx-watchos-clang/Info.plist.lib index ce28365500..34752ec40d 100644 --- a/mkspecs/macx-watchos-clang/Info.plist.lib +++ b/mkspecs/macx-watchos-clang/Info.plist.lib @@ -4,8 +4,6 @@ CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundlePackageType diff --git a/tests/auto/corelib/io/qdir/Info.plist b/tests/auto/corelib/io/qdir/Info.plist index 7dc5622bde..e1f6fbe24a 100644 --- a/tests/auto/corelib/io/qdir/Info.plist +++ b/tests/auto/corelib/io/qdir/Info.plist @@ -6,8 +6,6 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleGetInfoString - Created by Qt/QMake CFBundleIconFile ${ASSETCATALOG_COMPILER_APPICON_NAME} CFBundleIdentifier diff --git a/tests/auto/other/macplist/tst_macplist.cpp b/tests/auto/other/macplist/tst_macplist.cpp index 755cc462f5..dec63b1b66 100644 --- a/tests/auto/other/macplist/tst_macplist.cpp +++ b/tests/auto/other/macplist/tst_macplist.cpp @@ -59,8 +59,6 @@ void tst_MacPlist::test_plist_data() " \n" " CFBundlePackageType\n" " APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" " CFBundleExecutable\n" " app\n" " CFBundleIdentifier\n" @@ -77,8 +75,6 @@ void tst_MacPlist::test_plist_data() " \n" " CFBundlePackageType\n" " APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" " CFBundleExecutable\n" " app\n" " CFBundleIdentifier\n" @@ -97,8 +93,6 @@ void tst_MacPlist::test_plist_data() " \n" " CFBundlePackageType\n" " APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" " CFBundleExecutable\n" " app\n" " CFBundleIdentifier\n" @@ -117,8 +111,6 @@ void tst_MacPlist::test_plist_data() " \n" " CFBundlePackageType\n" " APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" " CFBundleExecutable\n" " app\n" " CFBundleIdentifier\n" @@ -137,8 +129,6 @@ void tst_MacPlist::test_plist_data() " \n" " CFBundlePackageType\n" " APPL\n" -" CFBundleGetInfoString\n" -" Created by Qt/QMake\n" " CFBundleExecutable\n" " app\n" " CFBundleIdentifier\n" -- cgit v1.2.3 From e46a0501d65e6f84e4c7358f48aab154e2d32598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 3 Oct 2019 16:20:19 +0200 Subject: CoreText: Use categorized logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4cfa6b0ef15adb7e600d66f4fe5b3dc17470f1c3 Reviewed-by: Volker Hilsheimer Reviewed-by: Tor Arne Vestbø --- src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index ac4a8f35f8..201a82864f 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -159,7 +159,7 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName) // A single family might match several different fonts with different styles eg. QCFType matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0); if (!matchingFonts) { - qWarning() << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName; + qCWarning(lcQpaFonts) << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName; return; } @@ -400,20 +400,20 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family) auto attributes = @{ id(kCTFontFamilyNameAttribute): family.toNSString() }; QCFType fontDescriptor = CTFontDescriptorCreateWithAttributes(CFDictionaryRef(attributes)); if (!fontDescriptor) { - qWarning() << "Failed to create fallback font descriptor for" << family; + qCWarning(lcQpaFonts) << "Failed to create fallback font descriptor for" << family; return QStringList(); } QCFType font = CTFontCreateWithFontDescriptor(fontDescriptor, 12.0, 0); if (!font) { - qWarning() << "Failed to create fallback font for" << family; + qCWarning(lcQpaFonts) << "Failed to create fallback font for" << family; return QStringList(); } QCFType cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font, (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:@"AppleLanguages"])); if (!cascadeList) { - qWarning() << "Failed to create fallback cascade list for" << family; + qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << family; return QStringList(); } -- cgit v1.2.3 From 0118e2e9151ae3e1e1cd72f24e8c129eaa69dc4f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 29 Apr 2019 12:33:55 +0200 Subject: Include likely-adjusted uiLanguages for the system locale QLocale::uiLanguages() on the system locale uses whatever the system locale's query(QSystemLocale::UILanguages,...) returns. On Android, this is just a list of locales. However, for non-system locales, we also include some results of removing likely sub-tags from the locale name, where equivalent. Thus zh-CN would also get zh and zh-Hans-CN added to it; however, if the system locale is zh-Hans-CN, the shorter forms are omitted. So post-process the system locale list in the same way, albeit tweaked to avoid duplicates and rearranged so that we can insert likely-adjusted entries between what they adjust and what followed it. Added QLocalePrivate::rawName() in the process, since it looks likely to be useful in other contexts (and I needed its value): it just joins such tags as are non-Any. This, however, uses QByteArrayList, so added that (it's small) to the bootstrap library and qmake. This follows up on commit 8796e3016fae1672e727e2fa4e48f671a0c667ba. [ChangeLog][QtCore][QLocale] The system locale's UI languages list now includes, as for that of an ordinary locale, the results of adding likely sub-tags from each locale name, and of removing some, where this doesn't change which locale is specified. This gives searches for translation files a better chance of finding a suitable file. Fixes: QTBUG-75413 Change-Id: Iaafd79aac6a0fdd5f44aed16e445e84a2267c9da Reviewed-by: Paul Wicking Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira --- qmake/Makefile.unix | 8 +++- qmake/Makefile.win32 | 1 + src/corelib/text/qlocale.cpp | 82 +++++++++++++++++++++++++++++++-------- src/corelib/text/qlocale_p.h | 1 + src/tools/bootstrap/bootstrap.pro | 1 + 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index e895feaef4..4d4f05e78a 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -27,7 +27,7 @@ QOBJS = \ qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \ qmetatype.o qsystemerror.o qvariant.o \ quuid.o \ - qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \ + qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o \ qcalendar.o qgregoriancalendar.o qromancalendar.o \ qcryptographichash.o qdatetime.o qhash.o qlist.o \ qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \ @@ -106,7 +106,8 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp \ - $(SOURCE_PATH)/src/corelib/text/qbytearray.cpp\ + $(SOURCE_PATH)/src/corelib/text/qbytearray.cpp \ + $(SOURCE_PATH)/src/corelib/text/qbytearraylist.cpp \ $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp \ $(SOURCE_PATH)/src/corelib/text/qlocale.cpp \ $(SOURCE_PATH)/src/corelib/text/qlocale_tools.cpp \ @@ -309,6 +310,9 @@ qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp qbytearray.o: $(SOURCE_PATH)/src/corelib/text/qbytearray.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qbytearraylist.o: $(SOURCE_PATH)/src/corelib/text/qbytearraylist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qvsnprintf.o: $(SOURCE_PATH)/src/corelib/text/qvsnprintf.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 672df47953..7324817af2 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -69,6 +69,7 @@ QTOBJS= \ qfsfileengine_iterator.obj \ qarraydata.obj \ qbytearray.obj \ + qbytearraylist.obj \ qvsnprintf.obj \ qbytearraymatcher.obj \ qcalendar.obj \ diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 48d57e5e6e..75a5bc802e 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -345,6 +345,23 @@ QByteArray QLocalePrivate::bcp47Name(char separator) const return localeId.withLikelySubtagsRemoved().name(separator); } +/*! + \internal + */ +QByteArray QLocalePrivate::rawName(char separator) const +{ + QByteArrayList parts; + if (m_data->m_language_id != QLocale::AnyLanguage) + parts.append(languageCode().latin1()); + if (m_data->m_script_id != QLocale::AnyScript) + parts.append(scriptCode().latin1()); + if (m_data->m_country_id != QLocale::AnyCountry) + parts.append(countryCode().latin1()); + + return parts.join(separator); +} + + static const QLocaleData *findLocaleDataById(const QLocaleId &lid) { QLocaleId localeId = lid.withLikelySubtagsAdded(); @@ -4367,30 +4384,63 @@ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats */ QStringList QLocale::uiLanguages() const { + QStringList uiLanguages; + QVector locales; #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant()); if (!res.isNull()) { - QStringList result = res.toStringList(); - if (!result.isEmpty()) - return result; + uiLanguages = res.toStringList(); + // ... but we need to include likely-adjusted forms of each of those, too: + for (const auto entry : qAsConst(uiLanguages)) + locales.append(QLocale(entry)); } - } + } else #endif - QLocaleId id = QLocaleId::fromIds(d->m_data->m_language_id, d->m_data->m_script_id, - d->m_data->m_country_id); - const QLocaleId max = id.withLikelySubtagsAdded(); - const QLocaleId min = max.withLikelySubtagsRemoved(); + { + locales.append(*this); + } + for (int i = locales.size(); i-- > 0; ) { + const QLocale &locale = locales.at(i); + int j; + QByteArray prior; + if (i < uiLanguages.size()) { + // Adding likely-adjusted forms to system locale's list. + // Name the locale is derived from: + const QString &name = uiLanguages.at(i); + prior = name.toLatin1(); + // Don't try to likely-adjust if construction's likely-adjustments + // were so drastic the result doesn't match the prior name: + if (locale.name() != name && locale.d->rawName() != prior) + continue; + // Insert just after prior: + j = i + 1; + } else { + // Plain locale, not system locale; just append. + j = uiLanguages.size(); + } + const auto data = locale.d->m_data; + + QLocaleId id + = QLocaleId::fromIds(data->m_language_id, data->m_script_id, data->m_country_id); + const QLocaleId max = id.withLikelySubtagsAdded(); + const QLocaleId min = max.withLikelySubtagsRemoved(); + id.script_id = 0; // For re-use as script-less variant. + + // Include version with all likely sub-tags (last) if distinct from the rest: + if (max != min && max != id && max.name() != prior) + uiLanguages.insert(j, QString::fromLatin1(max.name())); + + // Include scriptless version if likely-equivalent and distinct: + if (data->m_script_id && id != min && id.name() != prior + && id.withLikelySubtagsAdded() == max) { + uiLanguages.insert(j, QString::fromLatin1(id.name())); + } - QStringList uiLanguages; - uiLanguages.append(QString::fromLatin1(min.name())); - if (id.script_id) { - id.script_id = 0; - if (id != min && id.withLikelySubtagsAdded() == max) - uiLanguages.append(QString::fromLatin1(id.name())); + // Include minimal version (first) unless it's what our locale is derived from: + if (min.name() != prior) + uiLanguages.insert(j, QString::fromLatin1(min.name())); } - if (max != min && max != id) - uiLanguages.append(QString::fromLatin1(max.name())); return uiLanguages; } diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index 5ebed9b385..edee3a89c7 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -359,6 +359,7 @@ public: quint16 countryId() const { return m_data->m_country_id; } QByteArray bcp47Name(char separator = '-') const; + QByteArray rawName(char separator = '-') const; inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); } inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); } diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index f9ffd1bbea..09a1c68001 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -75,6 +75,7 @@ SOURCES += \ ../../corelib/serialization/qxmlutils.cpp \ ../../corelib/serialization/qxmlstream.cpp \ ../../corelib/text/qbytearray.cpp \ + ../../corelib/text/qbytearraylist.cpp \ ../../corelib/text/qbytearraymatcher.cpp \ ../../corelib/text/qlocale.cpp \ ../../corelib/text/qlocale_tools.cpp \ -- cgit v1.2.3 From 332232682e69f24ce41412b868b7247ca3c54cc0 Mon Sep 17 00:00:00 2001 From: Nils Jeisecke Date: Fri, 4 Oct 2019 10:47:51 +0200 Subject: Fix build with QT_NO_CSSPARSER / -no-feature-cssparser Some parts of the new QTextDocument table border logic depend on the QCss namespace which is not available with -no-feature-cssparser. Change-Id: Ib8396894dc35872f22c634e1d6c38968d3dd4756 Reviewed-by: Timo Aarnipuro Reviewed-by: Shawn Rutledge --- src/gui/text/qtextdocumentfragment.cpp | 2 ++ src/gui/text/qtextdocumentlayout.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index 723e5c907c..742c56382d 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -1062,6 +1062,7 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode() fmt.setLeftPadding(leftPadding(currentNodeIdx)); if (rightPadding(currentNodeIdx) >= 0) fmt.setRightPadding(rightPadding(currentNodeIdx)); +#ifndef QT_NO_CSSPARSER if (tableCellBorder(currentNodeIdx, QCss::TopEdge) > 0) fmt.setTopBorder(tableCellBorder(currentNodeIdx, QCss::TopEdge)); if (tableCellBorder(currentNodeIdx, QCss::RightEdge) > 0) @@ -1086,6 +1087,7 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode() fmt.setBottomBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::BottomEdge)); if (tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge) != Qt::NoBrush) fmt.setLeftBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge)); +#endif cell.setFormat(fmt); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index a9a177da8b..1d5afee16b 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -265,6 +265,9 @@ public: inline QFixed topPadding(QTextTable *table, const QTextTableCell &cell) const { +#ifdef QT_NO_CSSPARSER + Q_UNUSED(table); +#endif return paddingProperty(cell.format(), QTextFormat::TableCellTopPadding) #ifndef QT_NO_CSSPARSER + cellBorderWidth(table, cell, QCss::TopEdge) @@ -274,6 +277,9 @@ public: inline QFixed bottomPadding(QTextTable *table, const QTextTableCell &cell) const { +#ifdef QT_NO_CSSPARSER + Q_UNUSED(table); +#endif return paddingProperty(cell.format(), QTextFormat::TableCellBottomPadding) #ifndef QT_NO_CSSPARSER + cellBorderWidth(table, cell, QCss::BottomEdge) @@ -283,6 +289,9 @@ public: inline QFixed leftPadding(QTextTable *table, const QTextTableCell &cell) const { +#ifdef QT_NO_CSSPARSER + Q_UNUSED(table); +#endif return paddingProperty(cell.format(), QTextFormat::TableCellLeftPadding) #ifndef QT_NO_CSSPARSER + cellBorderWidth(table, cell, QCss::LeftEdge) @@ -292,6 +301,9 @@ public: inline QFixed rightPadding(QTextTable *table, const QTextTableCell &cell) const { +#ifdef QT_NO_CSSPARSER + Q_UNUSED(table); +#endif return paddingProperty(cell.format(), QTextFormat::TableCellRightPadding) #ifndef QT_NO_CSSPARSER + cellBorderWidth(table, cell, QCss::RightEdge) @@ -1034,15 +1046,22 @@ static bool cellClipTest(QTextTable *table, QTextTableData *td, const QTextTableCell &cell, QRectF cellRect) { +#ifdef QT_NO_CSSPARSER + Q_UNUSED(table); + Q_UNUSED(cell); +#endif + if (!cell_context.clip.isValid()) return false; if (td->borderCollapse) { // we need to account for the cell borders in the clipping test +#ifndef QT_NO_CSSPARSER cellRect.adjust(-axisEdgeData(table, td, cell, QCss::LeftEdge).width / 2, -axisEdgeData(table, td, cell, QCss::TopEdge).width / 2, axisEdgeData(table, td, cell, QCss::RightEdge).width / 2, axisEdgeData(table, td, cell, QCss::BottomEdge).width / 2); +#endif } else { qreal border = td->border.toReal(); cellRect.adjust(-border, -border, border, border); @@ -1798,6 +1817,13 @@ void QTextDocumentLayoutPrivate::drawTableCellBorder(const QRectF &cellRect, QPa if (turn_off_antialiasing) painter->setRenderHint(QPainter::Antialiasing, false); +#else + Q_UNUSED(cell); + Q_UNUSED(cellRect); + Q_UNUSED(painter); + Q_UNUSED(table); + Q_UNUSED(td); + Q_UNUSED(cell); #endif } @@ -2285,12 +2311,14 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT + td->border + td->paddingProperty(cell.format(), QTextFormat::TableCellTopPadding); // top cell-border is not repeated +#ifndef QT_NO_CSSPARSER const int headerRowCount = t->format().headerRowCount(); if (td->borderCollapse && headerRowCount > 0) { // consider the header row's bottom edge width qreal headerRowBottomBorderWidth = axisEdgeData(t, td, t->cellAt(headerRowCount - 1, cell.column()), QCss::BottomEdge).width; layoutStruct.pageTopMargin += QFixed::fromReal(scaleToDevice(headerRowBottomBorderWidth) / 2); } +#endif layoutStruct.pageBottomMargin = td->effectiveBottomMargin + td->cellSpacing + td->effectiveBottomBorder + td->bottomPadding(t, cell); layoutStruct.pageBottom = (currentPage + 1) * layoutStruct.pageHeight - layoutStruct.pageBottomMargin; -- cgit v1.2.3 From 64473c9320b8c521e3ea7030aee5c1c8193661b1 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 8 Sep 2019 20:20:29 +0200 Subject: tst_QColumnView: cleanup Cleanup QColumnView autotest: - use range-based for loops - use nullptr - use member initialization - use new signal/slot syntax - use static invocations - use override Change-Id: Iae94e9074b65cca1e4d9eb199ea2b13e0cfa2880 Reviewed-by: Friedemann Kleint --- .../itemviews/qcolumnview/tst_qcolumnview.cpp | 260 +++++++++------------ 1 file changed, 114 insertions(+), 146 deletions(-) diff --git a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp index c58dbf599c..8264d71e83 100644 --- a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp +++ b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp @@ -26,25 +26,21 @@ ** ****************************************************************************/ -#include "../../../../shared/fakedirmodel.h" -#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include "../../../../shared/fakedirmodel.h" #define ANIMATION_DELAY 300 -class tst_QColumnView : public QObject { - Q_OBJECT - +class tst_QColumnView : public QObject +{ + Q_OBJECT public: tst_QColumnView(); @@ -98,6 +94,7 @@ private: class TreeModel : public QStandardItemModel { + Q_OBJECT public: TreeModel() { @@ -122,51 +119,31 @@ public: inline QModelIndex thirdLevel() { return index(0, 0, secondLevel()); } }; -class ColumnView : public QColumnView { - +class ColumnView : public QColumnView +{ + Q_OBJECT public: - ColumnView(QWidget *parent = 0) : QColumnView(parent){} - - QList > createdColumns; - void ScrollContentsBy(int x, int y) {scrollContentsBy(x,y); } - int HorizontalOffset() const { return horizontalOffset(); } - void emitClicked() { emit clicked(QModelIndex()); } - - enum PublicCursorAction { - MoveUp = QAbstractItemView::MoveUp, - MoveDown = QAbstractItemView::MoveDown, - MoveLeft = QAbstractItemView::MoveLeft, - MoveRight = QAbstractItemView::MoveRight, - MoveHome = QAbstractItemView::MoveHome, - MoveEnd = QAbstractItemView::MoveEnd, - MovePageUp = QAbstractItemView::MovePageUp, - MovePageDown = QAbstractItemView::MovePageDown, - MoveNext = QAbstractItemView::MoveNext, - MovePrevious = QAbstractItemView::MovePrevious - }; - - inline QModelIndex MoveCursor(PublicCursorAction ca, Qt::KeyboardModifiers kbm) - { return QColumnView::moveCursor((CursorAction)ca, kbm); } - bool IsIndexHidden(const QModelIndex&index) const - { return isIndexHidden(index); } - - void setSelection(const QRect & rect, QItemSelectionModel::SelectionFlags command ) - { - QColumnView::setSelection(rect, command); - } + using QColumnView::QColumnView; + using QColumnView::horizontalOffset; + using QColumnView::clicked; + using QColumnView::isIndexHidden; + using QColumnView::moveCursor; + using QColumnView::scrollContentsBy; + using QColumnView::setSelection; + using QColumnView::visualRegionForSelection; + + friend class tst_QColumnView; + + QVector> createdColumns; - // visualRegionForSelection() is protected in QColumnView. - QRegion getVisualRegionForSelection(const QItemSelection &selection){ - return QColumnView::visualRegionForSelection(selection); - } protected: - QAbstractItemView *createColumn(const QModelIndex &index) { + QAbstractItemView *createColumn(const QModelIndex &index) override + { QAbstractItemView *view = QColumnView::createColumn(index); QPointer savedView = view; createdColumns.append(savedView); return view; } - }; tst_QColumnView::tst_QColumnView() @@ -183,7 +160,7 @@ void tst_QColumnView::initTestCase() void tst_QColumnView::init() { - qApp->setLayoutDirection(Qt::LeftToRight); + QGuiApplication::setLayoutDirection(Qt::LeftToRight); } void tst_QColumnView::rootIndex() @@ -199,7 +176,7 @@ void tst_QColumnView::rootIndex() QModelIndex drive = model.firstLevel(); QVERIFY(view.visualRect(drive).isValid()); view.setRootIndex(QModelIndex()); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); QCOMPARE(view.rootIndex(), QModelIndex()); QVERIFY(view.visualRect(drive).isValid()); @@ -210,7 +187,7 @@ void tst_QColumnView::rootIndex() while (i < model.rowCount(home) - 1 && !model.hasChildren(homeFile)) homeFile = model.index(++i, 0, home); view.setRootIndex(home); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); QCOMPARE(view.rootIndex(), home); QVERIFY(!view.visualRect(drive).isValid()); QVERIFY(!view.visualRect(home).isValid()); @@ -221,7 +198,7 @@ void tst_QColumnView::rootIndex() view.setRootIndex(home); view.setCurrentIndex(homeFile); view.scrollTo(model.index(0,0, homeFile)); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); QCOMPARE(view.rootIndex(), home); QVERIFY(!view.visualRect(drive).isValid()); QVERIFY(!view.visualRect(home).isValid()); @@ -238,17 +215,15 @@ void tst_QColumnView::rootIndex() QModelIndex two = model.index(0, 0, homeFile); while (i < model.rowCount(homeFile) - 1 && !model.hasChildren(two)) two = model.index(++i, 0, homeFile); - qApp->processEvents(); QTest::qWait(ANIMATION_DELAY); view.setCurrentIndex(two); view.scrollTo(two); QTest::qWait(ANIMATION_DELAY); - qApp->processEvents(); QVERIFY(two.isValid()); - QVERIFY(view.HorizontalOffset() != 0); + QVERIFY(view.horizontalOffset() != 0); view.setRootIndex(homeFile); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); } void tst_QColumnView::grips() @@ -262,9 +237,9 @@ void tst_QColumnView::grips() { const QObjectList list = view.viewport()->children(); - for (int i = 0 ; i < list.count(); ++i) { - if (QAbstractItemView *view = qobject_cast(list.at(i))) - QVERIFY(view->cornerWidget() != 0); + for (QObject *obj : list) { + if (QAbstractItemView *view = qobject_cast(obj)) + QVERIFY(view->cornerWidget() != nullptr); } } view.setResizeGripsVisible(false); @@ -272,8 +247,8 @@ void tst_QColumnView::grips() { const QObjectList list = view.viewport()->children(); - for (int i = 0 ; i < list.count(); ++i) { - if (QAbstractItemView *view = qobject_cast(list.at(i))) { + for (QObject *obj : list) { + if (QAbstractItemView *view = qobject_cast(obj)) { if (view->isVisible()) QVERIFY(!view->cornerWidget()); } @@ -288,9 +263,9 @@ void tst_QColumnView::isIndexHidden() { ColumnView view; QModelIndex idx; - QCOMPARE(view.IsIndexHidden(idx), false); + QCOMPARE(view.isIndexHidden(idx), false); view.setModel(&m_fakeDirModel); - QCOMPARE(view.IsIndexHidden(idx), false); + QCOMPARE(view.isIndexHidden(idx), false); } void tst_QColumnView::indexAt() @@ -319,7 +294,6 @@ void tst_QColumnView::indexAt() view.selectionModel()->select(child, QItemSelectionModel::SelectCurrent); view.setCurrentIndex(child); - qApp->processEvents(); QTest::qWait(200); // test that the second row doesn't start at 0 @@ -348,17 +322,17 @@ void tst_QColumnView::scrollContentsBy() ColumnView view; if (reverse) view.setLayoutDirection(Qt::RightToLeft); - view.ScrollContentsBy(-1, -1); - view.ScrollContentsBy(0, 0); + view.scrollContentsBy(-1, -1); + view.scrollContentsBy(0, 0); TreeModel model; view.setModel(&model); - view.ScrollContentsBy(0, 0); + view.scrollContentsBy(0, 0); QModelIndex home = model.thirdLevel(); view.setCurrentIndex(home); QTest::qWait(ANIMATION_DELAY); - view.ScrollContentsBy(0, 0); + view.scrollContentsBy(0, 0); } void tst_QColumnView::scrollTo_data() @@ -385,7 +359,7 @@ void tst_QColumnView::scrollTo() QVERIFY(QTest::qWaitForWindowActive(&topLevel)); view.scrollTo(QModelIndex(), QAbstractItemView::EnsureVisible); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); TreeModel model; view.setModel(&model); @@ -400,45 +374,44 @@ void tst_QColumnView::scrollTo() QModelIndex index = model.index(0, 0, home); view.scrollTo(index, QAbstractItemView::EnsureVisible); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); // Embedded requires that at least one widget have focus QWidget w; w.show(); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); if (giveFocus) view.setFocus(Qt::OtherFocusReason); else view.clearFocus(); - QCOMPARE(view.HorizontalOffset(), 0); - qApp->processEvents(); - QCOMPARE(view.HorizontalOffset(), 0); + QCOMPARE(view.horizontalOffset(), 0); + QCoreApplication::processEvents(); + QCOMPARE(view.horizontalOffset(), 0); QTRY_COMPARE(view.hasFocus(), giveFocus); // scroll to the right int level = 0; - int last = view.HorizontalOffset(); - while(model.hasChildren(index) && level < 5) { + int last = view.horizontalOffset(); + while (model.hasChildren(index) && level < 5) { view.setCurrentIndex(index); QTest::qWait(ANIMATION_DELAY); view.scrollTo(index, QAbstractItemView::EnsureVisible); QTest::qWait(ANIMATION_DELAY); - qApp->processEvents(); index = model.index(0, 0, index); level++; if (level >= 2) { if (!reverse) { - QTRY_VERIFY(view.HorizontalOffset() < 0); + QTRY_VERIFY(view.horizontalOffset() < 0); qDebug() << "last=" << last - << " ; HorizontalOffset= " << view.HorizontalOffset(); - QTRY_VERIFY(last > view.HorizontalOffset()); + << " ; horizontalOffset= " << view.horizontalOffset(); + QTRY_VERIFY(last > view.horizontalOffset()); } else { - QTRY_VERIFY(view.HorizontalOffset() > 0); - QTRY_VERIFY(last < view.HorizontalOffset()); + QTRY_VERIFY(view.horizontalOffset() > 0); + QTRY_VERIFY(last < view.horizontalOffset()); } } - last = view.HorizontalOffset(); + last = view.horizontalOffset(); } // scroll to the left @@ -450,17 +423,17 @@ void tst_QColumnView::scrollTo() index = index.parent(); if (start != level) { if (!reverse) { - QTRY_VERIFY(last < view.HorizontalOffset()); + QTRY_VERIFY(last < view.horizontalOffset()); } else { - if (last <= view.HorizontalOffset()) { + if (last <= view.horizontalOffset()) { qDebug() << "Test failure. last=" << last - << " ; HorizontalOffset= " << view.HorizontalOffset(); + << " ; horizontalOffset= " << view.horizontalOffset(); } - QTRY_VERIFY(last > view.HorizontalOffset()); + QTRY_VERIFY(last > view.horizontalOffset()); } } level--; - last = view.HorizontalOffset(); + last = view.horizontalOffset(); } // It shouldn't automatically steal focus if it doesn't have it QTRY_COMPARE(view.hasFocus(), giveFocus); @@ -490,20 +463,20 @@ void tst_QColumnView::moveCursor() if (reverse) view.setLayoutDirection(Qt::RightToLeft); // don't crash - view.MoveCursor(ColumnView::MoveUp, Qt::NoModifier); + view.moveCursor(ColumnView::MoveUp, Qt::NoModifier); // don't do anything - QCOMPARE(view.MoveCursor(ColumnView::MoveEnd, Qt::NoModifier), QModelIndex()); + QCOMPARE(view.moveCursor(ColumnView::MoveEnd, Qt::NoModifier), QModelIndex()); view.setModel(&m_fakeDirModel); QModelIndex ci = view.currentIndex(); - QCOMPARE(view.MoveCursor(ColumnView::MoveUp, Qt::NoModifier), QModelIndex()); - QCOMPARE(view.MoveCursor(ColumnView::MoveDown, Qt::NoModifier), QModelIndex()); + QCOMPARE(view.moveCursor(ColumnView::MoveUp, Qt::NoModifier), QModelIndex()); + QCOMPARE(view.moveCursor(ColumnView::MoveDown, Qt::NoModifier), QModelIndex()); // left at root view.setCurrentIndex(m_fakeDirModel.index(0,0)); - ColumnView::PublicCursorAction action = reverse ? ColumnView::MoveRight : ColumnView::MoveLeft; - QCOMPARE(view.MoveCursor(action, Qt::NoModifier), m_fakeDirModel.index(0,0)); + ColumnView::CursorAction action = reverse ? ColumnView::MoveRight : ColumnView::MoveLeft; + QCOMPARE(view.moveCursor(action, Qt::NoModifier), m_fakeDirModel.index(0,0)); // left shouldn't move up int i = 0; @@ -513,30 +486,29 @@ void tst_QColumnView::moveCursor() QVERIFY(m_fakeDirModel.hasChildren(ci)); view.setCurrentIndex(ci); action = reverse ? ColumnView::MoveRight : ColumnView::MoveLeft; - QCOMPARE(view.MoveCursor(action, Qt::NoModifier), ci); + QCOMPARE(view.moveCursor(action, Qt::NoModifier), ci); // now move to the left (i.e. move over one column) view.setCurrentIndex(m_fakeDirHomeIndex); - QCOMPARE(view.MoveCursor(action, Qt::NoModifier), m_fakeDirHomeIndex.parent()); + QCOMPARE(view.moveCursor(action, Qt::NoModifier), m_fakeDirHomeIndex.parent()); // right action = reverse ? ColumnView::MoveLeft : ColumnView::MoveRight; view.setCurrentIndex(ci); - QModelIndex mc = view.MoveCursor(action, Qt::NoModifier); + QModelIndex mc = view.moveCursor(action, Qt::NoModifier); QCOMPARE(mc, m_fakeDirModel.index(0,0, ci)); // for empty directories (no way to go 'right'), next one should move down QModelIndex idx = m_fakeDirModel.index(0, 0, ci); const int rowCount = m_fakeDirModel.rowCount(ci); - while (m_fakeDirModel.hasChildren(idx) && rowCount > idx.row() + 1) { + while (m_fakeDirModel.hasChildren(idx) && rowCount > idx.row() + 1) idx = idx.sibling(idx.row() + 1, idx.column()); - } static const char error[] = "This test requires an empty directory followed by another directory."; QVERIFY2(idx.isValid(), error); QVERIFY2(!m_fakeDirModel.hasChildren(idx), error); QVERIFY2(idx.row() + 1 < rowCount, error); view.setCurrentIndex(idx); - mc = view.MoveCursor(action, Qt::NoModifier); + mc = view.moveCursor(action, Qt::NoModifier); QCOMPARE(mc, idx.sibling(idx.row() + 1, idx.column())); } @@ -554,11 +526,12 @@ void tst_QColumnView::selectAll() QVERIFY(view.selectionModel()->selectedIndexes().count() > 0); QModelIndex file; - for (int i = 0; i < m_fakeDirModel.rowCount(m_fakeDirHomeIndex); ++i) + for (int i = 0; i < m_fakeDirModel.rowCount(m_fakeDirHomeIndex); ++i) { if (!m_fakeDirModel.hasChildren(m_fakeDirModel.index(i, 0, m_fakeDirHomeIndex))) { file = m_fakeDirModel.index(i, 0, m_fakeDirHomeIndex); break; } + } view.setCurrentIndex(file); view.selectAll(); QVERIFY(view.selectionModel()->selectedIndexes().count() > 0); @@ -572,7 +545,7 @@ void tst_QColumnView::clicked() ColumnView view; view.setModel(&m_fakeDirModel); - view.resize(800,300); + view.resize(800, 300); view.show(); view.setCurrentIndex(m_fakeDirHomeIndex); @@ -581,12 +554,12 @@ void tst_QColumnView::clicked() QModelIndex parent = m_fakeDirHomeIndex.parent(); QVERIFY(parent.isValid()); - QSignalSpy clickedSpy(&view, SIGNAL(clicked(QModelIndex))); + QSignalSpy clickedSpy(&view, &QAbstractItemView::clicked); QPoint localPoint = view.visualRect(m_fakeDirHomeIndex).center(); - QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, localPoint); + QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, localPoint); QCOMPARE(clickedSpy.count(), 1); - qApp->processEvents(); + QCoreApplication::processEvents(); if (sizeof(qreal) != sizeof(double)) QSKIP("Skipped due to rounding errors"); @@ -653,21 +626,21 @@ void tst_QColumnView::visualRegionForSelection() { ColumnView view; QItemSelection emptyItemSelection; - QCOMPARE(QRegion(), view.getVisualRegionForSelection(emptyItemSelection)); + QCOMPARE(QRegion(), view.visualRegionForSelection(emptyItemSelection)); // a region that isn't empty view.setModel(&m_fakeDirModel); QItemSelection itemSelection(m_fakeDirModel.index(0, 0, m_fakeDirHomeIndex), m_fakeDirModel.index(m_fakeDirModel.rowCount(m_fakeDirHomeIndex) - 1, 0, m_fakeDirHomeIndex)); - QVERIFY(QRegion() != view.getVisualRegionForSelection(itemSelection)); + QVERIFY(QRegion() != view.visualRegionForSelection(itemSelection)); } void tst_QColumnView::moveGrip_basic() { QColumnView view; QColumnViewGrip *grip = new QColumnViewGrip(&view); - QSignalSpy spy(grip, SIGNAL(gripMoved(int))); + QSignalSpy spy(grip, &QColumnViewGrip::gripMoved); view.setCornerWidget(grip); int oldX = view.width(); grip->moveGrip(10); @@ -707,12 +680,11 @@ void tst_QColumnView::moveGrip() int columnNum = view.createdColumns.count() - 2; QVERIFY(columnNum >= 0); - QObjectList list = view.createdColumns[columnNum]->children(); - QColumnViewGrip *grip = 0; - for (int i = 0; i < list.count(); ++i) { - if ((grip = qobject_cast(list[i]))) { + const QObjectList list = view.createdColumns[columnNum]->children(); + QColumnViewGrip *grip = nullptr; + for (QObject *obj : list) { + if ((grip = qobject_cast(obj))) break; - } } if (!grip) return; @@ -728,7 +700,7 @@ void tst_QColumnView::doubleClick() { QColumnView view; QColumnViewGrip *grip = new QColumnViewGrip(&view); - QSignalSpy spy(grip, SIGNAL(gripMoved(int))); + QSignalSpy spy(grip, &QColumnViewGrip::gripMoved); view.setCornerWidget(grip); view.resize(200, 200); QCOMPARE(view.width(), 200); @@ -741,24 +713,24 @@ void tst_QColumnView::gripMoved() { QColumnView view; QColumnViewGrip *grip = new QColumnViewGrip(&view); - QSignalSpy spy(grip, SIGNAL(gripMoved(int))); + QSignalSpy spy(grip, &QColumnViewGrip::gripMoved); view.setCornerWidget(grip); view.move(300, 300); view.resize(200, 200); - qApp->processEvents(); + QCoreApplication::processEvents(); int oldWidth = view.width(); - QTest::mousePress(grip, Qt::LeftButton, 0, QPoint(1,1)); + QTest::mousePress(grip, Qt::LeftButton, {}, QPoint(1, 1)); //QTest::mouseMove(grip, QPoint(grip->globalX()+50, y)); - QPoint posNew = QPoint(grip->mapToGlobal(QPoint(1,1)).x() + 65, 0); + QPoint posNew = QPoint(grip->mapToGlobal(QPoint(1, 1)).x() + 65, 0); QMouseEvent *event = new QMouseEvent(QEvent::MouseMove, posNew, posNew, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QCoreApplication::postEvent(grip, event); QCoreApplication::processEvents(); QTest::mouseRelease(grip, Qt::LeftButton); - QCOMPARE(spy.count(), 1); + QTRY_COMPARE(spy.count(), 1); QCOMPARE(view.width(), oldWidth + 65); } @@ -785,12 +757,12 @@ void tst_QColumnView::preview() } QVERIFY(file.isValid()); view.setCurrentIndex(file); - QVERIFY(view.previewWidget() != (QWidget*)0); + QVERIFY(view.previewWidget() != nullptr); QWidget *previewWidget = new QWidget(&view); view.setPreviewWidget(previewWidget); QCOMPARE(view.previewWidget(), previewWidget); - QVERIFY(previewWidget->parent() != ((QWidget*)&view)); + QVERIFY(previewWidget->parent() != &view); view.setCurrentIndex(home); // previewWidget should be marked for deletion @@ -803,21 +775,21 @@ void tst_QColumnView::swapPreview() { // swap the preview widget in updatePreviewWidget QColumnView view; - QStringList sl; - sl << QLatin1String("test"); - QStringListModel model(sl); + QStringListModel model({ QLatin1String("test") }); view.setModel(&model); view.setCurrentIndex(view.indexAt(QPoint(1, 1))); - connect(&view, SIGNAL(updatePreviewWidget(QModelIndex)), - this, SLOT(setPreviewWidget())); + connect(&view, &QColumnView::updatePreviewWidget, + this, &tst_QColumnView::setPreviewWidget); view.setCurrentIndex(view.indexAt(QPoint(1, 1))); QTest::qWait(ANIMATION_DELAY); - qApp->processEvents(); + QCoreApplication::processEvents(); } void tst_QColumnView::setPreviewWidget() { - ((QColumnView*)sender())->setPreviewWidget(new QWidget); + auto ptr = qobject_cast(sender()); + QVERIFY(ptr); + ptr->setPreviewWidget(new QWidget); } void tst_QColumnView::sizes() @@ -825,8 +797,7 @@ void tst_QColumnView::sizes() QColumnView view; QCOMPARE(view.columnWidths().count(), 0); - QList newSizes; - newSizes << 10 << 4 << 50 << 6; + const QList newSizes{ 10, 4, 50, 6 }; QList visibleSizes; view.setColumnWidths(newSizes); @@ -839,8 +810,7 @@ void tst_QColumnView::sizes() QCOMPARE(postSizes, newSizes.mid(0, postSizes.count())); QVERIFY(view.columnWidths().count() > 1); - QList smallerSizes; - smallerSizes << 6; + QList smallerSizes{ 6 }; view.setColumnWidths(smallerSizes); QList expectedSizes = newSizes; expectedSizes[0] = 6; @@ -851,13 +821,13 @@ void tst_QColumnView::sizes() void tst_QColumnView::rowDelegate() { ColumnView view; - QItemDelegate *d = new QItemDelegate; + QStyledItemDelegate *d = new QStyledItemDelegate; view.setItemDelegateForRow(3, d); view.setModel(&m_fakeDirModel); for (int i = 0; i < view.createdColumns.count(); ++i) { QAbstractItemView *column = view.createdColumns.at(i); - QCOMPARE(column->itemDelegateForRow(3), (QAbstractItemDelegate*)d); + QCOMPARE(column->itemDelegateForRow(3), d); } delete d; } @@ -900,7 +870,7 @@ void tst_QColumnView::changeSameColumn() } QVERIFY(second.isValid()); - QList > old = view.createdColumns; + const auto old = view.createdColumns; view.setCurrentIndex(second); QCOMPARE(old, view.createdColumns); @@ -973,7 +943,7 @@ void tst_QColumnView::pullRug() QModelIndex home = model.thirdLevel(); view.setCurrentIndex(home); if (removeModel) - view.setModel(0); + view.setModel(nullptr); else view.setCurrentIndex(QModelIndex()); QTest::qWait(ANIMATION_DELAY); @@ -982,19 +952,19 @@ void tst_QColumnView::pullRug() void tst_QColumnView::dynamicModelChanges() { - struct MyItemDelegate : public QItemDelegate + struct MyItemDelegate : public QStyledItemDelegate { void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const + const QModelIndex &index) const override { paintedIndexes += index; - QItemDelegate::paint(painter, option, index); + QStyledItemDelegate::paint(painter, option, index); } mutable QSet paintedIndexes; - } delegate;; + } delegate; QStandardItemModel model; ColumnView view; view.setModel(&model); @@ -1008,8 +978,6 @@ void tst_QColumnView::dynamicModelChanges() QVERIFY(QTest::qWaitForWindowExposed(&view)); //let the time for painting to occur QTRY_COMPARE(delegate.paintedIndexes.count(), 1); QCOMPARE(*delegate.paintedIndexes.begin(), model.index(0,0)); - - } -- cgit v1.2.3 From a2e718a71abad719ea196e9dc4d90d9267102f54 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Sep 2019 09:55:23 +0200 Subject: QSysInfo::prettyProductName(): Fix up dc042c6deea7e90b4a9dfcffdc33cbe61df421bd - Fix indentation - Fix empty name returned for WinRT. - Remove duplicated string "Version" for Windows 10 Change-Id: Ia093006a6f8d8c88257d6b4e31afa37510dc6037 Reviewed-by: Volker Hilsheimer --- src/corelib/global/qglobal.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 123aeb1f7c..17aab17fe4 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2940,11 +2940,10 @@ QString QSysInfo::prettyProductName() if (!name) return result + versionString; result += QLatin1String(name); -# if !defined(Q_OS_WIN) - return result + QLatin1String(" (") + versionString + QLatin1Char(')'); -# else +# if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) + return result + QLatin1String(" (") + versionString + QLatin1Char(')'); +# else // (resembling winver.exe): Windows 10 "Windows 10 Version 1809" - result += QLatin1String(" Version "); if (majorVersion >= 10) { const auto releaseId = windows10ReleaseId(); if (!releaseId.isEmpty()) @@ -2952,7 +2951,7 @@ QString QSysInfo::prettyProductName() return result; } // Windows 7: "Windows 7 Version 6.1 (Build 7601: Service Pack 1)" - result += versionString + QLatin1String(" ("); + result += QLatin1String(" Version ") + versionString + QLatin1String(" ("); const auto build = windows7Build(); if (!build.isEmpty()) result += QLatin1String("Build ") + build; @@ -2960,7 +2959,7 @@ QString QSysInfo::prettyProductName() if (!servicePack.isEmpty()) result += QLatin1String(": ") + servicePack; return result + QLatin1Char(')'); -# endif // Windows +# endif // Windows #elif defined(Q_OS_HAIKU) return QLatin1String("Haiku ") + productVersion(); #elif defined(Q_OS_UNIX) -- cgit v1.2.3 From da284ef10e0ef80776b9fc9b7bb0e6dc8d71ba63 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 17 Dec 2018 15:09:23 +0100 Subject: Add support for machine-readable JSON output to the MOC The --output-json parameter will make moc produce a .json file next to the regular output file. With --collect-json the .json files for a module can be merged into a single one. Task-number: QTBUG-68796 Change-Id: I0e8fb802d47bd22da219701a8df947973d4bd7b5 Reviewed-by: Simon Hausmann Reviewed-by: Ulf Hermann --- mkspecs/features/metatypes.prf | 34 + src/tools/moc/collectjson.cpp | 103 + src/tools/moc/collectjson.h | 42 + src/tools/moc/main.cpp | 41 +- src/tools/moc/moc.cpp | 200 +- src/tools/moc/moc.h | 12 +- src/tools/moc/moc.pri | 7 +- tests/auto/tools/moc/.gitignore | 1 + tests/auto/tools/moc/allmocs_baseline_in.json | 2608 +++++++++++++++++++++++++ tests/auto/tools/moc/moc.pro | 49 + tests/auto/tools/moc/tst_moc.cpp | 53 + 11 files changed, 3144 insertions(+), 6 deletions(-) create mode 100644 mkspecs/features/metatypes.prf create mode 100644 src/tools/moc/collectjson.cpp create mode 100644 src/tools/moc/collectjson.h create mode 100644 tests/auto/tools/moc/allmocs_baseline_in.json diff --git a/mkspecs/features/metatypes.prf b/mkspecs/features/metatypes.prf new file mode 100644 index 0000000000..a0a548eeb2 --- /dev/null +++ b/mkspecs/features/metatypes.prf @@ -0,0 +1,34 @@ +qtPrepareTool(MOC_COLLECT_JSON, moc) + +QMAKE_MOC_OPTIONS += --output-json + +moc_json_header.input = HEADERS +moc_json_header.output = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}.json +moc_json_header.CONFIG = no_link moc_verify +moc_json_header.depends = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)} +moc_json_header.commands = $$escape_expand(\\n) # force creation of rule +moc_json_header.variable_out = MOC_JSON_FILES + +moc_json_source.input = SOURCES +moc_json_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}.json +moc_json_source.CONFIG = no_link moc_verify +moc_json_source.depends = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC} +moc_json_source.commands = $$escape_expand(\\n) # force creation of rule +moc_json_source.variable_out = MOC_JSON_FILES + +MOC_COLLECT_JSON_OUTPUT = $$lower($$basename(TARGET))_metatypes.json + +moc_collect_json.CONFIG += no_link combine +moc_collect_json.commands = $$MOC_COLLECT_JSON --collect-json -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} +moc_collect_json.input = MOC_JSON_FILES +moc_collect_json.output = $$MOC_COLLECT_JSON_OUTPUT +moc_collect_json.name = Collect moc JSON output into central file + +install_metatypes { + do_install.path = $$[QT_INSTALL_LIBS]/metatypes + do_install.files = $$OUT_PWD/$$MOC_COLLECT_JSON_OUTPUT + prefix_build: INSTALLS += do_install + else: COPIES += do_install +} + +QMAKE_EXTRA_COMPILERS += moc_collect_json moc_json_header moc_json_source diff --git a/src/tools/moc/collectjson.cpp b/src/tools/moc/collectjson.cpp new file mode 100644 index 0000000000..4029bca5e9 --- /dev/null +++ b/src/tools/moc/collectjson.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +static bool readFromDevice(QIODevice *device, QJsonArray *allMetaObjects) +{ + const QByteArray contents = device->readAll(); + if (contents.isEmpty()) + return true; + + QJsonParseError error {}; + QJsonDocument metaObjects = QJsonDocument::fromJson(contents, &error); + if (error.error != QJsonParseError::NoError) { + fprintf(stderr, "%s at %d\n", error.errorString().toUtf8().constData(), error.offset); + return false; + } + + allMetaObjects->append(metaObjects.object()); + return true; +} + +int collectJson(const QStringList &jsonFiles, const QString &outputFile) +{ + qSetGlobalQHashSeed(0); + + QFile output; + if (outputFile.isEmpty()) { + if (!output.open(stdout, QIODevice::WriteOnly)) { + fprintf(stderr, "Error opening stdout for writing\n"); + return EXIT_FAILURE; + } + } else { + output.setFileName(outputFile); + if (!output.open(QIODevice::WriteOnly)) { + fprintf(stderr, "Error opening %s for writing\n", qPrintable(outputFile)); + return EXIT_FAILURE; + } + } + + QJsonArray allMetaObjects; + if (jsonFiles.isEmpty()) { + QFile f; + if (!f.open(stdin, QIODevice::ReadOnly)) { + fprintf(stderr, "Error opening stdin for reading\n"); + return EXIT_FAILURE; + } + + if (!readFromDevice(&f, &allMetaObjects)) { + fprintf(stderr, "Error parsing data from stdin\n"); + return EXIT_FAILURE; + } + } + + for (const QString &jsonFile: jsonFiles) { + QFile f(jsonFile); + if (!f.open(QIODevice::ReadOnly)) { + fprintf(stderr, "Error opening %s for reading\n", qPrintable(jsonFile)); + return EXIT_FAILURE; + } + + if (!readFromDevice(&f, &allMetaObjects)) { + fprintf(stderr, "Error parsing %s\n", qPrintable(jsonFile)); + return EXIT_FAILURE; + } + } + + QJsonDocument doc(allMetaObjects); + output.write(doc.toJson()); + + return EXIT_SUCCESS; +} diff --git a/src/tools/moc/collectjson.h b/src/tools/moc/collectjson.h new file mode 100644 index 0000000000..9d329c96ca --- /dev/null +++ b/src/tools/moc/collectjson.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLLECTJSON_H +#define COLLECTJSON_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +int collectJson(const QStringList &jsonFiles, const QString &outputFile); + +QT_END_NAMESPACE + +#endif // COLLECTOJSON_H diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index ba559b572f..4aa040a9bb 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -30,6 +30,7 @@ #include "preprocessor.h" #include "moc.h" #include "outputrevision.h" +#include "collectjson.h" #include #include @@ -37,10 +38,12 @@ #include #include #include +#include #include #include #include +#include QT_BEGIN_NAMESPACE @@ -77,6 +80,10 @@ void error(const char *msg = "Invalid argument") fprintf(stderr, "moc: %s\n", msg); } +struct ScopedPointerFileCloser +{ + static inline void cleanup(FILE *handle) { if (handle) fclose(handle); } +}; static inline bool hasNext(const Symbols &symbols, int i) { return (i < symbols.size()); } @@ -293,10 +300,20 @@ int runMoc(int argc, char **argv) ignoreConflictsOption.setDescription(QStringLiteral("Ignore all options that conflict with compilers, like -pthread conflicting with moc's -p option.")); parser.addOption(ignoreConflictsOption); + QCommandLineOption jsonOption(QStringLiteral("output-json")); + jsonOption.setDescription(QStringLiteral("In addition to generating C++ code, create a machine-readable JSON file in a file that matches the output file and an extra .json extension.")); + parser.addOption(jsonOption); + + QCommandLineOption collectOption(QStringLiteral("collect-json")); + collectOption.setDescription(QStringLiteral("Instead of processing C++ code, collect previously generated JSON output into a single file.")); + parser.addOption(collectOption); + parser.addPositionalArgument(QStringLiteral("[header-file]"), QStringLiteral("Header file to read from, otherwise stdin.")); parser.addPositionalArgument(QStringLiteral("[@option-file]"), QStringLiteral("Read additional options from option-file.")); + parser.addPositionalArgument(QStringLiteral("[MOC generated json file]"), + QStringLiteral("MOC generated json output")); const QStringList arguments = argumentsFromCommandLineAndFile(app.arguments()); if (arguments.isEmpty()) @@ -305,6 +322,10 @@ int runMoc(int argc, char **argv) parser.process(arguments); const QStringList files = parser.positionalArguments(); + output = parser.value(outputOption); + if (parser.isSet(collectOption)) + return collectJson(files, output); + if (files.count() > 1) { error(qPrintable(QLatin1String("Too many input files specified: '") + files.join(QLatin1String("' '")) + QLatin1Char('\''))); parser.showHelp(1); @@ -313,7 +334,6 @@ int runMoc(int argc, char **argv) } const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption); - output = parser.value(outputOption); pp.preprocessOnly = parser.isSet(preprocessOption); if (parser.isSet(noIncludeOption)) { moc.noInclude = true; @@ -485,6 +505,8 @@ int runMoc(int argc, char **argv) // 3. and output meta object code + QScopedPointer jsonOutput; + if (output.size()) { // output file specified #if defined(_MSC_VER) if (_wfopen_s(&out, reinterpret_cast(output.utf16()), L"w") != 0) @@ -496,6 +518,21 @@ int runMoc(int argc, char **argv) fprintf(stderr, "moc: Cannot create %s\n", QFile::encodeName(output).constData()); return 1; } + + if (parser.isSet(jsonOption)) { + const QString jsonOutputFileName = output + QLatin1String(".json"); + FILE *f; +#if defined(_MSC_VER) + if (_wfopen_s(&f, reinterpret_cast(jsonOutputFileName.utf16()), L"w") != 0) +#else + f = fopen(QFile::encodeName(jsonOutputFileName).constData(), "w"); + if (!f) +#endif + fprintf(stderr, "moc: Cannot create JSON output file %s. %s\n", + QFile::encodeName(jsonOutputFileName).constData(), + strerror(errno)); + jsonOutput.reset(f); + } } else { // use stdout out = stdout; } @@ -506,7 +543,7 @@ int runMoc(int argc, char **argv) if (moc.classList.isEmpty()) moc.note("No relevant classes found. No output generated."); else - moc.generate(out); + moc.generate(out, jsonOutput.data()); } if (output.size()) diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 50946443be..8cc605fd8a 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -35,6 +35,7 @@ #include #include #include +#include // for normalizeTypeInternal #include @@ -999,7 +1000,7 @@ static QByteArrayList requiredQtContainers(const QVector &classes) return required; } -void Moc::generate(FILE *out) +void Moc::generate(FILE *out, FILE *jsonOutput) { QByteArray fn = filename; int i = filename.length()-1; @@ -1062,6 +1063,23 @@ void Moc::generate(FILE *out) fprintf(out, "QT_WARNING_POP\n"); fprintf(out, "QT_END_MOC_NAMESPACE\n"); + + if (jsonOutput) { + QJsonObject mocData; + mocData[QLatin1String("outputRevision")] = mocOutputRevision; + mocData[QLatin1String("inputFile")] = QLatin1String(fn.constData()); + + QJsonArray classesJsonFormatted; + + for (const ClassDef &cdef: qAsConst(classList)) + classesJsonFormatted.append(cdef.toJson()); + + if (!classesJsonFormatted.isEmpty()) + mocData[QLatin1String("classes")] = classesJsonFormatted; + + QJsonDocument jsonDoc(mocData); + fputs(jsonDoc.toJson().constData(), jsonOutput); + } } void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) @@ -1784,6 +1802,186 @@ void Moc::checkProperties(ClassDef *cdef) } } +QJsonObject ClassDef::toJson() const +{ + QJsonObject cls; + cls[QLatin1String("className")] = QString::fromUtf8(classname.constData()); + cls[QLatin1String("qualifiedClassName")] = QString::fromUtf8(qualified.constData()); + + QJsonArray classInfos; + for (const auto &info: qAsConst(classInfoList)) { + QJsonObject infoJson; + infoJson[QLatin1String("name")] = QString::fromUtf8(info.name); + infoJson[QLatin1String("value")] = QString::fromUtf8(info.value); + classInfos.append(infoJson); + } + + if (classInfos.size()) + cls[QLatin1String("classInfos")] = classInfos; + + const auto appendFunctions = [&cls](const QString &type, const QVector &funcs) { + QJsonArray jsonFuncs; + + for (const FunctionDef &fdef: funcs) + jsonFuncs.append(fdef.toJson()); + + if (!jsonFuncs.isEmpty()) + cls[type] = jsonFuncs; + }; + + appendFunctions(QLatin1String("signals"), signalList); + appendFunctions(QLatin1String("slots"), slotList); + appendFunctions(QLatin1String("constructors"), constructorList); + appendFunctions(QLatin1String("methods"), methodList); + + QJsonArray props; + + for (const PropertyDef &propDef: qAsConst(propertyList)) + props.append(propDef.toJson()); + + if (!props.isEmpty()) + cls[QLatin1String("properties")] = props; + + if (hasQGadget) + cls[QLatin1String("gadget")] = true; + + QJsonArray superClasses; + + for (const auto &super: qAsConst(superclassList)) { + const auto name = super.first; + const auto access = super.second; + QJsonObject superCls; + superCls[QLatin1String("name")] = QString::fromUtf8(name); + FunctionDef::accessToJson(&superCls, access); + superClasses.append(superCls); + } + + if (!superClasses.isEmpty()) + cls[QLatin1String("superClasses")] = superClasses; + + QJsonArray enums; + for (const EnumDef &enumDef: qAsConst(enumList)) + enums.append(enumDef.toJson(*this)); + if (!enums.isEmpty()) + cls[QLatin1String("enums")] = enums; + + QJsonArray ifaces; + for (const QVector &ifaceList: interfaceList) { + QJsonArray jsonList; + for (const Interface &iface: ifaceList) { + QJsonObject ifaceJson; + ifaceJson[QLatin1String("id")] = QString::fromUtf8(iface.interfaceId); + ifaceJson[QLatin1String("className")] = QString::fromUtf8(iface.className); + jsonList.append(ifaceJson); + } + ifaces.append(jsonList); + } + if (!ifaces.isEmpty()) + cls[QLatin1String("interfaces")] = ifaces; + + return cls; +} + +QJsonObject FunctionDef::toJson() const +{ + QJsonObject fdef; + fdef[QLatin1String("name")] = QString::fromUtf8(name); + if (!tag.isEmpty()) + fdef[QLatin1String("tag")] = QString::fromUtf8(tag); + fdef[QLatin1String("returnType")] = QString::fromUtf8(normalizedType); + QJsonArray args; + for (const ArgumentDef &arg: arguments) + args.append(arg.toJson()); + + if (!args.isEmpty()) + fdef[QLatin1String("arguments")] = args; + + accessToJson(&fdef, access); + + if (revision > 0) + fdef[QLatin1String("revision")] = revision; + + return fdef; +} + +void FunctionDef::accessToJson(QJsonObject *obj, FunctionDef::Access acs) +{ + switch (acs) { + case Private: (*obj)[QLatin1String("access")] = QLatin1String("private"); break; + case Public: (*obj)[QLatin1String("access")] = QLatin1String("public"); break; + case Protected: (*obj)[QLatin1String("access")] = QLatin1String("protected"); break; + } +} + +QJsonObject ArgumentDef::toJson() const +{ + QJsonObject arg; + arg[QLatin1String("type")] = QString::fromUtf8(normalizedType); + if (!name.isEmpty()) + arg[QLatin1String("name")] = QString::fromUtf8(name); + return arg; +} + +QJsonObject PropertyDef::toJson() const +{ + QJsonObject prop; + prop[QLatin1String("name")] = QString::fromUtf8(name); + prop[QLatin1String("type")] = QString::fromUtf8(type); + + const auto jsonify = [&prop](const char *str, const QByteArray &member) { + if (!member.isEmpty()) + prop[QLatin1String(str)] = QString::fromUtf8(member); + }; + + jsonify("member", member); + jsonify("read", read); + jsonify("write", write); + jsonify("reset", reset); + jsonify("notify", notify); + jsonify("privateClass", inPrivateClass); + + const auto jsonifyBoolOrString = [&prop](const char *str, const QByteArray &boolOrString) { + QJsonValue value; + if (boolOrString == "true") + value = true; + else if (boolOrString == "false") + value = false; + else + value = QString::fromUtf8(boolOrString); // function name to query at run-time + prop[QLatin1String(str)] = value; + }; + + jsonifyBoolOrString("designable", designable); + jsonifyBoolOrString("scriptable", scriptable); + jsonifyBoolOrString("stored", stored); + jsonifyBoolOrString("user", user); + + prop[QLatin1String("constant")] = constant; + prop[QLatin1String("final")] = final; + + if (revision > 0) + prop[QLatin1String("revision")] = revision; + + return prop; +} + +QJsonObject EnumDef::toJson(const ClassDef &cdef) const +{ + QJsonObject def; + def[QLatin1String("name")] = QString::fromUtf8(name); + if (!enumName.isEmpty()) + def[QLatin1String("alias")] = QString::fromUtf8(enumName); + def[QLatin1String("isFlag")] = cdef.enumDeclarations.value(name); + def[QLatin1String("isClass")] = isEnumClass; + + QJsonArray valueArr; + for (const QByteArray &value: values) + valueArr.append(QString::fromUtf8(value)); + if (!valueArr.isEmpty()) + def[QLatin1String("values")] = valueArr; + + return def; +} QT_END_NAMESPACE diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index bb1c9501fe..687ea2552f 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -61,6 +61,7 @@ struct Type }; Q_DECLARE_TYPEINFO(Type, Q_MOVABLE_TYPE); +struct ClassDef; struct EnumDef { QByteArray name; @@ -68,6 +69,7 @@ struct EnumDef QVector values; bool isEnumClass; // c++11 enum class EnumDef() : isEnumClass(false) {} + QJsonObject toJson(const ClassDef &cdef) const; }; Q_DECLARE_TYPEINFO(EnumDef, Q_MOVABLE_TYPE); @@ -78,6 +80,8 @@ struct ArgumentDef QByteArray rightType, normalizedType, name; QByteArray typeNameForCast; // type name to be used in cast from void * in metacall bool isDefault; + + QJsonObject toJson() const; }; Q_DECLARE_TYPEINFO(ArgumentDef, Q_MOVABLE_TYPE); @@ -111,6 +115,9 @@ struct FunctionDef bool isConstructor = false; bool isDestructor = false; bool isAbstract = false; + + QJsonObject toJson() const; + static void accessToJson(QJsonObject *obj, Access acs); }; Q_DECLARE_TYPEINFO(FunctionDef, Q_MOVABLE_TYPE); @@ -130,6 +137,8 @@ struct PropertyDef int revision = 0; bool constant = false; bool final = false; + + QJsonObject toJson() const; }; Q_DECLARE_TYPEINFO(PropertyDef, Q_MOVABLE_TYPE); @@ -183,6 +192,7 @@ struct ClassDef : BaseDef { bool hasQObject = false; bool hasQGadget = false; + QJsonObject toJson() const; }; Q_DECLARE_TYPEINFO(ClassDef, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE); @@ -215,7 +225,7 @@ public: QMap metaArgs; void parse(); - void generate(FILE *out); + void generate(FILE *out, FILE *jsonOutput); bool parseClassHead(ClassDef *def); inline bool inClass(const ClassDef *def) const { diff --git a/src/tools/moc/moc.pri b/src/tools/moc/moc.pri index 90839a445b..278d5607cd 100644 --- a/src/tools/moc/moc.pri +++ b/src/tools/moc/moc.pri @@ -10,9 +10,12 @@ HEADERS = $$PWD/moc.h \ $$PWD/utils.h \ $$PWD/generator.h \ $$PWD/outputrevision.h \ - $$PWD/cbordevice.h + $$PWD/cbordevice.h \ + $$PWD/collectjson.h + SOURCES = $$PWD/moc.cpp \ $$PWD/preprocessor.cpp \ $$PWD/generator.cpp \ $$PWD/parser.cpp \ - $$PWD/token.cpp + $$PWD/token.cpp \ + $$PWD/collectjson.cpp diff --git a/tests/auto/tools/moc/.gitignore b/tests/auto/tools/moc/.gitignore index 86a604a776..59a275bc62 100644 --- a/tests/auto/tools/moc/.gitignore +++ b/tests/auto/tools/moc/.gitignore @@ -1 +1,2 @@ tst_moc +allmocs.json diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json new file mode 100644 index 0000000000..bde5a1c52b --- /dev/null +++ b/tests/auto/tools/moc/allmocs_baseline_in.json @@ -0,0 +1,2608 @@ +[ + { + "classes": [ + { + "className": "MyBooooooostishClass", + "qualifiedClassName": "MyBooooooostishClass", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "mySlot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "no-keywords.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Task87883", + "qualifiedClassName": "Task87883", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "task87883.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "IfdefedClass", + "qualifiedClassName": "IfdefedClass", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "c-comments.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "BackslashNewlines", + "qualifiedClassName": "BackslashNewlines", + "slots": [ + { + "access": "public", + "name": "works", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "backslash-newlines.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "OldStyleCast", + "qualifiedClassName": "OldStyleCast", + "slots": [ + { + "access": "public", + "name": "foo", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + }, + { + "type": "int*" + }, + { + "type": "const int*" + }, + { + "type": "volatile int*" + }, + { + "type": "const int*volatile*" + } + ], + "name": "bar", + "returnType": "int" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + }, + { + "type": "QObject*const" + } + ], + "name": "slot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "oldstyle-casts.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "SlotsWithVoidTemplateTest", + "qualifiedClassName": "SlotsWithVoidTemplateTest", + "signals": [ + { + "access": "public", + "arguments": [ + { + "type": "TestTemplate" + } + ], + "name": "mySignal", + "returnType": "void" + }, + { + "access": "public", + "name": "myVoidSignal", + "returnType": "void" + }, + { + "access": "public", + "name": "myVoidSignal2", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "dummySlot", + "returnType": "void" + }, + { + "access": "public", + "name": "dummySlot2", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "TestTemplate" + } + ], + "name": "anotherSlot", + "returnType": "void" + }, + { + "access": "public", + "name": "mySlot", + "returnType": "TestTemplate" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "slots-with-void-template.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "InvokableBeforeReturnType", + "methods": [ + { + "access": "public", + "name": "foo", + "returnType": "const char*" + } + ], + "qualifiedClassName": "InvokableBeforeReturnType", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "InvokableBeforeInline", + "methods": [ + { + "access": "public", + "name": "foo", + "returnType": "void" + }, + { + "access": "public", + "name": "bar", + "returnType": "void" + } + ], + "qualifiedClassName": "InvokableBeforeInline", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "qinvokable.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Bar", + "enums": [ + { + "alias": "Flag", + "isClass": false, + "isFlag": true, + "name": "Flags", + "values": [ + "Read", + "Write" + ] + } + ], + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "flags", + "read": "flags", + "scriptable": true, + "stored": true, + "type": "Flags", + "user": false, + "write": "setFlags" + } + ], + "qualifiedClassName": "Foo::Bar", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Baz", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "flags", + "read": "flags", + "scriptable": true, + "stored": true, + "type": "Foo::Bar::Flags", + "user": false, + "write": "setFlags" + }, + { + "constant": false, + "designable": true, + "final": false, + "name": "flagsList", + "read": "flagsList", + "scriptable": true, + "stored": true, + "type": "QList", + "user": false, + "write": "setFlagsList" + } + ], + "qualifiedClassName": "Foo::Baz", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "namespaced-flags.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Foo", + "qualifiedClassName": "BBB::Foo", + "signals": [ + { + "access": "public", + "arguments": [ + { + "type": "QList >" + } + ], + "name": "foo", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QList >" + } + ], + "name": "foo2", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QList< ::AAA::BaseA*>" + } + ], + "name": "bar", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QList< ::AAA::BaseA*>" + } + ], + "name": "bar2", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QList" + } + ], + "name": "bar3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + }, + { + "access": "public", + "name": "::AAA::BaseA" + } + ] + } + ], + "inputFile": "trigraphs.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "classInfos": [ + { + "name": "Test", + "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\x53" + }, + { + "name": "Test2", + "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\123" + }, + { + "name": "Test3", + "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nb" + } + ], + "className": "StringLiterals", + "qualifiedClassName": "StringLiterals", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "escapes-in-string-literals.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "CStyleEnums", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "Baz", + "values": [ + "Foo", + "Bar" + ] + }, + { + "isClass": false, + "isFlag": false, + "name": "Baz2", + "values": [ + "Foo2", + "Bar2" + ] + } + ], + "gadget": true, + "qualifiedClassName": "CStyleEnums" + } + ], + "inputFile": "cstyle-enums.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "TestQPrivateSlots", + "methods": [ + { + "access": "private", + "name": "method1", + "returnType": "void" + } + ], + "qualifiedClassName": "TestQPrivateSlots", + "slots": [ + { + "access": "private", + "name": "_q_privateslot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "qprivateslots.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "GadgetWithNoEnums", + "gadget": true, + "qualifiedClassName": "GadgetWithNoEnums" + }, + { + "className": "DerivedGadgetWithEnums", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "FooEnum", + "values": [ + "FooValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "DerivedGadgetWithEnums", + "superClasses": [ + { + "access": "public", + "name": "GadgetWithNoEnums" + } + ] + } + ], + "inputFile": "gadgetwithnoenums.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "DirInIncludePath", + "interfaces": [ + [ + { + "className": "MyInterface", + "id": "\"MyInterface\"" + } + ] + ], + "qualifiedClassName": "DirInIncludePath", + "superClasses": [ + { + "access": "public", + "name": "QObject" + }, + { + "access": "public", + "name": "MyInterface" + } + ] + } + ], + "inputFile": "dir-in-include-path.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "SingleFunctionKeywordBeforeReturnType", + "qualifiedClassName": "SingleFunctionKeywordBeforeReturnType", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "mySlot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "SingleFunctionKeywordBeforeInline", + "qualifiedClassName": "SingleFunctionKeywordBeforeInline", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "mySlot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "SingleFunctionKeywordAfterInline", + "qualifiedClassName": "SingleFunctionKeywordAfterInline", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "mySlot", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "single_function_keyword.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Task192552", + "qualifiedClassName": "Task192552", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "task192552.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "InlineSlotsWithThrowDeclaration", + "qualifiedClassName": "InlineSlotsWithThrowDeclaration", + "slots": [ + { + "access": "public", + "name": "a", + "returnType": "void" + }, + { + "access": "public", + "name": "b", + "returnType": "void" + }, + { + "access": "public", + "name": "c", + "returnType": "void" + }, + { + "access": "public", + "name": "d", + "returnType": "void" + }, + { + "access": "public", + "name": "e", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "task189996.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "TestObject", + "qualifiedClassName": "NS_A::NS_B::TestObject", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "TestMain", + "qualifiedClassName": "NS_A::NS_Main::TestMain", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "task234909.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "TypenameWithUnsigned", + "qualifiedClassName": "TypenameWithUnsigned", + "slots": [ + { + "access": "public", + "arguments": [ + { + "type": "uint" + } + ], + "name": "a", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "u", + "type": "uint" + } + ], + "name": "b", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "uint*" + } + ], + "name": "c", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "p", + "type": "uint*" + } + ], + "name": "d", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "uint&" + } + ], + "name": "e", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "r", + "type": "uint&" + } + ], + "name": "f", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "unsigned1" + } + ], + "name": "g", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "u1", + "type": "unsigned1" + } + ], + "name": "h", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "uint" + }, + { + "type": "unsigned1" + } + ], + "name": "i", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "unsigned1" + }, + { + "type": "uint" + } + ], + "name": "j", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "unsignedQImage" + } + ], + "name": "k", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "uqi", + "type": "unsignedQImage" + } + ], + "name": "l", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "task240368.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "PureVirtualSignalsTest", + "qualifiedClassName": "PureVirtualSignalsTest", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + }, + { + "access": "public", + "name": "myOtherSignal", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "foo", + "type": "int" + } + ], + "name": "mySignal2", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "PureVirtualSignalsImpl", + "qualifiedClassName": "PureVirtualSignalsImpl", + "signals": [ + { + "access": "public", + "name": "mySignal", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "name": "foo", + "type": "int" + } + ], + "name": "mySignal2", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "PureVirtualSignalsTest" + } + ] + } + ], + "inputFile": "pure-virtual-signals.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "CXX11Enums", + "enums": [ + { + "isClass": true, + "isFlag": false, + "name": "EnumClass", + "values": [ + "A0", + "A1", + "A2", + "A3" + ] + }, + { + "isClass": false, + "isFlag": false, + "name": "TypedEnum", + "values": [ + "B0", + "B1", + "B2", + "B3" + ] + }, + { + "isClass": true, + "isFlag": false, + "name": "TypedEnumClass", + "values": [ + "C0", + "C1", + "C2", + "C3" + ] + }, + { + "isClass": false, + "isFlag": false, + "name": "NormalEnum", + "values": [ + "D2", + "D3", + "D0", + "D1" + ] + }, + { + "alias": "ClassFlag", + "isClass": true, + "isFlag": true, + "name": "ClassFlags", + "values": [ + "F0", + "F1", + "F2", + "F3" + ] + }, + { + "isClass": true, + "isFlag": false, + "name": "EnumStruct", + "values": [ + "G0", + "G1", + "G2", + "G3" + ] + }, + { + "isClass": true, + "isFlag": false, + "name": "TypedEnumStruct", + "values": [ + "H0", + "H1", + "H2", + "H3" + ] + }, + { + "alias": "StructFlag", + "isClass": true, + "isFlag": true, + "name": "StructFlags", + "values": [ + "I0", + "I1", + "I2", + "I3" + ] + } + ], + "gadget": true, + "qualifiedClassName": "CXX11Enums" + }, + { + "className": "CXX11Enums2", + "enums": [ + { + "isClass": true, + "isFlag": false, + "name": "EnumClass", + "values": [ + "A0", + "A1", + "A2", + "A3" + ] + }, + { + "isClass": false, + "isFlag": false, + "name": "TypedEnum", + "values": [ + "B0", + "B1", + "B2", + "B3" + ] + }, + { + "isClass": true, + "isFlag": false, + "name": "TypedEnumClass", + "values": [ + "C0", + "C1", + "C2", + "C3" + ] + }, + { + "isClass": false, + "isFlag": false, + "name": "NormalEnum", + "values": [ + "D2", + "D3", + "D0", + "D1" + ] + }, + { + "alias": "ClassFlag", + "isClass": true, + "isFlag": true, + "name": "ClassFlags", + "values": [ + "F0", + "F1", + "F2", + "F3" + ] + } + ], + "gadget": true, + "qualifiedClassName": "CXX11Enums2" + } + ], + "inputFile": "cxx11-enums.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "FinalTestClassQt", + "qualifiedClassName": "FinalTestClassQt", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedFinalTestClassQt", + "qualifiedClassName": "ExportedFinalTestClassQt", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedFinalTestClassQtX", + "qualifiedClassName": "ExportedFinalTestClassQtX", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "FinalTestClassCpp11", + "qualifiedClassName": "FinalTestClassCpp11", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedFinalTestClassCpp11", + "qualifiedClassName": "ExportedFinalTestClassCpp11", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedFinalTestClassCpp11X", + "qualifiedClassName": "ExportedFinalTestClassCpp11X", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "SealedTestClass", + "qualifiedClassName": "SealedTestClass", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedSealedTestClass", + "qualifiedClassName": "ExportedSealedTestClass", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExportedSealedTestClassX", + "qualifiedClassName": "ExportedSealedTestClassX", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "cxx11-final-classes.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "ExplicitOverrideControlBase", + "qualifiedClassName": "ExplicitOverrideControlBase", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "ExplicitOverrideControlFinalQt", + "qualifiedClassName": "ExplicitOverrideControlFinalQt", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlFinalCxx11", + "qualifiedClassName": "ExplicitOverrideControlFinalCxx11", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlSealed", + "qualifiedClassName": "ExplicitOverrideControlSealed", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlOverrideQt", + "qualifiedClassName": "ExplicitOverrideControlOverrideQt", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlOverrideCxx11", + "qualifiedClassName": "ExplicitOverrideControlOverrideCxx11", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlFinalQtOverrideQt", + "qualifiedClassName": "ExplicitOverrideControlFinalQtOverrideQt", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlFinalCxx11OverrideCxx11", + "qualifiedClassName": "ExplicitOverrideControlFinalCxx11OverrideCxx11", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + }, + { + "className": "ExplicitOverrideControlSealedOverride", + "qualifiedClassName": "ExplicitOverrideControlSealedOverride", + "slots": [ + { + "access": "private", + "name": "pureSlot0", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot1", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot2", + "returnType": "void" + }, + { + "access": "private", + "name": "pureSlot3", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "ExplicitOverrideControlBase" + } + ] + } + ], + "inputFile": "cxx11-explicit-override-control.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "ForwardDeclaredParamClass", + "qualifiedClassName": "ForwardDeclaredParamClass", + "signals": [ + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredParam" + } + ], + "name": "signalNaked", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "signalFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "signalFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "signalFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "signalFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "signalQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "signalQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "signalQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "signalQSet", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredParam" + } + ], + "name": "slotNaked", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "slotFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "slotFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "slotFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "ForwardDeclaredContainer" + } + ], + "name": "slotFDC", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "slotQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "slotQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "slotQSet", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "QSet" + } + ], + "name": "slotQSet", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "forward-declared-param.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "classInfos": [ + { + "name": "TestString", + "value": "PD_CLASSNAME" + }, + { + "name": "TestString2", + "value": "ParseDefine" + }, + { + "name": "TestString3", + "value": "TestValue" + } + ], + "className": "ParseDefine", + "qualifiedClassName": "PD::ParseDefine", + "signals": [ + { + "access": "public", + "arguments": [ + { + "name": "i", + "type": "QMap" + } + ], + "name": "cmdlineSignal", + "returnType": "void" + }, + { + "access": "public", + "name": "signalQTBUG55853", + "returnType": "void" + } + ], + "slots": [ + { + "access": "public", + "name": "voidFunction", + "returnType": "void" + }, + { + "access": "public", + "name": "stringMethod", + "returnType": "QString" + }, + { + "access": "public", + "name": "combined1", + "returnType": "void" + }, + { + "access": "public", + "name": "combined2", + "returnType": "void" + }, + { + "access": "public", + "name": "combined3", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + }, + { + "type": "int" + } + ], + "name": "combined4", + "returnType": "void" + }, + { + "access": "public", + "name": "combined5", + "returnType": "void" + }, + { + "access": "public", + "name": "combined6", + "returnType": "void" + }, + { + "access": "public", + "name": "vararg1", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "vararg2", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + }, + { + "type": "int" + } + ], + "name": "vararg3", + "returnType": "void" + }, + { + "access": "public", + "name": "vararg4", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "vararg5", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + }, + { + "type": "int" + } + ], + "name": "vararg6", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "INNERFUNCTION", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "inner_expanded", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "expanded_method", + "returnType": "void" + }, + { + "access": "public", + "name": "conditionSlot", + "returnType": "void" + }, + { + "access": "public", + "arguments": [ + { + "type": "int" + } + ], + "name": "PD_DEFINE_ITSELF_SUFFIX", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "parse-defines.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "FunctionWithAttributes", + "qualifiedClassName": "FunctionWithAttributes", + "slots": [ + { + "access": "public", + "name": "test1", + "returnType": "void" + }, + { + "access": "public", + "name": "test2", + "returnType": "void" + } + ], + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "function-with-attributes.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "TestPluginMetaData", + "qualifiedClassName": "TestPluginMetaData", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "plugin_metadata.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "KDAB", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "Salaries", + "values": [ + "Steve" + ] + } + ], + "qualifiedClassName": "KDAB", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "single-quote-digit-separator-n3781.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "A", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "QTBUG_2151::A", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "B", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "blah", + "read": "blah", + "scriptable": true, + "stored": true, + "type": "A::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "QTBUG_2151::B", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "related-metaobjects-in-namespaces.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "A", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "QTBUG_35657::A" + } + ], + "inputFile": "qtbug-35657-gadget.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Derived", + "gadget": true, + "qualifiedClassName": "NonGadgetParent::Derived", + "superClasses": [ + { + "access": "public", + "name": "Base" + } + ] + } + ], + "inputFile": "non-gadget-parent-class.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "BaseGadget", + "gadget": true, + "qualifiedClassName": "GrandParentGadget::BaseGadget" + }, + { + "className": "DerivedGadget", + "gadget": true, + "qualifiedClassName": "GrandParentGadget::DerivedGadget", + "superClasses": [ + { + "access": "public", + "name": "Derived" + } + ] + } + ], + "inputFile": "grand-parent-gadget-class.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "B", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "blah", + "read": "blah", + "scriptable": true, + "stored": true, + "type": "A::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "QTBUG_35657::B", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "related-metaobjects-in-gadget.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "Unsused::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "Unsused::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS1::Nested::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS1::Nested::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS1::NestedUnsused::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS1::NestedUnsused::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS1::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS1::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingObject", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "gadgetPoperty", + "read": "gadgetPoperty", + "scriptable": true, + "stored": true, + "type": "Gadget::SomeEnum", + "user": false + }, + { + "constant": false, + "designable": true, + "final": false, + "name": "objectPoperty", + "read": "objectPoperty", + "scriptable": true, + "stored": true, + "type": "Object::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS1::DependingObject", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingNestedGadget", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "nestedGadgetPoperty", + "read": "nestedGadgetPoperty", + "scriptable": true, + "stored": true, + "type": "Nested::Gadget::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS1::DependingNestedGadget", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingNestedObject", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "nestedObjectPoperty", + "read": "nestedObjectPoperty", + "scriptable": true, + "stored": true, + "type": "Nested::Object::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS1::DependingNestedObject", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS2::Nested::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS2::Nested::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS2::NestedUnsused::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS2::NestedUnsused::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "Gadget", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "gadget": true, + "qualifiedClassName": "NS2::Gadget" + }, + { + "className": "Object", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "SomeEnum", + "values": [ + "SomeEnumValue" + ] + } + ], + "qualifiedClassName": "NS2::Object", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingObject", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "gadgetPoperty", + "read": "gadgetPoperty", + "scriptable": true, + "stored": true, + "type": "Gadget::SomeEnum", + "user": false + }, + { + "constant": false, + "designable": true, + "final": false, + "name": "objectPoperty", + "read": "objectPoperty", + "scriptable": true, + "stored": true, + "type": "Object::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS2::DependingObject", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingNestedGadget", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "nestedGadgetPoperty", + "read": "nestedGadgetPoperty", + "scriptable": true, + "stored": true, + "type": "Nested::Gadget::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS2::DependingNestedGadget", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "DependingNestedObject", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "nestedObjectPoperty", + "read": "nestedObjectPoperty", + "scriptable": true, + "stored": true, + "type": "Nested::Object::SomeEnum", + "user": false + } + ], + "qualifiedClassName": "NS2::DependingNestedObject", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + } + ], + "inputFile": "related-metaobjects-name-conflict.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "FooNamespace", + "enums": [ + { + "isClass": true, + "isFlag": false, + "name": "Enum1", + "values": [ + "Key1", + "Key2" + ] + } + ], + "gadget": true, + "qualifiedClassName": "FooNamespace" + }, + { + "className": "FooNestedNamespace", + "enums": [ + { + "isClass": true, + "isFlag": false, + "name": "Enum2", + "values": [ + "Key3", + "Key4" + ] + }, + { + "isClass": true, + "isFlag": false, + "name": "Enum3", + "values": [ + "Key5", + "Key6" + ] + } + ], + "gadget": true, + "qualifiedClassName": "FooNamespace::FooNestedNamespace" + }, + { + "className": "FooMoreNestedNamespace", + "enums": [ + { + "isClass": true, + "isFlag": false, + "name": "Enum4", + "values": [ + "Key7", + "Key8" + ] + } + ], + "gadget": true, + "qualifiedClassName": "FooNamespace::FooNestedNamespace::FooMoreNestedNamespace" + } + ], + "inputFile": "namespace.h", + "outputRevision": 67 + }, + { + "classes": [ + { + "className": "ClassInNamespace", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "GadEn", + "values": [ + "Value" + ] + } + ], + "gadget": true, + "qualifiedClassName": "CXX17Namespace::A::B::C::D::ClassInNamespace" + }, + { + "className": "D", + "enums": [ + { + "isClass": false, + "isFlag": false, + "name": "NamEn", + "values": [ + "Value" + ] + } + ], + "gadget": true, + "qualifiedClassName": "CXX17Namespace::A::B::C::D" + } + ], + "inputFile": "cxx17-namespaces.h", + "outputRevision": 67 + } +] diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index ad8c093add..1794bafd2c 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -32,6 +32,9 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n namespace.h cxx17-namespaces.h \ cxx-attributes.h +# No platform specifics in the JSON files, so that we can compare them +JSON_HEADERS = $$HEADERS +JSON_HEADERS -= cxx-attributes.h if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlines.h if(*-g++*|*-clang*): HEADERS += dollars.h @@ -50,3 +53,49 @@ QMAKE_MOC_OPTIONS += -Muri=com.company.app -Muri=com.company.app.private # Define macro on the command lines used in parse-defines.h QMAKE_MOC_OPTIONS += "-DDEFINE_CMDLINE_EMPTY=" "\"-DDEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap &i)\"" +QMAKE_MOC_OPTIONS += --output-json + +debug_and_release { + CONFIG(debug, debug|release) { + MOC_CPP_DIR = $$MOC_DIR/debug + } else { + MOC_CPP_DIR = $$MOC_DIR/release + } +} else { + MOC_CPP_DIR = $$MOC_DIR +} + +moc_json_header.input = JSON_HEADERS +moc_json_header.output = $$MOC_CPP_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}.json +moc_json_header.CONFIG = no_link moc_verify +moc_json_header.depends = $$MOC_CPP_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)} +moc_json_header.commands = $$escape_expand(\\n) # force creation of rule +moc_json_header.variable_out = MOC_JSON_HEADERS + +BASELINE_IN = allmocs_baseline_in.json +copy_baseline.commands = $${QMAKE_COPY} $$shell_path(${QMAKE_FILE_NAME}) ${QMAKE_FILE_OUT} +copy_baseline.input = BASELINE_IN +copy_baseline.output = $$OUT_PWD/allmocs_baseline.json +copy_baseline.CONFIG = no_link + +qtPrepareTool(MOC_COLLECT_JSON, moc) +jsoncollector.CONFIG += combine +jsoncollector.commands = $$MOC_COLLECT_JSON --collect-json -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} +jsoncollector.input = MOC_JSON_HEADERS +jsoncollector.output = $$OUT_PWD/allmocs.json +jsoncollector.variable_out = GENERATED_FILES + +allmocs_contents = \ + ""\ + ""\ + "allmocs.json"\ + "allmocs_baseline.json"\ + ""\ + "" + +allmocs_file = $$OUT_PWD/allmocs.qrc + +!write_file($$allmocs_file, allmocs_contents): error() +RESOURCES += $$allmocs_file + +QMAKE_EXTRA_COMPILERS += moc_json_header copy_baseline jsoncollector diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 89f563f11d..9fc00288fe 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "using-namespaces.h" #include "assign-namespace.h" @@ -717,6 +718,7 @@ private slots: void testQNamespace(); void cxx17Namespaces(); void cxxAttributes(); + void mocJsonOutput(); signals: void sigWithUnsignedArg(unsigned foo); @@ -3971,6 +3973,57 @@ void tst_Moc::cxxAttributes() QCOMPARE(meta.keyCount(), 7); } +void tst_Moc::mocJsonOutput() +{ + const auto readFile = [](const QString &fileName) { + QFile f(fileName); + f.open(QIODevice::ReadOnly); + return QJsonDocument::fromJson(f.readAll()); + }; + + const QString actualFile = QStringLiteral(":/allmocs.json"); + const QString expectedFile = QStringLiteral(":/allmocs_baseline.json"); + + QVERIFY2(QFile::exists(actualFile), qPrintable(actualFile)); + QVERIFY2(QFile::exists(expectedFile), qPrintable(expectedFile)); + + QJsonDocument actualOutput = readFile(QLatin1String(":/allmocs.json")); + QJsonDocument expectedOutput = readFile(QLatin1String(":/allmocs_baseline.json")); + + const auto showPotentialDiff = [](const QJsonDocument &actual, const QJsonDocument &expected) -> QByteArray { +#if defined(Q_OS_UNIX) + QByteArray actualStr = actual.toJson(); + QByteArray expectedStr = expected.toJson(); + + QTemporaryFile actualFile; + if (!actualFile.open()) + return "Error opening actual temp file"; + actualFile.write(actualStr); + actualFile.flush(); + + QTemporaryFile expectedFile; + if (!expectedFile.open()) + return "Error opening expected temp file"; + expectedFile.write(expectedStr); + expectedFile.flush(); + + QProcess diffProc; + diffProc.setProgram("diff"); + diffProc.setArguments(QStringList() << "-ub" << expectedFile.fileName() << actualFile.fileName()); + diffProc.start(); + if (!diffProc.waitForStarted()) + return "Error waiting for diff process to start."; + if (!diffProc.waitForFinished()) + return "Error waiting for diff process to finish."; + return diffProc.readAllStandardOutput(); +#else + return "Cannot launch diff. Please check allmocs.json and allmocs_baseline.json on disk."; +#endif + }; + + QVERIFY2(actualOutput == expectedOutput, showPotentialDiff(actualOutput, expectedOutput).constData()); +} + QTEST_MAIN(tst_Moc) // the generated code must compile with QT_NO_KEYWORDS -- cgit v1.2.3