summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp10
-rw-r--r--src/corelib/global/qcompilerdetection.h8
-rw-r--r--src/corelib/global/qglobal.h37
-rw-r--r--src/corelib/global/qlibraryinfo.cpp4
-rw-r--r--src/corelib/global/qnumeric.cpp2
-rw-r--r--src/corelib/io/qdatastream.cpp36
-rw-r--r--src/corelib/io/qdatastream.h8
-rw-r--r--src/corelib/io/qdebug.cpp5
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp39
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h6
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp4
-rw-r--r--src/corelib/kernel/qcoreevent.cpp103
-rw-r--r--src/corelib/kernel/qcoreevent.h4
-rw-r--r--src/corelib/kernel/qmetaobject.cpp26
-rw-r--r--src/corelib/kernel/qmetatype.h4
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp13
-rw-r--r--src/corelib/mimetypes/qmimetype.h5
-rw-r--r--src/corelib/tools/qarraydata.cpp4
-rw-r--r--src/corelib/tools/qarraydata.h4
-rw-r--r--src/corelib/tools/qbytearray.cpp2
-rw-r--r--src/corelib/tools/qchar.h2
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp22
-rw-r--r--src/corelib/tools/qcommandlineparser.h1
-rw-r--r--src/corelib/tools/qhash.cpp26
-rw-r--r--src/corelib/tools/qhash.h64
-rw-r--r--src/corelib/tools/qline.cpp14
-rw-r--r--src/corelib/tools/qpoint.cpp13
-rw-r--r--src/corelib/tools/qrect.cpp12
-rw-r--r--src/corelib/tools/qset.h2
-rw-r--r--src/corelib/tools/qsharedpointer.cpp29
-rw-r--r--src/corelib/tools/qsharedpointer.h3
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h65
-rw-r--r--src/corelib/tools/qsize.cpp12
-rw-r--r--src/corelib/tools/qstringlist.cpp41
-rw-r--r--src/corelib/tools/qstringlist.h3
-rw-r--r--src/corelib/tools/qtools_p.h2
-rw-r--r--src/corelib/tools/qvector.cpp22
-rw-r--r--src/corelib/tools/qvector.h19
-rw-r--r--src/gui/accessible/qaccessible.cpp9
-rw-r--r--src/gui/image/qimage_conversions.cpp6
-rw-r--r--src/gui/image/qimage_mips_dspr2.cpp20
-rw-r--r--src/gui/image/qimage_mips_dspr2_asm.S92
-rw-r--r--src/gui/image/qimagereader.cpp27
-rw-r--r--src/gui/image/qimagewriter.cpp31
-rw-r--r--src/gui/image/qjpeghandler.cpp4
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/opengl/opengl.pri1
-rw-r--r--src/gui/opengl/qopenglextensions_p.h2
-rw-r--r--src/gui/painting/qcolor_p.cpp10
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/painting/qpainterpath.cpp3
-rw-r--r--src/gui/painting/qpen.cpp18
-rw-r--r--src/gui/painting/qpen.h2
-rw-r--r--src/gui/text/qfont.cpp35
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/util/qgridlayoutengine.cpp26
-rw-r--r--src/gui/util/qgridlayoutengine_p.h12
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp6
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp2
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp4
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp12
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp15
-rw-r--r--src/network/ssl/qsslconfiguration.cpp13
-rw-r--r--src/network/ssl/qsslconfiguration.h1
-rw-r--r--src/network/ssl/qsslconfiguration_p.h4
-rw-r--r--src/network/ssl/qsslsocket.cpp42
-rw-r--r--src/network/ssl/qsslsocket.h3
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp32
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h1
-rw-r--r--src/network/ssl/qsslsocket_p.h3
-rw-r--r--src/opengl/opengl.pro1
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration.cpp9
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen.cpp6
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen_p.h2
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp75
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h10
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp13
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection.cpp8
-rw-r--r--src/plugins/accessible/accessible.pro5
-rw-r--r--src/plugins/accessible/widgets/widgets.json54
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.cpp15
-rw-r--r--src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml10
-rw-r--r--src/plugins/platforminputcontexts/ibus/main.cpp9
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h15
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp61
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.cpp140
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.h27
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp17
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp45
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/printsupport/kernel/qcups.cpp152
-rw-r--r--src/testlib/qplaintestlogger.cpp18
-rw-r--r--src/testlib/qxmltestlogger.cpp7
-rw-r--r--src/testlib/qxunittestlogger.cpp14
-rw-r--r--src/tools/bootstrap/bootstrap.pro1
-rw-r--r--src/tools/qdoc/codemarker.cpp2
-rw-r--r--src/tools/qdoc/codemarker.h3
-rw-r--r--src/tools/qdoc/codeparser.cpp61
-rw-r--r--src/tools/qdoc/codeparser.h2
-rw-r--r--src/tools/qdoc/config.cpp2
-rw-r--r--src/tools/qdoc/config.h4
-rw-r--r--src/tools/qdoc/cppcodemarker.cpp18
-rw-r--r--src/tools/qdoc/cppcodemarker.h2
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp207
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp524
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.h11
-rw-r--r--src/tools/qdoc/doc.cpp64
-rw-r--r--src/tools/qdoc/generator.cpp151
-rw-r--r--src/tools/qdoc/generator.h25
-rw-r--r--src/tools/qdoc/helpprojectwriter.cpp48
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp546
-rw-r--r--src/tools/qdoc/htmlgenerator.h13
-rw-r--r--src/tools/qdoc/main.cpp44
-rw-r--r--src/tools/qdoc/node.cpp769
-rw-r--r--src/tools/qdoc/node.h306
-rw-r--r--src/tools/qdoc/puredocparser.cpp2
-rw-r--r--src/tools/qdoc/puredocparser.h1
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp1454
-rw-r--r--src/tools/qdoc/qdocdatabase.h370
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp394
-rw-r--r--src/tools/qdoc/qdocindexfiles.h6
-rw-r--r--src/tools/qdoc/qdoctagfiles.cpp38
-rw-r--r--src/tools/qdoc/qmlcodeparser.h1
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp2
-rw-r--r--src/tools/qdoc/tree.cpp1106
-rw-r--r--src/tools/qdoc/tree.h143
-rw-r--r--src/widgets/accessible/accessible.pri21
-rw-r--r--src/widgets/accessible/complexwidgets.cpp (renamed from src/plugins/accessible/widgets/complexwidgets.cpp)2
-rw-r--r--src/widgets/accessible/complexwidgets.h (renamed from src/plugins/accessible/widgets/complexwidgets.h)0
-rw-r--r--src/widgets/accessible/itemviews.cpp (renamed from src/plugins/accessible/widgets/itemviews.cpp)2
-rw-r--r--src/widgets/accessible/itemviews.h (renamed from src/plugins/accessible/widgets/itemviews.h)0
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp (renamed from src/plugins/accessible/widgets/qaccessiblemenu.cpp)4
-rw-r--r--src/widgets/accessible/qaccessiblemenu.h (renamed from src/plugins/accessible/widgets/qaccessiblemenu.h)0
-rw-r--r--src/widgets/accessible/qaccessiblewidget.cpp4
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory.cpp (renamed from src/plugins/accessible/widgets/main.cpp)23
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory_p.h53
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp (renamed from src/plugins/accessible/widgets/qaccessiblewidgets.cpp)45
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.h (renamed from src/plugins/accessible/widgets/qaccessiblewidgets.h)0
-rw-r--r--src/widgets/accessible/rangecontrols.cpp (renamed from src/plugins/accessible/widgets/rangecontrols.cpp)7
-rw-r--r--src/widgets/accessible/rangecontrols.h (renamed from src/plugins/accessible/widgets/rangecontrols.h)0
-rw-r--r--src/widgets/accessible/simplewidgets.cpp (renamed from src/plugins/accessible/widgets/simplewidgets.cpp)4
-rw-r--r--src/widgets/accessible/simplewidgets.h (renamed from src/plugins/accessible/widgets/simplewidgets.h)0
-rw-r--r--src/widgets/accessible/widgets.pro (renamed from src/plugins/accessible/widgets/widgets.pro)0
-rw-r--r--src/widgets/dialogs/qwizard.cpp2
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc5
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc20
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp43
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.h3
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h15
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp88
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp24
-rw-r--r--src/widgets/graphicsview/qgraphicssceneindex.cpp3
-rw-r--r--src/widgets/kernel/qapplication.cpp6
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp5
-rw-r--r--src/widgets/kernel/qwidget.cpp9
-rw-r--r--src/widgets/styles/qcommonstyle.cpp3
-rw-r--r--src/widgets/styles/qstyle.cpp3
-rw-r--r--src/widgets/styles/qstyle.h1
-rw-r--r--src/widgets/styles/qstyleoption.cpp2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp2
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp8
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp68
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h9
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp51
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp40
-rw-r--r--src/widgets/widgets.pro3
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp2
-rw-r--r--src/widgets/widgets/qlineedit.cpp3
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp1
-rw-r--r--src/widgets/widgets/qmdiarea.cpp75
-rw-r--r--src/widgets/widgets/qmdiarea_p.h22
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp2
-rw-r--r--src/widgets/widgets/qtextedit.cpp2
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp6
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h5
192 files changed, 5702 insertions, 3217 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index 8c21083976..aa0473964c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -297,3 +297,13 @@ while (i != hash.end() && i.key() == "plenty") {
++i;
}
//! [26]
+
+//! [qhashbits]
+inline uint qHash(const std::vector<int> &key, uint seed = 0)
+{
+ if (key.empty())
+ return seed;
+ else
+ return qHashBits(&key.front(), key.size() * sizeof(int), seed);
+}
+//! [qhashbits]
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 950647004a..b62ae30fc5 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -200,6 +200,8 @@
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
# define Q_NORETURN __attribute__((__noreturn__))
# define Q_REQUIRED_RESULT __attribute__ ((__warn_unused_result__))
+# define Q_DECL_PURE_FUNCTION __attribute__((pure))
+# define Q_DECL_CONST_FUNCTION __attribute__((const))
# if !defined(QT_MOC_CPP)
# define Q_PACKED __attribute__ ((__packed__))
# ifndef __ARM_EABI__
@@ -981,6 +983,12 @@
#ifndef Q_DECL_NS_RETURNS_AUTORELEASED
# define Q_DECL_NS_RETURNS_AUTORELEASED
#endif
+#ifndef Q_DECL_PURE_FUNCTION
+# define Q_DECL_PURE_FUNCTION
+#endif
+#ifndef Q_DECL_CONST_FUNCTION
+# define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION
+#endif
/*
Workaround for static const members on MSVC++.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index fba8b019e7..3832e70c94 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -45,11 +45,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "5.3.0"
+#define QT_VERSION_STR "5.4.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050300
+#define QT_VERSION 0x050400
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -858,22 +858,37 @@ Q_CORE_EXPORT void qFreeAligned(void *ptr);
# endif
#endif
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT)
-/* make use of typeof-extension */
+#if defined(Q_COMPILER_DECLTYPE) || (defined(Q_CC_GNU) && !defined(Q_CC_RVCT))
+/* make use of decltype or GCC's __typeof__ extension */
template <typename T>
class QForeachContainer {
public:
- inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
+ inline QForeachContainer(const T& t) : c(t), i(c.begin()), e(c.end()), control(1) { }
const T c;
- int brk;
typename T::const_iterator i, e;
+ int control;
};
-#define Q_FOREACH(variable, container) \
-for (QForeachContainer<__typeof__((container))> _container_((container)); \
- !_container_.brk && _container_.i != _container_.e; \
- __extension__ ({ ++_container_.brk; ++_container_.i; })) \
- for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
+# ifdef Q_COMPILER_DECLTYPE
+# define QT_FOREACH_DECLTYPE(x) typename QtPrivate::remove_reference<decltype(x)>::type
+# else
+# define QT_FOREACH_DECLTYPE(x) __typeof__((x))
+# endif
+
+// Explanation of the control word:
+// - it's initialized to 1
+// - that means both the inner and outer loops start
+// - if there were no breaks, at the end of the inner loop, it's set to 0, which
+// causes it to exit (the inner loop is run exactly once)
+// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing
+// the outer loop to continue executing
+// - if there was a break inside the inner loop, it will exit with control still
+// set to 1; in that case, the outer loop will invert it to 0 and will exit too
+# define Q_FOREACH(variable, container) \
+for (QForeachContainer<QT_FOREACH_DECLTYPE(container)> _container_((container)); \
+ _container_.control && _container_.i != _container_.e; \
+ ++_container_.i, _container_.control ^= 1) \
+ for (variable = *_container_.i; _container_.control; _container_.control = 0)
#else
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 6d25325890..a4bb8cfacb 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -255,7 +255,9 @@ QLibraryInfo::buildDate()
}
#endif //QT_NO_DATESTRING
-#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
+#if defined(Q_CC_INTEL) // must be before GNU, Clang and MSVC because ICC/ICL claim to be them
+# define COMPILER_STRING __VERSION__ /* __VERSION__ starts with "Intel(R) C++" */
+#elif defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
# ifdef __apple_build_version__ // Apple clang has other version numbers
# define COMPILER_STRING "Clang " __clang_version__ " (Apple)"
# else
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index 7d8bd8c3c6..21d0209dd7 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -140,6 +140,7 @@ static inline quint32 f2i(float f)
\endcode
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint32 qFloatDistance(float a, float b)
@@ -197,6 +198,7 @@ static inline quint64 d2i(double d)
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index a6fbffee7e..127244e994 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -250,10 +250,6 @@ QT_BEGIN_NAMESPACE
if (q_status != Ok) \
return retVal;
-enum {
- DefaultStreamVersion = QDataStream::Qt_5_3
-};
-
/*!
Constructs a data stream that has no I/O device.
@@ -265,7 +261,7 @@ QDataStream::QDataStream()
dev = 0;
owndev = false;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -287,7 +283,7 @@ QDataStream::QDataStream(QIODevice *d)
dev = d; // set device
owndev = false;
byteorder = BigEndian; // default byte order
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -315,7 +311,7 @@ QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -339,7 +335,7 @@ QDataStream::QDataStream(const QByteArray &a)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -542,6 +538,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_1 Version 14 (Qt 5.1)
\value Qt_5_2 Version 15 (Qt 5.2)
\value Qt_5_3 Same as Qt_5_2
+ \value Qt_5_4 Version 16 (Qt 5.4)
+ \omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
*/
@@ -557,7 +555,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
/*!
\fn void QDataStream::setVersion(int v)
- Sets the version number of the data serialization format to \a v.
+ Sets the version number of the data serialization format to \a v,
+ a value of the \l Version enum.
You don't \e have to set a version if you are using the current
version of Qt, but for your own custom binary formats we
@@ -571,25 +570,6 @@ void QDataStream::setByteOrder(ByteOrder bo)
with an earlier version of Qt, use this function to modify the
serialization format used by QDataStream.
- \table
- \header \li Qt Version \li QDataStream Version
- \row \li Qt 5.2 \li 15
- \row \li Qt 5.1 \li 14
- \row \li Qt 5.0 \li 13
- \row \li Qt 4.6 \li 12
- \row \li Qt 4.5 \li 11
- \row \li Qt 4.4 \li 10
- \row \li Qt 4.3 \li 9
- \row \li Qt 4.2 \li 8
- \row \li Qt 4.0, 4.1 \li 7
- \row \li Qt 3.3 \li 6
- \row \li Qt 3.1, 3.2 \li 5
- \row \li Qt 3.0 \li 4
- \row \li Qt 2.1, 2.2, 2.3 \li 3
- \row \li Qt 2.0 \li 2
- \row \li Qt 1.x \li 1
- \endtable
-
The \l Version enum provides symbolic constants for the different
versions of Qt. For example:
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 28f1d51a12..808fbe73f6 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -88,10 +88,12 @@ public:
Qt_5_0 = 13,
Qt_5_1 = 14,
Qt_5_2 = 15,
- Qt_5_3 = Qt_5_2
-#if QT_VERSION >= 0x050400
-#error Add the datastream version for this Qt version
+ Qt_5_3 = Qt_5_2,
+ Qt_5_4 = 16,
+#if QT_VERSION >= 0x050500
+#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
+ Qt_DefaultCompiledVersion = Qt_5_4
};
enum ByteOrder {
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 3370cce6d5..79038e9138 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -334,7 +334,9 @@ QT_BEGIN_NAMESPACE
\brief Convenience class for custom QDebug operators
- Saves the settings used by QDebug, and restores them upon destruction.
+ Saves the settings used by QDebug, and restores them upon destruction,
+ then calls maybeSpace(), to separate arguments with a space if
+ autoInsertSpaces() was true at the time of constructing the QDebugStateSaver.
The automatic insertion of spaces between writes is one of the settings
that QDebugStateSaver stores for the duration of the current block.
@@ -391,6 +393,7 @@ QDebugStateSaver::QDebugStateSaver(QDebug &dbg)
QDebugStateSaver::~QDebugStateSaver()
{
d->restoreState();
+ d->m_dbg.maybeSpace();
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index b1e4dd7584..4c5fb38c67 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -506,6 +506,25 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *dev
}
/*!
+ Create a QNonContiguousByteDevice out of a QIODevice, return it in a QSharedPointer.
+ For QFile, QBuffer and all other QIODevice, sequential or not.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer *buffer = qobject_cast<QBuffer*>(device))
+ return QSharedPointer<QNonContiguousByteDeviceBufferImpl>::create(buffer);
+
+ // ### FIXME special case if device is a QFile that supports map()
+ // then we can actually deal with the file without using read/peek
+
+ // generic QIODevice
+ return QSharedPointer<QNonContiguousByteDeviceIoDeviceImpl>::create(device); // FIXME
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
Create a QNonContiguousByteDevice out of a QRingBuffer.
@@ -518,6 +537,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer
}
/*!
+ Create a QNonContiguousByteDevice out of a QRingBuffer, return it in a QSharedPointer.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QSharedPointer<QRingBuffer> ringBuffer)
+{
+ return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(qMove(ringBuffer));
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
Create a QNonContiguousByteDevice out of a QByteArray.
@@ -530,6 +559,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *by
}
/*!
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QByteArray *byteArray)
+{
+ return QSharedPointer<QNonContiguousByteDeviceByteArrayImpl>::create(byteArray);
+}
+
+/*!
\fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
Wrap the \a byteDevice (possibly again) into a QIODevice.
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index 4606ac2686..1e746db80f 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -90,8 +90,14 @@ class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
{
public:
static QNonContiguousByteDevice* create(QIODevice *device);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QIODevice *device);
+
static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QByteArray *byteArray);
+
static QNonContiguousByteDevice* create(QSharedPointer<QRingBuffer> ringBuffer);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QSharedPointer<QRingBuffer> ringBuffer);
+
static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
};
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 4241fe08ca..3e303e529c 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -990,9 +990,9 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
- \fn void *QModelIndex::internalId() const
+ \fn quintptr QModelIndex::internalId() const
- Returns a \c{qint64} used by the model to associate
+ Returns a \c{quintptr} used by the model to associate
the index with the internal data structure.
\sa QAbstractItemModel::createIndex()
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index edf262b8af..adc6db22a0 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -43,8 +43,9 @@
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
-#include "qmutex.h"
-#include "qset.h"
+#include "qbasicatomic.h"
+
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -192,6 +193,7 @@ QT_BEGIN_NAMESPACE
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
\value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
+ \value ReadOnlyChange Widget's read-only state has changed (since Qt 5.4).
\value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
\value Resize Widget's size changed (QResizeEvent).
\value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent).
@@ -389,13 +391,72 @@ QEvent::~QEvent()
The return value of this function is not defined for paint events.
*/
-class QEventUserEventRegistration
-{
-public:
- QMutex mutex;
- QSet<int> set;
+namespace {
+template <size_t N>
+struct QBasicAtomicBitField {
+ enum {
+ BitsPerInt = std::numeric_limits<uint>::digits,
+ NumInts = (N + BitsPerInt - 1) / BitsPerInt,
+ NumBits = N
+ };
+
+ // This atomic int points to the next (possibly) free ID saving
+ // the otherwise necessary scan through 'data':
+ QBasicAtomicInteger<uint> next;
+ QBasicAtomicInteger<uint> data[NumInts];
+
+ bool allocateSpecific(int which) Q_DECL_NOTHROW
+ {
+ QBasicAtomicInteger<uint> &entry = data[which / BitsPerInt];
+ const uint old = entry.load();
+ const uint bit = 1U << (which % BitsPerInt);
+ return !(old & bit) // wasn't taken
+ && entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
+
+ // don't update 'next' here - it's unlikely that it will need
+ // to be updated, in the general case, and having 'next'
+ // trailing a bit is not a problem, as it is just a starting
+ // hint for allocateNext(), which, when wrong, will just
+ // result in a few more rounds through the allocateNext()
+ // loop.
+ }
+
+ int allocateNext() Q_DECL_NOTHROW
+ {
+ // Unroll loop to iterate over ints, then bits? Would save
+ // potentially a lot of cmpxchgs, because we can scan the
+ // whole int before having to load it again.
+
+ // Then again, this should never execute many iterations, so
+ // leave like this for now:
+ for (uint i = next.load(); i < NumBits; ++i) {
+ if (allocateSpecific(i)) {
+ // remember next (possibly) free id:
+ const uint oldNext = next.load();
+ next.testAndSetRelaxed(oldNext, qMax(i + 1, oldNext));
+ return i;
+ }
+ }
+ return -1;
+ }
};
-Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
+
+} // unnamed namespace
+
+static const int UserEventRegistrationBitFieldSize = QEvent::MaxUser - QEvent::User + 1;
+typedef QBasicAtomicBitField<QEvent::MaxUser - QEvent::User + 1> UserEventTypeRegistry;
+
+static UserEventTypeRegistry userEventTypeRegistry;
+
+static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW
+{
+ // if the type hint hasn't been registered yet, take it:
+ if (id < UserEventTypeRegistry::NumBits && id >= 0 && userEventTypeRegistry.allocateSpecific(id))
+ return id;
+
+ // otherwise, ignore hint:
+ return userEventTypeRegistry.allocateNext();
+}
/*!
\since 4.4
@@ -410,30 +471,10 @@ Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
Returns -1 if all available values are already taken or the
program is shutting down.
*/
-int QEvent::registerEventType(int hint)
+int QEvent::registerEventType(int hint) Q_DECL_NOTHROW
{
- QEventUserEventRegistration *userEventRegistration
- = userEventRegistrationHelper();
- if (!userEventRegistration)
- return -1;
-
- QMutexLocker locker(&userEventRegistration->mutex);
-
- // if the type hint hasn't been registered yet, take it
- if (hint >= QEvent::User && hint <= QEvent::MaxUser && !userEventRegistration->set.contains(hint)) {
- userEventRegistration->set.insert(hint);
- return hint;
- }
-
- // find a free event type, starting at MaxUser and decreasing
- int id = QEvent::MaxUser;
- while (userEventRegistration->set.contains(id) && id >= QEvent::User)
- --id;
- if (id >= QEvent::User) {
- userEventRegistration->set.insert(id);
- return id;
- }
- return -1;
+ const int result = registerEventTypeZeroBased(QEvent::MaxUser - hint);
+ return result < 0 ? -1 : QEvent::MaxUser - result ;
}
/*!
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 3ee0eaaa61..2e0f781822 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -150,6 +150,8 @@ public:
WindowUnblocked = 104, // windows modal blocking has ended
WindowStateChange = 105,
+ ReadOnlyChange = 106, // readonly state has changed
+
ToolTip = 110,
WhatsThis = 111,
StatusTip = 112,
@@ -300,7 +302,7 @@ public:
inline void accept() { m_accept = true; }
inline void ignore() { m_accept = false; }
- static int registerEventType(int hint = -1);
+ static int registerEventType(int hint = -1) Q_DECL_NOTHROW;
protected:
QEventPrivate *d;
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 5be94429b4..d4bfa049ee 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -308,6 +308,11 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
return object->qt_metacall(cl, idx, argv);
}
+static inline const char *objectClassName(const QMetaObject *m)
+{
+ return rawStringData(m, priv(m->d.data)->className);
+}
+
/*!
Returns the class name.
@@ -315,7 +320,7 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
*/
const char *QMetaObject::className() const
{
- return rawStringData(this, 0);
+ return objectClassName(this);
}
/*!
@@ -369,7 +374,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(rawStringData(this, 0), s, c, n);
+ return QCoreApplication::translate(objectClassName(this), s, c, n);
}
#endif // QT_NO_TRANSLATION
@@ -728,7 +733,7 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
QMetaMethod conflictMethod = m->d.superdata->method(conflict);
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
conflictMethod.methodSignature().constData(),
- rawStringData(m->d.superdata, 0), rawStringData(m, 0));
+ objectClassName(m->d.superdata), objectClassName(m));
}
}
#endif
@@ -938,7 +943,7 @@ bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
{
while (self) {
- if (strcmp(rawStringData(self, 0), name) == 0)
+ if (strcmp(objectClassName(self), name) == 0)
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
@@ -1117,7 +1122,7 @@ QMetaProperty QMetaObject::property(int index) const
result.menum = enumerator(indexOfEnumerator(type));
if (!result.menum.isValid()) {
const char *enum_name = type;
- const char *scope_name = rawStringData(this, 0);
+ const char *scope_name = objectClassName(this);
char *scope_buffer = 0;
const char *colon = strrchr(enum_name, ':');
@@ -2412,7 +2417,7 @@ bool QMetaEnum::isFlag() const
*/
const char *QMetaEnum::scope() const
{
- return mobj?rawStringData(mobj, 0) : 0;
+ return mobj ? objectClassName(mobj) : 0;
}
/*!
@@ -2444,7 +2449,8 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i) {
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
if (ok != 0)
*ok = true;
@@ -2512,12 +2518,14 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
key += scope + 2;
}
int i;
- for (i = count-1; i >= 0; --i)
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
+ for (i = count-1; i >= 0; --i) {
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key.constData(), className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
value |= mobj->d.data[data + 2*i + 1];
break;
}
+ }
if (i < 0) {
if (ok != 0)
*ok = false;
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 80567d6a71..0a52aaf680 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -893,11 +893,11 @@ struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
template<typename T>
struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return t->size(); } };
+{ static int size(const std::vector<T> *t) { return int(t->size()); } };
template<typename T>
struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *t) { return t->size(); } };
+{ static int size(const std::list<T> *t) { return int(t->size()); } };
class QSequentialIterableImpl
{
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 0ffa186d2e..a23e545729 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -443,4 +443,17 @@ bool QMimeType::inherits(const QString &mimeTypeName) const
return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QMimeType &mime)
+{
+ QDebugStateSaver saver(debug);
+ if (!mime.isValid()) {
+ debug.nospace() << "QMimeType(invalid)";
+ } else {
+ debug.nospace() << "QMimeType(" << mime.name() << ")";
+ }
+ return debug;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 24d043eebc..d5acbc2184 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -110,5 +110,10 @@ protected:
Q_DECLARE_SHARED(QMimeType)
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMimeType &mime);
+#endif
+
QT_END_NAMESPACE
#endif // QMIMETYPE_H
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 825b3289c7..45587b1214 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -68,7 +68,7 @@ static const QArrayData &qt_array_empty = qt_array[0];
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options)
+ size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -111,7 +111,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
- size_t alignment)
+ size_t alignment) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index ffb2b8765e..534f310d36 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -116,9 +116,9 @@ struct Q_CORE_EXPORT QArrayData
static QArrayData *allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options = Default)
- Q_REQUIRED_RESULT;
+ Q_DECL_NOTHROW Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
- size_t alignment);
+ size_t alignment) Q_DECL_NOTHROW;
static const QArrayData shared_null[2];
static QArrayData *sharedNull() { return const_cast<QArrayData*>(shared_null); }
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index fb92d82f07..9c2a242e8e 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -67,7 +67,7 @@ int qFindByteArray(
const char *needle0, int needleLen);
-int qAllocMore(int alloc, int extra)
+int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
{
Q_ASSERT(alloc >= 0 && extra >= 0);
Q_ASSERT_X(alloc < (1 << 30) - extra, "qAllocMore", "Requested size is too large!");
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 266effb66a..88758bdd6d 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -384,7 +384,7 @@ public:
QT_DEPRECATED inline char toAscii() const { return toLatin1(); }
#endif
inline char toLatin1() const;
- inline ushort unicode() const { return ucs; }
+ Q_DECL_CONSTEXPR inline ushort unicode() const { return ucs; }
inline ushort &unicode() { return ucs; }
#if QT_DEPRECATED_SINCE(5, 0)
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 505ab5f46d..168701d13c 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -495,10 +495,8 @@ void QCommandLineParser::process(const QStringList &arguments)
::exit(EXIT_FAILURE);
}
- if (d->builtinVersionOption && isSet(QStringLiteral("version"))) {
- printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
- ::exit(EXIT_SUCCESS);
- }
+ if (d->builtinVersionOption && isSet(QStringLiteral("version")))
+ showVersion();
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
showHelp(EXIT_SUCCESS);
@@ -888,6 +886,22 @@ QStringList QCommandLineParser::unknownOptionNames() const
}
/*!
+ Displays the version information from QCoreApplication::applicationVersion(),
+ and exits the application.
+ This is automatically triggered by the --version option, but can also
+ be used to display the version when not using process().
+ The exit code is set to EXIT_SUCCESS (0).
+
+ \sa addVersionOption()
+ \since 5.4
+*/
+Q_NORETURN void QCommandLineParser::showVersion()
+{
+ fprintf(stdout, "%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
+ ::exit(EXIT_SUCCESS);
+}
+
+/*!
Displays the help information, and exits the application.
This is automatically triggered by the --help option, but can also
be used to display the help when the user is not invoking the
diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h
index 5a7061f031..946d4dd238 100644
--- a/src/corelib/tools/qcommandlineparser.h
+++ b/src/corelib/tools/qcommandlineparser.h
@@ -92,6 +92,7 @@ public:
QStringList optionNames() const;
QStringList unknownOptionNames() const;
+ Q_NORETURN void showVersion();
Q_NORETURN void showHelp(int exitCode = 0);
QString helpText() const;
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index a5d14a3535..928707660b 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -163,6 +163,11 @@ static inline uint hash(const uchar *p, int len, uint seed) Q_DECL_NOTHROW
return h;
}
+uint qHashBits(const void *p, size_t len, uint seed) Q_DECL_NOTHROW
+{
+ return hash(static_cast<const uchar*>(p), int(len), seed);
+}
+
static inline uint hash(const QChar *p, int len, uint seed) Q_DECL_NOTHROW
{
uint h = seed;
@@ -669,6 +674,25 @@ void QHashData::checkSanity()
Types \c T1 and \c T2 must be supported by qHash().
*/
+/*! \fn uint qHashBits(const void *p, size_t len, uint seed = 0)
+ \relates QHash
+ \since 5.4
+
+ Returns the hash value for the memory block of size \a len pointed
+ to by \a p, using \a seed to seed the calculation.
+
+ Use this function only to implement qHash() for your own custom
+ types. E.g., here's how you could implement a qHash() overload for
+ std::vector<int>:
+
+ \snippet code/src_corelib_tools_qhash.cpp qhashbits
+
+ It bears repeating that the implementation of qHashBits() - like
+ the qHash() overloads offered by Qt - may change at any time. You
+ \b{must not} rely on the fact that qHashBits() will give the same
+ results (for the same inputs) across different Qt versions.
+*/
+
/*! \fn uint qHash(char key, uint seed = 0)
\relates QHash
\since 5.0
@@ -778,7 +802,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
}
#endif
-/*! \fn uint qHash(QChar key, uint seed = 0)
+/*! \fn uint qHash(const QChar key, uint seed = 0)
\relates QHash
\since 5.0
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 40e501355c..67924c0888 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -66,44 +66,40 @@ class QString;
class QStringRef;
class QLatin1String;
-inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
-inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;
+
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(ulong) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return (sizeof(ulong) > sizeof(uint))
+ ? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed)
+ : (uint(key & (~0U)) ^ seed);
}
-inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
-inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(quint64) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
}
-inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
-Q_CORE_EXPORT uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
#ifndef Q_OS_DARWIN
-Q_CORE_EXPORT uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
#endif
-inline uint qHash(QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
-Q_CORE_EXPORT uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
@@ -301,7 +297,7 @@ public:
inline QHash(std::initializer_list<std::pair<Key,T> > list)
: d(const_cast<QHashData *>(&QHashData::shared_null))
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
@@ -977,7 +973,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
{
- this->reserve(list.size());
+ this->reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 990e6bef09..61c7899ef4 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -259,10 +259,11 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLine &p)
+QDebug operator<<(QDebug dbg, const QLine &p)
{
- d << "QLine(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLine(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
@@ -819,10 +820,11 @@ qreal QLineF::angle(const QLineF &l) const
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLineF &p)
+QDebug operator<<(QDebug dbg, const QLineF &p)
{
- d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLineF(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index 1063cda52b..090e8d0ff2 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -452,15 +452,18 @@ QDataStream &operator>>(QDataStream &s, QPoint &p)
*/
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QPoint &p) {
+QDebug operator<<(QDebug dbg, const QPoint &p)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPoint(" << p.x() << ',' << p.y() << ')';
- return dbg.space();
+ return dbg;
}
-QDebug operator<<(QDebug d, const QPointF &p)
+QDebug operator<<(QDebug dbg, const QPointF &p)
{
- d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
- return d.space();
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QPointF(" << p.x() << ',' << p.y() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 382793f175..04269e485b 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -1286,10 +1286,12 @@ QDataStream &operator>>(QDataStream &s, QRect &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRect &r) {
+QDebug operator<<(QDebug dbg, const QRect &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRect(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -2493,10 +2495,12 @@ QDataStream &operator>>(QDataStream &s, QRectF &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRectF &r) {
+QDebug operator<<(QDebug dbg, const QRectF &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRectF(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index ad2f91b983..291c8fe4f9 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -60,7 +60,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QSet(std::initializer_list<T> list)
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<T>::const_iterator it = list.begin(); it != list.end(); ++it)
insert(*it);
}
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index a610fc46e5..58a9a021d0 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -630,9 +630,15 @@
This function will attempt to call a constructor for type \tt T that can
accept all the arguments passed. Arguments will be perfectly-forwarded.
- \note This function is only available with a C++11 compiler that supports
- perfect forwarding of an arbitrary number of arguments. If the compiler
- does not support the necessary C++11 features, you must use the overload
+ \note This function is only fully available with a C++11 compiler that
+ supports perfect forwarding of an arbitrary number of arguments.
+
+ If the compiler does not support the necessary C++11 features,
+ then a restricted version is available since Qt 5.4: you may pass
+ one (but just one) argument, and it will always be passed by const
+ reference.
+
+ If you target Qt before version 5.4, you must use the overload
that calls the default constructor.
*/
@@ -771,6 +777,14 @@
*/
/*!
+ \fn void QWeakPointer::swap(QWeakPointer<T> &other)
+ \since 5.4
+
+ Swaps this weak pointer instance with \a other. This function is
+ very fast and never fails.
+*/
+
+/*!
\fn bool QWeakPointer::isNull() const
Returns \c true if this object is holding a reference to a null
@@ -894,6 +908,15 @@
*/
/*!
+ \fn QSharedPointer<T> QWeakPointer::lock() const
+ \since 5.4
+
+ Same as toStrongRef().
+
+ This function is provided for API compatibility with std::weak_ptr.
+*/
+
+/*!
\fn void QWeakPointer::clear()
Clears this QWeakPointer object, dropping the reference that it
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 34b4bfbb12..d9de48b7f4 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -122,10 +122,13 @@ public:
QWeakPointer(const QObject *other);
QWeakPointer<T> operator=(const QObject *other);
+ void swap(QWeakPointer<T> &other);
+
T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
+ QSharedPointer<T> lock() const;
};
template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 1423449a69..f3df32469f 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -318,16 +318,22 @@ public:
inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws
{ internalConstruct(ptr, deleter); }
- inline QSharedPointer(const QSharedPointer<T> &other) : value(other.value), d(other.d)
+ inline QSharedPointer(const QSharedPointer &other) : value(other.value), d(other.d)
{ if (d) ref(); }
- inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
+ inline QSharedPointer &operator=(const QSharedPointer &other)
{
QSharedPointer copy(other);
swap(copy);
return *this;
}
#ifdef Q_COMPILER_RVALUE_REFS
- inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
+ inline QSharedPointer(QSharedPointer &&other)
+ : value(other.value), d(other.d)
+ {
+ other.d = 0;
+ other.value = 0;
+ }
+ inline QSharedPointer &operator=(QSharedPointer &&other)
{
swap(other);
return *this;
@@ -339,7 +345,7 @@ public:
{ if (d) ref(); }
template <class X>
- inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
+ inline QSharedPointer &operator=(const QSharedPointer<X> &other)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalCopy(other);
@@ -355,7 +361,7 @@ public:
{ internalSet(other.d, other.value); return *this; }
inline void swap(QSharedPointer &other)
- { QSharedPointer<T>::internalSwap(other); }
+ { this->internalSwap(other); }
inline void reset() { clear(); }
inline void reset(T *t)
@@ -396,7 +402,7 @@ public:
#if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
template <typename... Args>
- static QSharedPointer<T> create(Args && ...arguments)
+ static QSharedPointer create(Args && ...arguments)
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -404,7 +410,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -416,7 +422,7 @@ public:
return result;
}
#else
- static inline QSharedPointer<T> create()
+ static inline QSharedPointer create()
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -424,7 +430,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -435,6 +441,27 @@ public:
result.d->setQObjectShared(result.value, true);
return result;
}
+
+ template <typename Arg>
+ static inline QSharedPointer create(const Arg &arg)
+ {
+ typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
+# else
+ typename Private::DestroyerFn destroy = &Private::deleter;
+# endif
+ QSharedPointer result(Qt::Uninitialized);
+ result.d = Private::create(&result.value, destroy);
+
+ // now initialize the data
+ new (result.data()) T(arg);
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ internalSafetyCheckAdd(result.d, result.value);
+# endif
+ result.d->setQObjectShared(result.value, true);
+ return result;
+ }
#endif
private:
@@ -573,17 +600,23 @@ public:
{ return *this = QWeakPointer(ptr); }
#endif
- inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
+ inline QWeakPointer(const QWeakPointer &o) : d(o.d), value(o.value)
{ if (d) d->weakref.ref(); }
- inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
+ inline QWeakPointer &operator=(const QWeakPointer &o)
{
internalSet(o.d, o.value);
return *this;
}
+ inline void swap(QWeakPointer &other)
+ {
+ qSwap(this->d, other.d);
+ qSwap(this->value, other.value);
+ }
+
inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
{ if (d) d->weakref.ref();}
- inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<T> &o)
{
internalSet(o.d, o.value);
return *this;
@@ -594,7 +627,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
+ inline QWeakPointer &operator=(const QWeakPointer<X> &o)
{
// conversion between X and T could require access to the virtual table
// so force the operation to go through QSharedPointer
@@ -615,7 +648,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<X> &o)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalSet(o.d, o.data());
@@ -630,9 +663,11 @@ public:
inline bool operator!=(const QSharedPointer<X> &o) const
{ return !(*this == o); }
- inline void clear() { *this = QWeakPointer<T>(); }
+ inline void clear() { *this = QWeakPointer(); }
inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+ // std::weak_ptr compatibility:
+ inline QSharedPointer<T> lock() const { return toStrongRef(); }
#if defined(QWEAKPOINTER_ENABLE_ARROW)
inline T *operator->() const { return data(); }
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index b53eced298..da447157ff 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -445,9 +445,11 @@ QDataStream &operator>>(QDataStream &s, QSize &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSize &s) {
+QDebug operator<<(QDebug dbg, const QSize &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSize(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -870,9 +872,11 @@ QDataStream &operator>>(QDataStream &s, QSizeF &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSizeF &s) {
+QDebug operator<<(QDebug dbg, const QSizeF &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSizeF(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 6b0b39c7bb..a9d704ca4c 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -191,20 +191,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringList::QStringList(const QStringList &other)
-
- Constructs a copy of the \a other string list.
-
- This operation takes \l{constant time} because QStringList is
- \l{implicitly shared}, making the process of returning a
- QStringList from a function very fast. If a shared instance is
- modified, it will be copied (copy-on-write), and that takes
- \l{linear time}.
-
- \sa operator=()
-*/
-
-/*!
\fn QStringList::QStringList(const QList<QString> &other)
Constructs a copy of \a other.
@@ -235,9 +221,14 @@ QT_BEGIN_NAMESPACE
integer index.
*/
-static inline bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.compare(s2, Qt::CaseInsensitive) < 0;
+namespace {
+struct CaseInsensitiveLessThan {
+ typedef bool result_type;
+ result_type operator()(const QString &s1, const QString &s2) const
+ {
+ return s1.compare(s2, Qt::CaseInsensitive) < 0;
+ }
+};
}
void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
@@ -245,7 +236,7 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
if (cs == Qt::CaseSensitive)
std::sort(that->begin(), that->end());
else
- std::sort(that->begin(), that->end(), caseInsensitiveLessThan);
+ std::sort(that->begin(), that->end(), CaseInsensitiveLessThan());
}
@@ -457,7 +448,7 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
if (totalLength == 0)
return res;
res.reserve(totalLength);
- for (int i = 0; i < that->size(); ++i) {
+ for (int i = 0; i < size; ++i) {
if (i)
res.append(sep, seplen);
res += that->at(i);
@@ -492,6 +483,16 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
the latter string list.
*/
+/*!
+ \fn QStringList &QStringList::operator<<(const QList<QString> &other)
+ \since 5.4
+
+ \overload
+
+ Appends the \a other string list to the string list and returns a reference to
+ the latter string list.
+*/
+
#ifndef QT_NO_DATASTREAM
/*!
\fn QDataStream &operator>>(QDataStream &in, QStringList &list)
@@ -725,7 +726,7 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that)
continue;
seen.insert(s);
if (j != i)
- (*that)[j] = s;
+ that->swap(i, j);
++j;
}
if (n != j)
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index a962b7c528..1cdafb4ec2 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -63,7 +63,6 @@ class QStringList : public QList<QString>
public:
inline QStringList() { }
inline explicit QStringList(const QString &i) { append(i); }
- inline QStringList(const QStringList &l) : QList<QString>(l) { }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
@@ -86,6 +85,8 @@ public:
{ append(str); return *this; }
inline QStringList &operator<<(const QStringList &l)
{ *this += l; return *this; }
+ inline QStringList &operator<<(const QList<QString> &l)
+ { *this += l; return *this; }
#ifndef QT_NO_REGEXP
inline QStringList filter(const QRegExp &rx) const;
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index b00343dd39..38073a6e30 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
// implemented in qbytearray.cpp
-int Q_CORE_EXPORT qAllocMore(int alloc, int extra);
+int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 89396540e0..b2b4315545 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -576,6 +576,28 @@
\sa remove(), QList::removeAt()
*/
+/*! \fn int QVector::removeAll(const T &t)
+ \since 5.4
+
+ Removes all elements that compare equal to \a t from the
+ vector. Returns the number of elements removed, if any.
+
+ Provided for compatibility with QList.
+
+ \sa removeOne(), QList::removeAll()
+*/
+
+/*! \fn bool QVector::removeOne(const T &t)
+ \since 5.4
+
+ Removes the first element that compares equal to \a t from the
+ vector. Returns whether an element was, in fact, removed.
+
+ Provided for compatibility with QList.
+
+ \sa removeAll(), QList::removeOne()
+*/
+
/*! \fn int QVector::length() const
\since 5.2
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index b0be98c296..22031645dc 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -154,6 +154,24 @@ public:
// QList compatibility
void removeAt(int i) { remove(i); }
+ int removeAll(const T &t)
+ {
+ const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
+ if (cit == ce)
+ return 0;
+ const iterator e = end(), it = std::remove(c2m(cit), e, t);
+ const int result = std::distance(it, e);
+ erase(it, e);
+ return result;
+ }
+ bool removeOne(const T &t)
+ {
+ const int i = indexOf(t);
+ if (i < 0)
+ return false;
+ remove(i);
+ return true;
+ }
int length() const { return size(); }
T takeAt(int i) { T t = at(i); remove(i); return t; }
@@ -250,6 +268,7 @@ private:
{
return (i <= d->end()) && (d->begin() <= i);
}
+ iterator c2m(const_iterator it) { return begin() + (it - cbegin()); }
class AlignmentDummy { Data header; T array[1]; };
};
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 776320a517..f7a4a53716 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -97,6 +97,15 @@ QT_BEGIN_NAMESPACE
Accessibility, and the Unix/X11 AT-SPI standard. Other backends
can be supported using QAccessibleBridge.
+ In the Unix/X11 AT-SPI implementation, applications become accessible
+ when two conditions are met:
+ \list
+ \li org.a11y.Status.IsEnabled DBus property is true
+ \li org.a11y.Status.ScreenReaderEnabled DBus property is true
+ \endlist
+ An alternative to setting the DBus AT-SPI properties is to set
+ the QT_LINUX_ACCESSIBILITY_ALWAYS_ON environment variable.
+
In addition to QAccessible's static functions, Qt offers one
generic interface, QAccessibleInterface, that can be used to wrap
all widgets and objects (e.g., QPushButton). This single
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 629a7c9b69..cf61d2d84b 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2176,7 +2176,11 @@ void qInitImageConversions()
#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
- return;
+
+ extern void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format::RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format::RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format::RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_mips_dspr2;
#endif
}
diff --git a/src/gui/image/qimage_mips_dspr2.cpp b/src/gui/image/qimage_mips_dspr2.cpp
index a1c40a16df..f61a2262d2 100644
--- a/src/gui/image/qimage_mips_dspr2.cpp
+++ b/src/gui/image/qimage_mips_dspr2.cpp
@@ -66,4 +66,24 @@ bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConve
return true;
}
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(uint *dst, const uchar *src, int len);
+
+void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB888);
+ Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = (const uchar*) src->data;
+ quint32 *dest_data = (quint32*) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ qt_convert_rgb888_to_rgb32_mips_dspr2_asm(dest_data, src_data, src->width);
+ src_data += src->bytes_per_line;
+ dest_data = (quint32*) ((uchar*) dest_data + dest->bytes_per_line);
+ }
+}
+
QT_END_NAMESPACE
+
diff --git a/src/gui/image/qimage_mips_dspr2_asm.S b/src/gui/image/qimage_mips_dspr2_asm.S
index 1f03b72dd4..df626586dc 100644
--- a/src/gui/image/qimage_mips_dspr2_asm.S
+++ b/src/gui/image/qimage_mips_dspr2_asm.S
@@ -205,3 +205,95 @@ LEAF_MIPS_DSPR2(premultiply_argb_inplace_mips_asm)
END(premultiply_argb_inplace_mips_asm)
+
+LEAF_MIPS_DSPR2(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
+/*
+ * Parameters:
+ * a0 - dst *a8r8g8b8
+ * a1 - src *r8g8b8
+ * a2 - len
+ *
+ * R G B r g b R G B r g b R G B r g b . . . -- input
+ * ------- ------- ------- ------- -------
+ * _ R G B _ r g b _ R G B _ r g b _ R G . . -- output
+ *
+ * Register usage:
+ * a2 - tail (len % 4) == (len & 0x3)
+ * t0 - batches (len / 4) == (len >> 2)
+ * t1-t7, s1-s3 - temporary
+ */
+
+ srl t0, a2, 2 /* batches = len / 4 */
+ andi a2, a2, 0x3 /* tail = len % 4 */
+
+ beqz t0, 5f /* if !batches: tail */
+ lui t7, 0xff00 /* [FF 00 00 00] */
+ SAVE_REGS_ON_STACK 8, s1, s2, s3, s0, v0, v1
+
+1: pref 4, 0 (a1) /* hint: read-streamed */
+ pref 5, 0 (a0) /* hint: prepare-write */
+ addiu t0, t0, -1 /* batches-- */
+
+ lbu t1, 0 (a1) /* [__ __ __ R1] */
+ lbu t2, 1 (a1) /* [__ __ __ G1] */
+ lbu t3, 2 (a1) /* [__ __ __ B1] */
+
+ lbu t4, 3 (a1) /* [__ __ __ r2] */
+ lbu t5, 4 (a1) /* [__ __ __ g2] */
+ lbu t6, 5 (a1) /* [__ __ __ b2] */
+
+ lbu s1, 6 (a1) /* [__ __ __ R3] */
+ lbu s2, 7 (a1) /* [__ __ __ G3] */
+ lbu s3, 8 (a1) /* [__ __ __ B3] */
+
+ lbu s0, 9 (a1) /* [__ __ __ r4] */
+ lbu v0, 10 (a1) /* [__ __ __ g4] */
+ lbu v1, 11 (a1) /* [__ __ __ b4] */
+
+ append t1, t2, 8 /* [__ __ R1 G1] */
+ append t4, t5, 8 /* [__ __ r2 g2] */
+ append s1, s2, 8 /* [__ __ R3 G3] */
+ append s0, v0, 8 /* [__ __ r4 g4] */
+ append t1, t3, 8 /* [__ R1 G1 B1] */
+ append t4, t6, 8 /* [__ r2 g2 b2] */
+ append s1, s3, 8 /* [__ R3 G4 B3] */
+ append s0, v1, 8 /* [__ r4 g4 b4] */
+ or t1, t1, t7 /* [FF R1 G1 B1] */
+ or t4, t4, t7 /* [FF r2 g2 b2] */
+ or s1, s1, t7 /* [FF R3 G3 B3] */
+ or s0, s0, t7 /* [FF r4 g4 b4] */
+
+ sw t1, 0 (a0)
+ sw t4, 4 (a0)
+ sw s1, 8 (a0)
+ sw s0, 12 (a0)
+
+ addiu a1, a1, 12 /* src += 4*3 */
+ bnez t0, 1b /* if batches: loop */
+ addiu a0, a0, 16 /* dst += 4 */
+
+ RESTORE_REGS_FROM_STACK 8, s1, s2, s3, s0, v0, v1
+
+ /* handle remaining "tail" (a2) items */
+5: beqz a2, 0f
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+1: lbu t1, 0 (a1) /* [__ __ __ RR] */
+ lbu t2, 1 (a1) /* [__ __ __ GG] */
+ lbu t3, 2 (a1) /* [__ __ __ BB] */
+ sll t1, t1, 16 /* [__ RR __ __] */
+ sll t2, t2, 8 /* [__ __ GG __] */
+ or t0, t0, t1 /* [FF RR __ __] */
+ or t2, t2, t3 /* [__ __ GG BB] */
+ addi a2, a2, -1 /* len-- */
+ or t0, t0, t2 /* [FF RR GG BB] */
+ addiu a1, a1, 3 /* src += 3 */
+ sw t0, 0 (a0)
+ addiu a0, a0, 4 /* dst++ */
+ bnez a2, 1b /* if tail: loop */
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+0: jr ra
+ nop
+
+END(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 091837b8b4..49370bb31c 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -125,7 +125,6 @@
#include <qimageiohandler.h>
#include <qlist.h>
#include <qrect.h>
-#include <qset.h>
#include <qsize.h>
#include <qcolor.h>
#include <qvariant.h>
@@ -1444,11 +1443,11 @@ QByteArray QImageReader::imageFormat(QIODevice *device)
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
#endif
/*!
@@ -1481,7 +1480,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QList<QByteArray> QImageReader::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
for (int i = 0; i < _qt_NumFormats; ++i)
formats << _qt_BuiltInFormats[i].extension;
@@ -1489,12 +1488,9 @@ QList<QByteArray> QImageReader::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanRead, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -1508,7 +1504,7 @@ QList<QByteArray> QImageReader::supportedImageFormats()
QList<QByteArray> QImageReader::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
for (int i = 0; i < _qt_NumFormats; ++i)
mimeTypes << _qt_BuiltInFormats[i].mimeType;
@@ -1516,12 +1512,9 @@ QList<QByteArray> QImageReader::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanRead, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index c12dbb6544..7b8af90357 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -678,7 +678,7 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
typedef QMultiMap<int, QString> PluginKeyMap;
typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
@@ -687,6 +687,7 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
const PluginKeyMapConstIterator cend = keyMap.constEnd();
int i = -1;
QImageIOPlugin *plugin = 0;
+ result->reserve(result->size() + keyMap.size());
for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) {
if (it.key() != i) {
i = it.key();
@@ -694,13 +695,13 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
}
const QByteArray key = it.value().toLatin1();
if (plugin && (plugin->capabilities(0, key) & cap) != 0)
- result->insert(key);
+ result->append(key);
}
}
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
QList<QJsonObject> metaDataList = loader->metaData();
@@ -713,7 +714,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
const int keyCount = keys.size();
for (int k = 0; k < keyCount; ++k) {
if (plugin && (plugin->capabilities(0, keys.at(k).toString().toLatin1()) & cap) != 0)
- result->insert(mimeTypes.at(k).toString().toLatin1());
+ result->append(mimeTypes.at(k).toString().toLatin1());
}
}
}
@@ -746,7 +747,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
*/
QList<QByteArray> QImageWriter::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
#ifndef QT_NO_IMAGEFORMAT_BMP
formats << "bmp";
#endif
@@ -770,12 +771,9 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanWrite, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -788,7 +786,7 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
*/
QList<QByteArray> QImageWriter::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
#ifndef QT_NO_IMAGEFORMAT_BMP
mimeTypes << "image/bmp";
#endif
@@ -814,12 +812,9 @@ QList<QByteArray> QImageWriter::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanWrite, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 5008b1982b..dfacf34097 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -856,6 +856,7 @@ bool QJpegHandlerPrivate::read(QImage *image)
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len);
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len);
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uchar *src, int len);
QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this))
@@ -874,6 +875,9 @@ QJpegHandler::QJpegHandler()
rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3;
}
#endif // QT_COMPILER_SUPPORTS_SSSE3
+#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
+ rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_mips_dspr2_asm;
+#endif // QT_COMPILER_SUPPORTS_DSPR2
}
QJpegHandler::~QJpegHandler()
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index ec89b405b5..807746a26e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -118,7 +118,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
*/
const char *qt_mfhdr_tag = "QPIC"; // header tag
-static const quint16 mfhdr_maj = 11; // major version #
+static const quint16 mfhdr_maj = QDataStream::Qt_DefaultCompiledVersion; // major version #
static const quint16 mfhdr_min = 0; // minor version #
/*!
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index cadba26797..f82401c973 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -2,7 +2,6 @@
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles2):CONFIG += opengles2
-contains(QT_CONFIG, egl):CONFIG += egl
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index 265771ce1b..065cbb0e57 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -106,8 +106,6 @@ public:
OpenGLExtensions openGLExtensions();
bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const;
- void initializeGLExtensions();
-
GLvoid *glMapBuffer(GLenum target, GLenum access);
GLboolean glUnmapBuffer(GLenum target);
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index 72b6279b2f..adc81582e2 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -301,9 +301,8 @@ inline bool operator<(const RGBData &data, const char *name)
static bool get_named_rgb(const char *name_no_space, QRgb *rgb)
{
- QByteArray name = QByteArray(name_no_space).toLower();
- const RGBData *r = std::lower_bound(rgbTbl, rgbTbl + rgbTblSize, name.constData());
- if ((r != rgbTbl + rgbTblSize) && !(name.constData() < *r)) {
+ const RGBData *r = std::lower_bound(rgbTbl, rgbTbl + rgbTblSize, name_no_space);
+ if ((r != rgbTbl + rgbTblSize) && !(name_no_space < *r)) {
*rgb = r->value;
return true;
}
@@ -319,7 +318,7 @@ bool qt_get_named_rgb(const char *name, QRgb* rgb)
int pos = 0;
for(int i = 0; i < len; i++) {
if(name[i] != '\t' && name[i] != ' ')
- name_no_space[pos++] = name[i];
+ name_no_space[pos++] = QChar::toLower(name[i]);
}
name_no_space[pos] = 0;
@@ -334,7 +333,7 @@ bool qt_get_named_rgb(const QChar *name, int len, QRgb *rgb)
int pos = 0;
for(int i = 0; i < len; i++) {
if(name[i] != QLatin1Char('\t') && name[i] != QLatin1Char(' '))
- name_no_space[pos++] = name[i].toLatin1();
+ name_no_space[pos++] = name[i].toLower().toLatin1();
}
name_no_space[pos] = 0;
return get_named_rgb(name_no_space, rgb);
@@ -352,6 +351,7 @@ QStringList qt_get_colornames()
{
int i = 0;
QStringList lst;
+ lst.reserve(rgbTblSize);
for (i = 0; i < rgbTblSize; i++)
lst << QLatin1String(rgbTbl[i].name);
return lst;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index fe5fc051df..a3b1f07c69 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6416,6 +6416,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
continue;
+ multi->ensureEngineAt(which);
QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
ti2.width = 0;
// set the high byte to zero and calc the width
@@ -6443,6 +6444,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
which = e;
}
+ multi->ensureEngineAt(which);
QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
ti2.width = 0;
// set the high byte to zero and calc the width
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index aa2b9bea54..7a29bb87b4 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1644,7 +1644,8 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
if (count == 0)
return polys;
- QList<QRectF> bounds;
+ QVector<QRectF> bounds;
+ bounds.reserve(count);
for (int i=0; i<count; ++i)
bounds += subpaths.at(i).boundingRect();
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index c0b3769c2d..b661057f64 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -327,17 +327,29 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
QPen::QPen(const QPen &p)
{
d = p.d;
- d->ref.ref();
+ if (d)
+ d->ref.ref();
}
/*!
+ \fn QPen::QPen(QPen &&pen)
+ \since 5.4
+
+ Constructs a pen that is moved from the given \a pen.
+
+ The moved-from pen can only be assigned to, copied, or
+ destroyed. Any other operation (prior to assignment) leads to
+ undefined behavior.
+*/
+
+/*!
Destroys the pen.
*/
QPen::~QPen()
{
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
}
@@ -373,7 +385,7 @@ void QPen::detach()
QPen &QPen::operator=(const QPen &p)
{
- qAtomicAssign(d, p.d);
+ QPen(p).swap(*this);
return *this;
}
diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h
index c5144f784f..486f699476 100644
--- a/src/gui/painting/qpen.h
+++ b/src/gui/painting/qpen.h
@@ -72,6 +72,8 @@ public:
QPen &operator=(const QPen &pen);
#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPen(QPen &&other)
+ : d(other.d) { other.d = 0; }
inline QPen &operator=(QPen &&other)
{ qSwap(d, other.d); return *this; }
#endif
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index cf40dd028d..1797905e93 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2165,6 +2165,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->request.family.toLatin1();
} else {
s << font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2185,8 +2187,14 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
}
s << (quint8) font.d->request.styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s << (quint8) font.d->request.styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
+ // even though we need 16 to store styleStrategy, so there is some data loss.
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint16) font.d->request.styleStrategy;
+ else
+ s << (quint8) font.d->request.styleStrategy;
+ }
s << (quint8) 0
<< (quint8) font.d->request.weight
<< get_font_bits(s.version(), font.d.data());
@@ -2198,6 +2206,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->letterSpacing.value();
s << font.d->wordSpacing.value();
}
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint8)font.d->request.hintingPreference;
return s;
}
@@ -2215,7 +2225,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d = new QFontPrivate;
font.resolve_mask = QFont::AllPropertiesResolved;
- quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
+ quint8 styleHint, charSet, weight, bits;
+ quint16 styleStrategy = QFont::PreferDefault;
if (s.version() == 1) {
QByteArray fam;
@@ -2223,6 +2234,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.family = QString::fromLatin1(fam);
} else {
s >> font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s >> font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2242,8 +2255,15 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.pixelSize = pixelSize;
}
s >> styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s >> styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ if (s.version() >= QDataStream::Qt_5_4) {
+ s >> styleStrategy;
+ } else {
+ quint8 tempStyleStrategy;
+ s >> tempStyleStrategy;
+ styleStrategy = tempStyleStrategy;
+ }
+ }
s >> charSet;
s >> weight;
@@ -2273,6 +2293,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->wordSpacing.setValue(value);
}
+ if (s.version() >= QDataStream::Qt_5_4) {
+ quint8 value;
+ s >> value;
+ font.d->request.hintingPreference = QFont::HintingPreference(value);
+ }
return s;
}
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 4d8712e76e..be0402b95a 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -92,7 +92,7 @@ struct QFontDef
uint weight : 7; // 0-99
uint fixedPitch : 1;
uint style : 2;
- uint stretch : 12; // 0-400
+ uint stretch : 12; // 0-4000
uint hintingPreference : 2;
uint ignorePitch : 1;
diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp
index 10b4a2ee35..7170477e84 100644
--- a/src/gui/util/qgridlayoutengine.cpp
+++ b/src/gui/util/qgridlayoutengine.cpp
@@ -983,9 +983,10 @@ void QGridLayoutEngine::invalidate()
q_cachedEffectiveFirstRows[Ver] = -1;
q_cachedEffectiveLastRows[Hor] = -1;
q_cachedEffectiveLastRows[Ver] = -1;
- q_totalBoxesValid = false;
- q_sizeHintValid[Hor] = false;
- q_sizeHintValid[Ver] = false;
+
+ q_totalBoxCachedConstraints[Hor] = NotCached;
+ q_totalBoxCachedConstraints[Ver] = NotCached;
+
q_cachedSize = QSizeF();
q_cachedConstraintOrientation = UnknownConstraint;
}
@@ -1530,7 +1531,11 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri
const QAbstractLayoutStyleInfo *styleInfo) const
{
const int o = (orientation == Qt::Vertical ? Ver : Hor);
- if (q_sizeHintValid[o] && !colPositions && !colSizes) {
+ const int cc = columnCount(orientation);
+
+ const qreal constraint = (colPositions && colSizes && hasDynamicConstraint()) ? (colPositions[cc - 1] + colSizes[cc - 1]) : qreal(CachedWithNoConstraint);
+ qreal &cachedConstraint = q_totalBoxCachedConstraints[o];
+ if (cachedConstraint == constraint) {
if (totalBox != &q_totalBoxes[o])
*totalBox = q_totalBoxes[o];
return;
@@ -1541,10 +1546,10 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri
rowData->distributeMultiCells(rowInfo);
*totalBox = rowData->totalBox(0, rowCount(orientation));
- if (!colPositions && !colSizes) {
+ if (totalBox != &q_totalBoxes[o])
q_totalBoxes[o] = *totalBox;
- q_sizeHintValid[o] = true;
- }
+
+ cachedConstraint = constraint;
}
/**
@@ -1593,10 +1598,9 @@ Qt::Orientation QGridLayoutEngine::constraintOrientation() const
void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
const QAbstractLayoutStyleInfo *styleInfo) const
{
- if (!styleInfo->hasChanged() && q_totalBoxesValid && q_cachedSize == size)
+ if (!styleInfo->hasChanged() && q_cachedSize == size)
return;
- q_totalBoxesValid = true;
q_cachedSize = size;
q_xx.resize(columnCount());
@@ -1606,7 +1610,7 @@ void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
q_descents.resize(rowCount());
if (constraintOrientation() != Qt::Horizontal) {
- //We might have items whose width depends on their height
+ //We might have items whose height depends on their width (HFW)
ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], NULL, NULL, Qt::Horizontal, styleInfo);
//Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
//constraints to find the row heights
@@ -1617,7 +1621,7 @@ void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]);
} else {
- //We have items whose height depends on their width
+ //We have items whose width depends on their height (WFH)
ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], NULL, NULL, Qt::Vertical, styleInfo);
//Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
//constraints to find the column widths
diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h
index 9650e7fffe..bbc94bd51f 100644
--- a/src/gui/util/qgridlayoutengine_p.h
+++ b/src/gui/util/qgridlayoutengine_p.h
@@ -450,15 +450,21 @@ private:
mutable int q_cachedEffectiveLastRows[NOrientations];
mutable quint8 q_cachedConstraintOrientation : 3;
+ // this is useful to cache
+ mutable QGridLayoutBox q_totalBoxes[NOrientations];
+ enum {
+ NotCached = -2, // Cache is empty. Happens when the engine is invalidated.
+ CachedWithNoConstraint = -1 // cache has a totalBox without any HFW/WFH constraints.
+ // >= 0 // cache has a totalBox with this specific constraint.
+ };
+ mutable qreal q_totalBoxCachedConstraints[NOrientations]; // holds the constraint used for the cached totalBox
+
// Layout item input
mutable QGridLayoutRowData q_columnData;
mutable QGridLayoutRowData q_rowData;
- mutable QGridLayoutBox q_totalBoxes[NOrientations];
// Output
mutable QSizeF q_cachedSize;
- mutable bool q_totalBoxesValid;
- mutable bool q_sizeHintValid[NOrientations];
mutable QVector<qreal> q_xx;
mutable QVector<qreal> q_yy;
mutable QVector<qreal> q_widths;
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 32b6d902d0..accad6e4c0 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -1203,7 +1203,7 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16
: QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt, connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = networkSession;
+ d->networkSession = qMove(networkSession);
d->init();
}
@@ -1215,7 +1215,7 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS
connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = networkSession;
+ d->networkSession = qMove(networkSession);
d->init();
}
#else
@@ -1339,7 +1339,7 @@ QSharedPointer<QSslContext> QHttpNetworkConnection::sslContext()
void QHttpNetworkConnection::setSslContext(QSharedPointer<QSslContext> context)
{
Q_D(QHttpNetworkConnection);
- d->sslContext = context;
+ d->sslContext = qMove(context);
}
void QHttpNetworkConnection::ignoreSslErrors(int channel)
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index e03dcb8ead..7b5ad1e2f1 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -188,7 +188,7 @@ public:
QHttpNetworkConnection::ConnectionType connectionType,
QSharedPointer<QNetworkSession> networkSession)
: QHttpNetworkConnection(hostName, port, encrypt, connectionType, /*parent=*/0,
- networkSession)
+ qMove(networkSession))
#endif
{
setExpires(true);
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 3c5e1e80a8..f387559cb3 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -130,9 +130,9 @@ QStringList QNetworkAccessManagerPrivate::backendSupportedSchemes() const
QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
{
if (reply->outgoingDataBuffer)
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(reply->outgoingDataBuffer);
else if (reply->outgoingData) {
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(reply->outgoingData));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(reply->outgoingData);
} else {
return 0;
}
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index f043307c10..f56c77505a 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -194,7 +194,7 @@ QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manage
if (d->synchronous && outgoingData) {
// The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer.
// Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway.
- d->outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ d->outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
qint64 previousDataSize = 0;
do {
previousDataSize = d->outgoingDataBuffer->size();
@@ -440,8 +440,8 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
, downloadBufferReadPosition(0)
, downloadBufferCurrentSize(0)
, downloadZerocopyBuffer(0)
- , pendingDownloadDataEmissions(new QAtomicInt())
- , pendingDownloadProgressEmissions(new QAtomicInt())
+ , pendingDownloadDataEmissions(QSharedPointer<QAtomicInt>::create())
+ , pendingDownloadProgressEmissions(QSharedPointer<QAtomicInt>::create())
#ifndef QT_NO_SSL
, pendingIgnoreAllSslErrors(false)
#endif
@@ -1714,7 +1714,7 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
if (!outgoingDataBuffer) {
// first call, create our buffer
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
@@ -1843,9 +1843,9 @@ QNonContiguousByteDevice* QNetworkReplyHttpImplPrivate::createUploadByteDevice()
Q_Q(QNetworkReplyHttpImpl);
if (outgoingDataBuffer)
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingDataBuffer));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(outgoingDataBuffer);
else if (outgoingData) {
- uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingData));
+ uploadByteDevice = QNonContiguousByteDeviceFactory::createShared(outgoingData);
} else {
return 0;
}
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index f51b85cba0..616019ea41 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -248,7 +248,7 @@ void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
if (!outgoingDataBuffer) {
// first call, create our buffer
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
@@ -367,7 +367,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
// The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer.
// Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway.
if (synchronousHttpAttribute.toBool() && outgoingData) {
- outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
qint64 previousDataSize = 0;
do {
previousDataSize = outgoingDataBuffer->size();
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 6ee8b696df..0181b9965a 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -403,6 +403,9 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
}
int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
if (connectResult == -1) {
switch (errno) {
case EISCONN:
@@ -454,7 +457,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
addr.toString().toLatin1().constData(), port,
socketState == QAbstractSocket::ConnectingState
- ? "Connection in progress" : socketErrorString.toLatin1().constData());
+ ? "Connection in progress" : strerror(ecopy));
#endif
return false;
}
@@ -522,6 +525,9 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
}
if (bindResult < 0) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
switch(errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
@@ -541,7 +547,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
- address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
+ address.toString().toLatin1().constData(), port, strerror(ecopy));
#endif
return false;
@@ -561,6 +567,9 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
bool QNativeSocketEnginePrivate::nativeListen(int backlog)
{
if (qt_safe_listen(socketDescriptor, backlog) < 0) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int ecopy = errno;
+#endif
switch (errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError,
@@ -572,7 +581,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
- backlog, socketErrorString.toLatin1().constData());
+ backlog, strerror(ecopy));
#endif
return false;
}
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 14881931af..64b75f98ec 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -208,6 +208,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->localCertificateChain == other.d->localCertificateChain &&
d->privateKey == other.d->privateKey &&
d->sessionCipher == other.d->sessionCipher &&
+ d->sessionProtocol == other.d->sessionProtocol &&
d->ciphers == other.d->ciphers &&
d->caCertificates == other.d->caCertificates &&
d->protocol == other.d->protocol &&
@@ -512,6 +513,18 @@ QSslCipher QSslConfiguration::sessionCipher() const
}
/*!
+ Returns the socket's SSL/TLS protocol or UnknownProtocol if the
+ connection isn't encrypted. The socket's protocol for the session
+ is set during the handshake phase.
+
+ \sa protocol(), setProtocol()
+*/
+QSsl::SslProtocol QSslConfiguration::sessionProtocol() const
+{
+ return d->sessionProtocol;
+}
+
+/*!
Returns the \l {QSslKey} {SSL key} assigned to this connection or
a null key if none has been assigned yet.
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 587187ca06..4c5799bf28 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -109,6 +109,7 @@ public:
QSslCertificate peerCertificate() const;
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
// Private keys, for server sockets
QSslKey privateKey() const;
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index d183c3335c..29bd4053ad 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -81,7 +81,8 @@ class QSslConfigurationPrivate: public QSharedData
{
public:
QSslConfigurationPrivate()
- : protocol(QSsl::SecureProtocols),
+ : sessionProtocol(QSsl::UnknownProtocol),
+ protocol(QSsl::SecureProtocols),
peerVerifyMode(QSslSocket::AutoVerifyPeer),
peerVerifyDepth(0),
allowRootCertOnDemandLoading(true),
@@ -98,6 +99,7 @@ public:
QSslKey privateKey;
QSslCipher sessionCipher;
+ QSsl::SslProtocol sessionProtocol;
QList<QSslCipher> ciphers;
QList<QSslCertificate> caCertificates;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index c5ae517fb0..04c0fb0487 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -878,6 +878,7 @@ QSslConfiguration QSslSocket::sslConfiguration() const
QSslConfigurationPrivate *copy = new QSslConfigurationPrivate(d->configuration);
copy->ref.store(0); // the QSslConfiguration constructor refs up
copy->sessionCipher = d->sessionCipher();
+ copy->sessionProtocol = d->sessionProtocol();
return QSslConfiguration(copy);
}
@@ -1073,6 +1074,20 @@ QSslCipher QSslSocket::sessionCipher() const
}
/*!
+ Returns the socket's SSL/TLS protocol or UnknownProtocol if the
+ connection isn't encrypted. The socket's protocol for the session
+ is set during the handshake phase.
+
+ \sa protocol(), setProtocol()
+*/
+QSsl::SslProtocol QSslSocket::sessionProtocol() const
+{
+ Q_D(const QSslSocket);
+ return d->sessionProtocol();
+}
+
+
+/*!
Sets the socket's private \l {QSslKey} {key} to \a key. The
private key and the local \l {QSslCertificate} {certificate} are
used by clients and servers that must prove their identity to
@@ -1665,6 +1680,32 @@ QString QSslSocket::sslLibraryVersionString()
}
/*!
+ \since 5.4
+ Returns the version number of the SSL library in use at compile
+ time. If no SSL support is available then this will return an
+ undefined value.
+
+ \sa sslLibraryVersionNumber()
+*/
+long QSslSocket::sslLibraryBuildVersionNumber()
+{
+ return QSslSocketPrivate::sslLibraryBuildVersionNumber();
+}
+
+/*!
+ \since 5.4
+ Returns the version string of the SSL library in use at compile
+ time. If no SSL support is available then this will return an
+ empty value.
+
+ \sa sslLibraryVersionString()
+*/
+QString QSslSocket::sslLibraryBuildVersionString()
+{
+ return QSslSocketPrivate::sslLibraryBuildVersionString();
+}
+
+/*!
Starts a delayed SSL handshake for a client connection. This
function can be called when the socket is in the \l ConnectedState
but still in the \l UnencryptedMode. If it is not yet connected,
@@ -2095,6 +2136,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->localCertificateChain = global->localCertificateChain;
ptr->privateKey = global->privateKey;
ptr->sessionCipher = global->sessionCipher;
+ ptr->sessionProtocol = global->sessionProtocol;
ptr->ciphers = global->ciphers;
ptr->caCertificates = global->caCertificates;
ptr->protocol = global->protocol;
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index d89933efda..9cc5e02de3 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -140,6 +140,7 @@ public:
QSslCertificate peerCertificate() const;
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
// Private keys, for server sockets.
void setPrivateKey(const QSslKey &key);
@@ -182,6 +183,8 @@ public:
static bool supportsSsl();
static long sslLibraryVersionNumber();
static QString sslLibraryVersionString();
+ static long sslLibraryBuildVersionNumber();
+ static QString sslLibraryBuildVersionString();
void ignoreSslErrors(const QList<QSslError> &errors);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 1b3928fdfb..52d8577abe 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -587,6 +587,16 @@ QString QSslSocketPrivate::sslLibraryVersionString()
return QString::fromLatin1(versionString);
}
+long QSslSocketPrivate::sslLibraryBuildVersionNumber()
+{
+ return OPENSSL_VERSION_NUMBER;
+}
+
+QString QSslSocketPrivate::sslLibraryBuildVersionString()
+{
+ return QLatin1String(OPENSSL_VERSION_TEXT);
+}
+
/*!
\internal
@@ -1431,6 +1441,28 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
}
+QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
+{
+ if (!ssl)
+ return QSsl::UnknownProtocol;
+ int ver = q_SSL_version(ssl);
+
+ switch (ver) {
+ case 0x2:
+ return QSsl::SslV2;
+ case 0x300:
+ return QSsl::SslV3;
+ case 0x301:
+ return QSsl::TlsV1_0;
+ case 0x302:
+ return QSsl::TlsV1_1;
+ case 0x303:
+ return QSsl::TlsV1_2;
+ }
+
+ return QSsl::UnknownProtocol;
+}
+
void QSslSocketBackendPrivate::continueHandshake()
{
Q_Q(QSslSocket);
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index c8b23e6cad..0a9d02287d 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -131,6 +131,7 @@ public:
void disconnectFromHost();
void disconnected();
QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
void continueHandshake();
bool checkSslErrors();
#ifdef Q_OS_WIN
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 01c0f6f810..65f186b9e9 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -238,6 +238,7 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, retu
#else
DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
#endif
+DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
@@ -744,6 +745,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_free)
RESOLVEFUNC(SSL_get_ciphers)
RESOLVEFUNC(SSL_get_current_cipher)
+ RESOLVEFUNC(SSL_version)
RESOLVEFUNC(SSL_get_error)
RESOLVEFUNC(SSL_get_peer_cert_chain)
RESOLVEFUNC(SSL_get_peer_certificate)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 1e68fdd6c2..70d4c25456 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -329,6 +329,7 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
#else
SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
#endif
+int q_SSL_version(const SSL *a);
int q_SSL_get_error(SSL *a, int b);
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
X509 *q_SSL_get_peer_certificate(SSL *a);
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 6281753225..0033a46d98 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -129,6 +129,8 @@ public:
static bool supportsSsl();
static long sslLibraryVersionNumber();
static QString sslLibraryVersionString();
+ static long sslLibraryBuildVersionNumber();
+ static QString sslLibraryBuildVersionString();
static void ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
@@ -190,6 +192,7 @@ public:
virtual void disconnectFromHost() = 0;
virtual void disconnected() = 0;
virtual QSslCipher sessionCipher() const = 0;
+ virtual QSsl::SslProtocol sessionProtocol() const = 0;
virtual void continueHandshake() = 0;
Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported();
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 5cd553a5e8..5fef609a2a 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -12,7 +12,6 @@ load(qt_module)
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles2):CONFIG += opengles2
-contains(QT_CONFIG, egl):CONFIG += egl
HEADERS += qgl.h \
qgl_p.h \
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
index b48f993436..820c433a2c 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
@@ -189,7 +189,8 @@ QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const
enum ResourceType {
EglDisplay,
EglWindow,
- EglContext
+ EglContext,
+ NativeDisplay
};
static int resourceType(const QByteArray &key)
@@ -197,7 +198,8 @@ static int resourceType(const QByteArray &key)
static const QByteArray names[] = { // match ResourceType
QByteArrayLiteral("egldisplay"),
QByteArrayLiteral("eglwindow"),
- QByteArrayLiteral("eglcontext")
+ QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("nativedisplay")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@@ -214,6 +216,9 @@ void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &re
case EglDisplay:
result = m_screen->display();
break;
+ case NativeDisplay:
+ result = reinterpret_cast<void*>(nativeDisplay());
+ break;
default:
break;
}
diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp
index 37d16ddeb6..a962a5eb59 100644
--- a/src/platformsupport/fbconvenience/qfbscreen.cpp
+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp
@@ -196,13 +196,13 @@ void QFbScreen::generateRects()
remainingScreen -= localGeometry;
QRegion windowRegion(localGeometry);
windowRegion -= remainingScreen;
- foreach (QRect rect, windowRegion.rects()) {
+ foreach (const QRect &rect, windowRegion.rects()) {
mCachedRects += QPair<QRect, int>(rect, i);
}
}
#endif
}
- foreach (QRect rect, remainingScreen.rects())
+ foreach (const QRect &rect, remainingScreen.rects())
mCachedRects += QPair<QRect, int>(rect, -1);
mIsUpToDate = true;
return;
@@ -242,7 +242,7 @@ QRegion QFbScreen::doRedraw()
rectRegion -= intersect;
// we only expect one rectangle, but defensive coding...
- foreach (QRect rect, intersect.rects()) {
+ foreach (const QRect &rect, intersect.rects()) {
bool firstLayer = true;
if (layer == -1) {
mCompositePainter->fillRect(rect, Qt::black);
diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h
index dd940c4a1d..924b49afda 100644
--- a/src/platformsupport/fbconvenience/qfbscreen_p.h
+++ b/src/platformsupport/fbconvenience/qfbscreen_p.h
@@ -108,7 +108,7 @@ private:
void generateRects();
QPainter *mCompositePainter;
- QList<QPair<QRect, int> > mCachedRects;
+ QVector<QPair<QRect, int> > mCachedRects;
QList <QFbBackingStore*> mBackingStores;
friend class QFbWindow;
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 92f807095f..611a7f9d6d 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -60,6 +60,8 @@
//#define QT_QPA_MOUSE_HANDLER_DEBUG
+#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8)))
+
QT_BEGIN_NAMESPACE
QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification)
@@ -71,6 +73,7 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
bool compression = true;
int jitterLimit = 0;
int grab = 0;
+ bool abs = false;
QStringList args = specification.split(QLatin1Char(':'));
foreach (const QString &arg, args) {
@@ -80,27 +83,37 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
jitterLimit = arg.mid(9).toInt();
else if (arg.startsWith(QLatin1String("grab=")))
grab = arg.mid(5).toInt();
+ else if (arg == QLatin1String("abs"))
+ abs = true;
}
int fd;
fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (fd >= 0) {
::ioctl(fd, EVIOCGRAB, grab);
- return new QEvdevMouseHandler(device, fd, compression, jitterLimit);
+ return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit);
} else {
qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno));
return 0;
}
}
-QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit)
+QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit)
: m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0),
- m_compression(compression), m_buttons(0), m_prevInvalid(true)
+ m_abs(abs), m_compression(compression), m_buttons(0), m_prevInvalid(true)
{
setObjectName(QLatin1String("Evdev Mouse Handler"));
m_jitterLimitSquared = jitterLimit * jitterLimit;
+ // Some touch screens present as mice with absolute coordinates.
+ // These can not be differentiated from touchpads, so supplying abs to QT_QPA_EVDEV_MOUSE_PARAMETERS
+ // will force qevdevmousehandler to treat the coordinates as absolute, scaled to the hardware maximums.
+ // Turning this on will not affect mice as these do not report in absolute coordinates
+ // but will make touchpads act like touch screens
+ if (m_abs)
+ m_abs = getHardwareMaximum();
+
// socket notifier for events on the mouse device
QSocketNotifier *notifier;
notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
@@ -113,16 +126,66 @@ QEvdevMouseHandler::~QEvdevMouseHandler()
qt_safe_close(m_fd);
}
+// Ask touch screen hardware for information on coordinate maximums
+// If any ioctls fail, revert to non abs mode
+bool QEvdevMouseHandler::getHardwareMaximum()
+{
+ unsigned char absFeatures[(ABS_MAX / 8) + 1];
+ memset(absFeatures, '\0', sizeof (absFeatures));
+
+ // test if ABS_X, ABS_Y are available
+ if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof (absFeatures)), absFeatures) == -1)
+ return false;
+
+ if ((!TEST_BIT(absFeatures, ABS_X)) || (!TEST_BIT(absFeatures, ABS_Y)))
+ return false;
+
+ // ask hardware for minimum and maximum values
+ struct input_absinfo absInfo;
+ if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) == -1)
+ return false;
+
+ m_hardwareWidth = absInfo.maximum - absInfo.minimum;
+
+ if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) == -1)
+ return false;
+
+ m_hardwareHeight = absInfo.maximum - absInfo.minimum;
+
+ QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
+ m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left());
+ m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top());
+
+#ifdef QT_QPA_MOUSE_HANDLER_DEBUG
+ qDebug() << "Absolute pointing device";
+ qDebug() << "hardware max x" << m_hardwareWidth;
+ qDebug() << "hardware max y" << m_hardwareHeight;
+ qDebug() << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY;
+#endif
+
+ return true;
+}
+
void QEvdevMouseHandler::sendMouseEvent()
{
- int x = m_x - m_prevx;
- int y = m_y - m_prevy;
+ int x;
+ int y;
+
+ if (!m_abs) {
+ x = m_x - m_prevx;
+ y = m_y - m_prevy;
+ }
+ else {
+ x = m_x / m_hardwareScalerX;
+ y = m_y / m_hardwareScalerY;
+ }
+
if (m_prevInvalid) {
x = y = 0;
m_prevInvalid = false;
}
- emit handleMouseEvent(x, y, m_buttons);
+ emit handleMouseEvent(x, y, m_abs, m_buttons);
m_prevx = m_x;
m_prevy = m_y;
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
index d419a1913e..027d2862b0 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
@@ -57,26 +57,32 @@ public:
~QEvdevMouseHandler();
signals:
- void handleMouseEvent(int x, int y, Qt::MouseButtons buttons);
+ void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
void handleWheelEvent(int delta, Qt::Orientation orientation);
private slots:
void readMouseData();
private:
- QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit);
+ QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit);
void sendMouseEvent();
+ bool getHardwareMaximum();
QString m_device;
int m_fd;
QSocketNotifier *m_notify;
int m_x, m_y;
int m_prevx, m_prevy;
+ bool m_abs;
bool m_compression;
Qt::MouseButtons m_buttons;
int m_jitterLimitSquared;
bool m_prevInvalid;
+ int m_hardwareWidth;
+ int m_hardwareHeight;
+ qreal m_hardwareScalerY;
+ qreal m_hardwareScalerX;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
index 6c430091c1..7b834a5c61 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
@@ -111,11 +111,16 @@ QEvdevMouseManager::~QEvdevMouseManager()
m_mice.clear();
}
-void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons)
+void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons)
{
// update current absolute coordinates
- m_x += x;
- m_y += y;
+ if (!abs) {
+ m_x += x;
+ m_y += y;
+ } else {
+ m_x = x;
+ m_y = y;
+ }
// clamp to screen geometry
QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
@@ -156,7 +161,7 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode)
QEvdevMouseHandler *handler;
handler = QEvdevMouseHandler::create(deviceNode, m_spec);
if (handler) {
- connect(handler, SIGNAL(handleMouseEvent(int,int,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,Qt::MouseButtons)));
+ connect(handler, SIGNAL(handleMouseEvent(int,int,bool,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,bool,Qt::MouseButtons)));
connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation)));
m_mice.insert(deviceNode, handler);
} else {
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index d52a16ea75..5280b5efbd 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -62,7 +62,7 @@ public:
QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; }
public slots:
- void handleMouseEvent(int x, int y, Qt::MouseButtons buttons);
+ void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
void handleWheelEvent(int delta, Qt::Orientation orientation);
private slots:
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index 18915f8e08..7bdd586a1f 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -84,8 +84,14 @@ void DBusConnection::serviceRegistered()
QDBusConnection c = QDBusConnection::sessionBus();
OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(A11Y_SERVICE, A11Y_PATH, c, this);
+ //The variable was introduced because on some embedded platforms there are custom accessibility
+ //clients which don't set Status.ScreenReaderEnabled to true. The variable is also useful for
+ //debugging.
+ static const bool a11yAlwaysOn = !qEnvironmentVariableIsSet("QT_LINUX_ACCESSIBILITY_ALWAYS_ON");
+
// a11yStatus->isEnabled() returns always true (since Gnome 3.6)
- bool enabled = a11yStatus->screenReaderEnabled();
+ bool enabled = a11yAlwaysOn || a11yStatus->screenReaderEnabled();
+
if (enabled != m_enabled) {
m_enabled = enabled;
if (m_a11yConnection.isConnected()) {
diff --git a/src/plugins/accessible/accessible.pro b/src/plugins/accessible/accessible.pro
deleted file mode 100644
index 26c7d3066d..0000000000
--- a/src/plugins/accessible/accessible.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = subdirs
-
-contains(QT_CONFIG, accessibility) {
- SUBDIRS += widgets
-}
diff --git a/src/plugins/accessible/widgets/widgets.json b/src/plugins/accessible/widgets/widgets.json
deleted file mode 100644
index 9ebcc89d35..0000000000
--- a/src/plugins/accessible/widgets/widgets.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "Keys": [
- "QLineEdit",
- "QComboBox",
- "QAbstractSpinBox",
- "QSpinBox",
- "QDoubleSpinBox",
- "QScrollBar",
- "QSlider",
- "QAbstractSlider",
- "QToolButton",
- "QCheckBox",
- "QRadioButton",
- "QPushButton",
- "QAbstractButton",
- "QDialog",
- "QMessageBox",
- "QMainWindow",
- "QLabel",
- "QLCDNumber",
- "QGroupBox",
- "QStatusBar",
- "QProgressBar",
- "QPlainTextEdit",
- "QMenuBar",
- "QMenu",
- "QTabBar",
- "QToolBar",
- "QSizeGrip",
- "QListView",
- "QTreeView",
- "QTableView",
- "QWidget",
- "QSplitter",
- "QSplitterHandle",
- "QTextEdit",
- "QTipLabel",
- "QFrame",
- "QStackedWidget",
- "QToolBox",
- "QMdiArea",
- "QMdiSubWindow",
- "QDialogButtonBox",
- "QDial",
- "QRubberBand",
- "QTextBrowser",
- "QAbstractScrollArea",
- "QScrollArea",
- "QCalendarWidget",
- "QDockWidget",
- "QDesktopScreenWidget",
- "QWindowContainer"
- ]
-}
diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp
index 797c30c7c6..0903496472 100644
--- a/src/plugins/bearer/connman/qconnmanengine.cpp
+++ b/src/plugins/bearer/connman/qconnmanengine.cpp
@@ -189,7 +189,20 @@ void QConnmanEngine::connectToId(const QString &id)
if (!serv->isValid()) {
emit connectionError(id, QBearerEngineImpl::InterfaceLookupError);
} else {
- serv->connect();
+ if (serv->type() == QLatin1String("cellular")) {
+ if (serv->roaming()) {
+ if (!isRoamingAllowed(serv->path())) {
+ emit connectionError(id, QBearerEngineImpl::OperationNotSupported);
+ return;
+ }
+ if (isAlwaysAskRoaming()) {
+ emit connectionError(id, QBearerEngineImpl::OperationNotSupported);
+ return;
+ }
+ }
+ }
+ if (serv->autoConnect())
+ serv->connect();
}
}
diff --git a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
index dbc79c178b..9c67a38c57 100644
--- a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
+++ b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
@@ -35,6 +35,11 @@
<method name="GetEngine">
<arg name="desc" direction="out" type="v"/>
</method>
+ <method name="SetSurroundingText">
+ <arg name="text" direction="in" type="v"/>
+ <arg name="cursor_pos" direction="in" type="u"/>
+ <arg name="anchor_pos" direction="in" type="u"/>
+ </method>
<method name="Destroy"/>
<signal name="CommitText">
<arg name="text" type="v"/>
@@ -75,6 +80,11 @@
<signal name="UpdateProperty">
<arg name="prop" type="v"/>
</signal>
+ <signal name="RequireSurroundingText"/>
+ <signal name="DeleteSurroundingText">
+ <arg name="offset" type="i"/>
+ <arg name="n_chars" type="u"/>
+ </signal>
</interface>
</node>
diff --git a/src/plugins/platforminputcontexts/ibus/main.cpp b/src/plugins/platforminputcontexts/ibus/main.cpp
index d7c34ee9b3..e33c328b9e 100644
--- a/src/plugins/platforminputcontexts/ibus/main.cpp
+++ b/src/plugins/platforminputcontexts/ibus/main.cpp
@@ -41,7 +41,9 @@
#include <qpa/qplatforminputcontextplugin_p.h>
#include <QtCore/QStringList>
+#include <QDBusMetaType>
#include "qibusplatforminputcontext.h"
+#include "qibustypes.h"
QT_BEGIN_NAMESPACE
@@ -58,8 +60,13 @@ QIBusPlatformInputContext *QIbusPlatformInputContextPlugin::create(const QString
{
Q_UNUSED(paramList);
- if (system.compare(system, QStringLiteral("ibus"), Qt::CaseInsensitive) == 0)
+ if (system.compare(system, QStringLiteral("ibus"), Qt::CaseInsensitive) == 0) {
+ qDBusRegisterMetaType<QIBusSerializable>();
+ qDBusRegisterMetaType<QIBusAttribute>();
+ qDBusRegisterMetaType<QIBusAttributeList>();
+ qDBusRegisterMetaType<QIBusText>();
return new QIBusPlatformInputContext;
+ }
return 0;
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
index 8df88b339b..454a1e6fda 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.cpp
@@ -1,5 +1,5 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusinputcontextproxy -c QIBusInputContextProxy interfaces/org.freedesktop.IBus.InputContext.xml
*
* qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
diff --git a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
index b1e33a3ecd..b75a5e0a93 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
@@ -1,5 +1,5 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusinputcontextproxy -c QIBusInputContextProxy interfaces/org.freedesktop.IBus.InputContext.xml
*
* qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
@@ -8,8 +8,8 @@
* Do not edit! All changes made to it will be lost.
*/
-#ifndef QIBUSINPUTCONTEXTPROXY_H_1308831153
-#define QIBUSINPUTCONTEXTPROXY_H_1308831153
+#ifndef QIBUSINPUTCONTEXTPROXY_H_1394889529
+#define QIBUSINPUTCONTEXTPROXY_H_1394889529
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -119,10 +119,18 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("SetEngine"), argumentList);
}
+ inline QDBusPendingReply<> SetSurroundingText(const QDBusVariant &text, uint cursor_pos, uint anchor_pos)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor_pos) << QVariant::fromValue(anchor_pos);
+ return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
+ }
+
Q_SIGNALS: // SIGNALS
void CommitText(const QDBusVariant &text);
void CursorDownLookupTable();
void CursorUpLookupTable();
+ void DeleteSurroundingText(int offset, uint n_chars);
void Disabled();
void Enabled();
void ForwardKeyEvent(uint keyval, uint keycode, uint state);
@@ -132,6 +140,7 @@ Q_SIGNALS: // SIGNALS
void PageDownLookupTable();
void PageUpLookupTable();
void RegisterProperties(const QDBusVariant &props);
+ void RequireSurroundingText();
void ShowAuxiliaryText();
void ShowLookupTable();
void ShowPreeditText();
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 53e9b171d5..be90bbecb0 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -43,6 +43,7 @@
#include <QtDebug>
#include <QTextCharFormat>
#include <QGuiApplication>
+#include <QDBusVariant>
#include <qwindow.h>
#include <qevent.h>
@@ -78,6 +79,7 @@ public:
bool valid;
QString predit;
+ bool needsSurroundingText;
};
@@ -87,6 +89,8 @@ QIBusPlatformInputContext::QIBusPlatformInputContext ()
if (d->context) {
connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant)));
connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool)));
+ connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
+ connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired()));
}
QInputMethod *p = qApp->inputMethod();
connect(p, SIGNAL(cursorRectangleChanged()), this, SLOT(cursorRectChanged()));
@@ -146,6 +150,33 @@ void QIBusPlatformInputContext::commit()
void QIBusPlatformInputContext::update(Qt::InputMethodQueries q)
{
+ QObject *input = qApp->focusObject();
+
+ if (d->needsSurroundingText && input
+ && (q.testFlag(Qt::ImSurroundingText)
+ || q.testFlag(Qt::ImCursorPosition)
+ || q.testFlag(Qt::ImAnchorPosition))) {
+ QInputMethodQueryEvent srrndTextQuery(Qt::ImSurroundingText);
+ QInputMethodQueryEvent cursorPosQuery(Qt::ImCursorPosition);
+ QInputMethodQueryEvent anchorPosQuery(Qt::ImAnchorPosition);
+
+ QCoreApplication::sendEvent(input, &srrndTextQuery);
+ QCoreApplication::sendEvent(input, &cursorPosQuery);
+ QCoreApplication::sendEvent(input, &anchorPosQuery);
+
+ QString surroundingText = srrndTextQuery.value(Qt::ImSurroundingText).toString();
+ uint cursorPosition = cursorPosQuery.value(Qt::ImCursorPosition).toUInt();
+ uint anchorPosition = anchorPosQuery.value(Qt::ImAnchorPosition).toUInt();
+
+ QIBusText text;
+ text.text = surroundingText;
+
+ QVariant variant;
+ variant.setValue(text);
+ QDBusVariant dbusText(variant);
+
+ d->context->SetSurroundingText(dbusText, cursorPosition, anchorPosition);
+ }
QPlatformInputContext::update(q);
}
@@ -191,7 +222,7 @@ void QIBusPlatformInputContext::commitText(const QDBusVariant &text)
QIBusText t;
if (debug)
qDebug() << arg.currentSignature();
- t.fromDBusArgument(arg);
+ arg >> t;
if (debug)
qDebug() << "commit text:" << t.text;
@@ -211,7 +242,7 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
const QDBusArgument arg = text.variant().value<QDBusArgument>();
QIBusText t;
- t.fromDBusArgument(arg);
+ arg >> t;
if (debug)
qDebug() << "preedit text:" << t.text;
@@ -225,6 +256,27 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
d->predit = t.text;
}
+void QIBusPlatformInputContext::surroundingTextRequired()
+{
+ if (debug)
+ qDebug() << "surroundingTextRequired";
+ d->needsSurroundingText = true;
+ update(Qt::ImSurroundingText);
+}
+
+void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars)
+{
+ QObject *input = qApp->focusObject();
+ if (!input)
+ return;
+
+ if (debug)
+ qDebug() << "deleteSurroundingText" << offset << n_chars;
+
+ QInputMethodEvent event;
+ event.setCommitString("", offset, n_chars);
+ QCoreApplication::sendEvent(input, &event);
+}
bool
QIBusPlatformInputContext::x11FilterEvent(uint keyval, uint keycode, uint state, bool press)
@@ -250,7 +302,8 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
: connection(createConnection()),
bus(0),
context(0),
- valid(false)
+ valid(false),
+ needsSurroundingText(false)
{
if (!connection || !connection->isConnected())
return;
@@ -284,7 +337,7 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
IBUS_CAP_PROPERTY = 1 << 4,
IBUS_CAP_SURROUNDING_TEXT = 1 << 5
};
- context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS);
+ context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS|IBUS_CAP_SURROUNDING_TEXT);
if (debug)
qDebug(">>>> valid!");
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 400ef3914a..a9e9ac18f9 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -69,6 +69,8 @@ public Q_SLOTS:
void commitText(const QDBusVariant &text);
void updatePreeditText(const QDBusVariant &text, uint cursor_pos, bool visible);
void cursorRectChanged();
+ void deleteSurroundingText(int offset, uint n_chars);
+ void surroundingTextRequired();
private:
QIBusPlatformInputContextPrivate *d;
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
index 6ab0b1ae3e..5fa0c9ef67 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
@@ -42,6 +42,7 @@
#include "qibustypes.h"
#include <qtextformat.h>
#include <QtDBus>
+#include <QHash>
QT_BEGIN_NAMESPACE
@@ -53,23 +54,45 @@ QIBusSerializable::~QIBusSerializable()
{
}
-void QIBusSerializable::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusSerializable &object)
{
- arg >> name;
- arg.beginMap();
- while (!arg.atEnd()) {
- arg.beginMapEntry();
+ argument >> object.name;
+
+ argument.beginMap();
+ while (!argument.atEnd()) {
+ argument.beginMapEntry();
QString key;
QDBusVariant value;
- arg >> key;
- arg >> value;
- arg.endMapEntry();
- attachments[key] = value.variant().value<QDBusArgument>();
+ argument >> key;
+ argument >> value;
+ argument.endMapEntry();
+ object.attachments[key] = value.variant().value<QDBusArgument>();
}
- arg.endMap();
+ argument.endMap();
+ return argument;
}
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusSerializable &object)
+{
+ argument << object.name;
+
+ argument.beginMap(qMetaTypeId<QString>(), qMetaTypeId<QDBusVariant>());
+
+ QHashIterator<QString, QDBusArgument> i(object.attachments);
+ while (i.hasNext()) {
+ i.next();
+ argument.beginMapEntry();
+ argument << i.key();
+
+ QDBusVariant variant(i.value().asVariant());
+
+ argument << variant;
+ argument.endMapEntry();
+ }
+ argument.endMap();
+ return argument;
+}
QIBusAttribute::QIBusAttribute()
: type(Invalid),
@@ -77,28 +100,46 @@ QIBusAttribute::QIBusAttribute()
start(0),
end(0)
{
+ name = "IBusAttribute";
}
QIBusAttribute::~QIBusAttribute()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttribute &attribute)
+{
+ argument.beginStructure();
+
+ argument << static_cast<const QIBusSerializable &>(attribute);
+
+ quint32 t = (quint32) attribute.type;
+ argument << t;
+ argument << attribute.value;
+ argument << attribute.start;
+ argument << attribute.end;
+ argument.endStructure();
+
+ return argument;
}
-void QIBusAttribute::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusAttribute &attribute)
{
-// qDebug() << "QIBusAttribute::fromDBusArgument()" << arg.currentSignature();
- arg.beginStructure();
+ argument.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ argument >> static_cast<QIBusSerializable &>(attribute);
quint32 t;
- arg >> t;
- type = (Type)t;
- arg >> value;
- arg >> start;
- arg >> end;
+ argument >> t;
+ attribute.type = (QIBusAttribute::Type) t;
+ argument >> attribute.value;
+ argument >> attribute.start;
+ argument >> attribute.end;
- arg.endStructure();
+ argument.endStructure();
+
+ return argument;
}
QTextFormat QIBusAttribute::format() const
@@ -141,36 +182,53 @@ QTextFormat QIBusAttribute::format() const
return fmt;
}
-
QIBusAttributeList::QIBusAttributeList()
{
-
+ name = "IBusAttrList";
}
QIBusAttributeList::~QIBusAttributeList()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttributeList &attrList)
+{
+ argument.beginStructure();
+ argument << static_cast<const QIBusSerializable &>(attrList);
+
+ argument.beginArray(qMetaTypeId<QDBusVariant>());
+ for (int i = 0; i < attrList.attributes.size(); ++i) {
+ QVariant variant;
+ variant.setValue(attrList.attributes.at(i));
+ argument << QDBusVariant (variant);
+ }
+ argument.endArray();
+
+ argument.endStructure();
+ return argument;
}
-void QIBusAttributeList::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &attrList)
{
// qDebug() << "QIBusAttributeList::fromDBusArgument()" << arg.currentSignature();
arg.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ arg >> static_cast<QIBusSerializable &>(attrList);
arg.beginArray();
- while(!arg.atEnd()) {
+ while (!arg.atEnd()) {
QDBusVariant var;
arg >> var;
QIBusAttribute attr;
- attr.fromDBusArgument(var.variant().value<QDBusArgument>());
- attributes.append(attr);
+ var.variant().value<QDBusArgument>() >> attr;
+ attrList.attributes.append(attr);
}
arg.endArray();
arg.endStructure();
+ return arg;
}
QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
@@ -183,30 +241,40 @@ QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
return imAttrs;
}
-
QIBusText::QIBusText()
{
-
+ name = "IBusText";
}
QIBusText::~QIBusText()
{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text)
+{
+ argument.beginStructure();
+
+ argument << static_cast<const QIBusSerializable &>(text);
+ argument << text.text << text.attributes;
+ argument.endStructure();
+ return argument;
}
-void QIBusText::fromDBusArgument(const QDBusArgument &arg)
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text)
{
// qDebug() << "QIBusText::fromDBusArgument()" << arg.currentSignature();
- arg.beginStructure();
+ argument.beginStructure();
- QIBusSerializable::fromDBusArgument(arg);
+ argument >> static_cast<QIBusSerializable &>(text);
- arg >> text;
+ argument >> text.text;
QDBusVariant variant;
- arg >> variant;
- attributes.fromDBusArgument(variant.variant().value<QDBusArgument>());
+ argument >> variant;
+ variant.variant().value<QDBusArgument>() >> text.attributes;
- arg.endStructure();
+ argument.endStructure();
+ return argument;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.h b/src/plugins/platforminputcontexts/ibus/qibustypes.h
index 8e6f853a52..0275c5eed2 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.h
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.h
@@ -43,19 +43,16 @@
#include <qvector.h>
#include <qevent.h>
+#include <QDBusArgument>
QT_BEGIN_NAMESPACE
-class QDBusArgument;
-
class QIBusSerializable
{
public:
QIBusSerializable();
virtual ~QIBusSerializable();
- virtual void fromDBusArgument(const QDBusArgument &arg);
-
QString name;
QHash<QString, QDBusArgument> attachments;
};
@@ -81,7 +78,6 @@ public:
QIBusAttribute();
~QIBusAttribute();
- void fromDBusArgument(const QDBusArgument &arg);
QTextFormat format() const;
Type type;
@@ -96,8 +92,6 @@ public:
QIBusAttributeList();
~QIBusAttributeList();
- void fromDBusArgument(const QDBusArgument &arg);
-
QList<QInputMethodEvent::Attribute> imAttributes() const;
QVector<QIBusAttribute> attributes;
@@ -109,12 +103,27 @@ public:
QIBusText();
~QIBusText();
- void fromDBusArgument(const QDBusArgument &arg);
-
QString text;
QIBusAttributeList attributes;
};
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusSerializable &object);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusSerializable &object);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttribute &attribute);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusAttribute &attribute);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttributeList &attributeList);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &attrList);
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text);
+
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QIBusSerializable)
+Q_DECLARE_METATYPE(QIBusAttribute)
+Q_DECLARE_METATYPE(QIBusAttributeList)
+Q_DECLARE_METATYPE(QIBusText)
+
#endif
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 6462cb8d3e..a74a7efb41 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -412,9 +412,17 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
&& (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
style |= CS_DROPSHADOW;
}
- if (type == Qt::Tool || type == Qt::ToolTip || type == Qt::Popup) {
+ switch (type) {
+ case Qt::Tool:
+ case Qt::ToolTip:
+ case Qt::Popup:
style |= CS_SAVEBITS; // Save/restore background
icon = false;
+ break;
+ case Qt::Dialog:
+ if (!(flags & Qt::WindowSystemMenuHint))
+ icon = false; // QTBUG-2027, dialogs without system menu.
+ break;
}
// Create a unique name for the flag combination
QString cname = QStringLiteral("Qt5QWindow");
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index ee9bf9936c..00229a7540 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -110,6 +110,8 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_CONTEXTHELP";
if (exStyle & WS_EX_LAYERED)
rc += " WS_EX_LAYERED";
+ if (exStyle & WS_EX_DLGMODALFRAME)
+ rc += " WS_EX_DLGMODALFRAME";
return rc;
}
@@ -513,6 +515,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
+ else if (dialog) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
+ }
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton(w, flags))
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index e7f8510706..3b30274f25 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -135,9 +135,10 @@ protected:
(void)formats(); // trigger update of format list
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
int size = format_atoms.size() / sizeof(xcb_atom_t);
+ atoms.reserve(size);
for (int i = 0; i < size; ++i)
atoms.append(targets[i]);
@@ -524,7 +525,7 @@ xcb_atom_t QXcbClipboard::sendTargetsSelection(QMimeData *d, xcb_window_t window
QVector<xcb_atom_t> types;
QStringList formats = QInternalMimeData::formatsHelper(d);
for (int i = 0; i < formats.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!types.contains(atoms.at(j)))
types.append(atoms.at(j));
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index a994c51c7d..c5fe2e33d5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -445,6 +445,7 @@ public:
void setFocusWindow(QXcbWindow *);
QByteArray startupId() const { return m_startupId; }
+ void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
void clearStartupId() { m_startupId.clear(); }
void grabServer();
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 4f0f57c375..bcadcd1f02 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -183,7 +183,7 @@ void QXcbDrag::startDrag()
QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!drag_types.contains(atoms.at(j)))
drag_types.append(atoms.at(j));
@@ -1211,7 +1211,7 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r
return result;
}
- QList<xcb_atom_t> atoms = drag->xdnd_types;
+ QVector<xcb_atom_t> atoms = drag->xdnd_types;
QByteArray encoding;
xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);
if (a == XCB_NONE)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index d94c42696f..7b0d337e7c 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -46,7 +46,6 @@
#include <private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
-#include <qlist.h>
#include <qpoint.h>
#include <qrect.h>
#include <qsharedpointer.h>
@@ -127,7 +126,7 @@ private:
// the types in this drop. 100 is no good, but at least it's big.
enum { xdnd_max_type = 100 };
- QList<xcb_atom_t> xdnd_types;
+ QVector<xcb_atom_t> xdnd_types;
// timestamp from XdndPosition and XdndDroptime for retrieving the data
xcb_timestamp_t target_time;
@@ -160,7 +159,7 @@ private:
QPointer<QDrag> drag;
QTime time;
};
- QList<Transaction> transactions;
+ QVector<Transaction> transactions;
int transaction_expiry_timer;
void restartDropExpiryTimer();
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index b205a63267..c0f6745e7f 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -136,9 +136,10 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
return ret;
}
-QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
+QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
{
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
+ atoms.reserve(7);
atoms.append(connection->internAtom(format.toLatin1()));
// special cases for strings
@@ -240,7 +241,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
}
xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
{
requestedEncoding->clear();
diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h
index 4a69a35ced..563716a75b 100644
--- a/src/plugins/platforms/xcb/qxcbmime.h
+++ b/src/plugins/platforms/xcb/qxcbmime.h
@@ -59,14 +59,14 @@ public:
QXcbMime();
~QXcbMime();
- static QList<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
+ static QVector<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
static QString mimeAtomToString(QXcbConnection *connection, xcb_atom_t a);
static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
xcb_atom_t *atomFormat, int *dataFormat);
static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
QVariant::Type requestedType, const QByteArray &encoding);
static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
};
#endif // !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index b45bd6a82e..37936a9c72 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -225,6 +225,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
return result;
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "setstartupid")
+ return NativeResourceForIntegrationFunction(setStartupId);
+ return 0;
+}
+
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
{
const QByteArray lowerCaseResource = resource.toLower();
@@ -287,6 +295,15 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
}
+void QXcbNativeInterface::setStartupId(const char *data)
+{
+ QByteArray startupId(data);
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QXcbConnection *defaultConnection = integration->defaultConnection();
+ if (defaultConnection)
+ defaultConnection->setStartupId(startupId);
+}
+
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
{
QByteArray lowerCaseResource = resource.toLower();
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index fb1a46014c..cf26aff011 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -77,11 +77,12 @@ public:
QXcbNativeInterface();
void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
- void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
+ void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE;
inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
@@ -96,6 +97,7 @@ public:
void *startupId();
void *x11Screen();
void *rootWindow();
+ static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);
static void *eglContextForContext(QOpenGLContext *context);
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 141a6cc0cb..17b40a45e1 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -42,6 +42,7 @@
#include "qxcbxsettings.h"
#include <QtCore/QByteArray>
+#include <QtCore/QtEndian>
#include <X11/extensions/XIproto.h>
@@ -149,47 +150,67 @@ public:
{
if (xSettings.length() < 12)
return;
- // we ignore byteorder for now
- char byteOrder = xSettings.at(1);
- Q_UNUSED(byteOrder);
- uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
+ char byteOrder = xSettings.at(0);
+ if (byteOrder != LSBFirst && byteOrder != MSBFirst) {
+ qWarning("%s ByteOrder byte %d not 0 or 1", Q_FUNC_INFO , byteOrder);
+ return;
+ }
+
+#define ADJUST_BO(b, t, x) \
+ ((b == LSBFirst) ? \
+ qFromLittleEndian<t>((const uchar *)(x)) : \
+ qFromBigEndian<t>((const uchar *)(x)))
+#define VALIDATE_LENGTH(x) \
+ if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
+ qWarning("%s Length %d runs past end of data", Q_FUNC_INFO , x); \
+ return; \
+ }
+ uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
const char *data = xSettings.constData() + 12;
size_t offset = 0;
for (uint i = 0; i < number_of_settings; i++) {
int local_offset = 0;
+ VALIDATE_LENGTH(2);
XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
local_offset += 2;
- quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2);
+ quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
+ VALIDATE_LENGTH(name_len);
QByteArray name(data + offset + local_offset, name_len);
local_offset += round_to_nearest_multiple_of_4(name_len);
- int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
Q_UNUSED(last_change_serial);
local_offset += 4;
QVariant value;
if (type == XSettingsTypeString) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset+=4;
+ VALIDATE_LENGTH(value_length);
QByteArray value_string(data + offset + local_offset, value_length);
value.setValue(value_string);
local_offset += round_to_nearest_multiple_of_4(value_length);
} else if (type == XSettingsTypeInteger) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset += 4;
value.setValue(value_length);
} else if (type == XSettingsTypeColor) {
- quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2*4);
+ quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
QColor color_value(red,green,blue,alpha);
value.setValue(color_value);
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 942db329ca..d1cbff59c1 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -3,6 +3,5 @@ TEMPLATE = subdirs
SUBDIRS *= sqldrivers
!winrt:qtHaveModule(network): SUBDIRS += bearer
qtHaveModule(gui): SUBDIRS *= imageformats platforms platforminputcontexts platformthemes generic
-qtHaveModule(widgets): SUBDIRS += accessible
!winrt:!wince*:qtHaveModule(widgets):SUBDIRS += printsupport
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index c6e3ddb54d..3a92f9b6db 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -67,61 +67,49 @@ void QCUPSSupport::setCupsOption(QStringList &cupsOptions, const QString &option
}
}
-void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
+static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, const QTime holdUntilTime)
{
- QStringList cupsOptions = cupsOptionsList(printer);
-
switch (jobHold) {
- case NoHold: //default
- break;
- case Indefinite:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("indefinite"));
- break;
- case DayTime:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("day-time"));
- break;
- case Night:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("night"));
- break;
- case SecondShift:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("second-shift"));
- break;
- case ThirdShift:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("third-shift"));
- break;
- case Weekend:
- setCupsOption(cupsOptions,
- QStringLiteral("job-hold-until"),
- QStringLiteral("weekend"));
- break;
- case SpecificTime:
- if (holdUntilTime.isNull()) {
- setJobHold(printer, NoHold);
- return;
+ case QCUPSSupport::Indefinite:
+ return QStringLiteral("indefinite");
+ case QCUPSSupport::DayTime:
+ return QStringLiteral("day-time");
+ case QCUPSSupport::Night:
+ return QStringLiteral("night");
+ case QCUPSSupport::SecondShift:
+ return QStringLiteral("second-shift");
+ case QCUPSSupport::ThirdShift:
+ return QStringLiteral("third-shift");
+ case QCUPSSupport::Weekend:
+ return QStringLiteral("weekend");
+ case QCUPSSupport::SpecificTime:
+ if (!holdUntilTime.isNull()) {
+ // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
+ QDateTime localDateTime = QDateTime::currentDateTime();
+ // Check if time is for tomorrow in case of DST change overnight
+ if (holdUntilTime < localDateTime.time())
+ localDateTime = localDateTime.addDays(1);
+ localDateTime.setTime(holdUntilTime);
+ return localDateTime.toUTC().time().toString(QStringLiteral("HH:mm"));
}
- // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
- QDateTime localDateTime = QDateTime::currentDateTime();
- // Check if time is for tomorrow in case of DST change overnight
- if (holdUntilTime < localDateTime.time())
- localDateTime = localDateTime.addDays(1);
- localDateTime.setTime(holdUntilTime);
+ // else fall through:
+ case QCUPSSupport::NoHold:
+ return QString();
+ }
+ Q_UNREACHABLE();
+ return QString();
+}
+
+void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
+{
+ const QString jobHoldUntilArgument = jobHoldToString(jobHold, holdUntilTime);
+ if (!jobHoldUntilArgument.isEmpty()) {
+ QStringList cupsOptions = cupsOptionsList(printer);
setCupsOption(cupsOptions,
QStringLiteral("job-hold-until"),
- localDateTime.toUTC().time().toString(QStringLiteral("HH:mm")));
- break;
+ jobHoldUntilArgument);
+ setCupsOptions(printer, cupsOptions);
}
-
- setCupsOptions(printer, cupsOptions);
}
void QCUPSSupport::setJobBilling(QPrinter *printer, const QString &jobBilling)
@@ -138,58 +126,26 @@ void QCUPSSupport::setJobPriority(QPrinter *printer, int priority)
setCupsOptions(printer, cupsOptions);
}
-void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage)
+static inline QString bannerPageToString(const QCUPSSupport::BannerPage bannerPage)
{
- QStringList cupsOptions = cupsOptionsList(printer);
- QString startBanner, endBanner;
-
- switch (startBannerPage) {
- case NoBanner:
- startBanner = QStringLiteral("none");
- break;
- case Standard:
- startBanner = QStringLiteral("standard");
- break;
- case Unclassified:
- startBanner = QStringLiteral("unclassified");
- break;
- case Confidential:
- startBanner = QStringLiteral("confidential");
- break;
- case Classified:
- startBanner = QStringLiteral("classified");
- break;
- case Secret:
- startBanner = QStringLiteral("secret");
- break;
- case TopSecret:
- startBanner = QStringLiteral("topsecret");
- break;
+ switch (bannerPage) {
+ case QCUPSSupport::NoBanner: return QStringLiteral("none");
+ case QCUPSSupport::Standard: return QStringLiteral("standard");
+ case QCUPSSupport::Unclassified: return QStringLiteral("unclassified");
+ case QCUPSSupport::Confidential: return QStringLiteral("confidential");
+ case QCUPSSupport::Classified: return QStringLiteral("classified");
+ case QCUPSSupport::Secret: return QStringLiteral("secret");
+ case QCUPSSupport::TopSecret: return QStringLiteral("topsecret");
}
+ Q_UNREACHABLE();
+ return QString();
+};
- switch (endBannerPage) {
- case NoBanner:
- endBanner = QStringLiteral("none");
- break;
- case Standard:
- endBanner = QStringLiteral("standard");
- break;
- case Unclassified:
- endBanner = QStringLiteral("unclassified");
- break;
- case Confidential:
- endBanner = QStringLiteral("confidential");
- break;
- case Classified:
- endBanner = QStringLiteral("classified");
- break;
- case Secret:
- endBanner = QStringLiteral("secret");
- break;
- case TopSecret:
- endBanner = QStringLiteral("topsecret");
- break;
- }
+void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage)
+{
+ QStringList cupsOptions = cupsOptionsList(printer);
+ const QString startBanner = bannerPageToString(startBannerPage);
+ const QString endBanner = bannerPageToString(endBannerPage);
setCupsOption(cupsOptions, QStringLiteral("job-sheets"), startBanner + QLatin1Char(',') + endBanner);
setCupsOptions(printer, cupsOptions);
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 39580f22d4..774f2cc4fb 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -51,21 +51,29 @@
#include <stdlib.h>
#include <string.h>
-#ifdef Q_OS_WIN
-#include <windows.h>
-#endif
-
#ifdef Q_OS_WINCE
#include <QtCore/QString>
#endif
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
#include <QtCore/QByteArray>
#include <QtCore/qmath.h>
+#include <QtCore/QLibraryInfo>
#ifdef Q_OS_ANDROID
# include <android/log.h>
#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QTest {
@@ -334,7 +342,7 @@ void QPlainTestLogger::startLogging()
qsnprintf(buf, sizeof(buf),
"********* Start testing of %s *********\n"
"Config: Using QtTest library " QTEST_VERSION_STR
- ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion());
+ ", %s\n", QTestResult::currentTestObjectName(), QLibraryInfo::build());
}
outputMessage(buf);
}
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp
index 3fff753c5c..5ea28bd46d 100644
--- a/src/testlib/qxmltestlogger.cpp
+++ b/src/testlib/qxmltestlogger.cpp
@@ -42,6 +42,7 @@
#include <stdio.h>
#include <string.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qlibraryinfo.h>
#include <QtTest/private/qxmltestlogger_p.h>
#include <QtTest/private/qtestresult_p.h>
@@ -115,11 +116,15 @@ void QXmlTestLogger::startLogging()
outputString(buf.constData());
}
+ QTestCharBuffer quotedBuild;
+ xmlQuote(&quotedBuild, QLibraryInfo::build());
+
QTest::qt_asprintf(&buf,
"<Environment>\n"
" <QtVersion>%s</QtVersion>\n"
+ " <QtBuild>%s</QtBuild>\n"
" <QTestVersion>" QTEST_VERSION_STR "</QTestVersion>\n"
- "</Environment>\n", qVersion());
+ "</Environment>\n", qVersion(), quotedBuild.constData());
outputString(buf.constData());
m_totalTime.start();
}
diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp
index a47f77ae49..fe5b13eeeb 100644
--- a/src/testlib/qxunittestlogger.cpp
+++ b/src/testlib/qxunittestlogger.cpp
@@ -46,6 +46,15 @@
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qbenchmark_p.h>
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
+#include <QtCore/qlibraryinfo.h>
+
#include <string.h>
QT_BEGIN_NAMESPACE
@@ -108,6 +117,11 @@ void QXunitTestLogger::stopLogging()
property->addAttribute(QTest::AI_PropertyValue, qVersion());
properties->addLogElement(property);
+ property = new QTestElement(QTest::LET_Property);
+ property->addAttribute(QTest::AI_Name, "QtBuild");
+ property->addAttribute(QTest::AI_PropertyValue, QLibraryInfo::build());
+ properties->addLogElement(property);
+
currentLogElement->addLogElement(properties);
currentLogElement->addLogElement(iterator);
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index fea4e2519f..630a8c985f 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -61,6 +61,7 @@ SOURCES += \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
../../corelib/io/qdatastream.cpp \
+ ../../corelib/io/qdebug.cpp \
../../corelib/io/qdir.cpp \
../../corelib/io/qdiriterator.cpp \
../../corelib/io/qfile.cpp \
diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp
index 99f2abfb2f..ec342c6df0 100644
--- a/src/tools/qdoc/codemarker.cpp
+++ b/src/tools/qdoc/codemarker.cpp
@@ -648,7 +648,7 @@ QString CodeMarker::macName(const Node *node, const QString &name)
/*!
Returns an empty list of documentation sections.
*/
-QList<Section> CodeMarker::qmlSections(const QmlClassNode* , SynopsisStyle )
+QList<Section> CodeMarker::qmlSections(QmlClassNode* , SynopsisStyle )
{
return QList<Section>();
}
diff --git a/src/tools/qdoc/codemarker.h b/src/tools/qdoc/codemarker.h
index 02caedf9b8..aa38b82e24 100644
--- a/src/tools/qdoc/codemarker.h
+++ b/src/tools/qdoc/codemarker.h
@@ -54,7 +54,6 @@
QT_BEGIN_NAMESPACE
class Config;
-class Tree;
typedef QMultiMap<QString, Node*> MemberMap; // the string is the member signature
typedef QPair<const QmlClassNode*, MemberMap> ClassMap; // the node is the QML type
@@ -155,7 +154,7 @@ public:
virtual QList<Section> sections(const InnerNode *inner,
SynopsisStyle style,
Status status) = 0;
- virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
+ virtual QList<Section> qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style);
virtual QStringList macRefsForNode(Node* node);
static void initialize(const Config& config);
diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp
index a0ea561b28..e25056e353 100644
--- a/src/tools/qdoc/codeparser.cpp
+++ b/src/tools/qdoc/codeparser.cpp
@@ -76,7 +76,6 @@ QT_BEGIN_NAMESPACE
QString CodeParser::currentSubDir_;
QList<CodeParser *> CodeParser::parsers;
bool CodeParser::showInternal = false;
-QMap<QString,QString> CodeParser::nameToTitle;
/*!
The constructor adds this code parser to the static
@@ -300,50 +299,30 @@ void CodeParser::processCommonMetaCommand(const Location& location,
else if (command == COMMAND_PAGEKEYWORDS) {
node->addPageKeywords(arg.first);
}
- else if (command == COMMAND_SUBTITLE) {
- if (node->type() == Node::Document) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setSubTitle(arg.first);
- }
- else
- location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
- }
else if (command == COMMAND_THREADSAFE) {
node->setThreadSafeness(Node::ThreadSafe);
}
else if (command == COMMAND_TITLE) {
- if (node->type() == Node::Document) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setTitle(arg.first);
- if (dn->subType() == Node::Example) {
- ExampleNode::exampleNodeMap.insert(dn->title(),static_cast<ExampleNode*>(dn));
- }
- nameToTitle.insert(dn->name(),arg.first);
- }
- else
- location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE));
+ node->setTitle(arg.first);
+ if (!node->isDocNode() && !node->isCollectionNode())
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
+ else if (node->isExample())
+ qdb_->addExampleNode(static_cast<ExampleNode*>(node));
+ }
+ else if (command == COMMAND_SUBTITLE) {
+ node->setSubTitle(arg.first);
+ if (!node->isDocNode() && !node->isCollectionNode())
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
}
else if (command == COMMAND_QTVARIABLE) {
- if (node->subType() == Node::Module) {
- DocNode *dn = static_cast<DocNode *>(node);
- dn->setQtVariable(arg.first);
- }
- else
- location.warning(tr("Command '\\%1' found outside of '\\module'. It can only be used within a module page.")
+ node->setQtVariable(arg.first);
+ if (!node->isModule() && !node->isQmlModule())
+ location.warning(tr("Command '\\%1' is only meanigfule in '\\module' and '\\qmlmodule'.")
.arg(COMMAND_QTVARIABLE));
}
}
/*!
- Find the page title given the page \a name and return it.
- */
-const QString CodeParser::titleFromName(const QString& name)
-{
- const QString t = nameToTitle.value(name);
- return t;
-}
-
-/*!
\internal
*/
void CodeParser::extractPageLinkAndDesc(const QString& arg,
@@ -412,9 +391,9 @@ bool CodeParser::isParsingQdoc() const
for an entity that will produce a documentation page will contain an
\inmodule command to tell qdoc which module the entity belongs to.
- But now that we normally run qdoc on each module in two passes. The
- first produces an index file; the second pass generates the docs
- after reading all the index files it needs.
+ But now we normally run qdoc on each module in two passes. The first
+ produces an index file; the second pass generates the docs after
+ reading all the index files it needs.
This means that all the pages generated during each pass 2 run of
qdoc almost certainly belong to a single module, and the name of
@@ -431,10 +410,10 @@ bool CodeParser::isParsingQdoc() const
void CodeParser::checkModuleInclusion(Node* n)
{
if (n->moduleName().isEmpty()) {
+ n->setModuleName(Generator::defaultModuleName());
switch (n->type()) {
case Node::Class:
if (n->access() != Node::Private && !n->doc().isEmpty()) {
- n->setModuleName(Generator::defaultModuleName());
n->doc().location().warning(tr("Class %1 has no \\inmodule command; "
"using project name by default: %2")
.arg(n->name()).arg(Generator::defaultModuleName()));
@@ -442,16 +421,15 @@ void CodeParser::checkModuleInclusion(Node* n)
break;
case Node::Namespace:
if (n->access() != Node::Private && !n->name().isEmpty() && !n->doc().isEmpty()) {
- n->setModuleName(Generator::defaultModuleName());
n->doc().location().warning(tr("Namespace %1 has no \\inmodule command; "
"using project name by default: %2")
.arg(n->name()).arg(Generator::defaultModuleName()));
}
break;
+#if 0
case Node::Document:
if (n->access() != Node::Private && !n->doc().isEmpty()) {
if (n->subType() == Node::HeaderFile) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Header file with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -459,7 +437,6 @@ void CodeParser::checkModuleInclusion(Node* n)
#endif
}
else if (n->subType() == Node::Page) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Page with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -467,7 +444,6 @@ void CodeParser::checkModuleInclusion(Node* n)
#endif
}
else if (n->subType() == Node::Example) {
- n->setModuleName(Generator::defaultModuleName());
#if 0
n->doc().location().warning(tr("Example with title \"%1\" has no \\inmodule command; "
"using project name by default: %2")
@@ -476,6 +452,7 @@ void CodeParser::checkModuleInclusion(Node* n)
}
}
break;
+#endif
default:
break;
}
diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h
index 89f661abeb..baa82fc650 100644
--- a/src/tools/qdoc/codeparser.h
+++ b/src/tools/qdoc/codeparser.h
@@ -81,7 +81,6 @@ public:
static CodeParser *parserForLanguage(const QString& language);
static CodeParser *parserForHeaderFile(const QString &filePath);
static CodeParser *parserForSourceFile(const QString &filePath);
- static const QString titleFromName(const QString& name);
static void setLink(Node* node, Node::LinkType linkType, const QString& arg);
static const QString& currentOutputSubdirectory() { return currentSubDir_; }
@@ -101,7 +100,6 @@ private:
static QString currentSubDir_;
static QList<CodeParser *> parsers;
static bool showInternal;
- static QMap<QString,QString> nameToTitle;
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp
index 56e7287c40..185c1c77f1 100644
--- a/src/tools/qdoc/config.cpp
+++ b/src/tools/qdoc/config.cpp
@@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
QString ConfigStrings::ALIAS = QStringLiteral("alias");
+QString ConfigStrings::AUTOLINKERRORS = QStringLiteral("autolinkerrors");
QString ConfigStrings::BASE = QStringLiteral("base");
QString ConfigStrings::BASEDIR = QStringLiteral("basedir");
QString ConfigStrings::BUILDVERSION = QStringLiteral("buildversion");
@@ -242,6 +243,7 @@ QStringList MetaStack::getExpanded(const Location& location)
}
QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String(".");
+bool Config::debug_ = false;
bool Config::generateExamples = true;
QString Config::overrideOutputDir;
QString Config::installDir;
diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h
index 54ee8de47f..ebe7956907 100644
--- a/src/tools/qdoc/config.h
+++ b/src/tools/qdoc/config.h
@@ -88,6 +88,8 @@ public:
Config(const QString& programName);
~Config();
+ static bool debug_;
+
void load(const QString& fileName);
void setStringList(const QString& var, const QStringList& values);
@@ -167,6 +169,7 @@ private:
struct ConfigStrings
{
static QString ALIAS;
+ static QString AUTOLINKERRORS;
static QString BASE;
static QString BASEDIR;
static QString BUILDVERSION;
@@ -239,6 +242,7 @@ struct ConfigStrings
};
#define CONFIG_ALIAS ConfigStrings::ALIAS
+#define CONFIG_AUTOLINKERRORS ConfigStrings::AUTOLINKERRORS
#define CONFIG_BASE ConfigStrings::BASE
#define CONFIG_BASEDIR ConfigStrings::BASEDIR
#define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION
diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp
index 64b11109f7..4690f6b212 100644
--- a/src/tools/qdoc/cppcodemarker.cpp
+++ b/src/tools/qdoc/cppcodemarker.cpp
@@ -629,7 +629,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
@@ -724,7 +725,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
@@ -1066,7 +1068,7 @@ QString CppCodeMarker::addMarkUp(const QString &in,
the list of documentation sections for the children of the
\a qmlClassNode.
*/
-QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style)
+QList<Section> CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style)
{
QList<Section> sections;
if (qmlClassNode) {
@@ -1107,7 +1109,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
"method",
"methods");
- const QmlClassNode* qcn = qmlClassNode;
+ QmlClassNode* qcn = qmlClassNode;
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
@@ -1146,7 +1148,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
++c;
}
if (qcn->qmlBaseNode() != 0) {
- qcn = static_cast<const QmlClassNode*>(qcn->qmlBaseNode());
+ qcn = static_cast<QmlClassNode*>(qcn->qmlBaseNode());
if (!qcn->isAbstract())
qcn = 0;
}
@@ -1172,7 +1174,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
FastSection qmlmethods(qmlClassNode,"Method Documentation","qmlmeth","member","members");
FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation","qmlattmeth",
"member","members");
- const QmlClassNode* qcn = qmlClassNode;
+ QmlClassNode* qcn = qmlClassNode;
while (qcn != 0) {
NodeList::ConstIterator c = qcn->childNodes().constBegin();
while (c != qcn->childNodes().constEnd()) {
@@ -1210,7 +1212,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
++c;
}
if (qcn->qmlBaseNode() != 0) {
- qcn = static_cast<const QmlClassNode*>(qcn->qmlBaseNode());
+ qcn = static_cast<QmlClassNode*>(qcn->qmlBaseNode());
if (!qcn->isAbstract())
qcn = 0;
}
@@ -1232,7 +1234,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, Syno
*/
ClassMap* classMap = 0;
FastSection all(qmlClassNode,QString(),QString(),"member","members");
- const QmlClassNode* current = qmlClassNode;
+ QmlClassNode* current = qmlClassNode;
while (current != 0) {
/*
If the QML type is abstract, do not create
diff --git a/src/tools/qdoc/cppcodemarker.h b/src/tools/qdoc/cppcodemarker.h
index 91a9c01a28..74faf1ca57 100644
--- a/src/tools/qdoc/cppcodemarker.h
+++ b/src/tools/qdoc/cppcodemarker.h
@@ -78,7 +78,7 @@ public:
virtual QList<Section> sections(const InnerNode *innerNode,
SynopsisStyle style,
Status status);
- virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
+ virtual QList<Section> qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style);
private:
QString addMarkUp(const QString& protectedCode,
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index bb403bd4d9..6603ba6385 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -52,6 +52,7 @@
#include "tokenizer.h"
#include "qdocdatabase.h"
#include <qdebug.h>
+#include "generator.h"
QT_BEGIN_NAMESPACE
@@ -173,7 +174,7 @@ void CppCodeParser::parseHeaderFile(const Location& location, const QString& fil
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
readToken();
- matchDeclList(qdb_->treeRoot());
+ matchDeclList(qdb_->primaryTreeRoot());
if (!fileTokenizer.version().isEmpty())
qdb_->setVersion(fileTokenizer.version());
in.close();
@@ -218,15 +219,13 @@ void CppCodeParser::parseSourceFile(const Location& location, const QString& fil
}
/*!
- This is called after all the header files have been parsed.
- I think the most important thing it does is resolve class
- inheritance links in the tree. But it also initializes a
- bunch of stuff.
+ This is called after all the C++ header files have been
+ parsed. The most important thing it does is resolve C++
+ class inheritance links in the tree. It also initializes
+ a bunch of other collections.
*/
void CppCodeParser::doneParsingHeaderFiles()
{
- qdb_->resolveInheritance();
-
QMapIterator<QString, QString> i(sequentialIteratorClasses);
while (i.hasNext()) {
i.next();
@@ -265,11 +264,10 @@ void CppCodeParser::doneParsingHeaderFiles()
*/
void CppCodeParser::doneParsingSourceFiles()
{
- qdb_->treeRoot()->clearCurrentChildPointers();
- qdb_->treeRoot()->normalizeOverloads();
+ qdb_->primaryTreeRoot()->normalizeOverloads();
qdb_->fixInheritance();
qdb_->resolveProperties();
- qdb_->treeRoot()->makeUndocumentedChildrenInternal();
+ qdb_->primaryTreeRoot()->makeUndocumentedChildrenInternal();
}
static QSet<QString> topicCommands_;
@@ -328,38 +326,33 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
}
else {
- func = qdb_->findNodeInOpenNamespace(parentPath, clone);
- /*
- Search the root namespace if no match was found.
- */
+ func = qdb_->findFunctionNode(parentPath, clone);
if (func == 0) {
- func = qdb_->findFunctionNode(parentPath, clone);
+ if (parentPath.isEmpty() && !lastPath_.isEmpty())
+ func = qdb_->findFunctionNode(lastPath_, clone);
}
+ /*
+ If the node was not found, then search for it in the
+ open C++ namespaces. We don't expect this search to
+ be necessary often. Nor do we expect it to succeed
+ very often.
+ */
+ if (func == 0)
+ func = qdb_->findNodeInOpenNamespace(parentPath, clone);
+
if (func == 0) {
- if (parentPath.isEmpty() && !lastPath_.isEmpty()) {
- func = qdb_->findFunctionNode(lastPath_, clone);
- }
- if (func == 0) {
- doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
- .arg(clone->name() + "(...)")
- .arg(COMMAND_FN)
- .arg(arg.first),
- tr("I cannot find any function of that name with the "
- "specified signature. Make sure that the signature "
- "is identical to the declaration, including 'const' "
- "qualifiers."));
- }
- else {
- doc.location().warning(tr("Missing '%1::' for '%2' in '\\%3'")
- .arg(lastPath_.join("::"))
- .arg(clone->name() + "()")
- .arg(COMMAND_FN));
- }
+ doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
+ .arg(clone->name() + "(...)")
+ .arg(COMMAND_FN)
+ .arg(arg.first),
+ tr("I cannot find any function of that name with the "
+ "specified signature. Make sure that the signature "
+ "is identical to the declaration, including 'const' "
+ "qualifiers."));
}
- else {
+ else
lastPath_ = parentPath;
- }
if (func) {
func->borrowParameterNames(clone);
func->setParentPath(clone->parentPath());
@@ -372,7 +365,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QStringList parentPath;
FunctionNode *func = 0;
- extra.root = qdb_->treeRoot();
+ extra.root = qdb_->primaryTreeRoot();
extra.isMacro = true;
if (makeFunctionNode(arg.first, &parentPath, &func, extra)) {
if (!parentPath.isEmpty()) {
@@ -394,7 +387,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return func;
}
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) {
- func = new FunctionNode(qdb_->treeRoot(), arg.first);
+ func = new FunctionNode(qdb_->primaryTreeRoot(), arg.first);
func->setAccess(Node::Public);
func->setLocation(doc.startLocation());
func->setMetaness(FunctionNode::MacroWithoutParams);
@@ -423,21 +416,9 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QStringList path = paths[0].split("::");
Node *node = 0;
- /*
- If the command refers to something that can be in a
- C++ namespace, search for it first in all the known
- C++ namespaces.
- */
node = qdb_->findNodeInOpenNamespace(path, type, subtype);
-
- /*
- If the node was not found in a C++ namespace, search
- for it in the root namespace.
- */
- if (node == 0) {
+ if (node == 0)
node = qdb_->findNodeByNameAndType(path, type, subtype);
- }
-
if (node == 0) {
doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
.arg(arg.first).arg(command));
@@ -446,53 +427,58 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else if (node->isInnerNode()) {
/*
- This treets a class as a namespace.
+ This treats a class as a namespace.
*/
- if (path.size() > 1) {
- path.pop_back();
- QString ns = path.join("::");
- qdb_->insertOpenNamespace(ns);
+ if ((type == Node::Class) || (type == Node::Namespace)) {
+ if (path.size() > 1) {
+ path.pop_back();
+ QString ns = path.join("::");
+ qdb_->insertOpenNamespace(ns);
+ }
}
}
return node;
}
else if (command == COMMAND_EXAMPLE) {
if (Config::generateExamples) {
- ExampleNode* en = new ExampleNode(qdb_->treeRoot(), arg.first);
+ ExampleNode* en = new ExampleNode(qdb_->primaryTreeRoot(), arg.first);
en->setLocation(doc.startLocation());
createExampleFileNodes(en);
return en;
}
}
else if (command == COMMAND_EXTERNALPAGE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::ExternalPage, Node::ArticlePage);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::ExternalPage, Node::ArticlePage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_FILE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::File, Node::NoPageType);
- dn->setLocation(doc.startLocation());
- return dn;
- }
- else if (command == COMMAND_GROUP) {
- DocNode* dn = qdb_->addGroup(arg.first);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::File, Node::NoPageType);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_HEADERFILE) {
- DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
+ DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
dn->setLocation(doc.startLocation());
return dn;
}
+ else if (command == COMMAND_GROUP) {
+ GroupNode* gn = qdb_->addGroup(arg.first);
+ gn->setLocation(doc.startLocation());
+ gn->markSeen();
+ return gn;
+ }
else if (command == COMMAND_MODULE) {
- DocNode* dn = qdb_->addModule(arg.first);
- dn->setLocation(doc.startLocation());
- return dn;
+ ModuleNode* mn = qdb_->addModule(arg.first);
+ mn->setLocation(doc.startLocation());
+ mn->markSeen();
+ return mn;
}
else if (command == COMMAND_QMLMODULE) {
- DocNode* dn = qdb_->addQmlModule(arg.first);
- dn->setLocation(doc.startLocation());
- return dn;
+ QmlModuleNode* qmn = qdb_->addQmlModule(arg.first);
+ qmn->setLocation(doc.startLocation());
+ qmn->markSeen();
+ return qmn;
}
else if (command == COMMAND_PAGE) {
Node::PageType ptype = Node::ArticlePage;
@@ -529,9 +515,9 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
NameCollisionNode* ncn = qdb_->checkForCollision(args[0]);
DocNode* dn = 0;
if (ptype == Node::DitaMapPage)
- dn = new DitaMapNode(qdb_->treeRoot(), args[0]);
+ dn = new DitaMapNode(qdb_->primaryTreeRoot(), args[0]);
else
- dn = new DocNode(qdb_->treeRoot(), args[0], Node::Page, ptype);
+ dn = new DocNode(qdb_->primaryTreeRoot(), args[0], Node::Page, ptype);
dn->setLocation(doc.startLocation());
if (ncn) {
ncn->addCollision(dn);
@@ -539,7 +525,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return dn;
}
else if (command == COMMAND_DITAMAP) {
- DocNode* dn = new DitaMapNode(qdb_->treeRoot(), arg.first);
+ DocNode* dn = new DitaMapNode(qdb_->primaryTreeRoot(), arg.first);
dn->setLocation(doc.startLocation());
return dn;
}
@@ -579,7 +565,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
node and return that one.
*/
NameCollisionNode* ncn = qdb_->checkForCollision(names[0]);
- QmlClassNode* qcn = new QmlClassNode(qdb_->treeRoot(), names[0]);
+ QmlClassNode* qcn = new QmlClassNode(qdb_->primaryTreeRoot(), names[0]);
qcn->setClassNode(classNode);
qcn->setLocation(doc.startLocation());
#if 0
@@ -598,12 +584,13 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
}
#endif
- if (ncn)
+ if (ncn) {
ncn->addCollision(qcn);
+ }
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {
- QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->treeRoot(), arg.first);
+ QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first);
n->setLocation(doc.startLocation());
return n;
}
@@ -959,38 +946,12 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else if (command == COMMAND_RELATES) {
- /*
- Find the node that this node relates to.
- */
- Node* n = 0;
- if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) {
- /*
- It should be a header file, I think.
- */
- n = qdb_->findNodeByNameAndType(QStringList(arg), Node::Document, Node::NoSubType);
- }
- else {
- /*
- If it wasn't a file, it should be either a class or a namespace.
- */
- QStringList newPath = arg.split("::");
- n = qdb_->findClassNode(newPath);
- if (!n)
- n = qdb_->findNamespaceNode(newPath);
- }
-
- if (!n) {
- /*
- Didn't ind it. Error...
- */
+ QStringList path = arg.split("::");
+ Node* n = qdb_->findRelatesNode(path);
+ if (!n)
doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
- }
- else {
- /*
- Found it. This node relates to it.
- */
+ else
node->setRelates(static_cast<InnerNode*>(n));
- }
}
else if (command == COMMAND_CONTENTSPAGE) {
setLink(node, Node::ContentsLink, arg);
@@ -1636,11 +1597,7 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
if (!matchDataType(&baseClass))
return false;
- qdb_->addBaseClass(classe,
- access,
- baseClass.toPath(),
- baseClass.toString(),
- classe->parent());
+ classe->addUnresolvedBaseClass(access, baseClass.toPath(), baseClass.toString());
return true;
}
@@ -1676,7 +1633,7 @@ bool CppCodeParser::matchClassDecl(InnerNode *parent,
while (tok == Tok_Ident)
readToken();
if (tok == Tok_Gulbrandsen) {
- Node* n = parent->findChildNodeByNameAndType(previousLexeme(),Node::Class);
+ Node* n = parent->findChildNode(previousLexeme(),Node::Class);
if (n) {
parent = static_cast<InnerNode*>(n);
if (parent) {
@@ -1735,9 +1692,8 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
*/
QString namespaceName = previousLexeme();
NamespaceNode* ns = 0;
- if (parent) {
- ns = static_cast<NamespaceNode*>(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace));
- }
+ if (parent)
+ ns = static_cast<NamespaceNode*>(parent->findChildNode(namespaceName, Node::Namespace));
if (!ns) {
ns = new NamespaceNode(parent, namespaceName);
ns->setAccess(access);
@@ -1875,7 +1831,7 @@ bool CppCodeParser::matchTypedefDecl(InnerNode *parent)
if (!match(Tok_Semicolon))
return false;
- if (parent && !parent->findChildNodeByNameAndType(name, Node::Typedef)) {
+ if (parent && !parent->findChildNode(name, Node::Typedef)) {
TypedefNode* td = new TypedefNode(parent, name);
td->setAccess(access);
td->setLocation(location());
@@ -2110,7 +2066,7 @@ bool CppCodeParser::matchDeclList(InnerNode *parent)
TypedefNode *flagsNode = new TypedefNode(parent, flagsType);
flagsNode->setAccess(access);
flagsNode->setLocation(location());
- EnumNode* en = static_cast<EnumNode*>(parent->findChildNodeByNameAndType(name, Node::Enum));
+ EnumNode* en = static_cast<EnumNode*>(parent->findChildNode(name, Node::Enum));
if (en)
en->setFlagsType(flagsNode);
}
@@ -2189,9 +2145,15 @@ bool CppCodeParser::matchDocsAndStuff()
FunctionNode *func = 0;
if (matchFunctionDecl(0, &parentPath, &clone, QString(), extra)) {
- func = qdb_->findNodeInOpenNamespace(parentPath, clone);
+ func = qdb_->findFunctionNode(parentPath, clone);
+ /*
+ If the node was not found, then search for it in the
+ open C++ namespaces. We don't expect this search to
+ be necessary often. Nor do we expect it to succeed
+ very often.
+ */
if (func == 0)
- func = qdb_->findFunctionNode(parentPath, clone);
+ func = qdb_->findNodeInOpenNamespace(parentPath, clone);
if (func) {
func->borrowParameterNames(clone);
@@ -2253,8 +2215,9 @@ bool CppCodeParser::matchDocsAndStuff()
checkModuleInclusion(*n);
if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
- while (m->parent() != qdb_->treeRoot())
+ while (m->parent() && m->moduleName().isEmpty()) {
m = m->parent();
+ }
if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name());
else
@@ -2391,7 +2354,7 @@ void CppCodeParser::instantiateIteratorMacro(const QString &container,
Tokenizer stringTokenizer(loc, latin1);
tokenizer = &stringTokenizer;
readToken();
- matchDeclList(QDocDatabase::qdocDB()->treeRoot());
+ matchDeclList(QDocDatabase::qdocDB()->primaryTreeRoot());
}
void CppCodeParser::createExampleFileNodes(DocNode *dn)
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index e3b9bdd264..90661d80e0 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -667,13 +667,12 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
}
/*!
- Traverses the database generating all the DITA XML documentation.
+ Traverses the current tree generating all the DITA XML documentation.
*/
-void DitaXmlGenerator::generateTree()
+void DitaXmlGenerator::generateDocs()
{
- qdb_->buildCollections();
if (!runPrepareOnly()) {
- Generator::generateTree();
+ Generator::generateDocs();
generateCollisionPages();
}
@@ -1013,9 +1012,9 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
break;
case Atom::AnnotatedList:
{
- DocNode* dn = qdb_->getGroup(atom->string());
- if (dn)
- generateAnnotatedList(relative, marker, dn->members());
+ GroupNode* gn = qdb_->getGroup(atom->string());
+ if (gn)
+ generateAnnotatedList(relative, marker, gn->members());
}
break;
case Atom::GeneratedList:
@@ -1032,10 +1031,10 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB();
- DocNode* dn = qdb->findModule(moduleName);
- if (dn) {
+ ModuleNode* mn = qdb->findModule(moduleName);
+ if (mn) {
NodeMap m;
- dn->getMemberClasses(m);
+ mn->getMemberClasses(m);
if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m);
}
@@ -1084,9 +1083,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
generateAnnotatedList(relative, marker, qdb_->getNamespaces());
}
else if (atom->string() == "related") {
- const DocNode *dn = static_cast<const DocNode *>(relative);
- if (dn)
- generateAnnotatedList(dn, marker, dn->members());
+ if (relative && relative->isCollectionNode()) {
+ const CollectionNode* cn = static_cast<const CollectionNode *>(relative);
+ if (cn)
+ generateAnnotatedList(cn, marker, cn->members());
+ }
}
break;
case Atom::SinceList:
@@ -2263,24 +2264,6 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
writeStartTag(DT_body);
enterSection(QString(), QString());
- if (dn->subType() == Node::Module) {
- generateStatus(dn, marker);
- NodeMap nm;
- dn->getMemberNamespaces(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Namespaces");
- generateAnnotatedList(dn, marker, nm);
- leaveSection();
- }
- nm.clear();
- dn->getMemberClasses(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Classes");
- generateAnnotatedList(dn, marker, nm);
- leaveSection();
- }
- nm.clear();
- }
if (dn->doc().isEmpty()) {
if (dn->subType() == Node::File) {
@@ -2299,23 +2282,70 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
}
}
else {
- if (dn->subType() == Node::Module) {
+ generateBody(dn, marker);
+ generateAlsoList(dn, marker);
+ }
+ leaveSection(); // </section>
+ if (!writeEndTag()) { // </body>
+ dn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(dn->name()));
+ return;
+ }
+ writeRelatedLinks(dn);
+ writeEndTag(); // </topic>
+}
+
+/*!
+ Generate the DITA XML file for a group, module, or QML module.
+ */
+void DitaXmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
+{
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+ QString fullTitle = cn->fullTitle();
+
+ generateHeader(cn, fullTitle);
+ generateBrief(cn, marker); // <shortdesc>
+ writeProlog(cn);
+
+ writeStartTag(DT_body);
+ enterSection(QString(), QString());
+ if (cn->isModule()) {
+ generateStatus(cn, marker);
+ NodeMap nm;
+ cn->getMemberNamespaces(nm);
+ if (!nm.isEmpty()) {
+ enterSection("h2","Namespaces");
+ generateAnnotatedList(cn, marker, nm);
+ leaveSection();
+ }
+ nm.clear();
+ cn->getMemberClasses(nm);
+ if (!nm.isEmpty()) {
+ enterSection("h2","Classes");
+ generateAnnotatedList(cn, marker, nm);
+ leaveSection();
+ }
+ nm.clear();
+ }
+
+ if (!cn->doc().isEmpty()) {
+ if (cn->isModule()) {
enterSection(QString(), QString());
- generateBody(dn, marker);
+ generateBody(cn, marker);
leaveSection();
}
else {
- generateBody(dn, marker);
+ generateBody(cn, marker);
}
- generateAlsoList(dn, marker);
- generateAnnotatedList(dn, marker, dn->members());
+ generateAlsoList(cn, marker);
+ generateAnnotatedList(cn, marker, cn->members());
}
leaveSection(); // </section>
if (!writeEndTag()) { // </body>
- dn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(dn->name()));
+ cn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(cn->name()));
return;
}
- writeRelatedLinks(dn);
+ writeRelatedLinks(cn);
writeEndTag(); // </topic>
}
@@ -2350,7 +2380,7 @@ void DitaXmlGenerator::writeLink(const Node* node,
value of the \e role attribute is \c{parent} for the
\c{start} link.
*/
-void DitaXmlGenerator::writeRelatedLinks(const DocNode* node)
+void DitaXmlGenerator::writeRelatedLinks(const Node* node)
{
const Node* linkNode = 0;
QPair<QString,QString> linkPair;
@@ -2405,12 +2435,9 @@ QString DitaXmlGenerator::fileExtension() const
Writes an XML file header to the current XML stream. This
depends on which kind of DITA XML file is being generated,
which is determined by the \a node type and subtype and the
- \a subpage flag. If the \subpage flag is true, a \c{<topic>}
- header is written, regardless of the type of \a node.
+ \a subpage flag.
*/
-void DitaXmlGenerator::generateHeader(const Node* node,
- const QString& name,
- bool subpage)
+void DitaXmlGenerator::generateHeader(const Node* node, const QString& name)
{
if (!node)
return;
@@ -2423,7 +2450,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
QString version;
QString outputclass;
- if (node->type() == Node::Class) {
+ if (node->isClass()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2432,7 +2459,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
" PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
version + "//EN\" \"" + dtd + "\">";
}
- else if (node->type() == Node::Namespace) {
+ else if (node->isNamespace()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2442,8 +2469,28 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">";
outputclass = "namespace";
}
- else if (node->type() == Node::Document || subpage) {
- if (node->subType() == Node::HeaderFile) {
+ else if (node->isCollectionNode()) {
+ mainTag = DT_topic;
+ nameTag = DT_title;
+ dtd = "dtd/topic.dtd";
+ doctype = "<!DOCTYPE " + ditaTags[mainTag] +
+ " PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">";
+ switch (node->type()) {
+ case Node::Group:
+ outputclass = "group";
+ break;
+ case Node::Module:
+ outputclass = "module";
+ break;
+ case Node::QmlModule:
+ outputclass = "qmlmodule";
+ break;
+ default:
+ outputclass = "page";
+ }
+ }
+ else if (node->isDocNode()) {
+ if (node->isHeaderFile()) {
mainTag = DT_cxxClass;
nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd";
@@ -2453,7 +2500,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">";
outputclass = "headerfile";
}
- else if (node->subType() == Node::QmlClass) {
+ else if (node->isQmlType()) {
mainTag = DT_qmlType;
nameTag = DT_apiName;
dtd = "dtd/qmlType.dtd";
@@ -2473,9 +2520,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Page:
outputclass = node->pageTypeString();
break;
- case Node::Group:
- outputclass = "group";
- break;
case Node::Example:
outputclass = "example";
break;
@@ -2485,9 +2529,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Image: // not used
outputclass = "image";
break;
- case Node::Module:
- outputclass = "module";
- break;
case Node::ExternalPage: // not used
outputclass = "externalpage";
break;
@@ -2696,8 +2737,8 @@ void DitaXmlGenerator::generateClassHierarchy(const Node* relative, NodeMap& cla
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && d.access_ != Node::Private && !d.node_->doc().isEmpty())
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -3106,100 +3147,57 @@ void DitaXmlGenerator::generateQmlItem(const Node* node,
*/
void DitaXmlGenerator::generateOverviewList(const Node* relative)
{
- QMap<const DocNode*, QMap<QString, DocNode*> > docNodeMap;
- QMap<QString, const DocNode*> groupTitlesMap;
- QMap<QString, DocNode*> uncategorizedNodeMap;
+ CNMap groups;
+ CNMap modules;
+ CNMap qmlModules;
QRegExp singleDigit("\\b([0-9])\\b");
- const NodeList children = qdb_->treeRoot()->childNodes();
- foreach (Node* child, children) {
- if (child->type() == Node::Document && child != relative) {
- DocNode* docNode = static_cast<DocNode*>(child);
-
- // Check whether the page is part of a group or is the group
- // definition page.
- QString group;
- bool isGroupPage = false;
- if (docNode->doc().metaCommandsUsed().contains("group")) {
- group = docNode->doc().metaCommandArgs("group")[0].first;
- isGroupPage = true;
- }
-
- // there are too many examples; they would clutter the list
- if (docNode->subType() == Node::Example)
- continue;
-
- // not interested either in individual (Qt Designer etc.) manual chapters
- if (docNode->links().contains(Node::ContentsLink))
- continue;
-
- // Discard external nodes.
- if (docNode->subType() == Node::ExternalPage)
- continue;
-
- QString sortKey = docNode->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
-
- if (!group.isEmpty()) {
- if (isGroupPage) {
- // If we encounter a group definition page, we add all
- // the pages in that group to the list for that group.
- foreach (Node* member, docNode->members()) {
- if (member->isInternal() || member->type() != Node::Document)
- continue;
- DocNode* page = static_cast<DocNode*>(member);
- if (page) {
- QString sortKey = page->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
- docNodeMap[const_cast<const DocNode*>(docNode)].insert(sortKey, page);
- groupTitlesMap[docNode->fullTitle()] = const_cast<const DocNode*>(docNode);
- }
- }
- }
- else if (!isGroupPage) {
- // If we encounter a page that belongs to a group then
- // we add that page to the list for that group.
- const DocNode* gn = qdb_->getGroup(group);
- if (gn && !docNode->isInternal())
- docNodeMap[gn].insert(sortKey, docNode);
- }
- }
- }
- }
-
- // We now list all the pages found that belong to groups.
- // If only certain pages were found for a group, but the definition page
- // for that group wasn't listed, the list of pages will be intentionally
- // incomplete. However, if the group definition page was listed, all the
- // pages in that group are listed for completeness.
+ qdb_->mergeCollections(Node::Group, groups, relative);
+ qdb_->mergeCollections(Node::Module, modules, relative);
+ qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
- if (!docNodeMap.isEmpty()) {
- foreach (const QString& groupTitle, groupTitlesMap.keys()) {
- const DocNode* groupNode = groupTitlesMap[groupTitle];
+ QStringList keys = groups.uniqueKeys();
+ foreach (QString key, keys) {
+ GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
+ if (gn) {
writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","h3");
writeStartTag(DT_xref);
// formathtml
- xmlWriter().writeAttribute("href",linkForNode(groupNode, relative));
- writeCharacters(protectEnc(groupNode->fullTitle()));
+ xmlWriter().writeAttribute("href",linkForNode(gn, relative));
+ writeCharacters(protectEnc(gn->fullTitle()));
writeEndTag(); // </xref>
writeEndTag(); // </p>
- if (docNodeMap[groupNode].count() == 0)
+
+ if (gn->members().isEmpty())
continue;
+ NodeMap nm;
+ foreach (Node* member, gn->members()) {
+ if (member->isInternal() || member->isExample() || member->isExternalPage() ||
+ member->isObsolete())
+ continue;
+ // not interested either in individual (Qt Designer etc.) manual chapters
+ if (member->links().contains(Node::ContentsLink))
+ continue;
+ QString sortKey = member->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ nm.insert(sortKey, member);
+ }
+
writeStartTag(DT_ul);
- foreach (const DocNode* docNode, docNodeMap[groupNode]) {
- QString title = docNode->fullTitle();
+ QStringList titles = nm.keys();
+ foreach (QString t, titles) {
+ Node* member = nm.value(t);
+ QString title = member->fullTitle();
if (title.startsWith("The "))
title.remove(0, 4);
writeStartTag(DT_li);
writeStartTag(DT_xref);
// formathtml
- xmlWriter().writeAttribute("href",linkForNode(docNode, relative));
+ xmlWriter().writeAttribute("href",linkForNode(member, relative));
writeCharacters(protectEnc(title));
writeEndTag(); // </xref>
writeEndTag(); // </li>
@@ -3207,27 +3205,6 @@ void DitaXmlGenerator::generateOverviewList(const Node* relative)
writeEndTag(); // </ul>
}
}
-
- if (!uncategorizedNodeMap.isEmpty()) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- xmlWriter().writeCharacters("Miscellaneous");
- writeEndTag(); // </p>
- writeStartTag(DT_ul);
- foreach (const DocNode *docNode, uncategorizedNodeMap) {
- QString title = docNode->fullTitle();
- if (title.startsWith("The "))
- title.remove(0, 4);
- writeStartTag(DT_li);
- writeStartTag(DT_xref);
- // formathtml
- xmlWriter().writeAttribute("href",linkForNode(docNode, relative));
- writeCharacters(protectEnc(title));
- writeEndTag(); // </xref>
- writeEndTag(); // </li>
- }
- writeEndTag(); // </ul>
- }
}
/*!
@@ -3412,68 +3389,71 @@ void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative
for (int k = 0; k != 6; ++k) {
if (parseArg(src, markTags[k], &i, n, &arg, &par1)) {
const Node* n = 0;
- if (k == 0) { // <@link>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- n = CodeMarker::nodeForString(par1.toString());
- QString link = linkForNode(n, relative);
- addLink(link, arg);
- }
- else if (k == 4) { // <@param>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_i);
- //writeCharacters(" " + arg.toString());
- writeCharacters(arg.toString());
- writeEndTag(); // </i>
- }
- else if (k == 5) { // <@extra>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_tt);
- writeCharacters(arg.toString());
- writeEndTag(); // </tt>
- }
- else {
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- par1 = QStringRef();
- QString link;
- n = qdb_->resolveTarget(arg.toString(), relative);
- if (n && n->subType() == Node::QmlBasicType) {
- if (relative && relative->subType() == Node::QmlClass) {
- link = linkForNode(n,relative);
- addLink(link, arg);
+ switch (k) {
+ case 0: // <@link>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
- else {
- writeCharacters(arg.toString());
+ n = CodeMarker::nodeForString(par1.toString());
+ addLink(linkForNode(n, relative), arg);
+ break;
+ case 4: // <@param>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
- }
- else {
- // (zzz) Is this correct for all cases?
- link = linkForNode(n,relative);
- addLink(link, arg);
- }
- }
+ writeStartTag(DT_i);
+ //writeCharacters(" " + arg.toString());
+ writeCharacters(arg.toString());
+ writeEndTag(); // </i>
+ break;
+ case 5: // <@extra>
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ writeStartTag(DT_tt);
+ writeCharacters(arg.toString());
+ writeEndTag(); // </tt>
+ break;
+ case 3:
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ par1 = QStringRef();
+ n = qdb_->resolveFunctionTarget(arg.toString(), relative);
+ addLink(linkForNode(n, relative), arg);
+ break;
+ case 1:
+ case 2:
+ default:
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
+ }
+ par1 = QStringRef();
+ n = qdb_->resolveType(arg.toString(), relative);
+ if (n && n->subType() == Node::QmlBasicType) {
+ if (relative && relative->subType() == Node::QmlClass)
+ addLink(linkForNode(n, relative), arg);
+ else
+ writeCharacters(arg.toString());
+ }
+ else
+ addLink(linkForNode(n, relative), arg); // (zzz) Is this correct for all cases?
+ break;
+ } // switch
break;
}
}
}
- else {
+ else
text += src.at(i++);
- }
}
- if (!text.isEmpty()) {
+ if (!text.isEmpty())
writeCharacters(text);
- }
}
void DitaXmlGenerator::generateLink(const Atom* atom, CodeMarker* marker)
@@ -3703,13 +3683,12 @@ QString DitaXmlGenerator::guidForNode(const Node* node)
/*!
Constructs a file name appropriate for the \a node and returns
- it. If the \a node is not a fake node, or if it is a fake node but
- it is neither an external page node nor an image node or a ditamap,
- call the Generator::fileName() function.
+ it. If the \a node is not a not an external page, an image, or
+ a ditamap, call fileName() in the base class, Generator.
*/
QString DitaXmlGenerator::fileName(const Node* node)
{
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
if (static_cast<const DocNode*>(node)->pageType() == Node::DitaMapPage)
return node->name();
if (static_cast<const DocNode*>(node)->subType() == Node::ExternalPage)
@@ -3854,18 +3833,18 @@ QString DitaXmlGenerator::getLink(const Atom* atom, const Node* relative, const
QString ref;
QString first = path.first().trimmed();
- if (first.isEmpty()) {
+ if (first.isEmpty())
*node = relative;
- }
- else if (first.endsWith(".html")) {
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
- }
+ else if (first.endsWith(".html"))
+ *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType);
+ else if (first.endsWith("()")) // The target is a C++ function or QML method.
+ *node = qdb_->resolveFunctionTarget(first, relative);
else {
*node = qdb_->resolveTarget(first, relative);
+ if (!(*node))
+ *node = qdb_->findDocNodeByTitle(first);
if (!*node)
- *node = qdb_->findDocNodeByTitle(first, relative);
- if (!*node)
- *node = qdb_->findUnambiguousTarget(first, ref, relative);
+ *node = qdb_->findUnambiguousTarget(first, ref);
}
if (*node) {
@@ -4050,7 +4029,7 @@ void DitaXmlGenerator::startQmlProperty(QmlPropertyNode* qpn,
writeStartTag(DT_qmlPropertyDetail);
writeStartTag(DT_qmlPropertyDef);
if (!qpn->isReadOnlySet())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
+ qpn->setReadOnly(!qpn->isWritable());
if (qpn->isReadOnly()) {
writeStartTag(DT_qmlQualifier);
xmlWriter().writeAttribute("name","read-only");
@@ -4187,11 +4166,11 @@ void DitaXmlGenerator::generateQmlModuleDef(QmlClassNode* qcn)
Output the "Inherits" line for the QML element,
if there should be one.
*/
-void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker)
+void DitaXmlGenerator::generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker)
{
if (!qcn)
return;
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -4365,25 +4344,27 @@ void DitaXmlGenerator::writeDerivations(const ClassNode* cn)
writeStartTag(DT_cxxClassDerivations);
r = cn->baseClasses().constBegin();
while (r != cn->baseClasses().constEnd()) {
- writeStartTag(DT_cxxClassDerivation);
- writeStartTag(DT_cxxClassDerivationAccessSpecifier);
- xmlWriter().writeAttribute("value",(*r).accessString());
- writeEndTag(); // </cxxClassDerivationAccessSpecifier>
-
- // not included: <cxxClassDerivationVirtual>
+ ClassNode* bcn = (*r).node_;
+ if (bcn) {
+ writeStartTag(DT_cxxClassDerivation);
+ writeStartTag(DT_cxxClassDerivationAccessSpecifier);
+ xmlWriter().writeAttribute("value",(*r).accessString());
+ writeEndTag(); // </cxxClassDerivationAccessSpecifier>
- writeStartTag(DT_cxxClassBaseClass);
- QString attr = fileName((*r).node) + QLatin1Char('#') + (*r).node->guid();
- xmlWriter().writeAttribute("href",attr);
- writeCharacters((*r).node->plainFullName());
- writeEndTag(); // </cxxClassBaseClass>
+ // not included: <cxxClassDerivationVirtual>
- // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
+ writeStartTag(DT_cxxClassBaseClass);
+ QString attr = fileName(bcn) + QLatin1Char('#') + bcn->guid();
+ xmlWriter().writeAttribute("href",attr);
+ writeCharacters(bcn->plainFullName());
+ writeEndTag(); // </cxxClassBaseClass>
- writeEndTag(); // </cxxClassDerivation>
+ // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
- // not included: <cxxStructDerivation>
+ writeEndTag(); // </cxxClassDerivation>
+ // not included: <cxxStructDerivation>
+ }
++r;
}
writeEndTag(); // </cxxClassDerivations>
@@ -4623,7 +4604,7 @@ void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* par
}
i += 2;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
- const Node* tn = qdb_->resolveTarget(arg.toString(), parent, n);
+ const Node* tn = qdb_->resolveType(arg.toString(), parent);
if (tn) {
//Do not generate a link from a C++ function to a QML Basic Type (such as int)
if (n->type() == Node::Function && tn->subType() == Node::QmlBasicType)
@@ -5420,6 +5401,18 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child))
nodeTypeMaps[Node::Class]->insert(child->name(),child);
break;
+ case Node::Group:
+ if (!isDuplicate(nodeTypeMaps[Node::Group],child->title(),child))
+ nodeTypeMaps[Node::Group]->insert(child->title(),child);
+ break;
+ case Node::Module:
+ if (!isDuplicate(nodeTypeMaps[Node::Module],child->title(),child))
+ nodeTypeMaps[Node::Module]->insert(child->title(),child);
+ break;
+ case Node::QmlModule:
+ if (!isDuplicate(nodeTypeMaps[Node::QmlModule],child->title(),child))
+ nodeTypeMaps[Node::QmlModule]->insert(child->title(),child);
+ break;
case Node::Document:
switch (child->subType()) {
case Node::Example:
@@ -5434,14 +5427,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
break;
case Node::Image:
break;
- case Node::Group:
- if (!isDuplicate(nodeSubtypeMaps[Node::Group],child->title(),child))
- nodeSubtypeMaps[Node::Group]->insert(child->title(),child);
- break;
- case Node::Module:
- if (!isDuplicate(nodeSubtypeMaps[Node::Module],child->title(),child))
- nodeSubtypeMaps[Node::Module]->insert(child->title(),child);
- break;
case Node::Page:
if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child))
pageTypeMaps[child->pageType()]->insert(child->title(),child);
@@ -5458,10 +5443,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child))
nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child);
break;
- case Node::QmlModule:
- if (!isDuplicate(nodeSubtypeMaps[Node::QmlModule],child->title(),child))
- nodeSubtypeMaps[Node::QmlModule]->insert(child->title(),child);
- break;
case Node::Collision:
if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child))
nodeSubtypeMaps[Node::Collision]->insert(child->title(),child);
@@ -5509,7 +5490,7 @@ void DitaXmlGenerator::writeDitaMap()
Remove #if 0 to get a flat ditamap.
*/
#if 0
- beginSubPage(qdb_->treeRoot(),"qt.ditamap");
+ beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
xmlWriter().writeDTD(doctype);
writeStartTag(DT_map);
@@ -5535,9 +5516,9 @@ void DitaXmlGenerator::writeDitaMap()
nodeSubtypeMaps[i] = new NodeMultiMap;
for (unsigned i=0; i<Node::OnBeyondZebra; ++i)
pageTypeMaps[i] = new NodeMultiMap;
- Node* rootPageNode = collectNodesByTypeAndSubtype(qdb_->treeRoot());
+ Node* rootPageNode = collectNodesByTypeAndSubtype(qdb_->primaryTreeRoot());
- beginSubPage(qdb_->treeRoot(),"qt.ditamap");
+ beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
xmlWriter().writeDTD(doctype);
@@ -5565,22 +5546,26 @@ void DitaXmlGenerator::writeDitaMap()
writeTopicrefs(pageTypeMaps[Node::FAQPage], "FAQs");
writeTopicrefs(pageTypeMaps[Node::ArticlePage], "Articles");
writeTopicrefs(nodeSubtypeMaps[Node::Example], "Examples");
- if (nodeSubtypeMaps[Node::QmlModule]->size() > 1)
- writeTopicrefs(nodeSubtypeMaps[Node::QmlModule], "QML modules");
- if (nodeSubtypeMaps[Node::QmlModule]->size() == 1)
- writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types", nodeSubtypeMaps[Node::QmlModule]->values()[0]);
+
+ if (nodeTypeMaps[Node::QmlModule]->size() > 1)
+ writeTopicrefs(nodeTypeMaps[Node::QmlModule], "QML modules");
+
+ if (nodeTypeMaps[Node::QmlModule]->size() == 1)
+ writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types", nodeTypeMaps[Node::QmlModule]->values()[0]);
else
writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types");
writeTopicrefs(nodeSubtypeMaps[Node::QmlBasicType], "QML basic types");
- if (nodeSubtypeMaps[Node::Module]->size() > 1)
- writeTopicrefs(nodeSubtypeMaps[Node::Module], "Modules");
- if (nodeSubtypeMaps[Node::Module]->size() == 1)
- writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeSubtypeMaps[Node::Module]->values()[0]);
+
+ if (nodeTypeMaps[Node::Module]->size() > 1)
+ writeTopicrefs(nodeTypeMaps[Node::Module], "Modules");
+
+ if (nodeTypeMaps[Node::Module]->size() == 1)
+ writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeTypeMaps[Node::Module]->values()[0]);
else
writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes");
writeTopicrefs(nodeTypeMaps[Node::Namespace], "C++ namespaces");
writeTopicrefs(nodeSubtypeMaps[Node::HeaderFile], "Header files");
- writeTopicrefs(nodeSubtypeMaps[Node::Group], "Groups");
+ writeTopicrefs(nodeTypeMaps[Node::Group], "Groups");
writeEndTag(); // </topicref>
endSubPage();
@@ -5929,6 +5914,12 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
category = "Class reference";
else if (inner->type() == Node::Namespace)
category = "Namespace";
+ else if (inner->type() == Node::Module)
+ category = "Module";
+ else if (inner->type() == Node::QmlModule)
+ category = "QML Module";
+ else if (inner->type() == Node::Group)
+ category = "Group";
else if (inner->type() == Node::Document) {
if (inner->subType() == Node::QmlClass)
category = "QML Reference";
@@ -5936,16 +5927,12 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
category = "QML Basic Type";
else if (inner->subType() == Node::HeaderFile)
category = "Header File";
- else if (inner->subType() == Node::Module)
- category = "Module";
else if (inner->subType() == Node::File)
category = "Example Source File";
else if (inner->subType() == Node::Example)
category = "Example";
else if (inner->subType() == Node::Image)
category = "Image";
- else if (inner->subType() == Node::Group)
- category = "Group";
else if (inner->subType() == Node::Page)
category = "Page";
else if (inner->subType() == Node::ExternalPage)
@@ -6096,7 +6083,6 @@ void DitaXmlGenerator::generateCollisionPages()
if (collisions.size() <= 1)
continue;
- ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->fullTitle();
QString ditaTitle = fullTitle;
@@ -6130,7 +6116,7 @@ void DitaXmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNodeByName(t.key())) {
+ if (n->findChildNode(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -6152,7 +6138,7 @@ void DitaXmlGenerator::generateCollisionPages()
writeStartTag(DT_ul);
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNodeByName(*t);
+ Node* p = n->findChildNode(*t);
if (p) {
QString link = linkForNode(p,0);
QString label;
diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h
index da05bb0274..a65ddfabed 100644
--- a/src/tools/qdoc/ditaxmlgenerator.h
+++ b/src/tools/qdoc/ditaxmlgenerator.h
@@ -302,7 +302,7 @@ public:
virtual void terminateGenerator();
virtual QString format();
virtual bool canHandleFormat(const QString& format);
- virtual void generateTree();
+ virtual void generateDocs();
void generateCollisionPages();
QString protectEnc(const QString& string);
@@ -316,6 +316,7 @@ protected:
CodeMarker* marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const;
virtual QString guidForNode(const Node* node);
virtual QString linkForNode(const Node* node, const Node* relative);
@@ -349,7 +350,7 @@ protected:
CodeMarker* marker,
const QString& attribute = QString());
void writePropertyParameter(const QString& tag, const NodeList& nlist);
- void writeRelatedLinks(const DocNode* dn);
+ void writeRelatedLinks(const Node* dn);
void writeLink(const Node* node, const QString& tex, const QString& role);
void writeProlog(const InnerNode* inner);
bool writeMetadataElement(const InnerNode* inner,
@@ -364,9 +365,7 @@ private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle };
const QPair<QString,QString> anchorForNode(const Node* node);
- void generateHeader(const Node* node,
- const QString& name,
- bool subpage = false);
+ void generateHeader(const Node* node, const QString& name);
void generateBrief(const Node* node, CodeMarker* marker);
void generateTableOfContents(const Node* node,
CodeMarker* marker,
@@ -403,7 +402,7 @@ private:
void generateDetailedQmlMember(Node* node,
const InnerNode* relative,
CodeMarker* marker);
- void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
diff --git a/src/tools/qdoc/doc.cpp b/src/tools/qdoc/doc.cpp
index 6e70671d1d..afc21bb518 100644
--- a/src/tools/qdoc/doc.cpp
+++ b/src/tools/qdoc/doc.cpp
@@ -316,17 +316,17 @@ Q_GLOBAL_STATIC(QHash_QString_Macro, macroHash)
class DocPrivateExtra
{
public:
- Doc::Sections granularity;
- Doc::Sections section; // ###
- QList<Atom*> tableOfContents;
- QList<int> tableOfContentsLevels;
- QList<Atom*> keywords;
- QList<Atom*> targets;
- QStringMultiMap metaMap;
+ Doc::Sections granularity_;
+ Doc::Sections section_; // ###
+ QList<Atom*> tableOfContents_;
+ QList<int> tableOfContentsLevels_;
+ QList<Atom*> keywords_;
+ QList<Atom*> targets_;
+ QStringMultiMap metaMap_;
DocPrivateExtra()
- : granularity(Doc::Part)
- , section(Doc::NoSection)
+ : granularity_(Doc::Part)
+ , section_(Doc::NoSection)
{ }
};
@@ -535,7 +535,7 @@ private:
int braceDepth;
int minIndent;
Doc::Sections currentSection;
- QMap<QString, Location> targetMap;
+ QMap<QString, Location> targetMap_;
QMap<int, QString> pendingFormats;
QStack<int> openedCommands;
QStack<OpenedList> openedLists;
@@ -880,7 +880,7 @@ void DocParser::parse(const QString& source,
break;
case CMD_GRANULARITY:
priv->constructExtra();
- priv->extra->granularity = getSectioningUnit();
+ priv->extra->granularity_ = getSectioningUnit();
break;
case CMD_HEADER:
if (openedCommands.top() == CMD_TABLE) {
@@ -1025,7 +1025,7 @@ void DocParser::parse(const QString& source,
case CMD_META:
priv->constructExtra();
p1 = getArgument();
- priv->extra->metaMap.insert(p1, getArgument());
+ priv->extra->metaMap_.insert(p1, getArgument());
break;
case CMD_NEWCODE:
location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_NEWCODE)));
@@ -1626,8 +1626,8 @@ void DocParser::parse(const QString& source,
currentSection = Doc::NoSection;
}
- if (priv->extra && priv->extra->granularity < priv->extra->section)
- priv->extra->granularity = priv->extra->section;
+ if (priv->extra && priv->extra->granularity_ < priv->extra->section_)
+ priv->extra->granularity_ = priv->extra->section_;
priv->text.stripFirstAtom();
}
@@ -1668,18 +1668,18 @@ QString DocParser::detailsUnknownCommand(const QSet<QString> &metaCommandSet,
void DocParser::insertTarget(const QString &target, bool keyword)
{
- if (targetMap.contains(target)) {
+ if (targetMap_.contains(target)) {
location().warning(tr("Duplicate target name '%1'").arg(target));
- targetMap[target].warning(tr("(The previous occurrence is here)"));
+ targetMap_[target].warning(tr("(The previous occurrence is here)"));
}
else {
- targetMap.insert(target, location());
+ targetMap_.insert(target, location());
append(Atom::Target, target);
priv->constructExtra();
if (keyword)
- priv->extra->keywords.append(priv->text.lastAtom());
+ priv->extra->keywords_.append(priv->text.lastAtom());
else
- priv->extra->targets.append(priv->text.lastAtom());
+ priv->extra->targets_.append(priv->text.lastAtom());
}
}
@@ -1883,15 +1883,15 @@ void DocParser::startSection(Doc::Sections unit, int cmd)
if (currentSection == Doc::NoSection) {
currentSection = (Doc::Sections) (unit);
priv->constructExtra();
- priv->extra->section = currentSection;
+ priv->extra->section_ = currentSection;
}
else
endSection(unit,cmd);
append(Atom::SectionLeft, QString::number(unit));
priv->constructExtra();
- priv->extra->tableOfContents.append(priv->text.lastAtom());
- priv->extra->tableOfContentsLevels.append(unit);
+ priv->extra->tableOfContents_.append(priv->text.lastAtom());
+ priv->extra->tableOfContentsLevels_.append(unit);
enterPara(Atom::SectionHeadingLeft,
Atom::SectionHeadingRight,
QString::number(unit));
@@ -2958,10 +2958,10 @@ Text Doc::legaleseText() const
Doc::Sections Doc::granularity() const
{
if (priv == 0 || priv->extra == 0) {
- return DocPrivateExtra().granularity;
+ return DocPrivateExtra().granularity_;
}
else {
- return priv->extra->granularity;
+ return priv->extra->granularity_;
}
}
@@ -3007,46 +3007,46 @@ const QList<Text> &Doc::alsoList() const
bool Doc::hasTableOfContents() const
{
- return priv && priv->extra && !priv->extra->tableOfContents.isEmpty();
+ return priv && priv->extra && !priv->extra->tableOfContents_.isEmpty();
}
bool Doc::hasKeywords() const
{
- return priv && priv->extra && !priv->extra->keywords.isEmpty();
+ return priv && priv->extra && !priv->extra->keywords_.isEmpty();
}
bool Doc::hasTargets() const
{
- return priv && priv->extra && !priv->extra->targets.isEmpty();
+ return priv && priv->extra && !priv->extra->targets_.isEmpty();
}
const QList<Atom *> &Doc::tableOfContents() const
{
priv->constructExtra();
- return priv->extra->tableOfContents;
+ return priv->extra->tableOfContents_;
}
const QList<int> &Doc::tableOfContentsLevels() const
{
priv->constructExtra();
- return priv->extra->tableOfContentsLevels;
+ return priv->extra->tableOfContentsLevels_;
}
const QList<Atom *> &Doc::keywords() const
{
priv->constructExtra();
- return priv->extra->keywords;
+ return priv->extra->keywords_;
}
const QList<Atom *> &Doc::targets() const
{
priv->constructExtra();
- return priv->extra->targets;
+ return priv->extra->targets_;
}
const QStringMultiMap &Doc::metaTagMap() const
{
- return priv && priv->extra ? priv->extra->metaMap : *null_QStringMultiMap();
+ return priv && priv->extra ? priv->extra->metaMap_ : *null_QStringMultiMap();
}
const Config* Doc::config_ = 0;
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 9b82e80927..264e489942 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -97,23 +97,26 @@ QStringList Generator::styleDirs;
QStringList Generator::styleFiles;
bool Generator::debugging_ = false;
bool Generator::noLinkErrors_ = false;
+bool Generator::autolinkErrors_ = false;
bool Generator::redirectDocumentationToDevNull_ = false;
Generator::Passes Generator::qdocPass_ = Both;
bool Generator::useOutputSubdirs_ = true;
-void Generator::setDebugSegfaultFlag(bool b)
+void Generator::setDebugFlag(bool b)
{
+#if 0
if (b)
qDebug() << "DEBUG: Setting debug flag.";
else
qDebug() << "DEBUG: Clearing debug flag.";
+#endif
debugging_ = b;
}
/*!
Prints \a message as an aid to debugging the release version.
*/
-void Generator::debugSegfault(const QString& message)
+void Generator::debug(const QString& message)
{
if (debugging())
qDebug() << "DEBUG:" << message;
@@ -189,19 +192,20 @@ void Generator::appendFullNames(Text& text, const NodeList& nodes, const Node* r
}
}
-void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes)
+void Generator::appendSortedNames(Text& text, const ClassNode* cn, const QList<RelatedClass>& rc)
{
QList<RelatedClass>::ConstIterator r;
QMap<QString,Text> classMap;
int index = 0;
- r = classes.constBegin();
- while (r != classes.constEnd()) {
- if ((*r).node->access() == Node::Public &&
- (*r).node->status() != Node::Internal
- && !(*r).node->doc().isEmpty()) {
+ r = rc.constBegin();
+ while (r != rc.constEnd()) {
+ ClassNode* rcn = (*r).node_;
+ if (rcn && rcn->access() == Node::Public &&
+ rcn->status() != Node::Internal &&
+ !rcn->doc().isEmpty()) {
Text className;
- appendFullName(className, (*r).node, classe);
+ appendFullName(className, rcn, cn);
classMap[className.toString().toLower()] = className;
}
++r;
@@ -274,7 +278,7 @@ void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
node->location().error(tr("HTML file already exists; overwriting %1").arg(outFile->fileName()));
if (!outFile->open(QFile::WriteOnly))
node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
- Generator::debugSegfault("Writing: " + path);
+ Generator::debug("Writing: " + path);
outFileNames.insert(fileName,fileName);
QTextStream* out = new QTextStream(outFile);
@@ -308,24 +312,14 @@ QString Generator::fileBase(const Node *node) const
node = node->parent();
}
- if (node->type() == Node::Document && node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
- }
-
- if (node->hasBaseName())
- return node->baseName();
+ if (node->hasFileNameBase())
+ return node->fileNameBase();
QString base;
- if (node->type() == Node::Document) {
+ if (node->isDocNode()) {
base = node->name();
- if (node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
+ if (node->subType() == Node::Collision)
base.prepend("collision-");
- }
//Was QDOC2_COMPAT, required for index.html
if (base.endsWith(".html"))
base.truncate(base.length() - 5);
@@ -343,12 +337,6 @@ QString Generator::fileBase(const Node *node) const
base.prepend(outputPrefix(QLatin1String("QML")));
}
}
- else if (node->subType() == Node::QmlModule) {
- base.append("-qmlmodule");
- }
- else if (node->subType() == Node::Module) {
- base.append("-module");
- }
if (node->isExample() || node->isExampleFile()) {
QString modPrefix(node->moduleName());
if (modPrefix.isEmpty()) {
@@ -360,6 +348,19 @@ QString Generator::fileBase(const Node *node) const
base.append(QLatin1String("-example"));
}
}
+ else if (node->isCollectionNode()) {
+ base = node->name();
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
+
+ if (node->isQmlModule()) {
+ base.append("-qmlmodule");
+ }
+ else if (node->isModule()) {
+ base.append("-module");
+ }
+ // Why not add "-group" for gropup pages?
+ }
else {
const Node *p = node;
forever {
@@ -401,7 +402,7 @@ QString Generator::fileBase(const Node *node) const
while (res.endsWith(QLatin1Char('-')))
res.chop(1);
Node* n = const_cast<Node*>(node);
- n->setBaseName(res);
+ n->setFileNameBase(res);
return res;
}
@@ -455,7 +456,7 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
if (!fdl.isEmpty())
fdl.append(QLatin1Char('/'));
}
- if (node->type() == Node::Namespace) {
+ if (node->isNamespace()) {
// The root namespace has no name - check for this before creating
// an attribute containing the location of any documentation.
@@ -465,9 +466,8 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
else
return QString();
}
- else if (node->type() == Node::Document) {
- if ((node->subType() == Node::QmlClass) ||
- (node->subType() == Node::QmlBasicType)) {
+ else if (node->isDocNode() || node->isCollectionNode()) {
+ if (node->isQmlType() || node->isQmlBasicType()) {
QString fb = fileBase(node);
if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML"))))
return fb + QLatin1Char('.') + currentGenerator()->fileExtension();
@@ -562,6 +562,9 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
anchorRef = QLatin1Char('#') + node->name() + "-var";
break;
case Node::Document:
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
{
parentName = fileBase(node);
parentName.replace(QLatin1Char('/'), QLatin1Char('-')).replace(QLatin1Char('.'), QLatin1Char('-'));
@@ -841,6 +844,10 @@ void Generator::generateDocNode(DocNode* /* dn */, CodeMarker* /* marker */)
{
}
+void Generator::generateCollectionNode(CollectionNode* , CodeMarker* )
+{
+}
+
/*!
This function is called when the documentation for an
example is being formatted. It outputs the list of source
@@ -936,18 +943,20 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
@@ -996,19 +1005,49 @@ void Generator::generateInnerNode(InnerNode* node)
later in generateCollisionPages(). Each one is
appended to a list for later.
*/
- if ((node->type() == Node::Document) && (node->subType() == Node::Collision)) {
+ if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
else {
- beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ if (node->isNamespace() || node->isClass()) {
+ beginSubPage(node, fileName(node));
generateClassLikeNode(node, marker);
+ endSubPage();
}
- else if (node->type() == Node::Document) {
+ else if (node->isDocNode()) {
+ beginSubPage(node, fileName(node));
generateDocNode(static_cast<DocNode*>(node), marker);
+ endSubPage();
+ }
+ else if (node->isCollectionNode()) {
+ CollectionNode* cn = static_cast<CollectionNode*>(node);
+ /*
+ A collection node is one of: group, module,
+ or QML module.
+
+ Don't output an HTML page for the collection
+ node unless the \group, \module, or \qmlmodule
+ command was actually seen by qdoc in the qdoc
+ comment for the node.
+
+ A key prerequisite in this case is the call to
+ mergeCollections(cn). We don't know if this
+ collection (group, module, or QML module) has
+ members in other modules. We know at this point
+ that cn's members list contains only members in
+ the current module. Therefore, before outputting
+ the page for cn, we must search for members of
+ cn in the other modules and add them to the
+ members list.
+ */
+ if (cn->wasSeen()) {
+ qdb_->mergeCollections(cn);
+ beginSubPage(node, fileName(node));
+ generateCollectionNode(cn, marker);
+ endSubPage();
+ }
}
- endSubPage();
}
}
@@ -1066,7 +1105,7 @@ void Generator::generateQmlInheritedBy(const QmlClassNode* qcn,
/*!
*/
-void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
+void Generator::generateQmlInherits(QmlClassNode* , CodeMarker* )
{
// stub.
}
@@ -1362,11 +1401,11 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
/*!
- Traverses the database recursivly to generate all the documentation.
+ Traverses the current tree to generate all the documentation.
*/
-void Generator::generateTree()
+void Generator::generateDocs()
{
- generateInnerNode(qdb_->treeRoot());
+ generateInnerNode(qdb_->primaryTreeRoot());
}
Generator *Generator::generatorForFormat(const QString& format)
@@ -1650,6 +1689,7 @@ void Generator::initialize(const Config &config)
else
outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
noLinkErrors_ = config.getBool(CONFIG_NOLINKERRORS);
+ autolinkErrors_ = config.getBool(CONFIG_AUTOLINKERRORS);
}
/*!
@@ -1916,7 +1956,6 @@ void Generator::terminate()
imageDirs.clear();
outDir_.clear();
QmlClassNode::terminate();
- ExampleNode::terminate();
}
void Generator::terminateGenerator()
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index b464014308..a142afeac6 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -77,7 +77,7 @@ public:
virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
virtual QString format() = 0;
- virtual void generateTree();
+ virtual void generateDocs();
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
@@ -92,10 +92,11 @@ public:
static void terminate();
static void writeOutFileNames();
static void augmentImageDirs(QSet<QString>& moreImageDirs);
- static void debugSegfault(const QString& message);
- static void setDebugSegfaultFlag(bool b);
+ static void debug(const QString& message);
+ static void setDebugFlag(bool b);
static bool debugging() { return debugging_; }
static bool noLinkErrors() { return noLinkErrors_; }
+ static bool autolinkErrors() { return autolinkErrors_; }
static void setQDocPass(Passes pass) { qdocPass_ = pass; }
static bool runPrepareOnly() { return (qdocPass_ == Prepare); }
static bool runGenerateOnly() { return (qdocPass_ == Generate); }
@@ -109,27 +110,22 @@ protected:
virtual QString fileBase(const Node* node) const;
virtual QString fileExtension() const = 0;
virtual void generateAlsoList(const Node *node, CodeMarker *marker);
- virtual int generateAtom(const Atom *atom,
- const Node *relative,
- CodeMarker *marker);
+ virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker);
virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
- virtual void generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker);
- virtual void generateInherits(const ClassNode *classe,
- CodeMarker *marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
+ virtual void generateInheritedBy(const ClassNode *classe, CodeMarker *marker);
+ virtual void generateInherits(const ClassNode *classe, CodeMarker *marker);
virtual void generateInnerNode(InnerNode* node);
virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
- virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ virtual void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
virtual bool generateQmlText(const Text& text,
const Node *relative,
CodeMarker *marker,
const QString& qmlName);
- virtual bool generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker);
+ virtual bool generateText(const Text& text, const Node *relative, CodeMarker *marker);
virtual QString imageFileName(const Node *relative, const QString& fileBase);
virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
virtual QString typeString(const Node *node);
@@ -219,6 +215,7 @@ private:
static QStringList styleFiles;
static bool debugging_;
static bool noLinkErrors_;
+ static bool autolinkErrors_;
static bool redirectDocumentationToDevNull_;
static Passes qdocPass_;
static bool useOutputSubdirs_;
diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp
index d46f887518..be81d5c8dd 100644
--- a/src/tools/qdoc/helpprojectwriter.cpp
+++ b/src/tools/qdoc/helpprojectwriter.cpp
@@ -131,6 +131,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["function"] = Node::Function;
typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable;
+ typeHash["group"] = Node::Group;
+ typeHash["module"] = Node::Module;
+ typeHash["qmlmodule"] = Node::QmlModule;
typeHash["qmlproperty"] = Node::QmlProperty;
typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
@@ -141,8 +144,6 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["example"] = Node::Example;
subTypeHash["headerfile"] = Node::HeaderFile;
subTypeHash["file"] = Node::File;
- subTypeHash["group"] = Node::Group;
- subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage;
subTypeHash["qmlclass"] = Node::QmlClass;
@@ -316,6 +317,34 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
}
break;
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
+ {
+ const CollectionNode* cn = static_cast<const CollectionNode*>(node);
+ if (!cn->fullTitle().isEmpty()) {
+ if (cn->doc().hasKeywords()) {
+ foreach (const Atom* keyword, cn->doc().keywords()) {
+ if (!keyword->string().isEmpty()) {
+ QStringList details;
+ details << keyword->string()
+ << keyword->string()
+ << gen_->fullDocumentLocation(node, Generator::useOutputSubdirs()) +
+ QLatin1Char('#') + Doc::canonicalTitle(keyword->string());
+ project.keywords.append(details);
+ }
+ else
+ cn->doc().location().warning(
+ tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()))
+ );
+ }
+ }
+ project.keywords.append(keywordDetails(node));
+ project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
+ }
+ }
+ break;
+
case Node::Property:
case Node::QmlProperty:
case Node::QmlSignal:
@@ -601,6 +630,17 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
writer.writeEndElement(); // section
}
break;
+ case Node::Group:
+ case Node::Module:
+ case Node::QmlModule:
+ {
+ const CollectionNode* cn = static_cast<const CollectionNode*>(node);
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ writer.writeAttribute("title", cn->fullTitle());
+ writer.writeEndElement(); // section
+ }
+ break;
default:
;
}
@@ -612,7 +652,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (!project.indexRoot.isEmpty())
rootNode = qdb_->findDocNodeByTitle(project.indexRoot);
else
- rootNode = qdb_->treeRoot();
+ rootNode = qdb_->primaryTreeRoot();
if (!rootNode)
return;
@@ -655,7 +695,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
writer.writeStartElement("section");
const Node* node = qdb_->findDocNodeByTitle(project.indexTitle);
if (node == 0)
- node = qdb_->findNode(QStringList("index.html"));
+ node = qdb_->findNodeByNameAndType(QStringList("index.html"), Node::Document, Node::Page);
QString indexPath;
// Never use a collision node as a landing page
if (node && !node->isCollisionNode())
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 641e59f018..ceed09a7cf 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -264,16 +264,15 @@ QString HtmlGenerator::format()
}
/*!
- Traverses the database generating all the HTML documentation.
+ Traverses the current tree generating all the HTML documentation.
*/
-void HtmlGenerator::generateTree()
+void HtmlGenerator::generateDocs()
{
- qdb_->buildCollections();
Node* qflags = qdb_->findNodeByNameAndType(QStringList("QFlags"), Node::Class, Node::NoSubType);
if (qflags)
qflagsHref_ = linkForNode(qflags,0);
if (!runPrepareOnly()) {
- Generator::generateTree();
+ Generator::generateDocs();
generateCollisionPages();
}
@@ -303,10 +302,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
{
int skipAhead = 0;
static bool in_para = false;
-
+#if 0
if (Generator::debugging()) {
atom->dump();
}
+#endif
switch (atom->type()) {
case Atom::AbstractLeft:
if (relative)
@@ -320,6 +320,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
if (!inLink_ && !inContents_ && !inSectionHeading_) {
const Node *node = 0;
QString link = getLink(atom, relative, &node);
+ QDocDatabase::debug = false;
if (!link.isEmpty()) {
beginLink(link, node, relative);
generateLink(atom, marker);
@@ -327,6 +328,8 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
}
else {
out() << protectEnc(atom->string());
+ if (autolinkErrors())
+ relative->doc().location().warning(tr("Can't autolink to '%1'").arg(atom->string()));
}
}
else {
@@ -485,9 +488,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break;
case Atom::AnnotatedList:
{
- DocNode* dn = qdb_->getGroup(atom->string());
- if (dn)
- generateAnnotatedList(relative, marker, dn->members());
+ GroupNode* gn = qdb_->getGroup(atom->string());
+ if (gn)
+ generateList(gn, marker, atom->string());
}
break;
case Atom::GeneratedList:
@@ -504,10 +507,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB();
- DocNode* dn = qdb->findModule(moduleName);
- if (dn) {
+ ModuleNode* mn = qdb->findModule(moduleName);
+ if (mn) {
NodeMap m;
- dn->getMemberClasses(m);
+ mn->getMemberClasses(m);
if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m);
}
@@ -550,16 +553,25 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateCompactList(Generic, relative, qdb_->getServiceClasses(), false, QStringLiteral("Q"));
}
else if (atom->string() == "overviews") {
- generateOverviewList(relative);
+ generateList(relative, marker, "overviews");
+ }
+ else if (atom->string() == "cpp-modules") {
+ generateList(relative, marker, "cpp-modules");
+ }
+ else if (atom->string() == "qml-modules") {
+ generateList(relative, marker, "qml-modules");
}
else if (atom->string() == "namespaces") {
generateAnnotatedList(relative, marker, qdb_->getNamespaces());
}
else if (atom->string() == "related") {
- const DocNode *dn = static_cast<const DocNode *>(relative);
- if (dn)
- generateAnnotatedList(dn, marker, dn->members());
+ generateList(relative, marker, "related");
}
+#if 0
+ /*
+ This is not used in Qt5, as of 10/02/2014
+ Remove permanently if it is not missed.
+ */
else if (atom->string() == "relatedinline") {
const DocNode *dn = static_cast<const DocNode *>(relative);
if (dn && !dn->members().isEmpty()) {
@@ -573,6 +585,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateBody(node, marker);
}
}
+#endif
break;
case Atom::SinceList:
{
@@ -1341,7 +1354,6 @@ void HtmlGenerator::generateCollisionPages()
if (collisions.size() <= 1)
continue;
- ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->fullTitle();
QString htmlTitle = fullTitle;
@@ -1374,7 +1386,7 @@ void HtmlGenerator::generateCollisionPages()
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- if (n->findChildNodeByName(t.key())) {
+ if (n->findChildNode(t.key())) {
++count;
if (count > 1) {
targets.append(t.key());
@@ -1393,7 +1405,7 @@ void HtmlGenerator::generateCollisionPages()
out() << "<ul>\n";
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
- Node* p = n->findChildNodeByName(*t);
+ Node* p = n->findChildNode(*t);
if (p) {
QString link = linkForNode(p,0);
QString label;
@@ -1470,29 +1482,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
dn,
marker);
- if (dn->subType() == Node::Module) {
- // Generate brief text and status for modules.
- generateBrief(dn, marker);
- generateStatus(dn, marker);
- generateSince(dn, marker);
-
- NodeMap nm;
- dn->getMemberNamespaces(nm);
- if (!nm.isEmpty()) {
- out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Namespaces</h2>\n";
- generateAnnotatedList(dn, marker, nm);
- }
- nm.clear();
- dn->getMemberClasses(nm);
- if (!nm.isEmpty()) {
- out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n';
- out() << "<h2>Classes</h2>\n";
- generateAnnotatedList(dn, marker, nm);
- }
- nm.clear();
- }
- else if (dn->subType() == Node::HeaderFile) {
+ if (dn->subType() == Node::HeaderFile) {
// Generate brief text and status for modules.
generateBrief(dn, marker);
generateStatus(dn, marker);
@@ -1523,7 +1513,6 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
out() << "</ul>\n";
}
else if (dn->subType() == Node::QmlClass) {
- const_cast<DocNode*>(dn)->setCurrentChild();
ClassNode* cn = qml_cn->classNode();
generateBrief(qml_cn, marker);
generateQmlRequisites(qml_cn, marker);
@@ -1568,7 +1557,6 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
++s;
}
generateFooter(dn);
- const_cast<DocNode*>(dn)->clearCurrentChild();
return;
}
@@ -1581,29 +1569,100 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
++s;
}
- Text brief = dn->doc().briefText();
- if (dn->subType() == Node::Module && !brief.isEmpty()) {
- generateExtractionMark(dn, DetailedDescriptionMark);
+ generateExtractionMark(dn, DetailedDescriptionMark);
+ out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
+
+ generateBody(dn, marker);
+ out() << "</div>\n"; // QTBUG-9504
+ generateAlsoList(dn, marker);
+ generateExtractionMark(dn, EndMark);
+
+ sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay);
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
+ //out() << "<hr />\n";
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+
+ NodeList::ConstIterator m = (*s).members.constBegin();
+ while (m != (*s).members.constEnd()) {
+ generateDetailedMember(*m, dn, marker);
+ ++m;
+ }
+ ++s;
+ }
+ generateFooter(dn);
+}
+
+/*!
+ Generate the HTML page for a group, module, or QML module.
+ */
+void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
+{
+ SubTitleSize subTitleSize = LargeSubTitle;
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+ QString fullTitle = cn->fullTitle();
+ QString htmlTitle = fullTitle;
+
+ generateHeader(htmlTitle, cn, marker);
+ generateTableOfContents(cn,marker,0);
+ generateTitle(fullTitle, Text() << cn->subTitle(), subTitleSize, cn, marker);
+
+ if (cn->isModule()) {
+ // Generate brief text and status for modules.
+ generateBrief(cn, marker);
+ generateStatus(cn, marker);
+ generateSince(cn, marker);
+
+ NodeMap nm;
+ cn->getMemberNamespaces(nm);
+ if (!nm.isEmpty()) {
+ out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>Namespaces</h2>\n";
+ generateAnnotatedList(cn, marker, nm);
+ }
+ nm.clear();
+ cn->getMemberClasses(nm);
+ if (!nm.isEmpty()) {
+ out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>Classes</h2>\n";
+ generateAnnotatedList(cn, marker, nm);
+ }
+ nm.clear();
+ }
+
+ sections = marker->sections(cn, CodeMarker::Summary, CodeMarker::Okay);
+ s = sections.constBegin();
+ while (s != sections.constEnd()) {
+ out() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n';
+ out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
+ generateSectionList(*s, cn, marker, CodeMarker::Summary);
+ ++s;
+ }
+
+ Text brief = cn->doc().briefText();
+ if (cn->isModule() && !brief.isEmpty()) {
+ generateExtractionMark(cn, DetailedDescriptionMark);
out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n';
out() << "<div class=\"descr\">\n"; // QTBUG-9504
out() << "<h2>" << "Detailed Description" << "</h2>\n";
}
else {
- generateExtractionMark(dn, DetailedDescriptionMark);
+ generateExtractionMark(cn, DetailedDescriptionMark);
out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
}
- generateBody(dn, marker);
+ generateBody(cn, marker);
out() << "</div>\n"; // QTBUG-9504
- generateAlsoList(dn, marker);
- generateExtractionMark(dn, EndMark);
+ generateAlsoList(cn, marker);
+ generateExtractionMark(cn, EndMark);
- if ((dn->subType() == Node::Group))
- generateAnnotatedList(dn, marker, dn->members());
- else if (dn->subType() == Node::QmlModule)
- generateAnnotatedList(dn, marker, dn->members());
+ if (cn->isGroup())
+ generateAnnotatedList(cn, marker, cn->members());
+ else if (cn->isQmlModule())
+ generateAnnotatedList(cn, marker, cn->members());
- sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay);
+ sections = marker->sections(cn, CodeMarker::Detailed, CodeMarker::Okay);
s = sections.constBegin();
while (s != sections.constEnd()) {
//out() << "<hr />\n";
@@ -1611,12 +1670,12 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
NodeList::ConstIterator m = (*s).members.constBegin();
while (m != (*s).members.constEnd()) {
- generateDetailedMember(*m, dn, marker);
+ generateDetailedMember(*m, cn, marker);
++m;
}
++s;
}
- generateFooter(dn);
+ generateFooter(cn);
}
/*!
@@ -1892,7 +1951,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
if (inner->type() == Node::Class || inner->type() == Node::Namespace) {
//add the QT variable to the map
if (!inner->moduleName().isEmpty()) {
- DocNode * moduleNode = qdb_->findModule(inner->moduleName());
+ ModuleNode* moduleNode = qdb_->findModule(inner->moduleName());
if (moduleNode && !moduleNode->qtVariable().isEmpty()) {
text.clear();
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE)
@@ -1923,18 +1982,20 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
@@ -2002,9 +2063,9 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker)
//add the module name and version to the map
QString qmlModuleVersion;
- DocNode* dn = qdb_->findQmlModule(qcn->qmlModuleName());
- if (dn)
- qmlModuleVersion = dn->qmlModuleVersion();
+ QmlModuleNode* qmn = qdb_->findQmlModule(qcn->qmlModuleName());
+ if (qmn)
+ qmlModuleVersion = qmn->qmlModuleVersion();
else
qmlModuleVersion = qcn->qmlModuleVersion();
text.clear();
@@ -2044,7 +2105,7 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker)
}
//add the inherits to the map
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -2136,7 +2197,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
QList<Atom*> toc;
if (node->doc().hasTableOfContents())
toc = node->doc().tableOfContents();
- if (toc.isEmpty() && !sections && (node->subType() != Node::Module))
+ if (toc.isEmpty() && !sections && !node->isModule())
return;
QStringList sectionNumber;
@@ -2151,7 +2212,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
sectionNumber.append("1");
out() << "<ul>\n";
- if (node->subType() == Node::Module) {
+ if (node->isModule()) {
if (node->hasNamespaces()) {
out() << "<li class=\"level"
<< sectionNumber.size()
@@ -2178,9 +2239,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
}
}
}
- else if (sections && ((node->type() == Node::Class) ||
- (node->type() == Node::Namespace) ||
- (node->subType() == Node::QmlClass))) {
+ else if (sections && (node->isClass() || node->isNamespace() || node->isQmlType())) {
QList<Section>::ConstIterator s = sections->constBegin();
while (s != sections->constEnd()) {
if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
@@ -2278,8 +2337,7 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
the members of QML class \a qml_cn, including the inherited
members. The \a marker is used for formatting stuff.
*/
-QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn,
- CodeMarker* marker)
+QString HtmlGenerator::generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarker* marker)
{
QList<Section> sections;
QList<Section>::ConstIterator s;
@@ -2448,8 +2506,8 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classM
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && !d.isPrivate() && !d.node_->isInternal() && d.node_->hasDoc())
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -2469,33 +2527,29 @@ void HtmlGenerator::generateAnnotatedList(const Node* relative,
{
if (nodeMap.isEmpty())
return;
- NodeList nl;
- NodeMap::const_iterator i = nodeMap.begin();
- while (i != nodeMap.end()) {
- nl.append(i.value());
- ++i;
- }
- generateAnnotatedList(relative, marker, nl);
+ generateAnnotatedList(relative, marker, nodeMap.values());
}
+/*!
+ */
void HtmlGenerator::generateAnnotatedList(const Node *relative,
CodeMarker *marker,
- const NodeList& nodes)
+ const NodeList& unsortedNodes)
{
+ NodeMap nm;
bool allInternal = true;
- foreach (const Node* node, nodes) {
- if (!node->isInternal() && node->status() != Node::Obsolete) {
+ foreach (Node* node, unsortedNodes) {
+ if (!node->isInternal() && !node->isObsolete()) {
allInternal = false;
+ nm.insert(node->fullName(relative), node);
}
}
if (allInternal)
return;
out() << "<table class=\"annotated\">\n";
int row = 0;
+ NodeList nodes = nm.values();
foreach (const Node* node, nodes) {
- if (node->isInternal() || node->status() == Node::Obsolete)
- continue;
-
if (++row % 2 == 1)
out() << "<tr class=\"odd topAlign\">";
else
@@ -2504,7 +2558,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative,
generateFullName(node, relative);
out() << "</p></td>";
- if (!(node->type() == Node::Document)) {
+ if (!node->isDocNode()) {
Text brief = node->doc().trimmedBriefText(node->name());
if (!brief.isEmpty()) {
out() << "<td class=\"tblDescr\"><p>";
@@ -2786,117 +2840,105 @@ void HtmlGenerator::generateQmlItem(const Node *node,
marked.remove("<@type>");
marked.remove("</@type>");
}
- out() << highlightedCode(marked, relative, false, node);
+ out() << highlightedCode(marked, relative, false);
}
-void HtmlGenerator::generateOverviewList(const Node *relative)
+void HtmlGenerator::generateList(const Node* relative, CodeMarker* marker, const QString& selector)
{
- QMap<const DocNode *, QMap<QString, DocNode *> > docNodeMap;
- QMap<QString, const DocNode *> groupTitlesMap;
- QMap<QString, DocNode *> uncategorizedNodeMap;
+ NodeList nl;
+ CollectionList cl;
QRegExp singleDigit("\\b([0-9])\\b");
- const NodeList children = qdb_->treeRoot()->childNodes();
- foreach (Node *child, children) {
- if (child->type() == Node::Document && child != relative) {
- DocNode *docNode = static_cast<DocNode *>(child);
-
- // Check whether the page is part of a group or is the group
- // definition page.
- QString group;
- bool isGroupPage = false;
- if (docNode->doc().metaCommandsUsed().contains("group")) {
- group = docNode->doc().metaCommandArgs("group")[0].first;
- isGroupPage = true;
- }
-
- // there are too many examples; they would clutter the list
- if (docNode->subType() == Node::Example)
- continue;
-
- // not interested either in individual (Qt Designer etc.) manual chapters
- if (docNode->links().contains(Node::ContentsLink))
- continue;
-
- // Discard external nodes.
- if (docNode->subType() == Node::ExternalPage)
- continue;
-
- QString sortKey = docNode->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
-
- if (!group.isEmpty()) {
- if (isGroupPage) {
- // If we encounter a group definition page, we add all
- // the pages in that group to the list for that group.
- foreach (Node *member, docNode->members()) {
- if (member->isInternal() || member->type() != Node::Document)
- continue;
- DocNode *page = static_cast<DocNode *>(member);
- if (page) {
- QString sortKey = page->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
- docNodeMap[const_cast<const DocNode *>(docNode)].insert(sortKey, page);
- groupTitlesMap[docNode->fullTitle()] = const_cast<const DocNode *>(docNode);
- }
- }
- }
- else if (!isGroupPage) {
- // If we encounter a page that belongs to a group then
- // we add that page to the list for that group.
- const DocNode* gn = qdb_->getGroup(group);
- if (gn && !docNode->isInternal())
- docNodeMap[gn].insert(sortKey, docNode);
- }
- }
+ if (selector == "overviews") {
+ CNMap groups;
+ qdb_->mergeCollections(Node::Group, groups, relative);
+ cl = groups.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else if (selector == "cpp-modules") {
+ CNMap modules;
+ qdb_->mergeCollections(Node::Module, modules, relative);
+ cl = modules.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else if (selector == "qml-modules") {
+ CNMap qmlModules;
+ qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
+ cl = qmlModules.values();
+ foreach (CollectionNode* cn, cl)
+ nl.append(cn);
+ generateAnnotatedList(relative, marker, nl);
+ }
+ else {
+ /*
+ \generatelist {selector} is only allowed in a
+ comment where the topic is \group, \module, or
+ \qmlmodule.
+ */
+ if (!relative || !relative->isCollectionNode()) {
+ relative->doc().location().warning(tr("\\generatelist {%1} is only allowed in \\group, \\module, and \\qmlmodule comments.").arg(selector));
+ return;
+ }
+ if (selector == "related") {
+ Node* n = const_cast<Node*>(relative);
+ CollectionNode* cn = static_cast<CollectionNode*>(n);
+ qdb_->mergeCollections(cn);
+ generateAnnotatedList(cn, marker, cn->members());
+ }
+ else {
+ Node* n = const_cast<Node*>(relative);
+ CollectionNode* cn = static_cast<CollectionNode*>(n);
+ qdb_->mergeCollections(cn);
+ generateAnnotatedList(cn, marker, cn->members());
}
}
- // We now list all the pages found that belong to groups.
- // If only certain pages were found for a group, but the definition page
- // for that group wasn't listed, the list of pages will be intentionally
- // incomplete. However, if the group definition page was listed, all the
- // pages in that group are listed for completeness.
-
- if (!docNodeMap.isEmpty()) {
- foreach (const QString &groupTitle, groupTitlesMap.keys()) {
- const DocNode *groupNode = groupTitlesMap[groupTitle];
+#if 0
+ QStringList keys = groups.uniqueKeys();
+ foreach (QString key, keys) {
+ GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
+ if (gn) {
out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg(
- linkForNode(groupNode, relative)).arg(
- protectEnc(groupNode->fullTitle()));
-
- if (docNodeMap[groupNode].count() == 0)
+ linkForNode(gn, relative)).arg(
+ protectEnc(gn->fullTitle()));
+#if 0
+ if (gn->members().isEmpty())
continue;
- out() << "<ul>\n";
+ NodeMap nm;
+ foreach (Node* member, gn->members()) {
+ if (member->isInternal() || member->isExample() || member->isExternalPage() ||
+ member->isObsolete())
+ continue;
+ // not interested either in individual (Qt Designer etc.) manual chapters
+ if (member->links().contains(Node::ContentsLink))
+ continue;
+ QString sortKey = member->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ nm.insert(sortKey, member);
+ }
- foreach (const DocNode *docNode, docNodeMap[groupNode]) {
- QString title = docNode->fullTitle();
+ out() << "<ul>\n";
+ QStringList titles = nm.keys();
+ foreach (QString t, titles) {
+ Node* member = nm.value(t);
+ QString title = member->fullTitle();
if (title.startsWith("The "))
title.remove(0, 4);
- out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">"
+ out() << "<li><a href=\"" << linkForNode(member, relative) << "\">"
<< protectEnc(title) << "</a></li>\n";
}
out() << "</ul>\n";
+#endif
}
}
-
- if (!uncategorizedNodeMap.isEmpty()) {
- out() << QString("<h3>Miscellaneous</h3>\n");
- out() << "<ul>\n";
- foreach (const DocNode *docNode, uncategorizedNodeMap) {
- QString title = docNode->fullTitle();
- if (title.startsWith("The "))
- title.remove(0, 4);
- out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">"
- << protectEnc(title) << "</a></li>\n";
- }
- out() << "</ul>\n";
- }
+#endif
}
void HtmlGenerator::generateSection(const NodeList& nl,
@@ -3099,8 +3141,7 @@ void HtmlGenerator::generateSynopsis(const Node *node,
QString HtmlGenerator::highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames,
- const Node* self)
+ bool alignNames)
{
QString src = markedCode;
QString html;
@@ -3148,8 +3189,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
i += 2;
if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
-
- const Node* n = qdb_->resolveTarget(par1.toString(), relative);
+ const Node* n = qdb_->resolveFunctionTarget(par1.toString(), relative);
QString link = linkForNode(n, relative);
addLink(link, arg, &html);
par1 = QStringRef();
@@ -3164,7 +3204,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
}
}
- // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
+ // replace all "(<@(type|headerfile)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
src = html;
html = QString();
@@ -3174,7 +3214,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative, self);
+ const Node* n = qdb_->resolveType(arg.toString(), relative);
html += QLatin1String("<span class=\"type\">");
if (n && n->subType() == Node::QmlBasicType) {
if (relative && relative->subType() == Node::QmlClass)
@@ -3189,17 +3229,18 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
}
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative);
- addLink(linkForNode(n,relative), arg, &html);
- handled = true;
- }
- else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
- par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative);
- addLink(linkForNode(n,relative), arg, &html);
+ if (arg.at(0) == QChar('&'))
+ html += arg.toString();
+ else {
+ // zzz resolveClassTarget()
+ const Node* n = qdb_->resolveTarget(arg.toString(), relative);
+ if (n)
+ addLink(linkForNode(n,relative), arg, &html);
+ else
+ html += arg.toString();
+ }
handled = true;
}
-
if (!handled) {
html += charLangle;
html += charAt;
@@ -3721,45 +3762,35 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
*node = 0;
inObsoleteLink = false;
- if (atom->string().contains(QLatin1Char(':')) &&
- (atom->string().startsWith("file:")
- || atom->string().startsWith("http:")
- || atom->string().startsWith("https:")
- || atom->string().startsWith("ftp:")
- || atom->string().startsWith("mailto:"))) {
-
- link = atom->string();
+ if (atom->string().contains(QLatin1Char(':')) && (atom->string().startsWith("file:") ||
+ atom->string().startsWith("http:") ||
+ atom->string().startsWith("https:") ||
+ atom->string().startsWith("ftp:") ||
+ atom->string().startsWith("mailto:"))) {
+ link = atom->string(); // It's some kind of protocol.
}
else {
QStringList path;
- if (atom->string().contains('#')) {
- path = atom->string().split('#');
- }
- else {
- path.append(atom->string());
- }
+ if (atom->string().contains('#'))
+ path = atom->string().split('#'); // The target is in the html file.
+ else
+ path.append(atom->string()); // It's a general case target.
QString ref;
QString first = path.first().trimmed();
- if (first.isEmpty()) {
+ if (first.isEmpty())
*node = relative;
- }
- else if (first.endsWith(".html")) {
- /*
- This is not a recursive search. That's ok in
- this case, because we are searching for a page
- node, which must be a direct child of the tree
- root.
- */
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
+ else if (first.endsWith(".html")) // The target is an html file.
+ *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType);
+ else if (first.endsWith("()")) { // The target is a C++ function or QML method.
+ *node = qdb_->resolveFunctionTarget(first, relative);
}
else {
*node = qdb_->resolveTarget(first, relative);
- if (!*node) {
- *node = qdb_->findDocNodeByTitle(first, relative);
- }
- if (!*node) {
- *node = qdb_->findUnambiguousTarget(first, ref, relative);
+ if (!(*node))
+ *node = qdb_->findDocNodeByTitle(first);
+ if (!(*node)) {
+ *node = qdb_->findUnambiguousTarget(first, ref);
if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
QString final = (*node)->url() + "#" + ref;
return final;
@@ -3767,16 +3798,13 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
}
}
if (*node) {
- if (!(*node)->url().isEmpty()) {
+ if (!(*node)->url().isEmpty())
return (*node)->url();
- }
- else {
+ else
path.removeFirst();
- }
}
- else {
+ else
*node = relative;
- }
if (*node) {
if ((*node)->status() == Node::Obsolete) {
@@ -3801,10 +3829,8 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
}
}
}
- else {
- qDebug() << "Link to Obsolete entity"
- << (*node)->name() << "no relative";
- }
+ else
+ qDebug() << "Link to Obsolete entity" << (*node)->name() << "no relative";
}
}
@@ -3832,9 +3858,8 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
link = linkForNode(*node, relative);
if (*node && (*node)->subType() == Node::Image)
link = "images/used-in-examples/" + link;
- if (!ref.isEmpty()) {
+ if (!ref.isEmpty())
link += QLatin1Char('#') + ref;
- }
}
}
return link;
@@ -4018,7 +4043,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
- if (!qpn->isWritable(qdb_))
+ if (!qpn->isWritable())
out() << "<span class=\"qmlreadonly\">read-only</span>";
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
@@ -4039,7 +4064,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
if (!qpn->isReadOnlySet()) {
if (qpn->declarativeCppNode())
- qpn->setReadOnly(!qpn->isWritable(qdb_));
+ qpn->setReadOnly(!qpn->isWritable());
}
if (qpn->isReadOnly())
out() << "<span class=\"qmlreadonly\">read-only</span>";
@@ -4101,11 +4126,11 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
Output the "Inherits" line for the QML element,
if there should be one.
*/
-void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker)
+void HtmlGenerator::generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker)
{
if (!qcn)
return;
- const QmlClassNode* base = qcn->qmlBaseNode();
+ QmlClassNode* base = qcn->qmlBaseNode();
while (base && base->isInternal()) {
base = base->qmlBaseNode();
}
@@ -4229,7 +4254,7 @@ void HtmlGenerator::generateManifestFiles()
{
generateManifestFile("examples", "example");
generateManifestFile("demos", "demo");
- ExampleNode::exampleNodeMap.clear();
+ qdb_->exampleNodeMap().clear();
manifestMetaContent.clear();
}
@@ -4240,7 +4265,8 @@ void HtmlGenerator::generateManifestFiles()
*/
void HtmlGenerator::generateManifestFile(QString manifest, QString element)
{
- if (ExampleNode::exampleNodeMap.isEmpty())
+ ExampleNodeMap& exampleNodeMap = qdb_->exampleNodeMap();
+ if (exampleNodeMap.isEmpty())
return;
QString fileName = manifest +"-manifest.xml";
QFile file(outputDir() + QLatin1Char('/') + fileName);
@@ -4251,8 +4277,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
demos = true;
bool proceed = false;
- ExampleNodeMap::Iterator i = ExampleNode::exampleNodeMap.begin();
- while (i != ExampleNode::exampleNodeMap.end()) {
+ ExampleNodeMap::Iterator i = exampleNodeMap.begin();
+ while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value();
if (demos) {
if (en->name().startsWith("demos")) {
@@ -4276,8 +4302,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
writer.writeAttribute("module", project);
writer.writeStartElement(manifest);
- i = ExampleNode::exampleNodeMap.begin();
- while (i != ExampleNode::exampleNodeMap.end()) {
+ i = exampleNodeMap.begin();
+ while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value();
if (demos) {
if (!en->name().startsWith("demos")) {
@@ -4501,6 +4527,12 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::Class:
break;
+ case Node::Group:
+ break;
+ case Node::Module:
+ break;
+ case Node::QmlModule:
+ break;
case Node::Document:
switch (child->subType()) {
case Node::Example:
@@ -4511,10 +4543,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::Image:
break;
- case Node::Group:
- break;
- case Node::Module:
- break;
case Node::Page:
break;
case Node::ExternalPage:
@@ -4523,8 +4551,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::QmlBasicType:
break;
- case Node::QmlModule:
- break;
case Node::Collision:
break;
default:
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index ae16f3c54f..58289d7030 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -88,7 +88,7 @@ public:
virtual void initializeGenerator(const Config& config);
virtual void terminateGenerator();
virtual QString format();
- virtual void generateTree();
+ virtual void generateDocs();
void generateCollisionPages();
void generateManifestFiles();
@@ -103,6 +103,7 @@ protected:
CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
+ virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const;
virtual QString refForNode(const Node *node);
virtual QString linkForNode(const Node *node, const Node *relative);
@@ -152,8 +153,7 @@ private:
QList<Section>* sections = 0);
QString generateListOfAllMemberFile(const InnerNode *inner,
CodeMarker *marker);
- QString generateAllQmlMembersFile(const QmlClassNode* qml_cn,
- CodeMarker* marker);
+ QString generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarker* marker);
QString generateLowStatusMemberFile(InnerNode *inner,
CodeMarker *marker,
CodeMarker::Status status);
@@ -167,7 +167,7 @@ private:
QString commonPrefix);
void generateFunctionIndex(const Node *relative);
void generateLegaleseList(const Node *relative, CodeMarker *marker);
- void generateOverviewList(const Node *relative);
+ void generateList(const Node* relative, CodeMarker* marker, const QString& selector);
void generateSectionList(const Section& section,
const Node *relative,
CodeMarker *marker,
@@ -182,7 +182,7 @@ private:
void generateDetailedQmlMember(Node *node,
const InnerNode *relative,
CodeMarker *marker);
- void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
+ void generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
@@ -200,8 +200,7 @@ private:
void generateSectionInheritedList(const Section& section, const Node *relative);
QString highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames = false,
- const Node* self = 0);
+ bool alignNames = false);
void generateFullName(const Node *apparentNode, const Node *relative, const Node *actualNode = 0);
void generateDetailedMember(const Node *node,
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 398d188464..9e0aecf393 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -78,6 +78,7 @@ static bool highlighting = false;
static bool showInternal = false;
static bool redirectDocumentationToDevNull = false;
static bool noLinkErrors = false;
+static bool autolinkErrors = false;
static bool obsoleteLinks = false;
static QStringList defines;
static QStringList dependModules;
@@ -282,6 +283,7 @@ static void processQdocconfFile(const QString &fileName)
config.setStringList(CONFIG_SHOWINTERNAL, QStringList(showInternal ? "true" : "false"));
config.setStringList(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL, QStringList(redirectDocumentationToDevNull ? "true" : "false"));
config.setStringList(CONFIG_NOLINKERRORS, QStringList(noLinkErrors ? "true" : "false"));
+ config.setStringList(CONFIG_AUTOLINKERRORS, QStringList(autolinkErrors ? "true" : "false"));
config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false"));
/*
@@ -296,7 +298,7 @@ static void processQdocconfFile(const QString &fileName)
currentDir = QFileInfo(fileName).path();
Location::initialize(config);
config.load(fileName);
-
+ //qDebug() << "\nSTART PROJECT:" << config.getString(CONFIG_PROJECT).toLower();
/*
Add the defines to the configuration variables.
*/
@@ -371,6 +373,8 @@ static void processQdocconfFile(const QString &fileName)
//if (!Generator::runPrepareOnly())
loadIndexFiles(config);
+ qdb->newPrimaryTree(config.getString(CONFIG_PROJECT));
+ qdb->setSearchOrder();
QSet<QString> excludedDirs;
QSet<QString> excludedFiles;
@@ -379,7 +383,7 @@ static void processQdocconfFile(const QString &fileName)
QStringList excludedDirsList;
QStringList excludedFilesList;
- Generator::debugSegfault("Reading excludedirs");
+ Generator::debug("Reading excludedirs");
excludedDirsList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS);
foreach (const QString &excludeDir, excludedDirsList) {
QString p = QDir::fromNativeSeparators(excludeDir);
@@ -388,14 +392,14 @@ static void processQdocconfFile(const QString &fileName)
excludedDirs.insert(p);
}
- Generator::debugSegfault("Reading excludefiles");
+ Generator::debug("Reading excludefiles");
excludedFilesList = config.getCleanPathList(CONFIG_EXCLUDEFILES);
foreach (const QString& excludeFile, excludedFilesList) {
QString p = QDir::fromNativeSeparators(excludeFile);
excludedFiles.insert(p);
}
- Generator::debugSegfault("Reading headerdirs");
+ Generator::debug("Reading headerdirs");
headerList = config.getAllFiles(CONFIG_HEADERS,CONFIG_HEADERDIRS,excludedDirs,excludedFiles);
QMap<QString,QString> headers;
QMultiMap<QString,QString> headerFileNames;
@@ -409,7 +413,7 @@ static void processQdocconfFile(const QString &fileName)
headerFileNames.insert(t,t);
}
- Generator::debugSegfault("Reading sourcedirs");
+ Generator::debug("Reading sourcedirs");
sourceList = config.getAllFiles(CONFIG_SOURCES,CONFIG_SOURCEDIRS,excludedDirs,excludedFiles);
QMap<QString,QString> sources;
QMultiMap<QString,QString> sourceFileNames;
@@ -426,7 +430,7 @@ static void processQdocconfFile(const QString &fileName)
Find all the qdoc files in the example dirs, and add
them to the source files to be parsed.
*/
- Generator::debugSegfault("Reading exampledirs");
+ Generator::debug("Reading exampledirs");
QStringList exampleQdocList = config.getExampleQdocFiles(excludedDirs, excludedFiles);
for (int i=0; i<exampleQdocList.size(); ++i) {
if (!sources.contains(exampleQdocList[i])) {
@@ -436,7 +440,7 @@ static void processQdocconfFile(const QString &fileName)
}
}
- Generator::debugSegfault("Adding doc/image dirs found in exampledirs to imagedirs");
+ Generator::debug("Adding doc/image dirs found in exampledirs to imagedirs");
QSet<QString> exampleImageDirs;
QStringList exampleImageList = config.getExampleImageFiles(excludedDirs, excludedFiles);
for (int i=0; i<exampleImageList.size(); ++i) {
@@ -454,8 +458,9 @@ static void processQdocconfFile(const QString &fileName)
to the big tree.
*/
QSet<CodeParser *> usedParsers;
+ //Config::debug_ = true;
- Generator::debugSegfault("Parsing header files");
+ Generator::debug("Parsing header files");
int parsed = 0;
QMap<QString,QString>::ConstIterator h = headers.constBegin();
while (h != headers.constEnd()) {
@@ -472,22 +477,28 @@ static void processQdocconfFile(const QString &fileName)
codeParser->doneParsingHeaderFiles();
usedParsers.clear();
+ qdb->resolveInheritance();
+
/*
Parse each source text file in the set using the appropriate parser and
add it to the big tree.
*/
parsed = 0;
- Generator::debugSegfault("Parsing source files");
+ Generator::debug("Parsing source files");
QMap<QString,QString>::ConstIterator s = sources.constBegin();
while (s != sources.constEnd()) {
CodeParser *codeParser = CodeParser::parserForSourceFile(s.key());
if (codeParser) {
++parsed;
+ //Generator::setDebugFlag(true);
+ Generator::debug(QString("Parsing " + s.key()));
codeParser->parseSourceFile(config.location(), s.key());
usedParsers.insert(codeParser);
}
++s;
}
+ Generator::debug(QString("Parsing done."));
+ //Generator::setDebugFlag(false);
foreach (CodeParser *codeParser, usedParsers)
codeParser->doneParsingSourceFiles();
@@ -497,7 +508,7 @@ static void processQdocconfFile(const QString &fileName)
source files. Resolve all the class names, function names,
targets, URLs, links, and other stuff that needs resolving.
*/
- Generator::debugSegfault("Resolving stuff prior to generating docs");
+ Generator::debug("Resolving stuff prior to generating docs");
qdb->resolveIssues();
/*
@@ -506,19 +517,19 @@ static void processQdocconfFile(const QString &fileName)
documentation output. More than one output format can be
requested. The tree is traversed for each one.
*/
- Generator::debugSegfault("Generating docs");
+ Generator::debug("Generating docs");
QSet<QString>::ConstIterator of = outputFormats.constBegin();
while (of != outputFormats.constEnd()) {
Generator* generator = Generator::generatorForFormat(*of);
if (generator == 0)
outputFormatsLocation.fatal(QCoreApplication::translate("QDoc", "Unknown output format '%1'").arg(*of));
- generator->generateTree();
+ generator->generateDocs();
++of;
}
//Generator::writeOutFileNames();
- Generator::debugSegfault("Shutting down qdoc");
+ Generator::debug("Shutting down qdoc");
QDocDatabase::qdocDB()->setVersion(QString());
Generator::terminate();
@@ -539,7 +550,7 @@ static void processQdocconfFile(const QString &fileName)
#ifdef DEBUG_SHUTDOWN_CRASH
qDebug() << "main(): qdoc database deleted";
#endif
- Generator::debugSegfault("qdoc finished!");
+ Generator::debug("qdoc finished!");
}
QT_END_NAMESPACE
@@ -639,8 +650,11 @@ int main(int argc, char **argv)
else if (opt == "-no-link-errors") {
noLinkErrors = true;
}
+ else if (opt == "-autolink-errors") {
+ autolinkErrors = true;
+ }
else if (opt == "-debug") {
- Generator::setDebugSegfaultFlag(true);
+ Generator::setDebugFlag(true);
}
else if (opt == "-prepare") {
Generator::setQDocPass(Generator::Prepare);
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index c88ebfc760..730d2d5663 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -50,7 +50,6 @@
QT_BEGIN_NAMESPACE
int Node::propertyGroupCount_ = 0;
-ExampleNodeMap ExampleNode::exampleNodeMap;
QStringMap Node::operators_;
/*!
@@ -127,14 +126,14 @@ QString Node::plainFullName(const Node* relative) const
*/
QString Node::fullName(const Node* relative) const
{
- if (type() == Node::Document) {
+ if (isDocNode() || isCollectionNode()) {
const DocNode* dn = static_cast<const DocNode*>(this);
// Only print modulename::type on collision pages.
if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode())
return dn->qmlModuleName() + "::" + dn->title();
return dn->title();
}
- else if (type() == Node::Class) {
+ else if (isClass()) {
const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty())
return cn->serviceName();
@@ -143,6 +142,31 @@ QString Node::fullName(const Node* relative) const
}
/*!
+ Try to match this node's type and subtype with one of the
+ pairs in \a types. If a match is found, return true. If no
+ match is found, return false.
+
+ \a types is a list of type/subtype pairs, where the first
+ value in the pair is a Node::Type, and the second value is
+ a Node::SubType. The second value is used in the match if
+ this node's type is Node::Document.
+ */
+bool Node::match(const NodeTypeList& types) const
+{
+ for (int i=0; i<types.size(); ++i) {
+ if (type() == types.at(i).first) {
+ if (type() == Node::Document) {
+ if (subType() == types.at(i).second)
+ return true;
+ }
+ else
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
Sets this Node's Doc to \a doc. If \a replace is false and
this Node already has a Doc, a warning is reported that the
Doc is being overridden, and it reports where the previous
@@ -170,7 +194,6 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
pageType_(NoPageType),
status_(Commendable),
indexNodeFlag_(false),
- seen_(true),
parent_(parent),
relatesTo_(0),
name_(name)
@@ -224,21 +247,13 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
}
}
-/*!
+/*! \fn QString Node::url() const
Returns the node's URL.
*/
-QString Node::url() const
-{
- return url_;
-}
-/*!
+/*! \fn void Node::setUrl(const QString &url)
Sets the node's URL to \a url
*/
-void Node::setUrl(const QString &url)
-{
- url_ = url;
-}
/*!
Returns this node's page type as a string, for use as an
@@ -309,6 +324,12 @@ QString Node::nodeTypeString(unsigned t)
return "property";
case Variable:
return "variable";
+ case Group:
+ return "group";
+ case Module:
+ return "module";
+ case QmlModule:
+ return "QML module";
case QmlProperty:
return "QML property";
case QmlPropertyGroup:
@@ -351,10 +372,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "file";
case Image:
return "image";
- case Group:
- return "group";
- case Module:
- return "module";
case Page:
return "page";
case ExternalPage:
@@ -363,8 +380,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "QML type";
case QmlBasicType:
return "QML basic type";
- case QmlModule:
- return "QML module";
case DitaMap:
return "ditamap";
case Collision:
@@ -515,7 +530,7 @@ QString Node::extractClassName(const QString &string) const
*/
QString RelatedClass::accessString() const
{
- switch (access) {
+ switch (access_) {
case Node::Protected:
return "protected";
case Node::Private:
@@ -654,101 +669,21 @@ InnerNode::~InnerNode()
}
/*!
- Returns \c true if this node's members coolection is not empty.
- */
-bool InnerNode::hasMembers() const
-{
- return !members_.isEmpty();
-}
-
-/*!
- Appends \a node to the members list, if and only if it
- isn't already in the members list.
- */
-void InnerNode::addMember(Node* node)
-{
- if (!members_.contains(node))
- members_.append(node);
-}
-
-/*!
- Returns \c true if this node's members collection contains at
- least one namespace node.
- */
-bool InnerNode::hasNamespaces() const
-{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- return true;
- ++i;
- }
- }
- return false;
-}
-
-/*!
- Returns \c true if this node's members collection contains at
- least one class node.
- */
-bool InnerNode::hasClasses() const
-{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- return true;
- ++i;
- }
- }
- return false;
-}
-
-/*!
- Loads \a out with all this node's member nodes that are namespace nodes.
- */
-void InnerNode::getMemberNamespaces(NodeMap& out)
-{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- out.insert((*i)->name(),(*i));
- ++i;
- }
-}
-
-/*!
- Loads \a out with all this node's member nodes that are class nodes.
- */
-void InnerNode::getMemberClasses(NodeMap& out)
-{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- out.insert((*i)->name(),(*i));
- ++i;
- }
-}
-
-/*!
Find the node in this node's children that has the
given \a name. If this node is a QML class node, be
sure to also look in the children of its property
group nodes. Return the matching node or 0.
*/
-Node *InnerNode::findChildNodeByName(const QString& name)
+Node *InnerNode::findChildNode(const QString& name) const
{
Node *node = childMap.value(name);
- if (node && node->type() != QmlPropertyGroup)
+ if (node && !node->isQmlPropertyGroup())
return node;
- if ((type() == Document) && (subType() == QmlClass)) {
+ if (isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
- if (n->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
+ if (n->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(n)->findChildNode(name);
if (node)
return node;
}
@@ -756,58 +691,6 @@ Node *InnerNode::findChildNodeByName(const QString& name)
}
return primaryFunctionMap.value(name);
}
-void InnerNode::findNodes(const QString& name, QList<Node*>& n)
-{
- n.clear();
- Node* node = 0;
- QList<Node*> nodes = childMap.values(name);
- /*
- <sigh> If this node's child map contains no nodes named
- name, then if this node is a QML class, seach each of its
- property group nodes for a node named name. If a match is
- found, append it to the output list and return immediately.
- */
- if (nodes.isEmpty()) {
- if ((type() == Document) && (subType() == QmlClass)) {
- for (int i=0; i<children_.size(); ++i) {
- node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
- if (node) {
- n.append(node);
- return;
- }
- }
- }
- }
- }
- else {
- /*
- If the childMap does contain one or more nodes named
- name, traverse the list of matching nodes. Append each
- matching node that is not a property group node to the
- output list. Search each property group node for a node
- named name and append that node to the output list.
- This is overkill, I think, but should produce a useful
- list.
- */
- for (int i=0; i<nodes.size(); ++i) {
- node = nodes.at(i);
- if (node->type() != QmlPropertyGroup)
- n.append(node);
- else {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
- if (node)
- n.append(node);
- }
- }
- }
- if (!n.isEmpty())
- return;
- node = primaryFunctionMap.value(name);
- if (node)
- n.append(node);
-}
/*!
Find the node in this node's children that has the given \a name. If
@@ -819,7 +702,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
returns \c true. If \a qml is false, only match a node for which
node->isQmlNode() returns \c false.
*/
-Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
+Node* InnerNode::findChildNode(const QString& name, bool qml) const
{
QList<Node*> nodes = childMap.values(name);
if (!nodes.isEmpty()) {
@@ -829,15 +712,15 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
if (!node->isQmlNode())
return node;
}
- else if (node->isQmlNode() && (node->type() != QmlPropertyGroup))
+ else if (node->isQmlNode() && !node->isQmlPropertyGroup())
return node;
}
}
- if (qml && (type() == Document) && (subType() == QmlClass)) {
+ if (qml && isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
if (node)
return node;
}
@@ -847,7 +730,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
}
/*!
- This function is like findChildNodeByName(), but if a node
+ This function is like findChildNode(), but if a node
with the specified \a name is found but it is not of the
specified \a type, 0 is returned.
@@ -857,7 +740,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
node because it looks up \a name in the child map, not the
list.
*/
-Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
+Node* InnerNode::findChildNode(const QString& name, Type type)
{
if (type == Function)
return primaryFunctionMap.value(name);
@@ -873,10 +756,65 @@ Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
}
/*!
+ */
+void InnerNode::findNodes(const QString& name, QList<Node*>& n)
+{
+ n.clear();
+ Node* node = 0;
+ QList<Node*> nodes = childMap.values(name);
+ /*
+ <sigh> If this node's child map contains no nodes named
+ name, then if this node is a QML class, search each of its
+ property group nodes for a node named name. If a match is
+ found, append it to the output list and return immediately.
+ */
+ if (nodes.isEmpty()) {
+ if (isQmlType()) {
+ for (int i=0; i<children_.size(); ++i) {
+ node = children_.at(i);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
+ if (node) {
+ n.append(node);
+ return;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /*
+ If the childMap does contain one or more nodes named
+ name, traverse the list of matching nodes. Append each
+ matching node that is not a property group node to the
+ output list. Search each property group node for a node
+ named name and append that node to the output list.
+ This is overkill, I think, but should produce a useful
+ list.
+ */
+ for (int i=0; i<nodes.size(); ++i) {
+ node = nodes.at(i);
+ if (!node->isQmlPropertyGroup())
+ n.append(node);
+ else {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
+ if (node)
+ n.append(node);
+ }
+ }
+ }
+ if (!n.isEmpty())
+ return;
+ node = primaryFunctionMap.value(name);
+ if (node)
+ n.append(node);
+}
+
+/*!
Find a function node that is a child of this nose, such
that the function node has the specified \a name.
*/
-FunctionNode *InnerNode::findFunctionNode(const QString& name)
+FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
}
@@ -985,19 +923,6 @@ void InnerNode::makeUndocumentedChildrenInternal()
}
/*!
- In each child node that is a collision node,
- clear the current child pointer.
- */
-void InnerNode::clearCurrentChildPointers()
-{
- foreach (Node* child, childNodes()) {
- if (child->subType() == Collision) {
- child->clearCurrentChild();
- }
- }
-}
-
-/*!
*/
void InnerNode::normalizeOverloads()
{
@@ -1092,64 +1017,17 @@ bool Node::isWrapper() const
}
/*!
- */
-const Node *InnerNode::findChildNodeByName(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByName(name);
-}
-
-/*!
- If \a qml is true, only match a node for which node->isQmlNode()
- returns \c true. If \a qml is false, only match a node for which
- node->isQmlNode() returns \c false.
- */
-const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
-{
- InnerNode*that = (InnerNode*) this;
- return that->findChildNodeByName(name, qml);
-}
-
-/*!
- Searches this node's children for a child named \a name
- with the specified node \a type.
- */
-const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByNameAndType(name, type);
-}
-
-/*!
- Find a function node that is a child of this nose, such
- that the function node has the specified \a name. This
- function calls the non-const version of itself.
- */
-const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(name);
-}
-
-/*!
- Find the function node that is a child of this node, such
- that the function has the same name and signature as the
- \a clone node. This function calls the non-const version.
- */
-const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(clone);
-}
-
-/*!
+ Finds the enum type node that has \a enumValue as one of
+ its enum values and returns a pointer to it. Returns 0 if
+ no enum type node is found that has \a enumValue as one
+ of its values.
*/
const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
{
foreach (const Node *node, enumChildren_) {
- const EnumNode *enume = static_cast<const EnumNode *>(node);
- if (enume->hasItem(enumValue))
- return enume;
+ const EnumNode *en = static_cast<const EnumNode *>(node);
+ if (en->hasItem(enumValue))
+ return en;
}
return 0;
}
@@ -1278,6 +1156,17 @@ void InnerNode::addChild(Node *child)
}
/*!
+ Adds the \a child to this node's child map using \a title
+ as the key. The \a child is not added to the child list
+ again, because it is presumed to already be there. We just
+ want to be able to find the child by its \a title.
+ */
+void InnerNode::addChild(Node* child, const QString& title)
+{
+ childMap.insertMulti(title, child);
+}
+
+/*!
*/
void InnerNode::removeChild(Node *child)
{
@@ -1307,6 +1196,16 @@ void InnerNode::removeChild(Node *child)
}
++ent;
}
+ if (child->title().isEmpty())
+ return;
+ ent = childMap.find(child->title());
+ while (ent != childMap.end() && ent.key() == child->title()) {
+ if (*ent == child) {
+ childMap.erase(ent);
+ break;
+ }
+ ++ent;
+ }
}
/*!
@@ -1381,7 +1280,7 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
if (child->name() == n)
return static_cast<QmlPropertyNode*>(child);
}
- else if (child->type() == Node::QmlPropertyGroup) {
+ else if (child->isQmlPropertyGroup()) {
QmlPropertyNode* t = child->hasQmlProperty(n);
if (t)
return t;
@@ -1480,13 +1379,36 @@ ClassNode::ClassNode(InnerNode *parent, const QString& name)
}
/*!
+ Adds the base class \a node to this class's list of base
+ classes. The base class has the specified \a access. This
+ is a resolved base class.
*/
-void ClassNode::addBaseClass(Access access,
- ClassNode *node,
- const QString &dataTypeWithTemplateArgs)
+void ClassNode::addResolvedBaseClass(Access access, ClassNode* node)
{
- bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
- node->derived.append(RelatedClass(access, this));
+ bases_.append(RelatedClass(access, node));
+ node->derived_.append(RelatedClass(access, this));
+}
+
+/*!
+ Adds the derived class \a node to this class's list of derived
+ classes. The derived class inherits this class with \a access.
+ */
+void ClassNode::addDerivedClass(Access access, ClassNode* node)
+{
+ derived_.append(RelatedClass(access, node));
+}
+
+/*!
+ Add an unresolved base class to this class node's list of
+ base classes. The unresolved base class will be resolved
+ before the generate phase of qdoc. In an unresolved base
+ class, the pointer to the base class node is 0.
+ */
+void ClassNode::addUnresolvedBaseClass(Access access,
+ const QStringList& path,
+ const QString& signature)
+{
+ bases_.append(RelatedClass(access, path, signature));
}
/*!
@@ -1498,15 +1420,15 @@ void ClassNode::fixBaseClasses()
QSet<ClassNode *> found;
// Remove private and duplicate base classes.
- while (i < bases.size()) {
- ClassNode* bc = bases.at(i).node;
- if (bc->access() == Node::Private || found.contains(bc)) {
- RelatedClass rc = bases.at(i);
- bases.removeAt(i);
- ignoredBases.append(rc);
+ while (i < bases_.size()) {
+ ClassNode* bc = bases_.at(i).node_;
+ if (bc && (bc->access() == Node::Private || found.contains(bc))) {
+ RelatedClass rc = bases_.at(i);
+ bases_.removeAt(i);
+ ignoredBases_.append(rc);
const QList<RelatedClass> &bb = bc->baseClasses();
for (int j = bb.size() - 1; j >= 0; --j)
- bases.insert(i, bb.at(j));
+ bases_.insert(i, bb.at(j));
}
else {
++i;
@@ -1515,13 +1437,13 @@ void ClassNode::fixBaseClasses()
}
i = 0;
- while (i < derived.size()) {
- ClassNode* dc = derived.at(i).node;
- if (dc->access() == Node::Private) {
- derived.removeAt(i);
+ while (i < derived_.size()) {
+ ClassNode* dc = derived_.at(i).node_;
+ if (dc && dc->access() == Node::Private) {
+ derived_.removeAt(i);
const QList<RelatedClass> &dd = dc->derivedClasses();
for (int j = dd.size() - 1; j >= 0; --j)
- derived.insert(i, dd.at(j));
+ derived_.insert(i, dd.at(j));
}
else {
++i;
@@ -1530,12 +1452,34 @@ void ClassNode::fixBaseClasses()
}
/*!
+ Not sure why this is needed.
+ */
+void ClassNode::fixPropertyUsingBaseClasses(PropertyNode* pn)
+{
+ QList<RelatedClass>::const_iterator bc = baseClasses().constBegin();
+ while (bc != baseClasses().constEnd()) {
+ ClassNode* cn = bc->node_;
+ if (cn) {
+ Node* n = cn->findChildNode(pn->name(), Node::Property);
+ if (n) {
+ PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
+ cn->fixPropertyUsingBaseClasses(baseProperty);
+ pn->setOverriddenFrom(baseProperty);
+ }
+ else
+ cn->fixPropertyUsingBaseClasses(pn);
+ }
+ ++bc;
+ }
+}
+
+/*!
Search the child list to find the property node with the
specified \a name.
*/
PropertyNode* ClassNode::findPropertyNode(const QString& name)
{
- Node* n = findChildNodeByNameAndType(name, Node::Property);
+ Node* n = findChildNode(name, Node::Property);
if (n)
return static_cast<PropertyNode*>(n);
@@ -1545,19 +1489,23 @@ PropertyNode* ClassNode::findPropertyNode(const QString& name)
const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = bases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) {
- ClassNode* cn = ignoredBases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = ignoredBases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
@@ -1577,13 +1525,13 @@ QmlClassNode* ClassNode::findQmlBaseNode()
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn && cn->qmlElement()) {
return cn->qmlElement();
}
}
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn) {
result = cn->findQmlBaseNode();
if (result != 0) {
@@ -1614,13 +1562,6 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
case DitaMap:
setPageType(ptype);
break;
- case Module:
- case Group:
- setPageType(OverviewPage);
- break;
- case QmlModule:
- setPageType(OverviewPage);
- break;
case QmlClass:
case QmlBasicType:
setPageType(ApiPage);
@@ -1636,12 +1577,17 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
}
}
-/*!
+/*! \fn QString DocNode::title() const
Returns the document node's title. This is used for the page title.
*/
-QString DocNode::title() const
+
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void DocNode::setTitle(const QString &title)
{
- return title_;
+ title_ = title;
+ parent()->addChild(this, title);
}
/*!
@@ -1693,16 +1639,6 @@ QString DocNode::subTitle() const
}
/*!
- The constructor calls the DocNode constructor with
- \a parent, \a name, and Node::Example.
- */
-ExampleNode::ExampleNode(InnerNode* parent, const QString& name)
- : DocNode(parent, name, Node::Example, Node::ExamplePage)
-{
- // nothing
-}
-
-/*!
\class EnumNode
*/
@@ -2126,7 +2062,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name)
wrapper_(false),
cnode_(0),
qmlModule_(0),
- baseNode_(0)
+ qmlBaseNode_(0)
{
int i = 0;
if (name.startsWith("QML:")) {
@@ -2198,6 +2134,14 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
}
}
+QmlClassNode* QmlClassNode::qmlBaseNode()
+{
+ if (!qmlBaseNode_ && !qmlBaseName_.isEmpty()) {
+ qmlBaseNode_ = QDocDatabase::qdocDB()->findQmlType(qmlBaseName_);
+ }
+ return qmlBaseNode_;
+}
+
/*!
If this QML type node has a base type node,
return the fully qualified name of that QML
@@ -2206,45 +2150,13 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
QString QmlClassNode::qmlFullBaseName() const
{
QString result;
- if (baseNode_) {
- result = baseNode_->qmlModuleName() + "::" + baseNode_->name();
+ if (qmlBaseNode_) {
+ result = qmlBaseNode_->qmlModuleName() + "::" + qmlBaseNode_->name();
}
return result;
}
/*!
- The name of this QML class node might be the same as the
- name of some other QML class node. If so, then this node's
- parent will be a NameCollisionNode.This function sets the
- NameCollisionNode's current child to this node. This is
- important when outputting the documentation for this node,
- when, for example, the documentation contains a link to
- the page being output. We don't want to generate a link
- to the disambiguation page if we can avoid it, and to be
- able to avoid it, the NameCollisionNode must maintain the
- current child pointer. That's the purpose of this function.
- */
-void QmlClassNode::setCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->setCurrentChild(this);
- }
-}
-
-/*!
- */
-void QmlClassNode::clearCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->clearCurrentChild();
- }
-}
-
-/*!
If the QML type's QML module pointer is set, return the QML
module name from the QML module node. Otherwise, return the
empty string.
@@ -2345,7 +2257,7 @@ QmlPropertyNode::QmlPropertyNode(InnerNode* parent,
...because the tokenizer gets confused on \e{explicit}.
*/
-bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
+bool QmlPropertyNode::isWritable()
{
if (readOnly_ != FlagValueDefault)
return !fromFlagValue(readOnly_, false);
@@ -2354,7 +2266,7 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
if (qcn) {
if (qcn->cppClassRequired()) {
if (qcn->classNode()) {
- PropertyNode* pn = correspondingProperty(qdb);
+ PropertyNode* pn = findCorrespondingCppProperty();
if (pn)
return pn->isWritable();
else
@@ -2377,10 +2289,9 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
Returns a pointer this QML property's corresponding C++
property, if it has one.
*/
-PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
+PropertyNode* QmlPropertyNode::findCorrespondingCppProperty()
{
PropertyNode* pn;
-
Node* n = parent();
while (n && n->subType() != Node::QmlClass)
n = n->parent();
@@ -2388,35 +2299,40 @@ PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
ClassNode* cn = qcn->classNode();
if (cn) {
+ /*
+ If there is a dot in the property name, first
+ find the C++ property corresponding to the QML
+ property group.
+ */
QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]);
if (pn) {
+ /*
+ Now find the C++ property corresponding to
+ the QML property in the QML property group,
+ <group>.<property>.
+ */
if (dotSplit.size() > 1) {
- // Find the C++ property corresponding to the QML property in
- // the property group, <group>.<property>.
-
QStringList path(extractClassName(pn->qualifiedDataType()));
- Node* nn = qdb->findClassNode(path);
+ Node* nn = QDocDatabase::qdocDB()->findClassNode(path);
if (nn) {
ClassNode* cn = static_cast<ClassNode*>(nn);
PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
- if (pn2)
- return pn2; // Return the property for the QML property.
- else
- return pn; // Return the property for the QML group.
+ /*
+ If found, return the C++ property
+ corresponding to the QML property.
+ Otherwise, return the C++ property
+ corresponding to the QML property
+ group.
+ */
+ return (pn2 ? pn2 : pn);
}
}
else
return pn;
}
- else {
- pn = cn->findPropertyNode(dotSplit[0]);
- if (pn)
- return pn;
- }
}
}
-
return 0;
}
@@ -2437,7 +2353,6 @@ NameCollisionNode::NameCollisionNode(InnerNode* child)
{
setTitle("Name Collision: " + child->name());
addCollision(child);
- current = 0;
}
/*!
@@ -2463,28 +2378,11 @@ NameCollisionNode::~NameCollisionNode()
// nothing.
}
-/*! \fn const InnerNode* NameCollisionNode::currentChild() const
- Returns a pointer to the current child, which may be 0.
- */
-
-/*! \fn void NameCollisionNode::setCurrentChild(InnerNode* child)
- Sets the current child to \a child. The current child is
- valid only within the file where it is defined.
- */
-
-/*! \fn void NameCollisionNode::clearCurrentChild()
- Sets the current child to 0. This should be called at the
- end of each file, because the current child is only valid
- within the file where the child is defined.
- */
-
/*!
Returns \c true if this collision node's current node is a QML node.
*/
bool NameCollisionNode::isQmlNode() const
{
- if (current)
- return current->isQmlNode();
return false;
}
@@ -2494,10 +2392,6 @@ bool NameCollisionNode::isQmlNode() const
*/
InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
{
- if (current) {
- if (current->type() == t && current->subType() == st)
- return current;
- }
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
@@ -2520,7 +2414,7 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
- if ((*i)->type() == Node::Document && (*i)->subType() == Node::QmlClass) {
+ if ((*i)->isQmlType()) {
if (origin->qmlModuleName() == (*i)->qmlModuleName())
return (*i);
}
@@ -2531,6 +2425,49 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
}
/*!
+ First, find all the colliding nodes that have the correct
+ type \a t and subtype \a st. If there is only one node
+ having the correct type and subtype, return that one.
+ If there is more than one node having the correct type
+ and subtype, then, in that subset, if there is only one
+ non-index node, return that one. If there are multiple
+ non-index nodes, return this collision node because we
+ can't disambiguate. Otherwise, if there are multiple
+ nodes having the correct type and subtype, return this
+ collision node because, again, we can't disambiguate.
+ But if there are no nodes at all that have the correct
+ type and subtype, return 0.
+ */
+Node* NameCollisionNode::disambiguate(Type t, SubType st)
+{
+ NodeList nl;
+ const NodeList& cn = childNodes();
+ NodeList::ConstIterator i = cn.constBegin();
+ while (i != cn.constEnd()) {
+ if ((*i)->type() == t) {
+ if ((st == NoSubType) || ((*i)->subType() == st))
+ nl.append((*i));
+ }
+ ++i;
+ }
+ Node* n = 0;
+ if (!nl.isEmpty()) {
+ i = nl.constBegin();
+ if (nl.size() == 1)
+ return (*i);
+ while (i != nl.constEnd()) {
+ if (!(*i)->isIndexNode()) {
+ if (n)
+ return this;
+ n = (*i);
+ }
+ ++i;
+ }
+ }
+ return n;
+}
+
+/*!
Construct the full document name for this node and return it.
*/
QString Node::fullDocumentName() const
@@ -2539,7 +2476,7 @@ QString Node::fullDocumentName() const
const Node* n = this;
do {
- if (!n->name().isEmpty() && n->type() != Node::QmlPropertyGroup)
+ if (!n->name().isEmpty() && !n->isQmlPropertyGroup())
pieces.insert(0, n->name());
if (n->type() == Node::Document) {
@@ -2759,8 +2696,6 @@ QString Node::idForNode() const
str = "qml-class-" + name();
break;
case Node::Page:
- case Node::Group:
- case Node::Module:
case Node::HeaderFile:
str = title();
if (str.isEmpty()) {
@@ -2781,9 +2716,6 @@ QString Node::idForNode() const
case Node::QmlBasicType:
str = "qml-basic-type-" + name();
break;
- case Node::QmlModule:
- str = "qml-module-" + name();
- break;
case Node::Collision:
str = title();
str.replace(": ","-");
@@ -2795,6 +2727,19 @@ QString Node::idForNode() const
}
}
break;
+ case Node::Group:
+ case Node::Module:
+ str = title();
+ if (str.isEmpty()) {
+ str = name();
+ if (str.endsWith(".html"))
+ str.remove(str.size()-5,5);
+ }
+ str.replace(QLatin1Char('/'), QLatin1Char('-'));
+ break;
+ case Node::QmlModule:
+ str = "qml-module-" + name();
+ break;
case Node::QmlProperty:
str = "qml-property-" + name();
break;
@@ -2855,10 +2800,93 @@ void InnerNode::printChildren(const QString& title)
}
/*!
- Prints the inner node's list of members.
+ Returns \c true if the collection node's member list is
+ not empty.
+ */
+bool CollectionNode::hasMembers() const
+{
+ return !members_.isEmpty();
+}
+
+/*!
+ Appends \a node to the collection node's member list, if
+ and only if it isn't already in the member list.
+ */
+void CollectionNode::addMember(Node* node)
+{
+ if (!members_.contains(node))
+ members_.append(node);
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one namespace node.
+ */
+bool CollectionNode::hasNamespaces() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one class node.
+ */
+bool CollectionNode::hasClasses() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are namespace nodes.
+ */
+void CollectionNode::getMemberNamespaces(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are class nodes.
+ */
+void CollectionNode::getMemberClasses(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Prints the collection node's list of members.
For debugging only.
*/
-void InnerNode::printMembers(const QString& title)
+void CollectionNode::printMembers(const QString& title)
{
qDebug() << title << name() << members_.size();
if (members_.size() > 0) {
@@ -2869,4 +2897,13 @@ void InnerNode::printMembers(const QString& title)
}
}
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void CollectionNode::setTitle(const QString& title)
+{
+ title_ = title;
+ parent()->addChild(this, title);
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 236b495bd0..e0f6e5202d 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -55,18 +55,27 @@
QT_BEGIN_NAMESPACE
class Node;
+class EnumNode;
class ClassNode;
class InnerNode;
class ExampleNode;
+class TypedefNode;
class QmlClassNode;
class QDocDatabase;
+class FunctionNode;
+class PropertyNode;
class QmlModuleNode;
+class CollectionNode;
class QmlPropertyNode;
+class NameCollisionNode;
typedef QList<Node*> NodeList;
typedef QMap<QString, Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
-typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
+typedef QPair<int, int> NodeTypePair;
+typedef QList<NodeTypePair> NodeTypeList;
+typedef QMap<QString, CollectionNode*> CNMap;
+typedef QMultiMap<QString, CollectionNode*> CNMultiMap;
class Node
{
@@ -82,6 +91,9 @@ public:
Function,
Property,
Variable,
+ Group,
+ Module,
+ QmlModule,
QmlPropertyGroup,
QmlProperty,
QmlSignal,
@@ -96,13 +108,10 @@ public:
HeaderFile,
File,
Image,
- Group,
- Module,
Page,
ExternalPage,
QmlClass,
QmlBasicType,
- QmlModule,
DitaMap,
Collision,
LastSubtype
@@ -165,10 +174,11 @@ public:
QString plainName() const;
QString plainFullName(const Node* relative = 0) const;
QString fullName(const Node* relative=0) const;
- const QString& baseName() const { return baseName_; }
- bool hasBaseName() const { return !baseName_.isEmpty(); }
- void setBaseName(const QString& bn) { baseName_ = bn; }
+ const QString& fileNameBase() const { return fileNameBase_; }
+ bool hasFileNameBase() const { return !fileNameBase_.isEmpty(); }
+ void setFileNameBase(const QString& t) { fileNameBase_ = t; }
+
void setAccess(Access access) { access_ = access; }
void setLocation(const Location& location) { loc_ = location; }
void setDoc(const Doc& doc, bool replace = false);
@@ -181,8 +191,7 @@ public:
void setSince(const QString &since);
void setRelates(InnerNode* pseudoParent);
void setModuleName(const QString &name) { moduleName_ = name; }
- void setLink(LinkType linkType, const QString &link, const QString &desc);
- void setUrl(const QString &url);
+ void setUrl(const QString& url) { url_ = url; }
void setTemplateStuff(const QString &templateStuff) { templateStuff_ = templateStuff; }
void setReconstitutedBrief(const QString &t) { reconstitutedBrief_ = t; }
void setPageType(PageType t) { pageType_ = t; }
@@ -190,14 +199,18 @@ public:
void setParent(InnerNode* n) { parent_ = n; }
void setIndexNodeFlag() { indexNodeFlag_ = true; }
virtual void setOutputFileName(const QString& ) { }
- void markSeen() { seen_ = true; }
- void markNotSeen() { seen_ = false; }
virtual bool isInnerNode() const = 0;
+ virtual bool isDocNode() const { return false; }
+ virtual bool isCollectionNode() const { return false; }
+ virtual bool isGroup() const { return false; }
+ virtual bool isModule() const { return false; }
virtual bool isQmlModule() const { return false; }
virtual bool isQmlType() const { return false; }
+ virtual bool isQmlBasicType() const { return false; }
virtual bool isExample() const { return false; }
virtual bool isExampleFile() const { return false; }
+ virtual bool isHeaderFile() const { return false; }
virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; }
@@ -210,7 +223,6 @@ public:
virtual bool isCollisionNode() const { return false; }
virtual bool isAttached() const { return false; }
virtual bool isAlias() const { return false; }
- virtual bool isGroup() const { return false; }
virtual bool isWrapper() const;
virtual bool isReadOnly() const { return false; }
virtual bool isDefault() const { return false; }
@@ -221,34 +233,47 @@ public:
virtual bool hasClasses() const { return false; }
virtual void setAbstract(bool ) { }
virtual void setWrapper() { }
- virtual QString title() const { return QString(); }
+ virtual QString title() const { return name(); }
+ virtual QString fullTitle() const { return name(); }
+ virtual QString subTitle() const { return QString(); }
+ virtual void setTitle(const QString& ) { }
+ virtual void setSubTitle(const QString& ) { }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; }
virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { }
virtual bool isInternal() const;
virtual void setDataType(const QString& ) { }
virtual void setReadOnly(bool ) { }
+ virtual Node* disambiguate(Type , SubType ) { return this; }
+ virtual bool wasSeen() const { return false; }
+ virtual void appendGroupName(const QString& ) { }
bool isIndexNode() const { return indexNodeFlag_; }
- bool wasSeen() const { return seen_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
+ bool match(const NodeTypeList& types) const;
InnerNode* parent() const { return parent_; }
InnerNode* relates() const { return relatesTo_; }
const QString& name() const { return name_; }
- const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
QString moduleName() const;
- QString url() const;
+ QString url() const { return url_; }
virtual QString nameForLists() const { return name_; }
virtual QString outputFileName() const { return QString(); }
virtual QString obsoleteLink() const { return QString(); }
virtual void setObsoleteLink(const QString& ) { };
+ virtual void setQtVariable(const QString& ) { }
+ virtual QString qtVariable() const { return QString(); }
+
+ const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
+ void setLink(LinkType linkType, const QString &link, const QString &desc);
Access access() const { return access_; }
QString accessString() const;
const Location& location() const { return loc_; }
const Doc& doc() const { return doc_; }
+ bool hasDoc() const { return !doc_.isEmpty(); }
Status status() const { return status_; }
Status inheritedStatus() const;
+ bool isObsolete() const { return (status_ == Obsolete); }
ThreadSafeness threadSafeness() const;
ThreadSafeness inheritedThreadSafeness() const;
QString since() const { return since_; }
@@ -274,7 +299,6 @@ public:
virtual void setQmlModule(QmlModuleNode* ) { }
virtual ClassNode* classNode() { return 0; }
virtual void setClassNode(ClassNode* ) { }
- virtual void clearCurrentChild() { }
virtual const Node* applyModuleName(const Node* ) const { return 0; }
virtual QString idNumber() { return "0"; }
QmlClassNode* qmlClassNode();
@@ -305,7 +329,6 @@ private:
PageType pageType_;
Status status_;
bool indexNodeFlag_;
- bool seen_;
InnerNode* parent_;
InnerNode* relatesTo_;
@@ -313,7 +336,7 @@ private:
Location loc_;
Doc doc_;
QMap<LinkType, QPair<QString, QString> > linkMap_;
- QString baseName_;
+ QString fileNameBase_;
QString moduleName_;
QString url_;
QString since_;
@@ -325,49 +348,31 @@ private:
static int propertyGroupCount_;
};
-class FunctionNode;
-class EnumNode;
-class NameCollisionNode;
-
class InnerNode : public Node
{
public:
virtual ~InnerNode();
- Node* findChildNodeByName(const QString& name);
- Node* findChildNodeByName(const QString& name, bool qml);
- Node* findChildNodeByNameAndType(const QString& name, Type type);
+ Node* findChildNode(const QString& name) const;
+ Node* findChildNode(const QString& name, bool qml) const;
+ Node* findChildNode(const QString& name, Type type);
void findNodes(const QString& name, QList<Node*>& n);
- FunctionNode* findFunctionNode(const QString& name);
+ FunctionNode* findFunctionNode(const QString& name) const;
FunctionNode* findFunctionNode(const FunctionNode* clone);
void addInclude(const QString &include);
void setIncludes(const QStringList &includes);
void setOverload(const FunctionNode* func, bool overlode);
void normalizeOverloads();
void makeUndocumentedChildrenInternal();
- void clearCurrentChildPointers();
void deleteChildren();
void removeFromRelated();
virtual bool isInnerNode() const { return true; }
virtual bool isLeaf() const { return false; }
- const Node* findChildNodeByName(const QString& name) const;
- const Node* findChildNodeByName(const QString& name, bool qml) const;
- const Node* findChildNodeByNameAndType(const QString& name, Type type) const;
- const FunctionNode* findFunctionNode(const QString& name) const;
- const FunctionNode* findFunctionNode(const FunctionNode* clone) const;
const EnumNode* findEnumNodeForValue(const QString &enumValue) const;
const NodeList & childNodes() const { return children_; }
const NodeList & relatedNodes() const { return related_; }
- virtual void addMember(Node* node);
- const NodeList& members() const { return members_; }
- virtual bool hasMembers() const;
- virtual bool hasNamespaces() const;
- virtual bool hasClasses() const;
- virtual void getMemberNamespaces(NodeMap& out);
- virtual void getMemberClasses(NodeMap& out);
-
int count() const { return children_.size(); }
int overloadNumber(const FunctionNode* func) const;
NodeList overloads(const QString &funcName) const;
@@ -377,14 +382,13 @@ public:
QStringList secondaryKeys();
const QStringList& pageKeywords() const { return pageKeywds; }
virtual void addPageKeywords(const QString& t) { pageKeywds << t; }
- virtual void setCurrentChild() { }
- virtual void setCurrentChild(InnerNode* ) { }
virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
virtual QString outputFileName() const { return outputFileName_; }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const;
-
+ void addChild(Node* child, const QString& title);
+ const QStringList& groupNames() const { return groupNames_; }
+ virtual void appendGroupName(const QString& t) { groupNames_.append(t); }
void printChildren(const QString& title);
- void printMembers(const QString& title);
protected:
InnerNode(Type type, InnerNode* parent, const QString& name);
@@ -401,8 +405,8 @@ private:
QString outputFileName_;
QStringList pageKeywds;
QStringList includes_;
+ QStringList groupNames_;
NodeList children_;
- NodeList members_;
NodeList enumChildren_;
NodeList related_;
QMap<QString, Node*> childMap;
@@ -432,26 +436,24 @@ public:
virtual bool isNamespace() const { return true; }
};
-class ClassNode;
-
struct RelatedClass
{
RelatedClass() { }
- RelatedClass(Node::Access access0,
- ClassNode* node0,
- const QString& dataTypeWithTemplateArgs0 = QString())
- : access(access0),
- node(node0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0) { }
+ // constructor for resolved base class
+ RelatedClass(Node::Access access, ClassNode* node)
+ : access_(access), node_(node) { }
+ // constructor for unresolved base class
+ RelatedClass(Node::Access access, const QStringList& path, const QString& signature)
+ : access_(access), node_(0), path_(path), signature_(signature) { }
QString accessString() const;
+ bool isPrivate() const { return (access_ == Node::Private); }
- Node::Access access;
- ClassNode* node;
- QString dataTypeWithTemplateArgs;
+ Node::Access access_;
+ ClassNode* node_;
+ QStringList path_;
+ QString signature_;
};
-class PropertyNode;
-
class ClassNode : public InnerNode
{
public:
@@ -463,14 +465,19 @@ public:
virtual void setObsoleteLink(const QString& t) { obsoleteLink_ = t; }
virtual void setWrapper() { wrapper_ = true; }
- void addBaseClass(Access access,
- ClassNode* node,
- const QString &dataTypeWithTemplateArgs = QString());
+ void addResolvedBaseClass(Access access, ClassNode* node);
+ void addDerivedClass(Access access, ClassNode* node);
+ void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
void fixBaseClasses();
+ void fixPropertyUsingBaseClasses(PropertyNode* pn);
+
+ QList<RelatedClass>& baseClasses() { return bases_; }
+ QList<RelatedClass>& derivedClasses() { return derived_; }
+ QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
- const QList<RelatedClass> &baseClasses() const { return bases; }
- const QList<RelatedClass> &derivedClasses() const { return derived; }
- const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases; }
+ const QList<RelatedClass> &baseClasses() const { return bases_; }
+ const QList<RelatedClass> &derivedClasses() const { return derived_; }
+ const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
@@ -482,9 +489,9 @@ public:
QmlClassNode* findQmlBaseNode();
private:
- QList<RelatedClass> bases;
- QList<RelatedClass> derived;
- QList<RelatedClass> ignoredBases;
+ QList<RelatedClass> bases_;
+ QList<RelatedClass> derived_;
+ QList<RelatedClass> ignoredBases_;
bool abstract_;
bool wrapper_;
QString sname;
@@ -502,49 +509,26 @@ public:
PageType ptype);
virtual ~DocNode() { }
- void setQtVariable(const QString &variable) { qtVariable_ = variable; }
- void setTitle(const QString &title) { title_ = title; }
- void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
+ virtual void setTitle(const QString &title);
+ virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
- QString qtVariable() const { return qtVariable_; }
SubType subType() const { return nodeSubtype_; }
- virtual QString title() const;
+ virtual QString title() const { return title_; }
virtual QString fullTitle() const;
virtual QString subTitle() const;
virtual QString imageFileName() const { return QString(); }
virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { }
- virtual bool isGroup() const { return (subType() == Node::Group); }
+ virtual bool isHeaderFile() const { return (subType() == Node::HeaderFile); }
virtual bool isExample() const { return (subType() == Node::Example); }
virtual bool isExampleFile() const { return (parent() && parent()->isExample()); }
virtual bool isExternalPage() const { return nodeSubtype_ == ExternalPage; }
+ virtual bool isDocNode() const { return true; }
protected:
SubType nodeSubtype_;
QString title_;
QString subtitle_;
-
-private:
- QString qtVariable_;
-};
-
-class QmlModuleNode : public DocNode
-{
- public:
- QmlModuleNode(InnerNode* parent, const QString& name)
- : DocNode(parent, name, Node::QmlModule, Node::OverviewPage) { }
- virtual ~QmlModuleNode() { }
-
- virtual bool isQmlModule() const { return true; }
- virtual QString qmlModuleName() const { return qmlModuleName_; }
- virtual QString qmlModuleVersion() const { return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_; }
- virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersionMajor_; }
- virtual void setQmlModuleInfo(const QString& );
-
- private:
- QString qmlModuleName_;
- QString qmlModuleVersionMajor_;
- QString qmlModuleVersionMinor_;
};
class NameCollisionNode : public DocNode
@@ -552,35 +536,28 @@ class NameCollisionNode : public DocNode
public:
NameCollisionNode(InnerNode* child);
~NameCollisionNode();
- const InnerNode* currentChild() const { return current; }
- virtual void setCurrentChild(InnerNode* child) { current = child; }
- virtual void clearCurrentChild() { current = 0; }
virtual bool isQmlNode() const;
virtual bool isCollisionNode() const { return true; }
virtual const Node* applyModuleName(const Node* origin) const;
+ virtual Node* disambiguate(Type t, SubType st);
InnerNode* findAny(Node::Type t, Node::SubType st);
void addCollision(InnerNode* child);
const QMap<QString,QString>& linkTargets() const { return targets; }
void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); }
private:
- InnerNode* current;
QMap<QString,QString> targets;
};
class ExampleNode : public DocNode
{
public:
- ExampleNode(InnerNode* parent, const QString& name);
+ ExampleNode(InnerNode* parent, const QString& name)
+ : DocNode(parent, name, Node::Example, Node::ExamplePage) { }
virtual ~ExampleNode() { }
virtual QString imageFileName() const { return imageFileName_; }
virtual void setImageFileName(const QString& ifn) { imageFileName_ = ifn; }
- static void terminate() { exampleNodeMap.clear(); }
-
-public:
- static ExampleNodeMap exampleNodeMap;
-
private:
QString imageFileName_;
};
@@ -615,8 +592,6 @@ public:
virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); }
virtual ClassNode* classNode() { return cnode_; }
virtual void setClassNode(ClassNode* cn) { cnode_ = cn; }
- virtual void setCurrentChild();
- virtual void clearCurrentChild();
virtual bool isAbstract() const { return abstract_; }
virtual bool isWrapper() const { return wrapper_; }
virtual void setAbstract(bool b) { abstract_ = b; }
@@ -632,10 +607,11 @@ public:
virtual void setQmlModule(QmlModuleNode* t) { qmlModule_ = t; }
const ImportList& importList() const { return importList_; }
void setImportList(const ImportList& il) { importList_ = il; }
- const QString& qmlBaseName() const { return baseName_; }
- void setQmlBaseName(const QString& name) { baseName_ = name; }
- const QmlClassNode* qmlBaseNode() const { return baseNode_; }
- void setQmlBaseNode(QmlClassNode* b) { baseNode_ = b; }
+ const QString& qmlBaseName() const { return qmlBaseName_; }
+ void setQmlBaseName(const QString& name) { qmlBaseName_ = name; }
+ bool qmlBaseNodeNotSet() const { return (qmlBaseNode_ == 0); }
+ QmlClassNode* qmlBaseNode();
+ void setQmlBaseNode(QmlClassNode* b) { qmlBaseNode_ = b; }
void requireCppClass() { cnodeRequired_ = true; }
bool cppClassRequired() const { return cnodeRequired_; }
static void addInheritedBy(const QString& base, Node* sub);
@@ -651,10 +627,10 @@ private:
bool cnodeRequired_;
bool wrapper_;
ClassNode* cnode_;
- QString baseName_;
+ QString qmlBaseName_;
QString obsoleteLink_;
QmlModuleNode* qmlModule_;
- QmlClassNode* baseNode_;
+ QmlClassNode* qmlBaseNode_;
ImportList importList_;
};
@@ -665,6 +641,7 @@ public:
const QString& name);
virtual ~QmlBasicTypeNode() { }
virtual bool isQmlNode() const { return true; }
+ virtual bool isQmlBasicType() const { return true; }
};
class QmlPropertyGroupNode : public InnerNode
@@ -687,8 +664,6 @@ public:
int idNumber_;
};
-class QmlPropertyNode;
-
class QmlPropertyNode : public LeafNode
{
Q_DECLARE_TR_FUNCTIONS(QDoc::QmlPropertyNode)
@@ -711,7 +686,7 @@ public:
bool isReadOnlySet() const { return (readOnly_ != FlagValueDefault); }
bool isStored() const { return fromFlagValue(stored_,true); }
bool isDesignable() const { return fromFlagValue(designable_,false); }
- bool isWritable(QDocDatabase* qdb);
+ bool isWritable();
virtual bool isDefault() const { return isdefault_; }
virtual bool isReadOnly() const { return fromFlagValue(readOnly_,false); }
virtual bool isAlias() const { return isAlias_; }
@@ -723,10 +698,11 @@ public:
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
- PropertyNode* correspondingProperty(QDocDatabase* qdb);
-
const QString& element() const { return static_cast<QmlPropertyGroupNode*>(parent())->element(); }
+ private:
+ PropertyNode* findCorrespondingCppProperty();
+
private:
QString type_;
FlagValue stored_;
@@ -756,8 +732,6 @@ private:
Text txt;
};
-class TypedefNode;
-
class EnumNode : public LeafNode
{
public:
@@ -831,8 +805,6 @@ private:
QString def;
};
-class PropertyNode;
-
class FunctionNode : public LeafNode
{
public:
@@ -1049,6 +1021,94 @@ public:
const DitaRefList& map() const { return doc().ditamap(); }
};
+class CollectionNode : public InnerNode
+{
+ public:
+ CollectionNode(Type type, InnerNode* parent, const QString& name)
+ : InnerNode(type, parent, name), seen_(false) {
+ setPageType(Node::OverviewPage);
+ }
+ virtual ~CollectionNode() { }
+
+ virtual bool isCollectionNode() const { return true; }
+ virtual void addMember(Node* node);
+ virtual bool hasMembers() const;
+ virtual bool hasNamespaces() const;
+ virtual bool hasClasses() const;
+ virtual void getMemberNamespaces(NodeMap& out);
+ virtual void getMemberClasses(NodeMap& out);
+ virtual bool wasSeen() const { return seen_; }
+ virtual QString title() const { return title_; }
+ virtual QString subTitle() const { return subtitle_; }
+ virtual QString fullTitle() const { return title_; }
+ virtual QString nameForLists() const { return title_; }
+ virtual void setTitle(const QString &title);
+ virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
+
+ const NodeList& members() const { return members_; }
+ void printMembers(const QString& title);
+
+ void markSeen() { seen_ = true; }
+ void markNotSeen() { seen_ = false; }
+
+ private:
+ bool seen_;
+ QString title_;
+ QString subtitle_;
+ NodeList members_;
+};
+
+class GroupNode : public CollectionNode
+{
+ public:
+ GroupNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::Group, parent, name) { }
+ virtual ~GroupNode() { }
+
+ virtual bool isGroup() const { return true; }
+};
+
+class ModuleNode : public CollectionNode
+{
+ public:
+ ModuleNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::Module, parent, name) { }
+ virtual ~ModuleNode() { }
+
+ virtual bool isModule() const { return true; }
+ virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
+ virtual QString qtVariable() const { return qtVariable_; }
+
+ private:
+ QString qtVariable_;
+};
+
+class QmlModuleNode : public CollectionNode
+{
+ public:
+ QmlModuleNode(InnerNode* parent, const QString& name)
+ : CollectionNode(Node::QmlModule, parent, name) { }
+ virtual ~QmlModuleNode() { }
+
+ virtual bool isQmlModule() const { return true; }
+ virtual QString qmlModuleName() const { return qmlModuleName_; }
+ virtual QString qmlModuleVersion() const {
+ return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_;
+ }
+ virtual QString qmlModuleIdentifier() const {
+ return qmlModuleName_ + qmlModuleVersionMajor_;
+ }
+ virtual void setQmlModuleInfo(const QString& );
+ virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
+ virtual QString qtVariable() const { return qtVariable_; }
+
+ private:
+ QString qmlModuleName_;
+ QString qmlModuleVersionMajor_;
+ QString qmlModuleVersionMinor_;
+ QString qtVariable_;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp
index 644fe05438..e8292e787e 100644
--- a/src/tools/qdoc/puredocparser.cpp
+++ b/src/tools/qdoc/puredocparser.cpp
@@ -202,7 +202,7 @@ bool PureDocParser::processQdocComments()
}
}
- Node* treeRoot = QDocDatabase::qdocDB()->treeRoot();
+ Node* treeRoot = QDocDatabase::qdocDB()->primaryTreeRoot();
NodeList::Iterator n = nodes.begin();
QList<Doc>::Iterator d = docs.begin();
while (n != nodes.end()) {
diff --git a/src/tools/qdoc/puredocparser.h b/src/tools/qdoc/puredocparser.h
index 0174af7a4e..b664367527 100644
--- a/src/tools/qdoc/puredocparser.h
+++ b/src/tools/qdoc/puredocparser.h
@@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
-class Tree;
class PureDocParser : public CppCodeParser
{
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index 1011a3ac97..ffd2dd9b3b 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -51,46 +51,429 @@ QT_BEGIN_NAMESPACE
static NodeMap emptyNodeMap_;
static NodeMultiMap emptyNodeMultiMap_;
+bool QDocDatabase::debug = false;
+
+/*! \class QDocForest
+ This class manages a collection of trees. Each tree is an
+ instance of class Tree, which is a private class.
+
+ The forest is populated as each index file is loaded.
+ Each index file adds a tree to the forest. Each tree
+ is named with the name of the module it represents.
+
+ The search order is created by searchOrder(), if it has
+ not already been created. The search order and module
+ names arrays have parallel structure, i.e. modulNames_[i]
+ is the module name of the Tree at searchOrder_[i].
+ */
+
+/*!
+ Destroys the qdoc forest. This requires deleting
+ each Tree in the forest. Note that the forest has
+ been transferred into the search order array, so
+ what is really being used to destroy the forest
+ is the search order array.
+ */
+QDocForest::~QDocForest()
+{
+ for (int i=0; i<searchOrder_.size(); ++i)
+ delete searchOrder_.at(i);
+ forest_.clear();
+ searchOrder_.clear();
+ indexSearchOrder_.clear();
+ moduleNames_.clear();
+ primaryTree_ = 0;
+}
+
+/*!
+ Initializes the forest prior to a traversal and
+ returns a pointer to the root node of the primary
+ tree. If the forest is empty, it return 0
+ */
+NamespaceNode* QDocForest::firstRoot()
+{
+ currentIndex_ = 0;
+ return (!searchOrder().isEmpty() ? searchOrder()[0]->root() : 0);
+}
+
+/*!
+ Increments the forest's current tree index. If the current
+ tree index is still within the forest, the function returns
+ the root node of the current tree. Otherwise it returns 0.
+ */
+NamespaceNode* QDocForest::nextRoot()
+{
+ ++currentIndex_;
+ return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_]->root() : 0);
+}
+
+/*!
+ Initializes the forest prior to a traversal and
+ returns a pointer to the primary tree. If the
+ forest is empty, it returns 0.
+ */
+Tree* QDocForest::firstTree()
+{
+ currentIndex_ = 0;
+ return (!searchOrder().isEmpty() ? searchOrder()[0] : 0);
+}
+
+/*!
+ Increments the forest's current tree index. If the current
+ tree index is still within the forest, the function returns
+ the pointer to the current tree. Otherwise it returns 0.
+ */
+Tree* QDocForest::nextTree()
+{
+ ++currentIndex_;
+ return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_] : 0);
+}
+
+/*!
+ \fn Tree* QDocForest::primaryTree()
+
+ Returns the pointer to the primary tree.
+ */
+
+/*!
+ If the search order array is empty, create the search order.
+ If the search order array is not empty, do nothing.
+ */
+void QDocForest::setSearchOrder()
+{
+ if (!searchOrder_.isEmpty())
+ return;
+ QString primaryName = primaryTree()->moduleName();
+ searchOrder_.clear();
+ searchOrder_.reserve(forest_.size()+1);
+ moduleNames_.reserve(forest_.size()+1);
+ searchOrder_.append(primaryTree_);
+ moduleNames_.append(primaryName);
+ QMap<QString, Tree*>::iterator i;
+ if (primaryName != "QtCore") {
+ i = forest_.find("QtCore");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtCore");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtGui") {
+ i = forest_.find("QtGui");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtGui");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtNetwork") {
+ i = forest_.find("QtNetwork");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtNetwork");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtOpenGL") {
+ i = forest_.find("QtOpenGL");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtOpenGL");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtWidgets") {
+ i = forest_.find("QtWidgets");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtWidgets");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtSql") {
+ i = forest_.find("QtSql");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtSql");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtXml") {
+ i = forest_.find("QtXml");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtXml");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtSvg") {
+ i = forest_.find("QtSvg");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtSvg");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtDoc") {
+ i = forest_.find("QtDoc");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtDoc");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtQuick") {
+ i = forest_.find("QtQuick");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtQuick");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtQml") {
+ i = forest_.find("QtQml");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtQml");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtPrintSupport") {
+ i = forest_.find("QtPrintSupport");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtPrintSupport");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtGraphicalEffects") {
+ i = forest_.find("QtGraphicalEffects");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtGraphicalEffects");
+ forest_.erase(i);
+ }
+ }
+ if (primaryName != "QtConcurrent") {
+ i = forest_.find("QtConcurrent");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("QtConcurrent");
+ forest_.erase(i);
+ }
+ }
+#if 0
+ if (primaryName != "zzz") {
+ i = forest_.find("zzz");
+ if (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append("zzz");
+ forest_.erase(i);
+ }
+ }
+#endif
+ /*
+ If any trees remain in the forest, just add them
+ to the search order sequentially, because we don't
+ know any better at this point.
+ */
+ if (!forest_.isEmpty()) {
+ i = forest_.begin();
+ while (i != forest_.end()) {
+ searchOrder_.append(i.value());
+ moduleNames_.append(i.key());
+ ++i;
+ }
+ forest_.clear();
+ }
+#if 0
+ qDebug() << " SEARCH ORDER:";
+ for (int i=0; i<moduleNames_.size(); ++i)
+ qDebug() << " " << i+1 << "." << moduleNames_.at(i);
+#endif
+}
+
+/*!
+ Returns an ordered array of Tree pointers that represents
+ the order in which the trees should be searched. The first
+ Tree in the array is the tree for the current module, i.e.
+ the module for which qdoc is generating documentation.
+
+ The other Tree pointers in the array represent the index
+ files that were loaded in preparation for generating this
+ module's documentation. Each Tree pointer represents one
+ index file. The index file Tree points have been ordered
+ heuristically to, hopefully, minimize searching. Thr order
+ will probably be changed.
+
+ If the search order array is empty, this function calls
+ indexSearchOrder(). The search order array is empty while
+ the index files are being loaded, but some searches must
+ be performed during this time, notably searches for base
+ class nodes. These searches require a temporary search
+ order. The temporary order changes throughout the loading
+ of the index files, but it is always the tree for the
+ current index file first, followed by the trees for the
+ index files that have already been loaded. The only
+ ordering required in this temporary search order is that
+ the current tree must be searched first.
+ */
+const QVector<Tree*>& QDocForest::searchOrder()
+{
+ if (searchOrder_.isEmpty())
+ return indexSearchOrder();
+ return searchOrder_;
+}
+
+/*!
+ There are two search orders used by qdoc when searching for
+ things. The normal search order is returned by searchOrder(),
+ but this normal search order is not known until all the index
+ files have been read. At that point, setSearchOrder() is
+ called.
+
+ During the reading of the index files, the vector holding
+ the normal search order remains empty. Whenever the search
+ order is requested, if that vector is empty, this function
+ is called to return a temporary search order, which includes
+ all the index files that have been read so far, plus the
+ one being read now. That one is prepended to the front of
+ the vector.
+ */
+const QVector<Tree*>& QDocForest::indexSearchOrder()
+{
+ if (forest_.size() > indexSearchOrder_.size())
+ indexSearchOrder_.prepend(primaryTree_);
+ return indexSearchOrder_;
+}
+
+/*!
+ Create a new Tree for the index file for the specified
+ \a module and add it to the forest. Return the pointer
+ to its root.
+ */
+NamespaceNode* QDocForest::newIndexTree(const QString& module)
+{
+ primaryTree_ = new Tree(module, qdb_);
+ forest_.insert(module, primaryTree_);
+ return primaryTree_->root();
+}
+
+/*!
+ Create a new Tree for use as the primary tree. This tree
+ will represent the primary module.
+ */
+void QDocForest::newPrimaryTree(const QString& module)
+{
+ primaryTree_ = new Tree(module, qdb_);
+}
+
+/*!
+ Searches the trees for a node named \a target and returns
+ a pointer to it if found. The \a relative node is the starting
+ point, but it only makes sense in the primary tree, which is
+ searched first. After the primary tree is searched, \a relative
+ is set to 0 for searching the index trees. When relative is 0,
+ the root node of the index tree is the starting point.
+ */
+const Node* QDocForest::resolveTarget(const QString& target, const Node* relative)
+{
+ QStringList path = target.split("::");
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findNode(path, relative, flags);
+ if (n)
+ return n;
+#if 0
+ n = t->findDocNodeByTitle(target);
+ if (n)
+ return n;
+#endif
+ relative = 0;
+ }
+ return 0;
+}
+
+/*!
+ Searches the Tree \a t for a type node named by the \a path
+ and returns a pointer to it if found. The \a relative node
+ is the starting point, but it only makes sense when searching
+ the primary tree. Therefore, when this function is called with
+ \a t being an index tree, \a relative is 0. When relative is 0,
+ the root node of \a t is the starting point.
+ */
+const Node* QDocForest::resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t)
+{
+ int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
+ return t->findNode(path, relative, flags);
+}
+
+/*!
+ This function merges all the collection maps for collection
+ nodes of node type \a t into the collection multimap \a cnmm,
+ which is cleared before starting.
+
+ This is mainly useful for groups, which often cross module
+ boundaries. It might be true that neither modules nor QML
+ modules cross module boundaries, but this function works for
+ those cases as well.
+ */
+void QDocForest::mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm)
+{
+ foreach (Tree* t, searchOrder()) {
+ const CNMap& cnm = t->getCollections(nt);
+ if (!cnm.isEmpty()) {
+ CNMap::const_iterator i = cnm.begin();
+ while (i != cnm.end()) {
+ if (!i.value()->isInternal())
+ cnmm.insert(i.key(), i.value());
+ ++i;
+ }
+ }
+ }
+}
/*! \class QDocDatabase
+ This class provides exclusive access to the qdoc database,
+ which consists of a forrest of trees and a lot of maps and
+ other useful data structures.
*/
QDocDatabase* QDocDatabase::qdocDB_ = NULL;
+NodeMap QDocDatabase::typeNodeMap_;
/*!
- Constructs the singleton qdoc database object.
- It constructs a singleton Tree object with this
- qdoc database pointer.
+ Constructs the singleton qdoc database object. The singleton
+ constructs the \a forest_ object, which is also a singleton.
+ \a showInternal_ is normally false. If it is true, qdoc will
+ write documentation for nodes marked \c internal.
*/
-QDocDatabase::QDocDatabase() : showInternal_(false)
+QDocDatabase::QDocDatabase() : showInternal_(false), forest_(this)
{
- tree_ = new Tree(this);
+ // nothing
}
/*!
- Destroys the qdoc database object. This requires deleting
- the tree of nodes, which deletes each node.
+ Destroys the qdoc database object. This requires destroying
+ the forest object, which contains an array of tree pointers.
+ Each tree is deleted.
*/
QDocDatabase::~QDocDatabase()
{
- masterMap_.clear();
- delete tree_;
+ // nothing.
}
-/*! \fn Tree* QDocDatabase::tree()
- Returns the pointer to the tree. This function is for compatibility
- with the current qdoc. It will be removed when the QDocDatabase class
- replaces the current structures.
- */
-
/*!
Creates the singleton. Allows only one instance of the class
to be created. Returns a pointer to the singleton.
*/
QDocDatabase* QDocDatabase::qdocDB()
{
- if (!qdocDB_)
+ if (!qdocDB_) {
qdocDB_ = new QDocDatabase;
+ initializeDB();
+ }
return qdocDB_;
}
@@ -106,36 +489,189 @@ void QDocDatabase::destroyQdocDB()
}
/*!
- \fn const DocNodeMap& QDocDatabase::groups() const
+ Initialize data structures in the singleton qdoc database.
+
+ In particular, the type node map is initialized with a lot
+ type names that don't refer to documented types. For example,
+ the C++ standard types are included. These might be documented
+ here at some point, but for now they are not. Other examples
+ include \c array and \c data, which are just generic names
+ used as place holders in function signatures that appear in
+ the documentation.
+ */
+void QDocDatabase::initializeDB()
+{
+ typeNodeMap_.insert( "accepted", 0);
+ typeNodeMap_.insert( "actionPerformed", 0);
+ typeNodeMap_.insert( "activated", 0);
+ typeNodeMap_.insert( "alias", 0);
+ typeNodeMap_.insert( "anchors", 0);
+ typeNodeMap_.insert( "any", 0);
+ typeNodeMap_.insert( "array", 0);
+ typeNodeMap_.insert( "autoSearch", 0);
+ typeNodeMap_.insert( "axis", 0);
+ typeNodeMap_.insert( "backClicked", 0);
+ typeNodeMap_.insert( "bool", 0);
+ typeNodeMap_.insert( "boomTime", 0);
+ typeNodeMap_.insert( "border", 0);
+ typeNodeMap_.insert( "buttonClicked", 0);
+ typeNodeMap_.insert( "callback", 0);
+ typeNodeMap_.insert( "char", 0);
+ typeNodeMap_.insert( "clicked", 0);
+ typeNodeMap_.insert( "close", 0);
+ typeNodeMap_.insert( "closed", 0);
+ typeNodeMap_.insert( "color", 0);
+ typeNodeMap_.insert( "cond", 0);
+ typeNodeMap_.insert( "data", 0);
+ typeNodeMap_.insert( "dataReady", 0);
+ typeNodeMap_.insert( "dateString", 0);
+ typeNodeMap_.insert( "dateTimeString", 0);
+ typeNodeMap_.insert( "datetime", 0);
+ typeNodeMap_.insert( "day", 0);
+ typeNodeMap_.insert( "deactivated", 0);
+ typeNodeMap_.insert( "double", 0);
+ typeNodeMap_.insert( "drag", 0);
+ typeNodeMap_.insert( "easing", 0);
+ typeNodeMap_.insert( "enumeration", 0);
+ typeNodeMap_.insert( "error", 0);
+ typeNodeMap_.insert( "exposure", 0);
+ typeNodeMap_.insert( "fatalError", 0);
+ typeNodeMap_.insert( "fileSelected", 0);
+ typeNodeMap_.insert( "flags", 0);
+ typeNodeMap_.insert( "float", 0);
+ typeNodeMap_.insert( "focus", 0);
+ typeNodeMap_.insert( "focusZone", 0);
+ typeNodeMap_.insert( "format", 0);
+ typeNodeMap_.insert( "framePainted", 0);
+ typeNodeMap_.insert( "from", 0);
+ typeNodeMap_.insert( "frontClicked", 0);
+ typeNodeMap_.insert( "function", 0);
+ typeNodeMap_.insert( "hasOpened", 0);
+ typeNodeMap_.insert( "hovered", 0);
+ typeNodeMap_.insert( "hoveredTitle", 0);
+ typeNodeMap_.insert( "hoveredUrl", 0);
+ typeNodeMap_.insert( "imageCapture", 0);
+ typeNodeMap_.insert( "imageProcessing", 0);
+ typeNodeMap_.insert( "index", 0);
+ typeNodeMap_.insert( "initialized", 0);
+ typeNodeMap_.insert( "int", 0);
+ typeNodeMap_.insert( "isLoaded", 0);
+ typeNodeMap_.insert( "item", 0);
+ typeNodeMap_.insert( "jsdict", 0);
+ typeNodeMap_.insert( "jsobject", 0);
+ typeNodeMap_.insert( "key", 0);
+ typeNodeMap_.insert( "keysequence", 0);
+ typeNodeMap_.insert( "list", 0);
+ typeNodeMap_.insert( "listViewClicked", 0);
+ typeNodeMap_.insert( "loadRequest", 0);
+ typeNodeMap_.insert( "locale", 0);
+ typeNodeMap_.insert( "location", 0);
+ typeNodeMap_.insert( "long", 0);
+ typeNodeMap_.insert( "message", 0);
+ typeNodeMap_.insert( "messageReceived", 0);
+ typeNodeMap_.insert( "mode", 0);
+ typeNodeMap_.insert( "month", 0);
+ typeNodeMap_.insert( "name", 0);
+ typeNodeMap_.insert( "number", 0);
+ typeNodeMap_.insert( "object", 0);
+ typeNodeMap_.insert( "offset", 0);
+ typeNodeMap_.insert( "ok", 0);
+ typeNodeMap_.insert( "openCamera", 0);
+ typeNodeMap_.insert( "openImage", 0);
+ typeNodeMap_.insert( "openVideo", 0);
+ typeNodeMap_.insert( "padding", 0);
+ typeNodeMap_.insert( "parent", 0);
+ typeNodeMap_.insert( "path", 0);
+ typeNodeMap_.insert( "photoModeSelected", 0);
+ typeNodeMap_.insert( "position", 0);
+ typeNodeMap_.insert( "precision", 0);
+ typeNodeMap_.insert( "presetClicked", 0);
+ typeNodeMap_.insert( "preview", 0);
+ typeNodeMap_.insert( "previewSelected", 0);
+ typeNodeMap_.insert( "progress", 0);
+ typeNodeMap_.insert( "puzzleLost", 0);
+ typeNodeMap_.insert( "qmlSignal", 0);
+ typeNodeMap_.insert( "real", 0);
+ typeNodeMap_.insert( "rectangle", 0);
+ typeNodeMap_.insert( "request", 0);
+ typeNodeMap_.insert( "requestId", 0);
+ typeNodeMap_.insert( "section", 0);
+ typeNodeMap_.insert( "selected", 0);
+ typeNodeMap_.insert( "send", 0);
+ typeNodeMap_.insert( "settingsClicked", 0);
+ typeNodeMap_.insert( "shoe", 0);
+ typeNodeMap_.insert( "short", 0);
+ typeNodeMap_.insert( "signed", 0);
+ typeNodeMap_.insert( "sizeChanged", 0);
+ typeNodeMap_.insert( "size_t", 0);
+ typeNodeMap_.insert( "sockaddr", 0);
+ typeNodeMap_.insert( "someOtherSignal", 0);
+ typeNodeMap_.insert( "sourceSize", 0);
+ typeNodeMap_.insert( "startButtonClicked", 0);
+ typeNodeMap_.insert( "state", 0);
+ typeNodeMap_.insert( "std::initializer_list", 0);
+ typeNodeMap_.insert( "std::list", 0);
+ typeNodeMap_.insert( "std::map", 0);
+ typeNodeMap_.insert( "std::pair", 0);
+ typeNodeMap_.insert( "std::string", 0);
+ typeNodeMap_.insert( "std::vector", 0);
+ typeNodeMap_.insert( "string", 0);
+ typeNodeMap_.insert( "stringlist", 0);
+ typeNodeMap_.insert( "swapPlayers", 0);
+ typeNodeMap_.insert( "symbol", 0);
+ typeNodeMap_.insert( "t", 0);
+ typeNodeMap_.insert( "T", 0);
+ typeNodeMap_.insert( "tagChanged", 0);
+ typeNodeMap_.insert( "timeString", 0);
+ typeNodeMap_.insert( "timeout", 0);
+ typeNodeMap_.insert( "to", 0);
+ typeNodeMap_.insert( "toggled", 0);
+ typeNodeMap_.insert( "type", 0);
+ typeNodeMap_.insert( "unsigned", 0);
+ typeNodeMap_.insert( "urllist", 0);
+ typeNodeMap_.insert( "va_list", 0);
+ typeNodeMap_.insert( "value", 0);
+ typeNodeMap_.insert( "valueEmitted", 0);
+ typeNodeMap_.insert( "videoFramePainted", 0);
+ typeNodeMap_.insert( "videoModeSelected", 0);
+ typeNodeMap_.insert( "videoRecorder", 0);
+ typeNodeMap_.insert( "void", 0);
+ typeNodeMap_.insert( "volatile", 0);
+ typeNodeMap_.insert( "wchar_t", 0);
+ typeNodeMap_.insert( "x", 0);
+ typeNodeMap_.insert( "y", 0);
+ typeNodeMap_.insert( "zoom", 0);
+ typeNodeMap_.insert( "zoomTo", 0);
+}
+
+/*! \fn NamespaceNode* QDocDatabase::primaryTreeRoot()
+ Returns a pointer to the root node of the primary tree.
+ */
+
+/*!
+ \fn const GroupMap& QDocDatabase::groups()
Returns a const reference to the collection of all
- group nodes.
+ group nodes in the primary tree.
*/
/*!
- \fn const DocNodeMap& QDocDatabase::modules() const
+ \fn const ModuleMap& QDocDatabase::modules()
Returns a const reference to the collection of all
- module nodes.
+ module nodes in the primary tree.
*/
/*!
- \fn const DocNodeMap& QDocDatabase::qmlModules() const
+ \fn const QmlModuleMap& QDocDatabase::qmlModules()
Returns a const reference to the collection of all
- QML module nodes.
+ QML module nodes in the primary tree.
*/
-/*!
+/*! \fn GroupNode* QDocDatabase::getGroup(const QString& name)
Find the group node named \a name and return a pointer
to it. If a matching node is not found, return 0.
*/
-DocNode* QDocDatabase::getGroup(const QString& name)
-{
- DocNodeMap::const_iterator i = groups_.find(name);
- if (i != groups_.end())
- return i.value();
- return 0;
-}
-/*!
+/*! \fn GroupNode* QDocDatabase::findGroup(const QString& name)
Find the group node named \a name and return a pointer
to it. If a matching node is not found, add a new group
node named \a name and return a pointer to that one.
@@ -143,20 +679,8 @@ DocNode* QDocDatabase::getGroup(const QString& name)
If a new group node is added, its parent is the tree root,
and the new group node is marked \e{not seen}.
*/
-DocNode* QDocDatabase::findGroup(const QString& name)
-{
- DocNodeMap::const_iterator i = groups_.find(name);
- if (i != groups_.end())
- return i.value();
- DocNode* dn = new DocNode(tree_->root(), name, Node::Group, Node::OverviewPage);
- dn->markNotSeen();
- groups_.insert(name,dn);
- if (!masterMap_.contains(name,dn))
- masterMap_.insert(name,dn);
- return dn;
-}
-/*!
+/*! \fn ModuleNode* QDocDatabase::findModule(const QString& name)
Find the module node named \a name and return a pointer
to it. If a matching node is not found, add a new module
node named \a name and return a pointer to that one.
@@ -164,20 +688,8 @@ DocNode* QDocDatabase::findGroup(const QString& name)
If a new module node is added, its parent is the tree root,
and the new module node is marked \e{not seen}.
*/
-DocNode* QDocDatabase::findModule(const QString& name)
-{
- DocNodeMap::const_iterator i = modules_.find(name);
- if (i != modules_.end())
- return i.value();
- DocNode* dn = new DocNode(tree_->root(), name, Node::Module, Node::OverviewPage);
- dn->markNotSeen();
- modules_.insert(name,dn);
- if (!masterMap_.contains(name,dn))
- masterMap_.insert(name,dn);
- return dn;
-}
-/*!
+/*! \fn QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
Find the QML module node named \a name and return a pointer
to it. If a matching node is not found, add a new QML module
node named \a name and return a pointer to that one.
@@ -185,68 +697,32 @@ DocNode* QDocDatabase::findModule(const QString& name)
If a new QML module node is added, its parent is the tree root,
and the new QML module node is marked \e{not seen}.
*/
-QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
-{
- if (qmlModules_.contains(name))
- return static_cast<QmlModuleNode*>(qmlModules_.value(name));
-
- QmlModuleNode* qmn = new QmlModuleNode(tree_->root(), name);
- qmn->markNotSeen();
- qmn->setQmlModuleInfo(name);
- qmlModules_.insert(name, qmn);
- masterMap_.insert(name, qmn);
- return qmn;
-}
-/*!
- Looks up the group node named \a name in the collection
- of all group nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new group node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The group node is marked \e{seen}
- in either case.
+/*! \fn GroupNode* QDocDatabase::addGroup(const QString& name)
+ Looks up the group named \a name in the primary tree. If
+ a match is found, a pointer to the node is returned.
+ Otherwise, a new group node named \a name is created and
+ inserted into the collection, and the pointer to that node
+ is returned.
*/
-DocNode* QDocDatabase::addGroup(const QString& name)
-{
- DocNode* group = findGroup(name);
- group->markSeen();
- return group;
-}
-/*!
- Looks up the module node named \a name in the collection
- of all module nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new module node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The module node is marked \e{seen}
- in either case.
+/*! \fn ModuleNode* QDocDatabase::addModule(const QString& name)
+ Looks up the module named \a name in the primary tree. If
+ a match is found, a pointer to the node is returned.
+ Otherwise, a new module node named \a name is created and
+ inserted into the collection, and the pointer to that node
+ is returned.
*/
-DocNode* QDocDatabase::addModule(const QString& name)
-{
- DocNode* module = findModule(name);
- module->markSeen();
- return module;
-}
-/*!
- Looks up the QML module node named \a name in the collection
- of all QML module nodes. If a match is found, a pointer to the
- node is returned. Otherwise, a new QML module node named \a name
- is created and inserted into the collection, and the pointer
- to that node is returned. The QML module node is marked \e{seen}
- in either case.
- */
-QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
-{
- QStringList blankSplit = name.split(QLatin1Char(' '));
- QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
- qmn->setQmlModuleInfo(name);
- qmn->markSeen();
- //masterMap_.insert(qmn->qmlModuleIdentifier(),qmn);
- return qmn;
-}
+/*! \fn QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
+ Looks up the QML module named \a name in the primary tree.
+ If a match is found, a pointer to the node is returned.
+ Otherwise, a new QML module node named \a name is created
+ and inserted into the collection, and the pointer to that
+ node is returned.
+ */
-/*!
+/*! \fn GroupNode* QDocDatabase::addToGroup(const QString& name, Node* node)
Looks up the group node named \a name in the collection
of all group nodes. If a match is not found, a new group
node named \a name is created and inserted into the collection.
@@ -255,62 +731,31 @@ QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
\a node is not changed by this function. Returns a pointer to
the group node.
*/
-DocNode* QDocDatabase::addToGroup(const QString& name, Node* node)
-{
- DocNode* dn = findGroup(name);
- dn->addMember(node);
- node->addMember(dn);
- return dn;
-}
-/*!
+/*! \fn ModuleNode* QDocDatabase::addToModule(const QString& name, Node* node)
Looks up the module node named \a name in the collection
of all module nodes. If a match is not found, a new module
node named \a name is created and inserted into the collection.
Then append \a node to the module's members list. The parent of
\a node is not changed by this function. Returns the module node.
*/
-DocNode* QDocDatabase::addToModule(const QString& name, Node* node)
-{
- DocNode* dn = findModule(name);
- dn->addMember(node);
- node->setModuleName(name);
- return dn;
-}
-/*!
+/*! \fn QmlModuleNode* QDocDatabase::addToQmlModule(const QString& name, Node* node)
Looks up the QML module named \a name. If it isn't there,
create it. Then append \a node to the QML module's member
list. The parent of \a node is not changed by this function.
*/
-void QDocDatabase::addToQmlModule(const QString& name, Node* node)
-{
- QStringList qmid;
- QStringList dotSplit;
- QStringList blankSplit = name.split(QLatin1Char(' '));
- qmid.append(blankSplit[0]);
- if (blankSplit.size() > 1) {
- qmid.append(blankSplit[0] + blankSplit[1]);
- dotSplit = blankSplit[1].split(QLatin1Char('.'));
- qmid.append(blankSplit[0] + dotSplit[0]);
- }
- QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
- qmn->addMember(node);
- node->setQmlModule(qmn);
-
- if (node->subType() == Node::QmlClass) {
- QmlClassNode* n = static_cast<QmlClassNode*>(node);
- for (int i=0; i<qmid.size(); ++i) {
- QString key = qmid[i] + "::" + node->name();
- if (!qmlTypeMap_.contains(key))
- qmlTypeMap_.insert(key,n);
- if (!masterMap_.contains(key))
- masterMap_.insert(key,node);
- }
- if (!masterMap_.contains(node->name(),node))
- masterMap_.insert(node->name(),node);
- }
+/*!
+ Looks up the QML type node identified by the qualified Qml
+ type \a name and returns a pointer to the QML type node.
+ */
+QmlClassNode* QDocDatabase::findQmlType(const QString& name)
+{
+ QmlClassNode* qcn = forest_.lookupQmlType(name);
+ if (qcn)
+ return qcn;
+ return 0;
}
/*!
@@ -321,13 +766,17 @@ void QDocDatabase::addToQmlModule(const QString& name, Node* node)
If the QML module id is empty, it looks up the QML type by
\a name only.
*/
-QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name) const
+QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name)
{
- if (!qmid.isEmpty())
- return qmlTypeMap_.value(qmid + "::" + name);
+ if (!qmid.isEmpty()) {
+ QString t = qmid + "::" + name;
+ QmlClassNode* qcn = forest_.lookupQmlType(t);
+ if (qcn)
+ return qcn;
+ }
QStringList path(name);
- Node* n = tree_->findNodeByNameAndType(path, Node::Document, Node::QmlClass, 0, true);
+ Node* n = forest_.findNodeByNameAndType(path, Node::Document, Node::QmlClass, true);
if (n) {
if (n->subType() == Node::QmlClass)
return static_cast<QmlClassNode*>(n);
@@ -346,7 +795,7 @@ QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name
QML type \a name and returns a pointer to the QML type node.
If a QML type node is not found, 0 is returned.
*/
-QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name) const
+QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name)
{
if (!import.isEmpty()) {
QStringList dotSplit;
@@ -358,7 +807,7 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
qmName = import.importUri_;
for (int i=0; i<dotSplit.size(); ++i) {
QString qualifiedName = qmName + "::" + dotSplit[i];
- QmlClassNode* qcn = qmlTypeMap_.value(qualifiedName);
+ QmlClassNode* qcn = forest_.lookupQmlType(qualifiedName);
if (qcn)
return qcn;
}
@@ -367,59 +816,157 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
}
/*!
- For debugging only.
+ This function calls \a func for each tree in the forest.
*/
-void QDocDatabase::printModules() const
+void QDocDatabase::processForest(void (QDocDatabase::*func) (InnerNode*))
{
- DocNodeMap::const_iterator i = modules_.begin();
- while (i != modules_.end()) {
- qDebug() << " " << i.key();
- ++i;
+ Tree* t = forest_.firstTree();
+ while (t) {
+ (this->*(func))(t->root());
+ t = forest_.nextTree();
}
}
/*!
- For debugging only.
+ Constructs the collection of legalese texts, if it has not
+ already been constructed and returns a reference to it.
*/
-void QDocDatabase::printQmlModules() const
+TextToNodeMap& QDocDatabase::getLegaleseTexts()
{
- DocNodeMap::const_iterator i = qmlModules_.begin();
- while (i != qmlModules_.end()) {
- qDebug() << " " << i.key();
- ++i;
- }
+ if (legaleseTexts_.isEmpty())
+ processForest(&QDocDatabase::findAllLegaleseTexts);
+ return legaleseTexts_;
}
/*!
- Traverses the database to construct useful data structures
- for use when outputting certain significant collections of
- things, C++ classes, QML types, "since" lists, and other
- stuff.
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of C++ classes with obsolete members.
*/
-void QDocDatabase::buildCollections()
+NodeMap& QDocDatabase::getClassesWithObsoleteMembers()
{
- nonCompatClasses_.clear();
- mainClasses_.clear();
- compatClasses_.clear();
- obsoleteClasses_.clear();
- funcIndex_.clear();
- legaleseTexts_.clear();
- serviceClasses_.clear();
- qmlClasses_.clear();
-
- findAllClasses(treeRoot());
- findAllFunctions(treeRoot());
- findAllLegaleseTexts(treeRoot());
- findAllNamespaces(treeRoot());
- findAllSince(treeRoot());
- findAllObsoleteThings(treeRoot());
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return classesWithObsoleteMembers_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete QML types.
+ */
+NodeMap& QDocDatabase::getObsoleteQmlTypes()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return obsoleteQmlTypes_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of QML types with obsolete members.
+ */
+NodeMap& QDocDatabase::getQmlTypesWithObsoleteMembers()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return qmlTypesWithObsoleteMembers_;
+}
+
+/*!
+ Constructs the C++ namespace data structure, if it has not
+ already been constructed. Returns a reference to it.
+ */
+NodeMap& QDocDatabase::getNamespaces()
+{
+ if (namespaceIndex_.isEmpty())
+ processForest(&QDocDatabase::findAllNamespaces);
+ return namespaceIndex_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of C++ service clases.
+
+ \note This is currently not used.
+ */
+NodeMap& QDocDatabase::getServiceClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return serviceClasses_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete QML types.
+ */
+NodeMap& QDocDatabase::getQmlTypes()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return qmlClasses_;
+}
+
+/*!
+ Construct the data structures for obsolete things, if they
+ have not already been constructed. Returns a reference to
+ the map of obsolete C++ clases.
+ */
+NodeMap& QDocDatabase::getObsoleteClasses()
+{
+ if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
+ processForest(&QDocDatabase::findAllObsoleteThings);
+ return obsoleteClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of compatibility C++ clases.
+ */
+NodeMap& QDocDatabase::getCompatibilityClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return compatClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of main C++ clases.
+
+ \note The main C++ classes data structure is currently not
+ used.
+ */
+NodeMap& QDocDatabase::getMainClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return mainClasses_;
+}
+
+/*!
+ Construct the C++ class data structures, if they have not
+ already been constructed. Returns a reference to the map
+ of all C++ classes.
+ */
+NodeMap& QDocDatabase::getCppClasses()
+{
+ if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
+ processForest(&QDocDatabase::findAllClasses);
+ return nonCompatClasses_;
}
/*!
Finds all the C++ class nodes and QML type nodes and
sorts them into maps.
*/
-void QDocDatabase::findAllClasses(const InnerNode* node)
+void QDocDatabase::findAllClasses(InnerNode* node)
{
NodeList::const_iterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -463,15 +1010,26 @@ void QDocDatabase::findAllClasses(const InnerNode* node)
}
/*!
+ Construct the function index data structure and return it.
+ This data structure is used to output the function index page.
+ */
+NodeMapMap& QDocDatabase::getFunctionIndex()
+{
+ funcIndex_.clear();
+ processForest(&QDocDatabase::findAllFunctions);
+ return funcIndex_;
+}
+
+/*!
Finds all the function nodes
*/
-void QDocDatabase::findAllFunctions(const InnerNode* node)
+void QDocDatabase::findAllFunctions(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode()) {
- findAllFunctions(static_cast<const InnerNode*>(*c));
+ findAllFunctions(static_cast<InnerNode*>(*c));
}
else if ((*c)->type() == Node::Function) {
const FunctionNode* func = static_cast<const FunctionNode*>(*c);
@@ -491,7 +1049,7 @@ void QDocDatabase::findAllFunctions(const InnerNode* node)
Finds all the nodes containing legalese text and puts them
in a map.
*/
-void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
+void QDocDatabase::findAllLegaleseTexts(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -499,7 +1057,7 @@ void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
if (!(*c)->doc().legaleseText().isEmpty())
legaleseTexts_.insertMulti((*c)->doc().legaleseText(), *c);
if ((*c)->isInnerNode())
- findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
+ findAllLegaleseTexts(static_cast<InnerNode *>(*c));
}
++c;
}
@@ -508,13 +1066,13 @@ void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
/*!
Finds all the namespace nodes and puts them in an index.
*/
-void QDocDatabase::findAllNamespaces(const InnerNode* node)
+void QDocDatabase::findAllNamespaces(InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode()) {
- findAllNamespaces(static_cast<const InnerNode *>(*c));
+ findAllNamespaces(static_cast<InnerNode *>(*c));
if ((*c)->type() == Node::Namespace) {
// Ensure that the namespace's name is not empty (the root
// namespace has no name).
@@ -532,7 +1090,7 @@ void QDocDatabase::findAllNamespaces(const InnerNode* node)
maps. They can be C++ classes, QML types, or they can be
functions, enum types, typedefs, methods, etc.
*/
-void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
+void QDocDatabase::findAllObsoleteThings(InnerNode* node)
{
NodeList::const_iterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
@@ -627,7 +1185,7 @@ void QDocDatabase::findAllObsoleteThings(const InnerNode* node)
This function is used for generating the "New Classes... in x.y"
section on the \e{What's New in Qt x.y} page.
*/
-void QDocDatabase::findAllSince(const InnerNode* node)
+void QDocDatabase::findAllSince(InnerNode* node)
{
NodeList::const_iterator child = node->childNodes().constBegin();
while (child != node->childNodes().constEnd()) {
@@ -702,8 +1260,10 @@ void QDocDatabase::findAllSince(const InnerNode* node)
reference to the value, which is a NodeMap. If \a key is not
found, return a reference to an empty NodeMap.
*/
-const NodeMap& QDocDatabase::getClassMap(const QString& key) const
+const NodeMap& QDocDatabase::getClassMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newClassMaps_.constFind(key);
if (i != newClassMaps_.constEnd())
return i.value();
@@ -715,8 +1275,10 @@ const NodeMap& QDocDatabase::getClassMap(const QString& key) const
reference to the value, which is a NodeMap. If the \a key is not
found, return a reference to an empty NodeMap.
*/
-const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
+const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newQmlTypeMaps_.constFind(key);
if (i != newQmlTypeMaps_.constEnd())
return i.value();
@@ -728,8 +1290,10 @@ const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
a reference to the value, which is a NodeMultiMap. If \a key
is not found, return a reference to an empty NodeMultiMap.
*/
-const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const
+const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key)
{
+ if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
+ processForest(&QDocDatabase::findAllSince);
NodeMultiMapMap::const_iterator i = newSinceMaps_.constFind(key);
if (i != newSinceMaps_.constEnd())
return i.value();
@@ -742,209 +1306,55 @@ const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const
to generating documentation.
*/
void QDocDatabase::resolveIssues() {
- resolveQmlInheritance(treeRoot());
- resolveTargets(treeRoot());
- tree_->resolveCppToQmlLinks();
+ resolveQmlInheritance(primaryTreeRoot());
+ resolveTargets();
+ primaryTree()->resolveCppToQmlLinks();
}
/*!
- Searches the \a database for a node named \a target and returns
- a pointer to it if found.
+ This function is called for autolinking to a \a type,
+ which could be a function return type or a parameter
+ type. The tree node that represents the \a type is
+ returned. All the trees are searched until a match is
+ found. When searching the primary tree, the search
+ begins at \a relative and proceeds up the parent chain.
+ When searching the index trees, the search begins at the
+ root.
*/
-const Node* QDocDatabase::resolveTarget(const QString& target,
- const Node* relative,
- const Node* self)
+const Node* QDocDatabase::resolveType(const QString& type, const Node* relative)
{
- const Node* node = 0;
- if (target.endsWith("()")) {
- QString funcName = target;
- funcName.chop(2);
- QStringList path = funcName.split("::");
- const FunctionNode* fn = tree_->findFunctionNode(path, relative, SearchBaseClasses);
- if (fn) {
- /*
- Why is this case not accepted?
- */
- if (fn->metaness() != FunctionNode::MacroWithoutParams)
- node = fn;
- }
- }
- else if (target.contains(QLatin1Char('#'))) {
- // This error message is never printed; I think we can remove the case.
- qDebug() << "qdoc: target case not handled:" << target;
+ QStringList path = type.split("::");
+ if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString("T"))) {
+ NodeMap::iterator i = typeNodeMap_.find(path.at(0));
+ if (i != typeNodeMap_.end())
+ return i.value();
}
- else {
- QStringList path = target.split("::");
- int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
- node = tree_->findNode(path, relative, flags, self);
- }
- return node;
+ return forest_.resolveType(path, relative);
}
/*!
Finds the node that will generate the documentation that
contains the \a target and returns a pointer to it.
+
+ Can this be improved by using the target map in Tree?
*/
const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* relative)
{
const Node* node = 0;
if (target.isEmpty())
node = relative;
- else if (target.endsWith(".html"))
- node = tree_->root()->findChildNodeByNameAndType(target, Node::Document);
+ else if (target.endsWith(".html")) {
+ node = findNodeByNameAndType(QStringList(target), Node::Document, Node::NoSubType);
+ }
else {
node = resolveTarget(target, relative);
if (!node)
- node = findDocNodeByTitle(target, relative);
+ node = findDocNodeByTitle(target);
}
return node;
}
/*!
- Inserts a new target into the target table with the specified
- \a name, \a node, and \a priority.
- */
-void QDocDatabase::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
-{
- TargetRec target;
- target.type_ = type;
- target.node_ = node;
- target.priority_ = priority;
- Atom a = Atom(Atom::Target, name);
- target.ref_ = refForAtom(&a);
- targetRecMultiMap_.insert(name, target);
-}
-
-/*!
- This function searches for a \a target anchor node. If it
- finds one, it sets \a ref and returns the found node.
- */
-const Node*
-QDocDatabase::findUnambiguousTarget(const QString& target, QString& ref, const Node* relative)
-{
- TargetRec bestTarget;
- int numBestTargets = 0;
- QList<TargetRec> bestTargetList;
-
- QString key = Doc::canonicalTitle(target);
- TargetRecMultiMap::iterator i = targetRecMultiMap_.find(key);
- while (i != targetRecMultiMap_.end()) {
- if (i.key() != key)
- break;
- const TargetRec& candidate = i.value();
- if (candidate.priority_ < bestTarget.priority_) {
- bestTarget = candidate;
- bestTargetList.clear();
- bestTargetList.append(candidate);
- numBestTargets = 1;
- } else if (candidate.priority_ == bestTarget.priority_) {
- bestTargetList.append(candidate);
- ++numBestTargets;
- }
- ++i;
- }
- if (numBestTargets > 0) {
- if (numBestTargets == 1) {
- ref = bestTarget.ref_;
- return bestTarget.node_;
- }
- else if (bestTargetList.size() > 1) {
- if (relative && !relative->qmlModuleName().isEmpty()) {
- for (int i=0; i<bestTargetList.size(); ++i) {
- const Node* n = bestTargetList.at(i).node_;
- if (n && relative->qmlModuleName() == n->qmlModuleName()) {
- ref = bestTargetList.at(i).ref_;
- return n;
- }
- }
- }
- }
- }
- ref.clear();
- return 0;
-}
-
-/*!
- This function searches for a node with the specified \a title.
- If \a relative node is provided, it is used to disambiguate if
- it has a QML module identifier.
- */
-const DocNode* QDocDatabase::findDocNodeByTitle(const QString& title, const Node* relative) const
-{
- QString key = Doc::canonicalTitle(title);
- DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key);
- if (i != docNodesByTitle_.constEnd()) {
- if (relative && !relative->qmlModuleName().isEmpty()) {
- const DocNode* dn = i.value();
- InnerNode* parent = dn->parent();
- if (parent && parent->type() == Node::Document && parent->subType() == Node::Collision) {
- const NodeList& nl = parent->childNodes();
- NodeList::ConstIterator it = nl.constBegin();
- while (it != nl.constEnd()) {
- if ((*it)->qmlModuleName() == relative->qmlModuleName()) {
- /*
- By returning here, we avoid printing
- all the duplicate header warnings,
- which are not really duplicates now,
- because of the QML module name being
- used as a namespace qualifier.
- */
- dn = static_cast<const DocNode*>(*it);
- return dn;
- }
- ++it;
- }
- }
- }
- /*
- Reporting all these duplicate section titles is probably
- overkill. We should report the duplicate file and let
- that suffice.
- */
- DocNodeMultiMap::const_iterator j = i;
- ++j;
- if (j != docNodesByTitle_.constEnd() && j.key() == i.key()) {
- QList<Location> internalLocations;
- while (j != docNodesByTitle_.constEnd()) {
- if (j.key() == i.key() && j.value()->url().isEmpty()) {
- internalLocations.append(j.value()->location());
- break; // Just report one duplicate for now.
- }
- ++j;
- }
- if (internalLocations.size() > 0) {
- i.value()->location().warning(tr("This page title exists in more than one file: \"%1\"").arg(title));
- foreach (const Location &location, internalLocations)
- location.warning(tr("[It also exists here]"));
- }
- }
- return i.value();
- }
- return 0;
-}
-
-/*!
- This function searches for a node with a canonical title
- constructed from \a target. If the node it finds is \a node,
- it returns the ref from that node. Otherwise it returns an
- empty string.
- */
-QString QDocDatabase::findTarget(const QString& target, const Node* node) const
-{
- QString key = Doc::canonicalTitle(target);
- TargetRecMultiMap::const_iterator i = targetRecMultiMap_.constFind(key);
-
- if (i != targetRecMultiMap_.constEnd()) {
- do {
- if (i.value().node_ == node)
- return i.value().ref_;
- ++i;
- } while (i != targetRecMultiMap_.constEnd() && i.key() == key);
- }
- return QString();
-}
-
-/*!
For each QML Type node in the tree beginning at \a root,
if it has a QML base type name but its QML base type node
pointer is 0, use the QML base type name to look up the
@@ -953,111 +1363,40 @@ QString QDocDatabase::findTarget(const QString& target, const Node* node) const
*/
void QDocDatabase::resolveQmlInheritance(InnerNode* root)
{
- // Dop we need recursion?
+ NodeMap previousSearches;
+ // Do we need recursion?
foreach (Node* child, root->childNodes()) {
if (child->type() == Node::Document && child->subType() == Node::QmlClass) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
- if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) {
- QmlClassNode* bqcn = 0;
- if (qcn->qmlBaseName().contains("::")) {
- bqcn = qmlTypeMap_.value(qcn->qmlBaseName());
- }
- else {
- const ImportList& imports = qcn->importList();
- for (int i=0; i<imports.size(); ++i) {
- bqcn = findQmlType(imports[i], qcn->qmlBaseName());
- if (bqcn)
- break;
- }
- }
- if (bqcn == 0) {
- bqcn = findQmlType(QString(), qcn->qmlBaseName());
- }
- if (bqcn) {
+ if (qcn->qmlBaseNodeNotSet() && !qcn->qmlBaseName().isEmpty()) {
+ QmlClassNode* bqcn = static_cast<QmlClassNode*>(previousSearches.value(qcn->qmlBaseName()));
+ if (bqcn)
qcn->setQmlBaseNode(bqcn);
- }
-#if 0
else {
- qDebug() << "Temporary error message (ignore): UNABLE to resolve QML base type:"
- << qcn->qmlBaseName() << "for QML type:" << qcn->name();
- }
-#endif
- }
- }
- }
-}
-
-/*!
- */
-void QDocDatabase::resolveTargets(InnerNode* root)
-{
- // need recursion
-
- foreach (Node* child, root->childNodes()) {
- if (child->type() == Node::Document) {
- DocNode* node = static_cast<DocNode*>(child);
- if (!node->title().isEmpty()) {
- QString key = Doc::canonicalTitle(node->title());
- QList<DocNode*> nodes = docNodesByTitle_.values(key);
- bool alreadyThere = false;
- if (!nodes.empty()) {
- for (int i=0; i< nodes.size(); ++i) {
- if (nodes[i]->subType() == Node::ExternalPage) {
- if (node->name() == nodes[i]->name()) {
- alreadyThere = true;
+ if (!qcn->importList().isEmpty()) {
+ const ImportList& imports = qcn->importList();
+ for (int i=0; i<imports.size(); ++i) {
+ bqcn = findQmlType(imports[i], qcn->qmlBaseName());
+ if (bqcn)
break;
- }
}
}
- }
- if (!alreadyThere) {
- docNodesByTitle_.insert(key, node);
- }
- }
- if (node->subType() == Node::Collision) {
- resolveTargets(node);
- }
- }
-
- if (child->doc().hasTableOfContents()) {
- const QList<Atom*>& toc = child->doc().tableOfContents();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 3;
-
- for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
- QString title = Text::sectionHeading(toc.at(i)).toString();
- if (!title.isEmpty()) {
- QString key = Doc::canonicalTitle(title);
- targetRecMultiMap_.insert(key, target);
+ if (bqcn == 0) {
+ bqcn = findQmlType(QString(), qcn->qmlBaseName());
+ }
+ if (bqcn) {
+ qcn->setQmlBaseNode(bqcn);
+ previousSearches.insert(qcn->qmlBaseName(), bqcn);
+ }
+#if 0
+ else {
+ qDebug() << "Temporary error message (ignore): UNABLE to resolve QML base type:"
+ << qcn->qmlBaseName() << "for QML type:" << qcn->name();
+ }
+#endif
}
}
}
- if (child->doc().hasKeywords()) {
- const QList<Atom*>& keywords = child->doc().keywords();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 1;
-
- for (int i = 0; i < keywords.size(); ++i) {
- target.ref_ = refForAtom(keywords.at(i));
- QString key = Doc::canonicalTitle(keywords.at(i)->string());
- targetRecMultiMap_.insert(key, target);
- }
- }
- if (child->doc().hasTargets()) {
- const QList<Atom*>& toc = child->doc().targets();
- TargetRec target;
- target.node_ = child;
- target.priority_ = 2;
-
- for (int i = 0; i < toc.size(); ++i) {
- target.ref_ = refForAtom(toc.at(i));
- QString key = Doc::canonicalTitle(toc.at(i)->string());
- targetRecMultiMap_.insert(key, target);
- }
- }
}
}
@@ -1096,17 +1435,6 @@ void QDocDatabase::generateIndex(const QString& fileName,
QDocIndexFiles::destroyQDocIndexFiles();
}
-QString QDocDatabase::refForAtom(const Atom* atom)
-{
- if (atom) {
- if (atom->type() == Atom::SectionLeft)
- return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
- if (atom->type() == Atom::Target)
- return Doc::canonicalTitle(atom->string());
- }
- return QString();
-}
-
/*!
If there are open namespaces, search for the function node
having the same function name as the \a clone node in each
@@ -1136,20 +1464,29 @@ FunctionNode* QDocDatabase::findNodeInOpenNamespace(const QStringList& parentPat
/*!
Find a node of the specified \a type and \a subtype that is
- reached with the specified \a path. If such a node is found
- in an open namespace, prefix \a path with the name of the
- open namespace and "::" and return a pointer to the node.
- Othewrwise return 0.
+ reached with the specified \a path qualified with the name
+ of one of the open namespaces (might not be any open ones).
+ If the node is found in an open namespace, prefix \a path
+ with the name of the open namespace and "::" and return a
+ pointer to the node. Othewrwise return 0.
+
+ This function only searches in the current primary tree.
*/
Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
Node::Type type,
Node::SubType subtype)
{
+ if (path.isEmpty())
+ return 0;
Node* n = 0;
if (!openNamespaces_.isEmpty()) {
foreach (const QString& t, openNamespaces_) {
- QStringList p = t.split("::") + path;
- n = findNodeByNameAndType(p, type, subtype);
+ QStringList p;
+ if (t != path[0])
+ p = t.split("::") + path;
+ else
+ p = path;
+ n = primaryTree()->findNodeByNameAndType(p, type, subtype);
if (n) {
path = p;
break;
@@ -1159,4 +1496,129 @@ Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
return n;
}
+/*!
+ Finds all the collection nodes of type \a nt into the
+ collection node map \a cnn. Nodes that match \a relative
+ are not included.
+ */
+void QDocDatabase::mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative)
+{
+ QRegExp singleDigit("\\b([0-9])\\b");
+ CNMultiMap cnmm;
+ forest_.mergeCollectionMaps(nt, cnmm);
+ cnm.clear();
+ if (cnmm.isEmpty())
+ return;
+ QStringList keys = cnmm.uniqueKeys();
+ foreach (QString key, keys) {
+ QList<CollectionNode*> values = cnmm.values(key);
+ CollectionNode* n = 0;
+ foreach (CollectionNode* v, values) {
+ if (v && v->wasSeen() && (v != relative)) {
+ n = v;
+ break;
+ }
+ }
+ if (n) {
+ if (values.size() > 1) {
+ foreach (CollectionNode* v, values) {
+ if (v != n) {
+ foreach (Node* t, v->members())
+ n->addMember(t);
+ }
+ }
+ }
+ if (!n->members().isEmpty()) {
+ QString sortKey = n->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ cnm.insert(sortKey, n);
+ }
+ }
+ }
+}
+
+/*!
+ Finds all the collection nodes with the same name
+ and type as \a cn and merges their members into the
+ members list of \a cn.
+ */
+void QDocDatabase::mergeCollections(CollectionNode* cn)
+{
+ CollectionList cl;
+ forest_.getCorrespondingCollections(cn, cl);
+ if (!cl.empty()) {
+ foreach (CollectionNode* v, cl) {
+ if (v != cn) {
+ foreach (Node* t, v->members())
+ cn->addMember(t);
+ }
+ }
+ }
+}
+
QT_END_NAMESPACE
+
+#if 0
+ void getAllGroups(CNMM& t);
+ void getAllModules(CNMM& t);
+ void getAllQmlModules(CNMM& t);
+
+/*!
+ For each tree in the forest, get the group map from the tree.
+ Insert each pair from the group map into the collection node
+ multimap \a t.
+ */
+void QDocForest::getAllGroups(CNMM& t)
+{
+ foreach (Tree* t, searchOrder()) {
+ const GroupMap& gm = t->groups();
+ if (!gm.isEmpty()) {
+ GroupMap::const_iterator i = gm.begin();
+ while (i != gm.end()) {
+ t.insert(i.key(), i.value());
+ ++i;
+ }
+ }
+ }
+}
+
+/*!
+ For each tree in the forest, get the module map from the tree.
+ Insert each pair from the module map into the collection node
+ multimap \a t.
+ */
+void QDocForest::getAllModules(CNMM& t)
+{
+ foreach (Tree* t, searchOrder()) {
+ const ModuleMap& mm = t->modules();
+ if (!mm.isEmpty()) {
+ ModuleMap::const_iterator i = mm.begin();
+ while (i != mm.end()) {
+ t.insert(i.key(), i.value());
+ ++i;
+ }
+ }
+ }
+}
+
+/*!
+ For each tree in the forest, get the QML module map from the
+ tree. Insert each pair from the QML module map into the
+ collection node multimap \a t.
+ */
+void QDocForest::getAllQmlModules(CNMM& t)
+{
+ foreach (Tree* t, searchOrder()) {
+ const QmlModuleMap& qmm = t->groups();
+ if (!qmm.isEmpty()) {
+ QmlModuleMap::const_iterator i = qmm.begin();
+ while (i != qmm.end()) {
+ t.insert(i.key(), i.value());
+ ++i;
+ }
+ }
+ }
+}
+#endif
diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h
index 4decba5f79..7bbff89fa3 100644
--- a/src/tools/qdoc/qdocdatabase.h
+++ b/src/tools/qdoc/qdocdatabase.h
@@ -45,19 +45,20 @@
#include <qstring.h>
#include <qmap.h>
#include "tree.h"
+#include "config.h"
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
-typedef QMap<QString, DocNode*> DocNodeMap;
-typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMap<QString, NodeMap> NodeMapMap;
typedef QMap<QString, NodeMultiMap> NodeMultiMapMap;
typedef QMultiMap<QString, Node*> QDocMultiMap;
typedef QMap<Text, const Node*> TextToNodeMap;
-typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
+typedef QList<CollectionNode*> CollectionList;
class Atom;
class Generator;
+class QDocDatabase;
enum FindFlag {
SearchBaseClasses = 0x1,
@@ -65,20 +66,159 @@ enum FindFlag {
NonFunction = 0x4
};
-struct TargetRec
+class QDocForest
{
public:
- enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
- TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
- bool isEmpty() const { return ref_.isEmpty(); }
- //void debug(int idx, const QString& key);
- Node* node_;
- QString ref_;
- int priority_;
- Type type_;
-};
-typedef QMultiMap<QString, TargetRec> TargetRecMultiMap;
+ friend class QDocDatabase;
+ QDocForest(QDocDatabase* qdb)
+ : qdb_(qdb), primaryTree_(0), currentIndex_(0) { }
+ ~QDocForest();
+
+ NamespaceNode* firstRoot();
+ NamespaceNode* nextRoot();
+ Tree* firstTree();
+ Tree* nextTree();
+ Tree* primaryTree() { return primaryTree_; }
+ NamespaceNode* primaryTreeRoot() { return (primaryTree_ ? primaryTree_->root() : 0); }
+ bool isEmpty() { return searchOrder().isEmpty(); }
+ bool done() { return (currentIndex_ >= searchOrder().size()); }
+ const QVector<Tree*>& searchOrder();
+ const QVector<Tree*>& indexSearchOrder();
+ void setSearchOrder();
+
+ const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findNode(path, relative, findFlags);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ //qDebug() << "FAILED SEARCH 1" << path;
+ return 0;
+ }
+
+ Node* findNodeByNameAndType(const QStringList& path,
+ Node::Type type,
+ Node::SubType subtype,
+ bool acceptCollision = false) {
+ foreach (Tree* t, searchOrder()) {
+ Node* n = t->findNodeByNameAndType(path, type, subtype, acceptCollision);
+ if (n)
+ return n;
+ }
+ //qDebug() << "FAILED SEARCH 2" << path << type << subtype;
+ return 0;
+ }
+ ClassNode* findClassNode(const QStringList& path) {
+ foreach (Tree* t, searchOrder()) {
+ ClassNode* n = t->findClassNode(path);
+ if (n)
+ return n;
+ }
+ //qDebug() << "FAILED SEARCH 3" << path;
+ return 0;
+ }
+
+ InnerNode* findRelatesNode(const QStringList& path) {
+ foreach (Tree* t, searchOrder()) {
+ InnerNode* n = t->findRelatesNode(path);
+ if (n)
+ return n;
+ }
+ //qDebug() << "FAILED SEARCH 4" << path;
+ return 0;
+ }
+
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->resolveFunctionTarget(target, relative);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ return 0;
+ }
+ const Node* resolveTarget(const QString& target, const Node* relative);
+
+ const Node* resolveType(const QStringList& path, const Node* relative)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = resolveTypeHelper(path, relative, t);
+ if (n)
+ return n;
+ relative = 0;
+ }
+ //qDebug() << "FAILED SEARCH 5" << path;
+ return 0;
+ }
+
+ QString findTarget(const QString& target, const Node* node)
+ {
+ foreach (Tree* t, searchOrder()) {
+ QString ref = t->findTarget(target, node);
+ if (!ref.isEmpty())
+ return ref;
+ }
+ //qDebug() << "FAILED SEARCH 7" << target;
+ return QString();
+ }
+
+ const Node* findUnambiguousTarget(const QString& target, QString& ref)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const Node* n = t->findUnambiguousTarget(target, ref);
+ if (n)
+ return n;
+ }
+ //qDebug() << "FAILED SEARCH 8" << target;
+ return 0;
+ }
+
+ const DocNode* findDocNodeByTitle(const QString& title)
+ {
+ foreach (Tree* t, searchOrder()) {
+ const DocNode* n = t->findDocNodeByTitle(title);
+ if (n)
+ return n;
+ }
+ //qDebug() << "FAILED SEARCH 9" << title;
+ return 0;
+ }
+
+ QmlClassNode* lookupQmlType(const QString& name)
+ {
+ foreach (Tree* t, searchOrder()) {
+ QmlClassNode* qcn = t->lookupQmlType(name);
+ if (qcn)
+ return qcn;
+ }
+ return 0;
+ }
+ void mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm);
+ void getCorrespondingCollections(CollectionNode* cn, CollectionList& cl)
+ {
+ foreach (Tree* t, searchOrder()) {
+ CollectionNode* ccn = t->getCorrespondingCollection(cn);
+ if (ccn)
+ cl.append(ccn);
+ }
+ }
+
+ private:
+ void newPrimaryTree(const QString& module);
+ NamespaceNode* newIndexTree(const QString& module);
+ const Node* resolveTypeHelper(const QStringList& path, const Node* relative, Tree* t);
+
+ private:
+ QDocDatabase* qdb_;
+ Tree* primaryTree_;
+ int currentIndex_;
+ QMap<QString, Tree*> forest_;
+ QVector<Tree*> searchOrder_;
+ QVector<Tree*> indexSearchOrder_;
+ QVector<QString> moduleNames_;
+};
class QDocDatabase
{
@@ -89,100 +229,124 @@ class QDocDatabase
static void destroyQdocDB();
~QDocDatabase();
- const DocNodeMap& groups() const { return groups_; }
- const DocNodeMap& modules() const { return modules_; }
- const DocNodeMap& qmlModules() const { return qmlModules_; }
+ const CNMap& groups() { return primaryTree()->groups(); }
+ const CNMap& modules() { return primaryTree()->modules(); }
+ const CNMap& qmlModules() { return primaryTree()->qmlModules(); }
- DocNode* getGroup(const QString& name);
- DocNode* findGroup(const QString& name);
- DocNode* findModule(const QString& name);
- QmlModuleNode* findQmlModule(const QString& name);
+ GroupNode* getGroup(const QString& name) { return primaryTree()->getGroup(name); }
+ GroupNode* findGroup(const QString& name) { return primaryTree()->findGroup(name); }
+ ModuleNode* findModule(const QString& name) { return primaryTree()->findModule(name); }
+ QmlModuleNode* findQmlModule(const QString& name) { return primaryTree()->findQmlModule(name); }
- DocNode* addGroup(const QString& name);
- DocNode* addModule(const QString& name);
- QmlModuleNode* addQmlModule(const QString& name);
+ GroupNode* addGroup(const QString& name) { return primaryTree()->addGroup(name); }
+ ModuleNode* addModule(const QString& name) { return primaryTree()->addModule(name); }
+ QmlModuleNode* addQmlModule(const QString& name) { return primaryTree()->addQmlModule(name); }
- DocNode* addToGroup(const QString& name, Node* node);
- DocNode* addToModule(const QString& name, Node* node);
- void addToQmlModule(const QString& name, Node* node);
-
- QmlClassNode* findQmlType(const QString& qmid, const QString& name) const;
- QmlClassNode* findQmlType(const ImportRec& import, const QString& name) const;
+ GroupNode* addToGroup(const QString& name, Node* node) {
+ return primaryTree()->addToGroup(name, node);
+ }
+ ModuleNode* addToModule(const QString& name, Node* node) {
+ return primaryTree()->addToModule(name, node);
+ }
+ QmlModuleNode* addToQmlModule(const QString& name, Node* node) {
+ return primaryTree()->addToQmlModule(name, node);
+ }
+ void addExampleNode(ExampleNode* n) { primaryTree()->addExampleNode(n); }
+ ExampleNodeMap& exampleNodeMap() { return primaryTree()->exampleNodeMap(); }
- void findAllClasses(const InnerNode *node);
- void findAllFunctions(const InnerNode *node);
- void findAllLegaleseTexts(const InnerNode *node);
- void findAllNamespaces(const InnerNode *node);
- void findAllObsoleteThings(const InnerNode* node);
- void findAllSince(const InnerNode *node);
- void buildCollections();
+ QmlClassNode* findQmlType(const QString& name);
+ QmlClassNode* findQmlType(const QString& qmid, const QString& name);
+ QmlClassNode* findQmlType(const ImportRec& import, const QString& name);
+ private:
+ void findAllClasses(InnerNode *node);
+ void findAllFunctions(InnerNode *node);
+ void findAllLegaleseTexts(InnerNode *node);
+ void findAllNamespaces(InnerNode *node);
+ void findAllObsoleteThings(InnerNode* node);
+ void findAllSince(InnerNode *node);
+
+ public:
// special collection access functions
- NodeMap& getCppClasses() { return nonCompatClasses_; }
- NodeMap& getMainClasses() { return mainClasses_; }
- NodeMap& getCompatibilityClasses() { return compatClasses_; }
- NodeMap& getObsoleteClasses() { return obsoleteClasses_; }
- NodeMap& getClassesWithObsoleteMembers() { return classesWithObsoleteMembers_; }
- NodeMap& getObsoleteQmlTypes() { return obsoleteQmlTypes_; }
- NodeMap& getQmlTypesWithObsoleteMembers() { return qmlTypesWithObsoleteMembers_; }
- NodeMap& getNamespaces() { return namespaceIndex_; }
- NodeMap& getServiceClasses() { return serviceClasses_; }
- NodeMap& getQmlTypes() { return qmlClasses_; }
- NodeMapMap& getFunctionIndex() { return funcIndex_; }
- TextToNodeMap& getLegaleseTexts() { return legaleseTexts_; }
- const NodeMap& getClassMap(const QString& key) const;
- const NodeMap& getQmlTypeMap(const QString& key) const;
- const NodeMultiMap& getSinceMap(const QString& key) const;
-
- const Node* resolveTarget(const QString& target, const Node* relative, const Node* self=0);
- const Node* findNodeForTarget(const QString& target, const Node* relative);
- void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
+ NodeMap& getCppClasses();
+ NodeMap& getMainClasses();
+ NodeMap& getCompatibilityClasses();
+ NodeMap& getObsoleteClasses();
+ NodeMap& getClassesWithObsoleteMembers();
+ NodeMap& getObsoleteQmlTypes();
+ NodeMap& getQmlTypesWithObsoleteMembers();
+ NodeMap& getNamespaces();
+ NodeMap& getServiceClasses();
+ NodeMap& getQmlTypes();
+ NodeMapMap& getFunctionIndex();
+ TextToNodeMap& getLegaleseTexts();
+ const NodeMap& getClassMap(const QString& key);
+ const NodeMap& getQmlTypeMap(const QString& key);
+ const NodeMultiMap& getSinceMap(const QString& key);
/* convenience functions
Many of these will be either eliminated or replaced.
*/
- QString refForAtom(const Atom* atom);
- Tree* tree() { return tree_; }
- NamespaceNode* treeRoot() { return tree_->root(); }
- void resolveInheritance() { tree_->resolveInheritance(); }
+ void resolveInheritance() { primaryTree()->resolveInheritance(); }
void resolveQmlInheritance(InnerNode* root);
void resolveIssues();
- void fixInheritance() { tree_->fixInheritance(); }
- void resolveProperties() { tree_->resolveProperties(); }
+ void fixInheritance() { primaryTree()->fixInheritance(); }
+ void resolveProperties() { primaryTree()->resolveProperties(); }
- const Node* findNode(const QStringList& path) { return tree_->findNode(path); }
- ClassNode* findClassNode(const QStringList& path) { return tree_->findClassNode(path); }
- NamespaceNode* findNamespaceNode(const QStringList& path) { return tree_->findNamespaceNode(path); }
-
- NameCollisionNode* findCollisionNode(const QString& name) const {
- return tree_->findCollisionNode(name);
+ void resolveTargets() {
+ primaryTree()->resolveTargets(primaryTreeRoot());
+ }
+ void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority) {
+ primaryTree()->insertTarget(name, type, node, priority);
}
- const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const;
- const Node *findUnambiguousTarget(const QString &target, QString& ref, const Node* relative);
- QString findTarget(const QString &target, const Node *node) const;
- void resolveTargets(InnerNode* root);
-
+ /*******************************************************************
+ The functions declared below are called for the current tree only.
+ ********************************************************************/
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) {
- return tree_->findFunctionNode(parentPath, clone);
+ return primaryTree()->findFunctionNode(parentPath, clone);
}
- Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){
- return tree_->findNodeByNameAndType(path, type, subtype, 0);
+ FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
+ Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
+ NameCollisionNode* findCollisionNode(const QString& name) {
+ return primaryTree()->findCollisionNode(name);
}
- NameCollisionNode* checkForCollision(const QString& name) const {
- return tree_->checkForCollision(name);
+ NameCollisionNode* checkForCollision(const QString& name) {
+ return primaryTree()->checkForCollision(name);
}
- void addBaseClass(ClassNode* subclass,
- Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent) {
- tree_->addBaseClass(subclass, access, basePath, dataTypeWithTemplateArgs, parent);
+ /*******************************************************************/
+
+ /*******************************************************************
+ The functions declared below are called for all trees.
+ ********************************************************************/
+ ClassNode* findClassNode(const QStringList& path) { return forest_.findClassNode(path); }
+ InnerNode* findRelatesNode(const QStringList& path) { return forest_.findRelatesNode(path); }
+ QString findTarget(const QString& target, const Node* node) {
+ return forest_.findTarget(target, node);
}
+ const Node* resolveTarget(const QString& target, const Node* relative) {
+ return forest_.resolveTarget(target, relative);
+ }
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative) {
+ return forest_.resolveFunctionTarget(target, relative);
+ }
+ const Node* resolveType(const QString& type, const Node* relative);
+ const Node* findNodeForTarget(const QString& target, const Node* relative);
+ const DocNode* findDocNodeByTitle(const QString& title) {
+ return forest_.findDocNodeByTitle(title);
+ }
+ const Node* findUnambiguousTarget(const QString& target, QString& ref) {
+ return forest_.findUnambiguousTarget(target, ref);
+ }
+ Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){
+ return forest_.findNodeByNameAndType(path, type, subtype, false);
+ }
+ /*******************************************************************/
+
void addPropertyFunction(PropertyNode* property,
const QString& funcName,
PropertyNode::FunctionRole funcRole) {
- tree_->addPropertyFunction(property, funcName, funcRole);
+ primaryTree()->addPropertyFunction(property, funcName, funcRole);
}
void setVersion(const QString& v) { version_ = v; }
@@ -198,37 +362,43 @@ class QDocDatabase
void clearOpenNamespaces() { openNamespaces_.clear(); }
void insertOpenNamespace(const QString& path) { openNamespaces_.insert(path); }
- FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
- Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
void setShowInternal(bool value) { showInternal_ = value; }
- /* debugging functions */
- void printModules() const;
- void printQmlModules() const;
+ // Try to make this function private.
+ QDocForest& forest() { return forest_; }
+ NamespaceNode* primaryTreeRoot() { return forest_.primaryTreeRoot(); }
+ void newPrimaryTree(const QString& module) { forest_.newPrimaryTree(module); }
+ NamespaceNode* newIndexTree(const QString& module) { return forest_.newIndexTree(module); }
+ const QVector<Tree*>& searchOrder() { return forest_.searchOrder(); }
+ void setSearchOrder() { forest_.setSearchOrder(); }
+ void mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative);
+ void mergeCollections(CollectionNode* cn);
private:
friend class QDocIndexFiles;
friend class QDocTagFiles;
const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
- return tree_->findNode(path, relative, findFlags);
+ return forest_.findNode(path, relative, findFlags);
}
+ void processForest(void (QDocDatabase::*) (InnerNode*));
+ static void initializeDB();
private:
QDocDatabase();
- QDocDatabase(QDocDatabase const& ) { }; // copy constructor is private
- QDocDatabase& operator=(QDocDatabase const& ); // assignment operator is private
+ QDocDatabase(QDocDatabase const& ) : showInternal_(false), forest_(this) { }
+ QDocDatabase& operator=(QDocDatabase const& );
+ Tree* primaryTree() { return forest_.primaryTree(); }
+
+ public:
+ static bool debug;
private:
static QDocDatabase* qdocDB_;
+ static NodeMap typeNodeMap_;
bool showInternal_;
QString version_;
- QDocMultiMap masterMap_;
- Tree* tree_;
- DocNodeMap groups_;
- DocNodeMap modules_;
- DocNodeMap qmlModules_;
- QmlTypeMap qmlTypeMap_;
+ QDocForest forest_;
NodeMap nonCompatClasses_;
NodeMap mainClasses_;
@@ -245,8 +415,6 @@ class QDocDatabase
NodeMultiMapMap newSinceMaps_;
NodeMapMap funcIndex_;
TextToNodeMap legaleseTexts_;
- DocNodeMultiMap docNodesByTitle_;
- TargetRecMultiMap targetRecMultiMap_;
QSet<QString> openNamespaces_;
};
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 47e302dad6..be8184b596 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -77,6 +77,7 @@ QDocIndexFiles::QDocIndexFiles()
QDocIndexFiles::~QDocIndexFiles()
{
qdb_ = 0;
+ gen_ = 0;
}
/*!
@@ -109,6 +110,7 @@ void QDocIndexFiles::readIndexes(const QStringList& indexFiles)
foreach (const QString& indexFile, indexFiles) {
QString msg = "Loading index file: " + indexFile;
Location::logToStdErr(msg);
+ //qDebug() << " LOAD INDEX FILE:" << indexFile;
readIndexFile(indexFile);
}
}
@@ -144,12 +146,13 @@ void QDocIndexFiles::readIndexFile(const QString& path)
basesList_.clear();
relatedList_.clear();
+ NamespaceNode* root = qdb_->newIndexTree(project_);
+
// Scan all elements in the XML file, constructing a map that contains
// base classes for each class found.
-
QDomElement child = indexElement.firstChildElement();
while (!child.isNull()) {
- readIndexSection(child, qdb_->treeRoot(), indexUrl);
+ readIndexSection(child, root, indexUrl);
child = child.nextSiblingElement();
}
@@ -189,9 +192,11 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "class") {
node = new ClassNode(parent, name);
- basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node),
- element.attribute("bases")));
-
+ if (element.hasAttribute("bases")) {
+ QString bases = element.attribute("bases");
+ if (!bases.isEmpty())
+ basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases));
+ }
if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html");
else if (!indexUrl.isNull())
@@ -213,8 +218,9 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
abstract = true;
qcn->setAbstract(abstract);
QString qmlFullBaseName = element.attribute("qml-base-type");
- if (!qmlFullBaseName.isEmpty())
+ if (!qmlFullBaseName.isEmpty()) {
qcn->setQmlBaseName(qmlFullBaseName);
+ }
if (element.hasAttribute("location"))
name = element.attribute("location", QString());
if (!indexUrl.isEmpty())
@@ -277,6 +283,31 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
FunctionNode* fn = new FunctionNode(t, parent, name, attached);
node = fn;
}
+ else if (element.nodeName() == "group") {
+ GroupNode* gn = qdb_->addGroup(name);
+ gn->setTitle(element.attribute("title"));
+ gn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ gn->markSeen();
+ node = gn;
+ }
+ else if (element.nodeName() == "module") {
+ ModuleNode* mn = qdb_->addModule(name);
+ mn->setTitle(element.attribute("title"));
+ mn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ mn->markSeen();
+ node = mn;
+ }
+ else if (element.nodeName() == "qmlmodule") {
+ QString t = element.attribute("qml-module-name") + " " + element.attribute("qml-module-version");
+ QmlModuleNode* qmn = qdb_->addQmlModule(t);
+ qmn->setTitle(element.attribute("title"));
+ qmn->setSubTitle(element.attribute("subtitle"));
+ if (element.attribute("seen") == "true")
+ qmn->markSeen();
+ node = qmn;
+ }
else if (element.nodeName() == "page") {
Node::SubType subtype;
Node::PageType ptype = Node::NoPageType;
@@ -293,18 +324,6 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
subtype = Node::File;
ptype = Node::NoPageType;
}
- else if (attr == "group") {
- subtype = Node::Group;
- ptype = Node::OverviewPage;
- }
- else if (attr == "module") {
- subtype = Node::Module;
- ptype = Node::OverviewPage;
- }
- else if (attr == "qmlmodule") {
- subtype = Node::QmlModule;
- ptype = Node::OverviewPage;
- }
else if (attr == "page") {
subtype = Node::Page;
ptype = Node::ArticlePage;
@@ -324,14 +343,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
else
return;
- DocNode* docNode = 0;
- if (subtype == Node::QmlModule) {
- QString t = element.attribute("qml-module-name") + " " +
- element.attribute("qml-module-version");
- docNode = qdb_->addQmlModule(t);
- }
- else
- docNode = new DocNode(parent, name, subtype, ptype);
+ DocNode* docNode = new DocNode(parent, name, subtype, ptype);
docNode->setTitle(element.attribute("title"));
if (element.hasAttribute("location"))
@@ -383,31 +395,33 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "function") {
FunctionNode::Virtualness virt;
- if (element.attribute("virtual") == "non")
+ QString t = element.attribute("virtual");
+ if (t == "non")
virt = FunctionNode::NonVirtual;
- else if (element.attribute("virtual") == "impure")
+ else if (t == "impure")
virt = FunctionNode::ImpureVirtual;
- else if (element.attribute("virtual") == "pure")
+ else if (t == "pure")
virt = FunctionNode::PureVirtual;
else
return;
+ t = element.attribute("meta");
FunctionNode::Metaness meta;
- if (element.attribute("meta") == "plain")
+ if (t == "plain")
meta = FunctionNode::Plain;
- else if (element.attribute("meta") == "signal")
+ else if (t == "signal")
meta = FunctionNode::Signal;
- else if (element.attribute("meta") == "slot")
+ else if (t == "slot")
meta = FunctionNode::Slot;
- else if (element.attribute("meta") == "constructor")
+ else if (t == "constructor")
meta = FunctionNode::Ctor;
- else if (element.attribute("meta") == "destructor")
+ else if (t == "destructor")
meta = FunctionNode::Dtor;
- else if (element.attribute("meta") == "macro")
+ else if (t == "macro")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithparams")
+ else if (t == "macrowithparams")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithoutparams")
+ else if (t == "macrowithoutparams")
meta = FunctionNode::MacroWithoutParams;
else
return;
@@ -426,6 +440,10 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QPair<FunctionNode*,QString>(functionNode,
element.attribute("relates")));
}
+ /*
+ Note: The "signature" attribute was written to the
+ index file, but it is not read back in. Is that ok?
+ */
QDomElement child = element.firstChildElement("parameter");
while (!child.isNull()) {
@@ -513,7 +531,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QString moduleName = element.attribute("module");
if (!moduleName.isEmpty())
- node->setModuleName(moduleName);
+ qdb_->addToModule(moduleName, node);
if (!href.isEmpty()) {
if (node->isExternalPage())
node->setUrl(href);
@@ -529,15 +547,8 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QString groupsAttr = element.attribute("groups");
if (!groupsAttr.isEmpty()) {
QStringList groupNames = groupsAttr.split(",");
- for (int i=0; i<groupNames.size(); ++i) {
- DocNode* dn = qdb_->findGroup(groupNames[i]);
- if (dn) {
- dn->addMember(node);
- }
- else {
- qDebug() << "NODE:" << node->name() << "GROUPS:" << groupNames;
- qDebug() << "DID NOT FIND GROUP:" << dn->name() << "for:" << node->name();
- }
+ foreach (QString name, groupNames) {
+ qdb_->addToGroup(name, node);
}
}
@@ -584,57 +595,44 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
/*!
+ This function tries to resolve class inheritance immediately
+ after the index file is read. It is not always possible to
+ resolve a class inheritance at this point, because the base
+ class might be in an index file that hasn't been read yet, or
+ it might be in one of the header files that will be read for
+ the current module. These cases will be resolved after all
+ the index files and header and source files have been read,
+ just prior to beginning the generate phase for the current
+ module.
+
+ I don't think this is completely correct because it always
+ sets the access to public.
*/
void QDocIndexFiles::resolveIndex()
{
QPair<ClassNode*,QString> pair;
foreach (pair, basesList_) {
foreach (const QString& base, pair.second.split(QLatin1Char(','))) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(base, Node::Class);
- if (n) {
- pair.first->addBaseClass(Node::Public, static_cast<ClassNode*>(n));
- }
+ QStringList basePath = base.split(QString("::"));
+ Node* n = qdb_->findNodeByNameAndType(basePath, Node::Class, Node::NoSubType);
+ if (n)
+ pair.first->addResolvedBaseClass(Node::Public, static_cast<ClassNode*>(n));
+ else
+ pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString());
}
}
QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, relatedList_) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(relatedPair.second, Node::Class);
+ QStringList path = relatedPair.second.split("::");
+ Node* n = qdb_->findRelatesNode(path);
if (n)
relatedPair.first->setRelates(static_cast<ClassNode*>(n));
}
-}
-
-/*!
- Normally this is used for writing the \e groups attribute,
- but it can be used for writing any attribute with a list
- value that comes from some subset of the members of \a n.
-
- \note The members of \a n are \e not the children of \a n.
- The names we want to include are the names of the members
- of \a n that have node type \a t and node subtype \a st.
- The attribute name is \a attr. The names are joined with
- the space character and written with \a writer.
- */
-void QDocIndexFiles::writeMembersAttribute(QXmlStreamWriter& writer,
- const InnerNode* n,
- Node::Type t,
- Node::SubType st,
- const QString& attr)
-{
- const NodeList& members = n->members();
- if (!members.isEmpty()) {
- QStringList names;
- NodeList::ConstIterator i = members.constBegin();
- while (i != members.constEnd()) {
- if ((*i)->type() == t && (*i)->subType() == st)
- names.append((*i)->name());
- ++i;
- }
- if (!names.isEmpty())
- writer.writeAttribute(attr, names.join(","));
- }
+ // No longer needed.
+ basesList_.clear();
+ relatedList_.clear();
}
/*!
@@ -675,6 +673,15 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
else if (node->subType() == Node::QmlBasicType)
nodeName = "qmlbasictype";
break;
+ case Node::Group:
+ nodeName = "group";
+ break;
+ case Node::Module:
+ nodeName = "module";
+ break;
+ case Node::QmlModule:
+ nodeName = "qmlmodule";
+ break;
case Node::Enum:
nodeName = "enum";
break;
@@ -741,14 +748,17 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
return false;
writer.writeStartElement(nodeName);
QXmlStreamAttributes attributes;
- if (node->type() != Node::Document) {
+ if ((node->type() != Node::Document) &&
+ (node->type() != Node::Group) &&
+ (node->type() != Node::Module) &&
+ (node->type() != Node::QmlModule)) {
QString threadSafety;
switch (node->threadSafeness()) {
case Node::NonReentrant:
@@ -832,10 +842,15 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!href.isEmpty())
writer.writeAttribute("href", href);
- writer.writeAttribute("access", access);
writer.writeAttribute("status", status);
- if (node->isAbstract())
- writer.writeAttribute("abstract", "true");
+ if ((node->type() != Node::Document) &&
+ (node->type() != Node::Group) &&
+ (node->type() != Node::Module) &&
+ (node->type() != Node::QmlModule)) {
+ writer.writeAttribute("access", access);
+ if (node->isAbstract())
+ writer.writeAttribute("abstract", "true");
+ }
if (!node->location().fileName().isEmpty())
writer.writeAttribute("location", node->location().fileName());
if (!node->location().filePath().isEmpty()) {
@@ -847,7 +862,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("since", node->since());
}
- QString brief = node->doc().briefText().toString();
+ QString brief = node->doc().trimmedBriefText(node->name()).toString();
switch (node->type()) {
case Node::Class:
{
@@ -856,13 +871,16 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QList<RelatedClass> bases = classNode->baseClasses();
QSet<QString> baseStrings;
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- baseStrings.insert(baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ baseStrings.insert(n->fullName());
}
- writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
+ if (!baseStrings.isEmpty())
+ writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
if (!node->moduleName().isEmpty())
writer.writeAttribute("module", node->moduleName());
- writeMembersAttribute(writer, classNode, Node::Document, Node::Group, "groups");
+ if (!classNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", classNode->groupNames().join(","));
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -872,7 +890,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
const NamespaceNode* namespaceNode = static_cast<const NamespaceNode*>(node);
if (!namespaceNode->moduleName().isEmpty())
writer.writeAttribute("module", namespaceNode->moduleName());
- writeMembersAttribute(writer, namespaceNode, Node::Document, Node::Group, "groups");
+ if (!namespaceNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", namespaceNode->groupNames().join(","));
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -880,8 +899,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::Document:
{
/*
- Document nodes (such as manual pages) contain subtypes,
- titles and other attributes.
+ Document nodes (such as manual pages) have a subtype,
+ a title, and other attributes.
*/
bool writeModuleName = false;
const DocNode* docNode = static_cast<const DocNode*>(node);
@@ -897,26 +916,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::File:
writer.writeAttribute("subtype", "file");
break;
- case Node::Group:
- {
- writer.writeAttribute("subtype", "group");
- writer.writeAttribute("seen", docNode->wasSeen() ? "true" : "false");
- // Groups contain information about their group members.
- const NodeList& members = docNode->members();
- QStringList names;
- foreach (const Node* member, members) {
- names.append(member->name());
- }
- writer.writeAttribute("members", names.join(","));
- writeModuleName = true;
- }
- break;
- case Node::Module:
- writer.writeAttribute("subtype", "module");
- break;
- case Node::QmlModule:
- writer.writeAttribute("subtype", "qmlmodule");
- break;
case Node::Page:
writer.writeAttribute("subtype", "page");
writeModuleName = true;
@@ -939,7 +938,82 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!node->moduleName().isEmpty() && writeModuleName) {
writer.writeAttribute("module", node->moduleName());
}
- writeMembersAttribute(writer, docNode, Node::Document, Node::Group, "groups");
+ if (!docNode->groupNames().isEmpty())
+ writer.writeAttribute("groups", docNode->groupNames().join(","));
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
+ case Node::Group:
+ {
+ const GroupNode* gn = static_cast<const GroupNode*>(node);
+ writer.writeAttribute("seen", gn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", gn->title());
+ if (!gn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", gn->subTitle());
+ if (!gn->moduleName().isEmpty())
+ writer.writeAttribute("module", gn->moduleName());
+ if (!gn->groupNames().isEmpty())
+ writer.writeAttribute("groups", gn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!gn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, gn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ break;
+ case Node::Module:
+ {
+ const ModuleNode* mn = static_cast<const ModuleNode*>(node);
+ writer.writeAttribute("seen", mn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", mn->title());
+ if (!mn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", mn->subTitle());
+ if (!mn->moduleName().isEmpty())
+ writer.writeAttribute("module", mn->moduleName());
+ if (!mn->groupNames().isEmpty())
+ writer.writeAttribute("groups", mn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!mn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, mn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
+ if (!brief.isEmpty())
+ writer.writeAttribute("brief", brief);
+ }
+ case Node::QmlModule:
+ {
+ const QmlModuleNode* qmn = static_cast<const QmlModuleNode*>(node);
+ writer.writeAttribute("seen", qmn->wasSeen() ? "true" : "false");
+ writer.writeAttribute("title", qmn->title());
+ if (!qmn->subTitle().isEmpty())
+ writer.writeAttribute("subtitle", qmn->subTitle());
+ if (!qmn->moduleName().isEmpty())
+ writer.writeAttribute("module", qmn->moduleName());
+ if (!qmn->groupNames().isEmpty())
+ writer.writeAttribute("groups", qmn->groupNames().join(","));
+ /*
+ This is not read back in, so it probably
+ shouldn't be written out in the first place.
+ */
+ if (!qmn->members().isEmpty()) {
+ QStringList names;
+ foreach (const Node* member, qmn->members())
+ names.append(member->name());
+ writer.writeAttribute("members", names.join(","));
+ }
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -995,8 +1069,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("overload", functionNode->isOverload()?"true":"false");
if (functionNode->isOverload())
writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber()));
- if (functionNode->relates())
+ if (functionNode->relates()) {
writer.writeAttribute("relates", functionNode->relates()->name());
+ }
const PropertyNode* propertyNode = functionNode->associatedProperty();
if (propertyNode)
writer.writeAttribute("associated-property", propertyNode->name());
@@ -1010,7 +1085,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
writer.writeAttribute("type", qpn->dataType());
writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false");
- writer.writeAttribute("writable", qpn->isWritable(qdb_) ? "true" : "false");
+ writer.writeAttribute("writable", qpn->isWritable() ? "true" : "false");
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
@@ -1127,36 +1202,11 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
}
else if (node->type() == Node::Function) {
const FunctionNode* functionNode = static_cast<const FunctionNode*>(node);
- // Write a signature attribute for convenience.
- QStringList signatureList;
- QStringList resolvedParameters;
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- if (leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- else
- leftType = leftNode->fullDocumentName();
- }
- resolvedParameters.append(leftType);
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = functionNode->name() + QLatin1Char('(') + signatureList.join(", ") +
- QLatin1Char(')');
+ /*
+ Note: The "signature" attribute is written to the
+ index file, but it is not read back in. Is that ok?
+ */
+ QString signature = functionNode->signature();
if (functionNode->isConst())
signature += " const";
writer.writeAttribute("signature", signature);
@@ -1164,7 +1214,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
for (int i = 0; i < functionNode->parameters().size(); ++i) {
Parameter parameter = functionNode->parameters()[i];
writer.writeStartElement("parameter");
- writer.writeAttribute("left", resolvedParameters[i]);
+ writer.writeAttribute("left", parameter.leftType());
writer.writeAttribute("right", parameter.rightType());
writer.writeAttribute("name", parameter.name());
writer.writeAttribute("default", parameter.defaultValue());
@@ -1262,9 +1312,13 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
bool generateInternalNodes)
{
/*
- Note that the groups are written after all the other nodes.
+ Note that groups, modules, and QML modules are written
+ after all the other nodes.
*/
- if (!node->isGroup() && generateIndexSection(writer, node, generateInternalNodes)) {
+ if (node->isGroup() || node->isModule() || node->isQmlModule())
+ return;
+
+ if (generateIndexSection(writer, node, generateInternalNodes)) {
if (node->isInnerNode()) {
const InnerNode* inner = static_cast<const InnerNode*>(node);
@@ -1320,17 +1374,19 @@ void QDocIndexFiles::generateIndex(const QString& fileName,
writer.writeAttribute("version", qdb_->version());
writer.writeAttribute("project", g->config()->getString(CONFIG_PROJECT));
- generateIndexSections(writer, qdb_->treeRoot(), generateInternalNodes);
+ generateIndexSections(writer, qdb_->primaryTreeRoot(), generateInternalNodes);
/*
- We wait until the end of the index file to output the group elements.
- By waiting until the end, when we read each group element, its members
- will have already been created. It is then only necessary to create
- the group page and add each member to its member list.
+ We wait until the end of the index file to output the group, module,
+ and QML module elements. By outputting them at the end, when we read
+ the index file back in, all the group, module, and QML module member
+ elements will have already been created. It is then only necessary to
+ create the group, module, or QML module element and add each member to
+ its member list.
*/
- const DocNodeMap& groups = qdb_->groups();
+ const CNMap& groups = qdb_->groups();
if (!groups.isEmpty()) {
- DocNodeMap::ConstIterator g = groups.constBegin();
+ CNMap::ConstIterator g = groups.constBegin();
while (g != groups.constEnd()) {
if (generateIndexSection(writer, g.value(), generateInternalNodes))
writer.writeEndElement();
@@ -1338,6 +1394,26 @@ void QDocIndexFiles::generateIndex(const QString& fileName,
}
}
+ const CNMap& modules = qdb_->modules();
+ if (!modules.isEmpty()) {
+ CNMap::ConstIterator g = modules.constBegin();
+ while (g != modules.constEnd()) {
+ if (generateIndexSection(writer, g.value(), generateInternalNodes))
+ writer.writeEndElement();
+ ++g;
+ }
+ }
+
+ const CNMap& qmlModules = qdb_->qmlModules();
+ if (!qmlModules.isEmpty()) {
+ CNMap::ConstIterator g = qmlModules.constBegin();
+ while (g != qmlModules.constEnd()) {
+ if (generateIndexSection(writer, g.value(), generateInternalNodes))
+ writer.writeEndElement();
+ ++g;
+ }
+ }
+
writer.writeEndElement(); // INDEX
writer.writeEndElement(); // QDOCINDEX
writer.writeEndDocument();
diff --git a/src/tools/qdoc/qdocindexfiles.h b/src/tools/qdoc/qdocindexfiles.h
index e4a83176a2..bd94fdb215 100644
--- a/src/tools/qdoc/qdocindexfiles.h
+++ b/src/tools/qdoc/qdocindexfiles.h
@@ -76,11 +76,6 @@ class QDocIndexFiles
void resolveIndex();
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
- void writeMembersAttribute(QXmlStreamWriter& writer,
- const InnerNode* n,
- Node::Type t,
- Node::SubType st,
- const QString& attr);
private:
static QDocIndexFiles* qdocIndexFiles_;
@@ -89,7 +84,6 @@ class QDocIndexFiles
QString project_;
QList<QPair<ClassNode*,QString> > basesList_;
QList<QPair<FunctionNode*,QString> > relatedList_;
-
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/qdoctagfiles.cpp b/src/tools/qdoc/qdoctagfiles.cpp
index a0054ea229..cc2bd3f1f0 100644
--- a/src/tools/qdoc/qdoctagfiles.cpp
+++ b/src/tools/qdoc/qdoctagfiles.cpp
@@ -147,7 +147,7 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
continue;
// *** Write the starting tag for the element here. ***
@@ -162,8 +162,9 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
const ClassNode* classNode = static_cast<const ClassNode*>(node);
QList<RelatedClass> bases = classNode->baseClasses();
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- writer.writeTextElement("base", baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ writer.writeTextElement("base", n->name());
}
// Recurse to write all members.
@@ -243,7 +244,7 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
QString objName = node->name();
// Special case: only the root node should have an empty name.
- if (objName.isEmpty() && node != qdb_->treeRoot())
+ if (objName.isEmpty() && node != qdb_->primaryTreeRoot())
continue;
// *** Write the starting tag for the element here. ***
@@ -294,31 +295,8 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
-
- // Write a signature attribute for convenience.
- QStringList signatureList;
-
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = QLatin1Char('(')+signatureList.join(", ")+QLatin1Char(')');
+ QString signature = functionNode->signature();
+ signature = signature.mid(signature.indexOf(QChar('('))).trimmed();
if (functionNode->isConst())
signature += " const";
if (functionNode->virtualness() == FunctionNode::PureVirtual)
@@ -395,7 +373,7 @@ void QDocTagFiles::generateTagFile(const QString& fileName, Generator* g)
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeStartElement("tagfile");
- generateTagFileCompounds(writer, qdb_->treeRoot());
+ generateTagFileCompounds(writer, qdb_->primaryTreeRoot());
writer.writeEndElement(); // tagfile
writer.writeEndDocument();
file.close();
diff --git a/src/tools/qdoc/qmlcodeparser.h b/src/tools/qdoc/qmlcodeparser.h
index 71b4660fe7..7f6f8d1a81 100644
--- a/src/tools/qdoc/qmlcodeparser.h
+++ b/src/tools/qdoc/qmlcodeparser.h
@@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
-class Tree;
class QmlCodeParser : public CodeParser
{
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index ec1ef41256..d16fdfa5d4 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -97,7 +97,7 @@ QmlDocVisitor::QmlDocVisitor(const QString &filePath,
this->engine = engine;
this->commands_ = commands;
this->topics_ = topics;
- current = QDocDatabase::qdocDB()->treeRoot();
+ current = QDocDatabase::qdocDB()->primaryTreeRoot();
}
/*!
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 113220059c..d17468f3a9 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -60,132 +60,90 @@ QT_BEGIN_NAMESPACE
This class is now private. Only class QDocDatabase has access.
Please don't change this. If you must access class Tree, do it
though the pointer to the singleton QDocDatabase.
+
+ Tree is being converted to a forest. A static member provides a
+ map of Tree* values with the module names as the keys. There is
+ one Tree in the map for each index file read, and there is one
+ tree that is not in the map for the module whose documentation
+ is being generated.
*/
/*!
- Constructs the singleton tree. \a qdb is the pointer to the
+ Constructs a Tree. \a qdb is the pointer to the singleton
qdoc database that is constructing the tree. This might not
be necessary, and it might be removed later.
*/
-Tree::Tree(QDocDatabase* qdb)
- : qdb_(qdb), root_(0, QString())
+Tree::Tree(const QString& module, QDocDatabase* qdb)
+ : module_(module), qdb_(qdb), root_(0, QString())
{
+ root_.setModuleName(module_);
}
/*!
- Destroys the singleton Tree.
+ Destroys the Tree. The root node is a data member
+ of this object, so its destructor is called. The
+ destructor of each child node is called, and these
+ destructors are recursive. Thus the entire tree is
+ destroyed.
*/
Tree::~Tree()
{
+ // nothing
}
-// 1 calls 2
+/* API members */
+
/*!
- Searches the tree for a node that matches the \a path. The
- search begins at \a start but can move up the parent chain
- recursively if no match is found.
+ Find the C++ class node named \a path. Begin the search at the
+ \a start node. If the \a start node is 0, begin the search
+ at the root of the tree. Only a C++ class node named \a path is
+ acceptible. If one is not found, 0 is returned.
*/
-const Node* Tree::findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- const Node* self) const
+ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
{
- const Node* current = start;
- if (!current)
- current = root();
-
- /*
- First, search for a node assuming we don't want a QML node.
- If that search fails, search again assuming we do want a
- QML node.
- */
- const Node* n = findNode(path,current,findFlags,self,false);
- if (!n) {
- n = findNode(path,current,findFlags,self,true);
- }
- return n;
+ if (!start)
+ start = const_cast<NamespaceNode*>(root());
+ return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
}
-// 2 is private; it is only called by 1.
/*!
- This overload function was extracted from the one above that has the
- same signature without the last bool parameter, \a qml. This version
- is called only by that other one. It is therefore private. It can
- be called a second time by that other version, if the first call
- returns null. If \a qml is false, the search will only match a node
- that is not a QML node. If \a qml is true, the search will only
- match a node that is a QML node.
-*/
-const Node* Tree::findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- const Node* self,
- bool qml) const
+ Find the Namespace node named \a path. Begin the search at
+ the root of the tree. Only a Namespace node named \a path
+ is acceptible. If one is not found, 0 is returned.
+ */
+NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
{
- const Node* current = start;
- do {
- const Node* node = current;
- int i;
- int start_idx = 0;
-
- /*
- If the path contains one or two double colons ("::"),
- check first to see if the first two path strings refer
- to a QML element. If they do, path[0] will be the QML
- module identifier, and path[1] will be the QML type.
- If the anser is yes, the reference identifies a QML
- class node.
- */
- if (qml && path.size() >= 2 && !path[0].isEmpty()) {
- QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
- if (qcn) {
- node = qcn;
- if (path.size() == 2)
- return node;
- start_idx = 2;
- }
- }
-
- for (i = start_idx; i < path.size(); ++i) {
- if (node == 0 || !node->isInnerNode())
- break;
-
- const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
- if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
- next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+ Node* start = const_cast<NamespaceNode*>(root());
+ return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+}
- if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
- NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
- foreach (const Node* baseClass, baseClasses) {
- next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
- if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
- next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
- if (next)
- break;
- }
- }
- node = next;
- }
- if (node && i == path.size()
- && (!(findFlags & NonFunction) || node->type() != Node::Function
- || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
- if ((node != self) && (node->type() != Node::QmlPropertyGroup)) {
- if (node->subType() == Node::Collision) {
- node = node->applyModuleName(start);
- }
- return node;
- }
- }
- current = current->parent();
- } while (current);
+/*!
+ This function first ignores the \a clone node and searches
+ for the parent node with \a parentPath. If that search is
+ successful, it searches for a child node of the parent that
+ matches the \a clone node. If it finds a node that is just
+ like the \a clone, it returns a pointer to the found node.
- return 0;
+ There should be a way to avoid creating the clone in the
+ first place. Investigate when time allows.
+ */
+FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const FunctionNode* clone)
+{
+ const Node* parent = findNamespaceNode(parentPath);
+ if (parent == 0)
+ parent = findClassNode(parentPath, 0);
+ if (parent == 0)
+ parent = findNode(parentPath);
+ if (parent == 0 || !parent->isInnerNode())
+ return 0;
+ return ((InnerNode*)parent)->findFunctionNode(clone);
}
+
/*!
Find the Qml type node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only a Qml type node named \a path is
+ at the root of the tree. Only a Qml type node named <\a path is
acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
@@ -215,7 +173,7 @@ QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
node as its first child, and return a pointer to the new
NameCollisionNode. Otherwise return 0.
*/
-NameCollisionNode* Tree::checkForCollision(const QString& name) const
+NameCollisionNode* Tree::checkForCollision(const QString& name)
{
Node* n = const_cast<Node*>(findNode(QStringList(name)));
if (n) {
@@ -248,18 +206,6 @@ NameCollisionNode* Tree::findCollisionNode(const QString& name) const
}
/*!
- This function just calls the const version of the same function
- and returns the function node.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& path,
- Node* relative,
- int findFlags)
-{
- return const_cast<FunctionNode*>
- (const_cast<const Tree*>(this)->findFunctionNode(path,relative,findFlags));
-}
-
-/*!
This function begins searching the tree at \a relative for
the \l {FunctionNode} {function node} identified by \a path.
The \a findFlags are used to restrict the search. If a node
@@ -274,17 +220,23 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (!relative)
relative = root();
- /*
- If the path contains two double colons ("::"), check
- first to see if it is a reference to a QML method. If
- it is a reference to a QML method, first look up the
- QML class node in the QML module map.
- */
if (path.size() == 3 && !path[0].isEmpty()) {
- QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
- if (qcn) {
- return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
+ QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
+ if (!qcn) {
+ QStringList p(path[1]);
+ Node* n = findNodeByNameAndType(p, Node::Document, Node::QmlClass, true);
+ if (n) {
+ if (n->subType() == Node::QmlClass)
+ qcn = static_cast<QmlClassNode*>(n);
+ else if (n->subType() == Node::Collision) {
+ NameCollisionNode* ncn;
+ ncn = static_cast<NameCollisionNode*>(n);
+ qcn = static_cast<QmlClassNode*>(ncn->findAny(Node::Document, Node::QmlClass));
+ }
+ }
}
+ if (qcn)
+ return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
}
do {
@@ -299,7 +251,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = ((InnerNode*) node)->findFunctionNode(path.at(i));
else
- next = ((InnerNode*) node)->findChildNodeByName(path.at(i));
+ next = ((InnerNode*) node)->findChildNode(path.at(i));
if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
@@ -307,7 +259,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i));
else
- next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
if (next)
break;
@@ -339,57 +291,34 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
return 0;
}
-/*!
- This function just calls the const version of itself and
- returns the result.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- Node* relative,
- int findFlags)
+static NodeTypeList t;
+static const NodeTypeList& relatesTypes()
{
- return const_cast<FunctionNode*>(
- const_cast<const Tree*>(this)->findFunctionNode(parentPath,
- clone,
- relative,
- findFlags));
+ if (t.isEmpty()) {
+ t.reserve(3);
+ t.append(NodeTypePair(Node::Class, Node::NoSubType));
+ t.append(NodeTypePair(Node::Namespace, Node::NoSubType));
+ t.append(NodeTypePair(Node::Document, Node::HeaderFile));
+ }
+ return t;
}
/*!
- This function first ignores the \a clone node and searches
- for the node having the \a parentPath by calling the main
- findFunction(\a {parentPath}, \a {relative}, \a {findFlags}).
- If that search is successful, then it searches for the \a clone
- in the found parent node.
- */
-const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- const Node* relative,
- int findFlags) const
-{
- const Node* parent = findNamespaceNode(parentPath);
- if (parent == 0)
- parent = findClassNode(parentPath, 0);
- if (parent == 0)
- parent = findNode(parentPath, relative, findFlags);
- if (parent == 0 || !parent->isInnerNode())
- return 0;
- return ((InnerNode*)parent)->findFunctionNode(clone);
-}
+ This function searches for the node specified by \a path.
+ The matching node can be one of several different types
+ including a C++ class, a C++ namespace, or a C++ header
+ file.
-/*!
+ I'm not sure if it can be a QML type, but if that is a
+ possibility, the code can easily accommodate it.
+
+ If a matching node is found, a pointer to it is returned.
+ Otherwise 0 is returned.
*/
-void Tree::addBaseClass(ClassNode* subclass, Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent)
+InnerNode* Tree::findRelatesNode(const QStringList& path)
{
- unresolvedInheritanceMap[subclass].append(
- InheritanceBound(access,
- basePath,
- dataTypeWithTemplateArgs,
- parent)
- );
+ Node* n = findNodeRecursive(path, 0, root(), relatesTypes());
+ return ((n && n->isInnerNode()) ? static_cast<InnerNode*>(n) : 0);
}
/*!
@@ -402,24 +331,25 @@ void Tree::addPropertyFunction(PropertyNode* property,
}
/*!
- This function resolves inheritance and reimplementation settings
- for each C++ class node found in the namspace beginning at \a rootNode.
- If it finds another namespace node in the child list of \a rootNode,
- it calls itself recursively. For each child of \a rootNode that is a
- class node, it calls the other resolveInheritance() function.
+ This function resolves C++ inheritance and reimplementation
+ settings for each C++ class node found in the tree beginning
+ at \a n. It also calls itself recursively for each C++ class
+ node or namespace node it encounters. For each child of \a n
+ that is a class node, it calls resolveInheritanceHelper().
This function does not resolve QML inheritance.
*/
-void Tree::resolveInheritance(NamespaceNode* rootNode)
+void Tree::resolveInheritance(InnerNode* n)
{
- if (!rootNode)
- rootNode = root();
+ if (!n)
+ n = root();
for (int pass = 0; pass < 2; pass++) {
- NodeList::ConstIterator c = rootNode->childNodes().constBegin();
- while (c != rootNode->childNodes().constEnd()) {
+ NodeList::ConstIterator c = n->childNodes().constBegin();
+ while (c != n->childNodes().constEnd()) {
if ((*c)->type() == Node::Class) {
- resolveInheritance(pass, (ClassNode*)* c);
+ resolveInheritanceHelper(pass, (ClassNode*)*c);
+ resolveInheritance((ClassNode*)*c);
}
else if ((*c)->type() == Node::Namespace) {
NamespaceNode* ns = static_cast<NamespaceNode*>(*c);
@@ -427,8 +357,73 @@ void Tree::resolveInheritance(NamespaceNode* rootNode)
}
++c;
}
- if (rootNode == root())
- unresolvedInheritanceMap.clear();
+ }
+}
+
+/*!
+ This function is run twice for eachclass node \a cn in the
+ tree. First it is run with \a pass set to 0 for each
+ class node \a cn. Then it is run with \a pass set to 1 for
+ eachclass node \a cn.
+
+ In \a pass 0, all the base classes ofclass node \a cn are
+ found and added to the base class list forclass node \a cn.
+
+ In \a pass 1, each child ofclass node \a cn that is a function
+ that is reimplemented from one of the base classes is marked
+ as being reimplemented from that class.
+
+ Some property node fixing up is also done in \a pass 1.
+ */
+void Tree::resolveInheritanceHelper(int pass, ClassNode* cn)
+{
+ if (pass == 0) {
+ QList<RelatedClass>& bases = cn->baseClasses();
+ QList<RelatedClass>::iterator b = bases.begin();
+ while (b != bases.end()) {
+ if (!(*b).node_) {
+ Node* n = qdb_->findClassNode((*b).path_);
+#if 0
+ /*
+ If the node for the base class was not found,
+ the reason might be that the subclass is in a
+ namespace and the base class is in the same
+ namespace, but the base class name was not
+ qualified with the namespace name. That is the
+ case most of the time. Then restart the search
+ at the parent of the subclass node (the namespace
+ node) using the unqualified base class name.
+ */
+ if (!n) {
+ InnerNode* parent = cn->parent();
+ n = findClassNode((*b).path_, parent);
+ }
+#endif
+ if (n) {
+ ClassNode* bcn = static_cast<ClassNode*>(n);
+ (*b).node_ = bcn;
+ bcn->addDerivedClass((*b).access_, cn);
+ }
+ }
+ ++b;
+ }
+ }
+ else {
+ NodeList::ConstIterator c = cn->childNodes().constBegin();
+ while (c != cn->childNodes().constEnd()) {
+ if ((*c)->type() == Node::Function) {
+ FunctionNode* func = (FunctionNode*)* c;
+ FunctionNode* from = findVirtualFunctionInBaseClasses(cn, func);
+ if (from != 0) {
+ if (func->virtualness() == FunctionNode::NonVirtual)
+ func->setVirtualness(FunctionNode::ImpureVirtual);
+ func->setReimplementedFrom(from);
+ }
+ }
+ else if ((*c)->type() == Node::Property)
+ cn->fixPropertyUsingBaseClasses(static_cast<PropertyNode*>(*c));
+ ++c;
+ }
}
}
@@ -486,57 +481,6 @@ void Tree::resolveProperties()
}
/*!
- This function is run twice for each \a classNode in the
- tree. First it is run with \a pass set to 0 for each
- \a classNode. Then it is run with \a pass set to 1 for
- each \a classNode.
-
- In \a pass 0, all the base classes of \a classNode are
- found and added to the base class list for \a classNode.
-
- In \a pass 1, each child of \a classNode that is a function
- that is reimplemented from one of the base classes is marked
- as being reimplemented from that class.
-
- Some property node fixing up is also done in \a pass 1.
- */
-void Tree::resolveInheritance(int pass, ClassNode* classNode)
-{
- if (pass == 0) {
- QList<InheritanceBound> bounds = unresolvedInheritanceMap[classNode];
- QList<InheritanceBound>::ConstIterator b = bounds.constBegin();
- while (b != bounds.constEnd()) {
- Node* n = findClassNode((*b).basePath);
- if (!n && (*b).parent) {
- n = findClassNode((*b).basePath, (*b).parent);
- }
- if (n) {
- classNode->addBaseClass((*b).access, static_cast<ClassNode*>(n), (*b).dataTypeWithTemplateArgs);
- }
- ++b;
- }
- }
- else {
- NodeList::ConstIterator c = classNode->childNodes().constBegin();
- while (c != classNode->childNodes().constEnd()) {
- if ((*c)->type() == Node::Function) {
- FunctionNode* func = (FunctionNode*)* c;
- FunctionNode* from = findVirtualFunctionInBaseClasses(classNode, func);
- if (from != 0) {
- if (func->virtualness() == FunctionNode::NonVirtual)
- func->setVirtualness(FunctionNode::ImpureVirtual);
- func->setReimplementedFrom(from);
- }
- }
- else if ((*c)->type() == Node::Property) {
- fixPropertyUsingBaseClasses(classNode, static_cast<PropertyNode*>(*c));
- }
- ++c;
- }
- }
-}
-
-/*!
For each QML class node that points to a C++ class node,
follow its C++ class node pointer and set the C++ class
node's QML class node pointer back to the QML class node.
@@ -575,16 +519,18 @@ void Tree::fixInheritance(NamespaceNode* rootNode)
/*!
*/
-FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
- FunctionNode* clone)
+FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* cn, FunctionNode* clone)
{
- QList<RelatedClass>::ConstIterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
+ const QList<RelatedClass>& rc = cn->baseClasses();
+ QList<RelatedClass>::ConstIterator r = rc.constBegin();
+ while (r != rc.constEnd()) {
FunctionNode* func;
- if (((func = findVirtualFunctionInBaseClasses((*r).node, clone)) != 0 ||
- (func = (*r).node->findFunctionNode(clone)) != 0)) {
- if (func->virtualness() != FunctionNode::NonVirtual)
- return func;
+ if ((*r).node_) {
+ if (((func = findVirtualFunctionInBaseClasses((*r).node_, clone)) != 0 ||
+ (func = (*r).node_->findFunctionNode(clone)) != 0)) {
+ if (func->virtualness() != FunctionNode::NonVirtual)
+ return func;
+ }
}
++r;
}
@@ -593,31 +539,14 @@ FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
/*!
*/
-void Tree::fixPropertyUsingBaseClasses(ClassNode* classNode, PropertyNode* property)
-{
- QList<RelatedClass>::const_iterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
- Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property);
- if (n) {
- PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
- fixPropertyUsingBaseClasses(r->node, baseProperty);
- property->setOverriddenFrom(baseProperty);
- }
- else {
- fixPropertyUsingBaseClasses(r->node, property);
- }
- ++r;
- }
-}
-
-/*!
- */
NodeList Tree::allBaseClasses(const ClassNode* classNode) const
{
NodeList result;
foreach (const RelatedClass& r, classNode->baseClasses()) {
- result += r.node;
- result += allBaseClasses(r.node);
+ if (r.node_) {
+ result += r.node_;
+ result += allBaseClasses(r.node_);
+ }
}
return result;
}
@@ -632,15 +561,14 @@ NodeList Tree::allBaseClasses(const ClassNode* classNode) const
Node* Tree::findNodeByNameAndType(const QStringList& path,
Node::Type type,
Node::SubType subtype,
- Node* start,
- bool acceptCollision)
+ bool acceptCollision) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- Node* result = findNodeRecursive(path, 0, start, type, subtype, acceptCollision);
+ Node* result = findNodeRecursive(path, 0, root(), type, subtype, acceptCollision);
return result;
}
+/* internal members */
+
/*!
Recursive search for a node identified by \a path. Each
path element is a name. \a pathIndex specifies the index
@@ -659,22 +587,23 @@ Node* Tree::findNodeByNameAndType(const QStringList& path,
*/
Node* Tree::findNodeRecursive(const QStringList& path,
int pathIndex,
- Node* start,
+ const Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision) const
{
if (!start || path.isEmpty())
return 0; // no place to start, or nothing to search for.
+ Node* node = const_cast<Node*>(start);
if (start->isLeaf()) {
if (pathIndex >= path.size())
- return start; // found a match.
+ return node; // found a match.
return 0; // premature leaf
}
if (pathIndex >= path.size())
return 0; // end of search path.
- InnerNode* current = static_cast<InnerNode*>(start);
+ InnerNode* current = static_cast<InnerNode*>(node);
const NodeList& children = current->childNodes();
const QString& name = path.at(pathIndex);
for (int i=0; i<children.size(); ++i) {
@@ -694,24 +623,27 @@ Node* Tree::findNodeRecursive(const QStringList& path,
if (type == Node::Document) {
if (n->subType() == subtype)
return n;
- else if (n->subType() == Node::Collision && acceptCollision)
- return n;
+ else if (n->subType() == Node::Collision) {
+ if (acceptCollision)
+ return n;
+ return n->disambiguate(type, subtype);
+ }
else if (subtype == Node::NoSubType)
- return n; // don't care what subtype is.
- return 0;
+ return n;
+ continue;
}
- else
- return n;
+ return n;
}
else if (n->isCollisionNode()) {
if (acceptCollision)
return n;
return findNodeRecursive(path, pathIndex, n, type, subtype);
}
- else
- return 0;
+ else {
+ continue;
+ }
}
- else { // Not at the end of the path.
+ else { // Search the children of n for the next name in the path.
n = findNodeRecursive(path, pathIndex+1, n, type, subtype);
if (n)
return n;
@@ -722,40 +654,620 @@ Node* Tree::findNodeRecursive(const QStringList& path,
}
/*!
- Find the Enum type node named \a path. Begin the search at the
- \a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only an Enum type node named \a path is
- acceptible. If one is not found, 0 is returned.
+ Recursive search for a node identified by \a path. Each
+ path element is a name. \a pathIndex specifies the index
+ of the name in \a path to try to match. \a start is the
+ node whose children shoulod be searched for one that has
+ that name. Each time a name match is found, increment the
+ \a pathIndex and call this function recursively.
+
+ If the end of the path is reached (i.e. if a matching
+ node is found for each name in the \a path), test the
+ matching node's type and subtype values against the ones
+ listed in \a types. If a match is found there, return the
+ pointer to the final node. Otherwise return 0.
*/
-EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
+Node* Tree::findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ const NodeTypeList& types) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<EnumNode*>(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType));
+ /*
+ Safety checks
+ */
+ if (!start || path.isEmpty())
+ return 0;
+ if (start->isLeaf())
+ return ((pathIndex >= path.size()) ? start : 0);
+ if (pathIndex >= path.size())
+ return 0;
+
+ InnerNode* current = static_cast<InnerNode*>(start);
+ const NodeList& children = current->childNodes();
+ for (int i=0; i<children.size(); ++i) {
+ Node* n = children.at(i);
+ if (n && n->name() == path.at(pathIndex)) {
+ if (pathIndex+1 >= path.size()) {
+ if (n->match(types))
+ return n;
+ }
+ else if (!n->isLeaf()) {
+ n = findNodeRecursive(path, pathIndex+1, n, types);
+ if (n)
+ return n;
+ }
+ }
+ }
+ return 0;
}
/*!
- Find the C++ class node named \a path. Begin the search at the
- \a start node. If the \a start node is 0, begin the search
- at the root of the tree. Only a C++ class node named \a path is
- acceptible. If one is not found, 0 is returned.
+ Searches the tree for a node that matches the \a path. The
+ search begins at \a start but can move up the parent chain
+ recursively if no match is found.
+
+ This findNode() callse the other findNode(), which is not
+ called anywhere else.
*/
-ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
+ const Node* current = start;
+ if (!current)
+ current = root();
+
+ /*
+ First, search for a node assuming we don't want a QML node.
+ If that search fails, search again assuming we do want a
+ QML node.
+ */
+ const Node* n = findNode(path, current, findFlags, false);
+ if (n)
+ return n;
+ return findNode(path, current, findFlags, true);
}
/*!
- Find the Namespace node named \a path. Begin the search at
- the root of the tree. Only a Namespace node named \a path
- is acceptible. If one is not found, 0 is returned.
+ This overload function was extracted from the one above that has the
+ same signature without the last bool parameter, \a qml. This version
+ is called only by that other one. It is therefore private. It can
+ be called a second time by that other version, if the first call
+ returns null. If \a qml is false, the search will only match a node
+ that is not a QML node. If \a qml is true, the search will only
+ match a node that is a QML node.
+
+ This findNode() is only called by the other findNode().
+*/
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags, bool qml) const
+{
+ const Node* current = start;
+ do {
+ const Node* node = current;
+ int i;
+ int start_idx = 0;
+
+ /*
+ If the path contains one or two double colons ("::"),
+ check first to see if the first two path strings refer
+ to a QML element. If they do, path[0] will be the QML
+ module identifier, and path[1] will be the QML type.
+ If the anser is yes, the reference identifies a QML
+ class node.
+ */
+ if (qml && path.size() >= 2 && !path[0].isEmpty()) {
+ QmlClassNode* qcn = lookupQmlType(QString(path[0] + "::" + path[1]));
+ if (qcn) {
+ node = qcn;
+ if (path.size() == 2)
+ return node;
+ start_idx = 2;
+ }
+ }
+
+ for (i = start_idx; i < path.size(); ++i) {
+ if (node == 0 || !node->isInnerNode())
+ break;
+
+ const Node* next = static_cast<const InnerNode*>(node)->findChildNode(path.at(i), qml);
+ if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) {
+ next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+ }
+ if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
+ foreach (const Node* baseClass, baseClasses) {
+ next = static_cast<const InnerNode*>(baseClass)->findChildNode(path.at(i));
+ if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
+ next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
+ if (next) {
+ break;
+ }
+ }
+ }
+ node = next;
+ }
+ if (node && i == path.size()
+ && (!(findFlags & NonFunction) || node->type() != Node::Function
+ || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
+ if (!node->isQmlPropertyGroup()) {
+ if (node->isCollisionNode())
+ node = node->applyModuleName(start);
+ return node;
+ }
+ }
+ current = current->parent();
+ } while (current);
+
+ return 0;
+}
+
+/*!
+ This function searches for a node with a canonical title
+ constructed from \a target. If the node it finds is \a node,
+ it returns the ref from that node. Otherwise it returns an
+ empty string.
*/
-NamespaceNode* Tree::findNamespaceNode(const QStringList& path) const
+QString Tree::findTarget(const QString& target, const Node* node) const
{
- Node* start = const_cast<NamespaceNode*>(root());
- return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+ QString key = Doc::canonicalTitle(target);
+ TargetMap::const_iterator i = nodesByTarget_.constFind(key);
+ if (i != nodesByTarget_.constEnd()) {
+ do {
+ if (i.value().node_ == node)
+ return i.value().ref_;
+ ++i;
+ } while (i != nodesByTarget_.constEnd() && i.key() == key);
+ }
+ return QString();
+}
+
+/*!
+ Inserts a new target into the target table. \a name is the
+ key. The target record contains the \a type, a pointer to
+ the \a node, the \a priority. and a canonicalized form of
+ the \a name, which is later used.
+ */
+void Tree::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
+{
+ TargetRec target;
+ target.type_ = type;
+ target.node_ = node;
+ target.priority_ = priority;
+ target.ref_ = Doc::canonicalTitle(name);
+ nodesByTarget_.insert(name, target);
+}
+
+/*!
+ */
+void Tree::resolveTargets(InnerNode* root)
+{
+ // need recursion
+ foreach (Node* child, root->childNodes()) {
+ if (child->type() == Node::Document) {
+ DocNode* node = static_cast<DocNode*>(child);
+ if (!node->title().isEmpty()) {
+ QString key = Doc::canonicalTitle(node->title());
+ QList<DocNode*> nodes = docNodesByTitle_.values(key);
+ bool alreadyThere = false;
+ if (!nodes.empty()) {
+ for (int i=0; i< nodes.size(); ++i) {
+ if (nodes[i]->subType() == Node::ExternalPage) {
+ if (node->name() == nodes[i]->name()) {
+ alreadyThere = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!alreadyThere) {
+ docNodesByTitle_.insert(key, node);
+ }
+ }
+ if (node->subType() == Node::Collision) {
+ resolveTargets(node);
+ }
+ }
+
+ if (child->doc().hasTableOfContents()) {
+ const QList<Atom*>& toc = child->doc().tableOfContents();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 3;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.ref_ = refForAtom(toc.at(i));
+ QString title = Text::sectionHeading(toc.at(i)).toString();
+ if (!title.isEmpty()) {
+ QString key = Doc::canonicalTitle(title);
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ }
+ if (child->doc().hasKeywords()) {
+ const QList<Atom*>& keywords = child->doc().keywords();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 1;
+
+ for (int i = 0; i < keywords.size(); ++i) {
+ target.ref_ = refForAtom(keywords.at(i));
+ QString key = Doc::canonicalTitle(keywords.at(i)->string());
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ if (child->doc().hasTargets()) {
+ const QList<Atom*>& toc = child->doc().targets();
+ TargetRec target;
+ target.node_ = child;
+ target.priority_ = 2;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.ref_ = refForAtom(toc.at(i));
+ QString key = Doc::canonicalTitle(toc.at(i)->string());
+ nodesByTarget_.insert(key, target);
+ }
+ }
+ }
+}
+
+/*!
+ This function searches for a \a target anchor node. If it
+ finds one, it sets \a ref and returns the found node.
+ */
+const Node*
+Tree::findUnambiguousTarget(const QString& target, QString& ref)
+{
+ TargetRec bestTarget;
+ int numBestTargets = 0;
+ QList<TargetRec> bestTargetList;
+
+ QString key = Doc::canonicalTitle(target);
+ TargetMap::iterator i = nodesByTarget_.find(key);
+ while (i != nodesByTarget_.end()) {
+ if (i.key() != key)
+ break;
+ const TargetRec& candidate = i.value();
+ if (candidate.priority_ < bestTarget.priority_) {
+ bestTarget = candidate;
+ bestTargetList.clear();
+ bestTargetList.append(candidate);
+ numBestTargets = 1;
+ } else if (candidate.priority_ == bestTarget.priority_) {
+ bestTargetList.append(candidate);
+ ++numBestTargets;
+ }
+ ++i;
+ }
+ if (numBestTargets > 0) {
+ if (numBestTargets == 1) {
+ ref = bestTarget.ref_;
+ return bestTarget.node_;
+ }
+ else if (bestTargetList.size() > 1) {
+#if 0
+ qDebug() << "TARGET:" << target << numBestTargets;
+ for (int i=0; i<bestTargetList.size(); ++i) {
+ const Node* n = bestTargetList.at(i).node_;
+ qDebug() << " " << n->name() << n->title();
+ }
+#endif
+ ref = bestTargetList.at(0).ref_;
+ return bestTargetList.at(0).node_;
+ }
+ }
+ ref.clear();
+ return 0;
+}
+
+/*!
+ This function searches for a node with the specified \a title.
+ */
+const DocNode* Tree::findDocNodeByTitle(const QString& title) const
+{
+ QString key = Doc::canonicalTitle(title);
+ DocNodeMultiMap::const_iterator i = docNodesByTitle_.constFind(key);
+ if (i != docNodesByTitle_.constEnd()) {
+ /*
+ Reporting all these duplicate section titles is probably
+ overkill. We should report the duplicate file and let
+ that suffice.
+ */
+ DocNodeMultiMap::const_iterator j = i;
+ ++j;
+ if (j != docNodesByTitle_.constEnd() && j.key() == i.key()) {
+ QList<Location> internalLocations;
+ while (j != docNodesByTitle_.constEnd()) {
+ if (j.key() == i.key() && j.value()->url().isEmpty()) {
+ internalLocations.append(j.value()->location());
+ break; // Just report one duplicate for now.
+ }
+ ++j;
+ }
+ if (internalLocations.size() > 0) {
+ i.value()->location().warning("This page title exists in more than one file: " + title);
+ foreach (const Location &location, internalLocations)
+ location.warning("[It also exists here]");
+ }
+ }
+ return i.value();
+ }
+ return 0;
+}
+
+/*!
+ Returns a canonical title for the \a atom, if the \a atom
+ is a SectionLeft or a Target.
+ */
+QString Tree::refForAtom(const Atom* atom)
+{
+ if (atom) {
+ if (atom->type() == Atom::SectionLeft)
+ return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
+ if (atom->type() == Atom::Target)
+ return Doc::canonicalTitle(atom->string());
+ }
+ return QString();
+}
+
+/*!
+ \fn const CNMap& Tree::groups() const
+ Returns a const reference to the collection of all
+ group nodes.
+*/
+
+/*!
+ \fn const ModuleMap& Tree::modules() const
+ Returns a const reference to the collection of all
+ module nodes.
+*/
+
+/*!
+ \fn const QmlModuleMap& Tree::qmlModules() const
+ Returns a const reference to the collection of all
+ QML module nodes.
+*/
+
+/*!
+ Returns the collection node in this tree that has the same
+ name and type as \a cn. Returns 0 if no match is found.
+
+ If the matching node is \a cn, return 0.
+ */
+CollectionNode* Tree::getCorrespondingCollection(CollectionNode* cn)
+{
+ CollectionNode* ccn = 0;
+ if (cn->isGroup())
+ ccn = getGroup(cn->name());
+ else if (cn->isModule())
+ ccn = getModule(cn->name());
+ else if (cn->isQmlModule())
+ ccn = getQmlModule(cn->name());
+ if (ccn == cn)
+ ccn = 0;
+ return ccn;
+}
+
+/*!
+ Find the group node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+GroupNode* Tree::getGroup(const QString& name)
+{
+ CNMap::const_iterator i = groups_.find(name);
+ if (i != groups_.end())
+ return static_cast<GroupNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the module node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+ModuleNode* Tree::getModule(const QString& name)
+{
+ CNMap::const_iterator i = modules_.find(name);
+ if (i != modules_.end())
+ return static_cast<ModuleNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the QML module node named \a name and return a pointer
+ to it. If a matching node is not found, return 0.
+ */
+QmlModuleNode* Tree::getQmlModule(const QString& name)
+{
+ CNMap::const_iterator i = qmlModules_.find(name);
+ if (i != qmlModules_.end())
+ return static_cast<QmlModuleNode*>(i.value());
+ return 0;
+}
+
+/*!
+ Find the group node named \a name and return a pointer
+ to it. If the group node is not found, add a new group
+ node named \a name and return a pointer to the new one.
+
+ If a new group node is added, its parent is the tree root,
+ and the new group node is marked \e{not seen}.
+ */
+GroupNode* Tree::findGroup(const QString& name)
+{
+ CNMap::const_iterator i = groups_.find(name);
+ if (i != groups_.end())
+ return static_cast<GroupNode*>(i.value());;
+ GroupNode* gn = new GroupNode(root(), name);
+ gn->markNotSeen();
+ groups_.insert(name, gn);
+ return gn;
+}
+
+/*!
+ Find the module node named \a name and return a pointer
+ to it. If a matching node is not found, add a new module
+ node named \a name and return a pointer to that one.
+
+ If a new module node is added, its parent is the tree root,
+ and the new module node is marked \e{not seen}.
+ */
+ModuleNode* Tree::findModule(const QString& name)
+{
+ CNMap::const_iterator i = modules_.find(name);
+ if (i != modules_.end())
+ return static_cast<ModuleNode*>(i.value());
+ ModuleNode* mn = new ModuleNode(root(), name);
+ mn->markNotSeen();
+ modules_.insert(name, mn);
+ return mn;
+}
+
+/*!
+ Find the QML module node named \a name and return a pointer
+ to it. If a matching node is not found, add a new QML module
+ node named \a name and return a pointer to that one.
+
+ If a new QML module node is added, its parent is the tree root,
+ and the new QML module node is marked \e{not seen}.
+ */
+QmlModuleNode* Tree::findQmlModule(const QString& name)
+{
+ CNMap::const_iterator i = qmlModules_.find(name);
+ if (i != qmlModules_.end())
+ return static_cast<QmlModuleNode*>(i.value());
+ QmlModuleNode* qmn = new QmlModuleNode(root(), name);
+ qmn->markNotSeen();
+ qmn->setQmlModuleInfo(name);
+ qmlModules_.insert(name, qmn);
+ return qmn;
+}
+
+/*!
+ Looks up the group node named \a name in the collection
+ of all group nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new group node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+GroupNode* Tree::addGroup(const QString& name)
+{
+ GroupNode* group = findGroup(name);
+ return group;
+}
+
+/*!
+ Looks up the module node named \a name in the collection
+ of all module nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new module node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+ModuleNode* Tree::addModule(const QString& name)
+{
+ ModuleNode* module = findModule(name);
+ return module;
+}
+
+/*!
+ Looks up the QML module node named \a name in the collection
+ of all QML module nodes. If a match is found, a pointer to the
+ node is returned. Otherwise, a new QML module node named \a name
+ is created and inserted into the collection, and the pointer
+ to that node is returned.
+ */
+QmlModuleNode* Tree::addQmlModule(const QString& name)
+{
+ QStringList blankSplit = name.split(QLatin1Char(' '));
+ QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
+ qmn->setQmlModuleInfo(name);
+ return qmn;
+}
+
+/*!
+ Looks up the group node named \a name in the collection
+ of all group nodes. If a match is not found, a new group
+ node named \a name is created and inserted into the collection.
+ Then append \a node to the group's members list, and append the
+ group name to the list of group names in \a node. The parent of
+ \a node is not changed by this function. Returns a pointer to
+ the group node.
+ */
+GroupNode* Tree::addToGroup(const QString& name, Node* node)
+{
+ GroupNode* gn = findGroup(name);
+ if (!node->isInternal()) {
+ gn->addMember(node);
+ node->appendGroupName(name);
+ }
+ return gn;
+}
+
+/*!
+ Looks up the module node named \a name in the collection
+ of all module nodes. If a match is not found, a new module
+ node named \a name is created and inserted into the collection.
+ Then append \a node to the module's members list. The parent of
+ \a node is not changed by this function. Returns the module node.
+ */
+ModuleNode* Tree::addToModule(const QString& name, Node* node)
+{
+ ModuleNode* mn = findModule(name);
+ mn->addMember(node);
+ node->setModuleName(name);
+ return mn;
+}
+
+/*!
+ Looks up the QML module named \a name. If it isn't there,
+ create it. Then append \a node to the QML module's member
+ list. The parent of \a node is not changed by this function.
+ Returns the pointer to the QML module node.
+ */
+QmlModuleNode* Tree::addToQmlModule(const QString& name, Node* node)
+{
+ QStringList qmid;
+ QStringList dotSplit;
+ QStringList blankSplit = name.split(QLatin1Char(' '));
+ qmid.append(blankSplit[0]);
+ if (blankSplit.size() > 1) {
+ qmid.append(blankSplit[0] + blankSplit[1]);
+ dotSplit = blankSplit[1].split(QLatin1Char('.'));
+ qmid.append(blankSplit[0] + dotSplit[0]);
+ }
+
+ QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
+ qmn->addMember(node);
+ node->setQmlModule(qmn);
+ if (node->subType() == Node::QmlClass) {
+ QmlClassNode* n = static_cast<QmlClassNode*>(node);
+ for (int i=0; i<qmid.size(); ++i) {
+ QString key = qmid[i] + "::" + node->name();
+ insertQmlType(key, n);
+ }
+ }
+ return qmn;
+}
+
+/*!
+ If the QML type map does not contain \a key, insert node
+ \a n with the specified \a key.
+ */
+void Tree::insertQmlType(const QString& key, QmlClassNode* n)
+{
+ if (!qmlTypeMap_.contains(key))
+ qmlTypeMap_.insert(key,n);
+}
+
+/*!
+ Split \a target on "::" and find the function node with that
+ path.
+ */
+const Node* Tree::resolveFunctionTarget(const QString& target, const Node* relative)
+{
+ QString t = target;
+ t.chop(2);
+ QStringList path = t.split("::");
+ const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses);
+ if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
+ return fn;
+ return 0;
}
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h
index 26dd982abd..916682daad 100644
--- a/src/tools/qdoc/tree.h
+++ b/src/tools/qdoc/tree.h
@@ -46,6 +46,7 @@
#ifndef TREE_H
#define TREE_H
+#include <QtCore/qstack.h>
#include "node.h"
QT_BEGIN_NAMESPACE
@@ -53,81 +54,82 @@ QT_BEGIN_NAMESPACE
class QStringList;
class QDocDatabase;
+struct TargetRec
+{
+ public:
+ enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
+ TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
+ bool isEmpty() const { return ref_.isEmpty(); }
+ Node* node_;
+ QString ref_;
+ int priority_;
+ Type type_;
+};
+
+typedef QMultiMap<QString, TargetRec> TargetMap;
+typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
+typedef QMap<QString, QmlClassNode*> QmlTypeMap;
+typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
+
class Tree
{
private:
+ friend class QDocForest;
friend class QDocDatabase;
typedef QMap<PropertyNode::FunctionRole, QString> RoleMap;
typedef QMap<PropertyNode*, RoleMap> PropertyMap;
- struct InheritanceBound
- {
- Node::Access access;
- QStringList basePath;
- QString dataTypeWithTemplateArgs;
- InnerNode* parent;
-
- InheritanceBound() : access(Node::Public) { }
- InheritanceBound(Node::Access access0,
- const QStringList& basePath0,
- const QString& dataTypeWithTemplateArgs0,
- InnerNode* parent)
- : access(access0), basePath(basePath0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0),
- parent(parent) { }
- };
-
- Tree(QDocDatabase* qdb);
+ Tree(const QString& module, QDocDatabase* qdb);
~Tree();
- EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
ClassNode* findClassNode(const QStringList& path, Node* start = 0) const;
- QmlClassNode* findQmlTypeNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path) const;
-
- Node* findNodeByNameAndType(const QStringList& path,
- Node::Type type,
- Node::SubType subtype,
- Node* start,
- bool acceptCollision = false);
+ FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone);
+ const Node* resolveFunctionTarget(const QString& target, const Node* relative);
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
- Node* start,
+ const Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision = false) const;
+ Node* findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ const NodeTypeList& types) const;
const Node* findNode(const QStringList &path,
const Node* relative = 0,
- int findFlags = 0,
- const Node* self=0) const;
+ int findFlags = 0) const;
const Node* findNode(const QStringList& path,
const Node* start,
int findFlags,
- const Node* self,
bool qml) const;
- NameCollisionNode* checkForCollision(const QString& name) const;
+ QmlClassNode* findQmlTypeNode(const QStringList& path);
+
+ Node* findNodeByNameAndType(const QStringList& path,
+ Node::Type type,
+ Node::SubType subtype,
+ bool acceptCollision = false) const;
+
+
+ InnerNode* findRelatesNode(const QStringList& path);
+ NameCollisionNode* checkForCollision(const QString& name);
NameCollisionNode* findCollisionNode(const QString& name) const;
- FunctionNode *findFunctionNode(const QStringList &path,
- Node *relative = 0,
- int findFlags = 0);
- FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- Node *relative = 0,
- int findFlags = 0);
- void addBaseClass(ClassNode *subclass,
- Node::Access access,
- const QStringList &basePath,
- const QString &dataTypeWithTemplateArgs,
- InnerNode *parent);
+ QString findTarget(const QString& target, const Node* node) const;
+ void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
+ void resolveTargets(InnerNode* root);
+ const Node* findUnambiguousTarget(const QString& target, QString& ref);
+ const DocNode* findDocNodeByTitle(const QString& title) const;
+
void addPropertyFunction(PropertyNode *property,
const QString &funcName,
PropertyNode::FunctionRole funcRole);
- void resolveInheritance(NamespaceNode *rootNode = 0);
+ void resolveInheritance(InnerNode* n = 0);
+ void resolveInheritanceHelper(int pass, ClassNode* cn);
void resolveProperties();
void resolveCppToQmlLinks();
void fixInheritance(NamespaceNode *rootNode = 0);
@@ -136,23 +138,62 @@ class Tree
const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0,
int findFlags = 0) const;
- const FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- const Node *relative = 0,
- int findFlags = 0) const;
const NamespaceNode *root() const { return &root_; }
- void resolveInheritance(int pass, ClassNode *classe);
FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
FunctionNode *clone);
- void fixPropertyUsingBaseClasses(ClassNode *classe, PropertyNode *property);
NodeList allBaseClasses(const ClassNode *classe) const;
+ QString refForAtom(const Atom* atom);
+
+ const CNMap& groups() const { return groups_; }
+ const CNMap& modules() const { return modules_; }
+ const CNMap& qmlModules() const { return qmlModules_; }
+ const CNMap& getCollections(Node::Type t) const {
+ if (t == Node::Group)
+ return groups_;
+ if (t == Node::Module)
+ return modules_;
+ return qmlModules_;
+ }
+
+ CollectionNode* getCorrespondingCollection(CollectionNode* cn);
+
+ GroupNode* getGroup(const QString& name);
+ ModuleNode* getModule(const QString& name);
+ QmlModuleNode* getQmlModule(const QString& name);
+
+ GroupNode* findGroup(const QString& name);
+ ModuleNode* findModule(const QString& name);
+ QmlModuleNode* findQmlModule(const QString& name);
+
+ GroupNode* addGroup(const QString& name);
+ ModuleNode* addModule(const QString& name);
+ QmlModuleNode* addQmlModule(const QString& name);
+
+ GroupNode* addToGroup(const QString& name, Node* node);
+ ModuleNode* addToModule(const QString& name, Node* node);
+ QmlModuleNode* addToQmlModule(const QString& name, Node* node);
+
+ QmlClassNode* lookupQmlType(const QString& name) const { return qmlTypeMap_.value(name); }
+ void insertQmlType(const QString& key, QmlClassNode* n);
+ void addExampleNode(ExampleNode* n) { exampleNodeMap_.insert(n->title(), n); }
+ ExampleNodeMap& exampleNodeMap() { return exampleNodeMap_; }
+
+ public:
+ const QString& moduleName() const { return module_; }
private:
+ QString module_;
QDocDatabase* qdb_;
NamespaceNode root_;
- QMap<ClassNode* , QList<InheritanceBound> > unresolvedInheritanceMap;
PropertyMap unresolvedPropertyMap;
+ DocNodeMultiMap docNodesByTitle_;
+ TargetMap nodesByTarget_;
+ CNMap groups_;
+ CNMap modules_;
+ CNMap qmlModules_;
+ QmlTypeMap qmlTypeMap_;
+ ExampleNodeMap exampleNodeMap_;
};
QT_END_NAMESPACE
diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri
index 9fb2f18950..bcdfbd639c 100644
--- a/src/widgets/accessible/accessible.pri
+++ b/src/widgets/accessible/accessible.pri
@@ -1,6 +1,23 @@
# Qt accessibility module
contains(QT_CONFIG, accessibility) {
- HEADERS += accessible/qaccessiblewidget.h
- SOURCES += accessible/qaccessiblewidget.cpp
+ HEADERS += \
+ accessible/qaccessiblewidget.h \
+ accessible/qaccessiblewidgetfactory_p.h \
+ accessible/complexwidgets.h \
+ accessible/itemviews.h \
+ accessible/qaccessiblemenu.h \
+ accessible/qaccessiblewidgets.h \
+ accessible/rangecontrols.h \
+ accessible/simplewidgets.h
+
+ SOURCES += \
+ accessible/qaccessiblewidget.cpp \
+ accessible/qaccessiblewidgetfactory.cpp \
+ accessible/complexwidgets.cpp \
+ accessible/itemviews.cpp \
+ accessible/qaccessiblemenu.cpp \
+ accessible/qaccessiblewidgets.cpp \
+ accessible/rangecontrols.cpp \
+ accessible/simplewidgets.cpp
}
diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index b1df6d816a..5d76ecafbc 100644
--- a/src/plugins/accessible/widgets/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -66,7 +66,7 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
+QString qt_accStripAmp(const QString &text);
#ifndef QT_NO_TABBAR
/*!
diff --git a/src/plugins/accessible/widgets/complexwidgets.h b/src/widgets/accessible/complexwidgets.h
index 00186282f3..00186282f3 100644
--- a/src/plugins/accessible/widgets/complexwidgets.h
+++ b/src/widgets/accessible/complexwidgets.h
diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index 7d3668ee5a..36b48cfd05 100644
--- a/src/plugins/accessible/widgets/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -51,8 +51,6 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-
#ifndef QT_NO_ITEMVIEWS
/*
Implementation of the IAccessible2 table2 interface. Much simpler than
diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/widgets/accessible/itemviews.h
index 45a07c5972..45a07c5972 100644
--- a/src/plugins/accessible/widgets/itemviews.h
+++ b/src/widgets/accessible/itemviews.h
diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 39ac335131..a6877404eb 100644
--- a/src/plugins/accessible/widgets/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -52,8 +52,8 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENU
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action)
{
diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu.h
index e8c9f8af3a..e8c9f8af3a 100644
--- a/src/plugins/accessible/widgets/qaccessiblemenu.h
+++ b/src/widgets/accessible/qaccessiblemenu.h
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp
index 4e5fade3f4..8a2e38df7e 100644
--- a/src/widgets/accessible/qaccessiblewidget.cpp
+++ b/src/widgets/accessible/qaccessiblewidget.cpp
@@ -134,7 +134,7 @@ static int qt_accAmpIndex(const QString &text)
#endif
}
-QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
+QString qt_accStripAmp(const QString &text)
{
QString newText(text);
int ampIndex = qt_accAmpIndex(newText);
@@ -144,7 +144,7 @@ QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
return newText.replace(QLatin1String("&&"), QLatin1String("&"));
}
-QString Q_WIDGETS_EXPORT qt_accHotKey(const QString &text)
+QString qt_accHotKey(const QString &text)
{
int ampIndex = qt_accAmpIndex(text);
if (ampIndex != -1)
diff --git a/src/plugins/accessible/widgets/main.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
index 717c15edd1..a925dd2708 100644
--- a/src/plugins/accessible/widgets/main.cpp
+++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
@@ -46,8 +46,6 @@
#include "complexwidgets.h"
#include "itemviews.h"
-#include <qaccessibleplugin.h>
-#include <qplugin.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qtreeview.h>
@@ -58,23 +56,7 @@
QT_BEGIN_NAMESPACE
-
-class AccessibleFactory : public QAccessiblePlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QAccessibleFactoryInterface" FILE "widgets.json")
-
-public:
- AccessibleFactory();
-
- QAccessibleInterface *create(const QString &classname, QObject *object);
-};
-
-AccessibleFactory::AccessibleFactory()
-{
-}
-
-QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObject *object)
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object)
{
QAccessibleInterface *iface = 0;
if (!object || !object->isWidgetType())
@@ -254,9 +236,6 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
return iface;
}
-
QT_END_NAMESPACE
-#include "main.moc"
-
#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
new file mode 100644
index 0000000000..70ac462950
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEWIDGETFACTORY_H
+#define QACCESSIBLEWIDGETFACTORY_H
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index b502682938..afef14485f 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -72,8 +72,7 @@
QT_BEGIN_NAMESPACE
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel)
{
@@ -712,7 +711,7 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end
return QString();
}
- QMap<QString, QString> attrs;
+ QMap<QByteArray, QString> attrs;
QTextCursor cursor = textCursor();
@@ -753,58 +752,58 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end
QString family = charFormat.fontFamily();
if (!family.isEmpty()) {
- family = family.replace('\\',"\\\\");
- family = family.replace(':',"\\:");
- family = family.replace(',',"\\,");
- family = family.replace('=',"\\=");
- family = family.replace(';',"\\;");
- family = family.replace('\"',"\\\"");
- attrs["font-family"] = '"'+family+'"';
+ family = family.replace('\\',QStringLiteral("\\\\"));
+ family = family.replace(':',QStringLiteral("\\:"));
+ family = family.replace(',',QStringLiteral("\\,"));
+ family = family.replace('=',QStringLiteral("\\="));
+ family = family.replace(';',QStringLiteral("\\;"));
+ family = family.replace('\"',QStringLiteral("\\\""));
+ attrs["font-family"] = QString::fromLatin1("\"%1\"").arg(family);
}
int fontSize = int(charFormat.fontPointSize());
if (fontSize)
- attrs["font-size"] = QString::number(fontSize).append("pt");
+ attrs["font-size"] = QString::fromLatin1("%1pt").arg(fontSize);
//Different weight values are not handled
- attrs["font-weight"] = (charFormat.fontWeight() > QFont::Normal) ? "bold" : "normal";
+ attrs["font-weight"] = QString::fromLatin1(charFormat.fontWeight() > QFont::Normal ? "bold" : "normal");
QFont::Style style = charFormat.font().style();
- attrs["font-style"] = (style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal");
+ attrs["font-style"] = QString::fromLatin1((style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal"));
- attrs["text-underline-style"] = charFormat.font().underline() ? "solid" : "none";
+ attrs["text-underline-style"] = QString::fromLatin1(charFormat.font().underline() ? "solid" : "none");
QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
- attrs["text-position"] = (alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" );
+ attrs["text-position"] = QString::fromLatin1((alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" ));
QBrush background = charFormat.background();
if (background.style() == Qt::SolidPattern) {
- attrs["background-color"] = QString("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
+ attrs["background-color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
}
QBrush foreground = charFormat.foreground();
if (foreground.style() == Qt::SolidPattern) {
- attrs["color"] = QString("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
+ attrs["color"] = QString::fromLatin1("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
}
switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
case Qt::AlignLeft:
- attrs["text-align"] = "left";
+ attrs["text-align"] = QStringLiteral("left");
break;
case Qt::AlignRight:
- attrs["text-align"] = "right";
+ attrs["text-align"] = QStringLiteral("right");
break;
case Qt::AlignHCenter:
- attrs["text-align"] = "center";
+ attrs["text-align"] = QStringLiteral("center");
break;
case Qt::AlignJustify:
- attrs["text-align"] = "left";
+ attrs["text-align"] = QStringLiteral("left");
break;
}
QString result;
- foreach (const QString &attributeName, attrs.keys()) {
- result.append(attributeName).append(':').append(attrs[attributeName]).append(';');
+ foreach (const QByteArray &attributeName, attrs.keys()) {
+ result.append(QString::fromLatin1(attributeName)).append(':').append(attrs[attributeName]).append(';');
}
return result;
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets.h
index 3f50010685..3f50010685 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.h
+++ b/src/widgets/accessible/qaccessiblewidgets.h
diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
index f2aa5522e8..f2d98df719 100644
--- a/src/plugins/accessible/widgets/rangecontrols.cpp
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -57,13 +57,6 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
-extern QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-#ifndef QT_NO_SCROLLBAR
-extern QStyleOptionSlider Q_GUI_EXPORT qt_qscrollbarStyleOption(QScrollBar *scrollBar);
-#endif
-#ifndef QT_NO_SLIDER
-extern QStyleOptionSlider Q_GUI_EXPORT qt_qsliderStyleOption(QSlider *slider);
-#endif
#ifndef QT_NO_SPINBOX
QAccessibleAbstractSpinBox::QAccessibleAbstractSpinBox(QWidget *w)
diff --git a/src/plugins/accessible/widgets/rangecontrols.h b/src/widgets/accessible/rangecontrols.h
index dd69788bb1..dd69788bb1 100644
--- a/src/plugins/accessible/widgets/rangecontrols.h
+++ b/src/widgets/accessible/rangecontrols.h
diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index 646eeb06a1..b3170278ee 100644
--- a/src/plugins/accessible/widgets/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -71,8 +71,8 @@ QT_BEGIN_NAMESPACE
extern QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel = false);
-QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
-QString Q_GUI_EXPORT qt_accHotKey(const QString &text);
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
/*!
\class QAccessibleButton
diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/widgets/accessible/simplewidgets.h
index be19d8324f..be19d8324f 100644
--- a/src/plugins/accessible/widgets/simplewidgets.h
+++ b/src/widgets/accessible/simplewidgets.h
diff --git a/src/plugins/accessible/widgets/widgets.pro b/src/widgets/accessible/widgets.pro
index c6af6d3f71..c6af6d3f71 100644
--- a/src/plugins/accessible/widgets/widgets.pro
+++ b/src/widgets/accessible/widgets.pro
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index b294e98c30..15f922a5b8 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -1475,7 +1475,7 @@ void QWizardPrivate::updateButtonTexts()
void QWizardPrivate::updateButtonLayout()
{
if (buttonsHaveCustomLayout) {
- QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
+ QVarLengthArray<QWizard::WizardButton, QWizard::NButtons> array(buttonsCustomLayout.count());
for (int i = 0; i < buttonsCustomLayout.count(); ++i)
array[i] = buttonsCustomLayout.at(i);
setButtonLayout(array.constData(), array.count());
diff --git a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
index 36d3dc6af4..702c17bc26 100644
--- a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
+++ b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
@@ -1864,3 +1864,8 @@ QTabBar::close-button:hover {
}
//! [159]
+
+//! [160]
+* { lineedit-password-mask-delay: 1000 }
+//! [160]
+
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index e8c1be4c46..32fe384c75 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -862,6 +862,9 @@
\l{#lineedit-password-character-prop}{lineedit-password-character}
property.
+ The password mask delay can be changed using the
+ \l{#lineedit-password-mask-delay-prop}{lineedit-password-mask-delay}
+
See \l{Qt Style Sheets Examples#Customizing QLineEdit}{Customizing QLineEdit}
for an example.
@@ -2009,6 +2012,23 @@
\snippet code/doc_src_stylesheet.qdoc 61
\row
+ \li \b{\c lineedit-password-mask-delay*} \target lineedit-password-mask-delay-prop
+ \li \l{#Number}{Number}
+ \li The QLineEdit password mask delay in milliseconds before
+ \l{#lineedit-password-character-prop}{lineedit-password-character} is applied to visible character.
+
+ If this property is not specified, it defaults to the
+ value specified by the current style for the
+ \l{QStyle::}{SH_LineEdit_PasswordMaskDelay} style hint.
+
+ \b{This property was added in Qt 5.4.}
+
+ Example:
+
+ \snippet code/doc_src_stylesheet.qdoc 160
+
+
+ \row
\li \b{\c margin} \target margin-prop
\li \l {Box Lengths}
\li The widget's margins. Equivalent to specifying \c
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index d4edc63403..605e96802b 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -332,6 +332,8 @@
this flag is disabled; children can draw anywhere. This behavior is
enforced by QGraphicsView::drawItems() or
QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
+ \note This flag is similar to ItemContainsChildrenInShape but in addition
+ enforces the containment by clipping the children.
\value ItemIgnoresTransformations The item ignores inherited
transformations (i.e., its position is still anchored to its parent, but
@@ -423,6 +425,19 @@
ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
allows you to completely take over focus handling.
This flag was introduced in Qt 4.7. \endomit
+
+ \value ItemContainsChildrenInShape This flag indicates that all of the
+ item's direct or indirect children only draw within the item's shape.
+ Unlike ItemClipsChildrenToShape, this restriction is not enforced. Set
+ ItemContainsChildrenInShape when you manually assure that drawing
+ is bound to the item's shape and want to avoid the cost associated with
+ enforcing the clip. Setting this flag enables more efficient drawing and
+ collision detection. The flag is disabled by default.
+ \note If both this flag and ItemClipsChildrenToShape are set, the clip
+ will be enforced. This is equivalent to just setting
+ ItemClipsChildrenToShape.
+ .
+ This flag was introduced in Qt 5.4.
*/
/*!
@@ -836,6 +851,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
flag = AncestorIgnoresTransformations;
enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ flag = AncestorContainsChildren;
+ enabled = flags & QGraphicsItem::ItemContainsChildrenInShape;
+ break;
default:
return;
}
@@ -895,6 +914,8 @@ void QGraphicsItemPrivate::updateAncestorFlags()
flags |= AncestorClipsChildren;
if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
flags |= AncestorIgnoresTransformations;
+ if (pd->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ flags |= AncestorContainsChildren;
}
if (ancestorFlags == flags)
@@ -1831,6 +1852,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->markParentDirty(true);
}
+ if ((flags & ItemContainsChildrenInShape) != (oldFlags & ItemContainsChildrenInShape)) {
+ // Item children containtment changes. Propagate the ancestor flag to all children.
+ d_ptr->updateAncestorFlag(ItemContainsChildrenInShape);
+ }
+
if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
// Item children clipping changes. Propagate the ancestor flag to
// all children.
@@ -2322,7 +2348,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
}
// Update children with explicitly = false.
- const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape)
+ const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
+ || flags & QGraphicsItem::ItemContainsChildrenInShape)
&& !(flags & QGraphicsItem::ItemHasNoContents));
foreach (QGraphicsItem *child, children) {
if (!newVisible || !child->d_ptr->explicitlyHidden)
@@ -2835,7 +2862,9 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
#ifndef QT_NO_GRAPHICSEFFECT
Q_Q(const QGraphicsItem);
QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
- if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
+ if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
+ || topMostEffectItem == q)
return brect;
const QGraphicsItem *effectParent = parent;
@@ -2847,6 +2876,7 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
}
if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
|| topMostEffectItem == effectParent) {
return brect;
}
@@ -7442,7 +7472,8 @@ QVariant QGraphicsItem::extension(const QVariant &variant) const
*/
void QGraphicsItem::addToIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### add to child index only if applicable
return;
}
@@ -7459,7 +7490,8 @@ void QGraphicsItem::addToIndex()
*/
void QGraphicsItem::removeFromIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### remove from child index only if applicable
return;
}
@@ -11451,6 +11483,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStopsFocusHandling:
str = "ItemStopsFocusHandling";
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ str = "ItemContainsChildrenInShape";
+ break;
}
debug << str;
return debug;
diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h
index 4283deb5b8..dfc06fdaea 100644
--- a/src/widgets/graphicsview/qgraphicsitem.h
+++ b/src/widgets/graphicsview/qgraphicsitem.h
@@ -105,7 +105,8 @@ public:
ItemIsFocusScope = 0x8000, // internal
ItemSendsScenePositionChanges = 0x10000,
ItemStopsClickFocusPropagation = 0x20000,
- ItemStopsFocusHandling = 0x40000
+ ItemStopsFocusHandling = 0x40000,
+ ItemContainsChildrenInShape = 0x80000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 3968d89a13..4d1835f178 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -172,7 +172,8 @@ public:
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
AncestorIgnoresTransformations = 0x4,
- AncestorFiltersChildEvents = 0x8
+ AncestorFiltersChildEvents = 0x8,
+ AncestorContainsChildren = 0x10
};
inline QGraphicsItemPrivate()
@@ -213,7 +214,6 @@ public:
needSortChildren(0),
allChildrenDirty(0),
fullUpdatePending(0),
- dirtyChildrenBoundingRect(1),
flags(0),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -239,6 +239,7 @@ public:
mayHaveChildWithGraphicsEffect(0),
isDeclarativeItem(0),
sendParentChangeNotification(0),
+ dirtyChildrenBoundingRect(1),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -544,7 +545,7 @@ public:
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 4;
+ quint32 ancestorFlags : 5;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
@@ -555,10 +556,9 @@ public:
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
quint32 fullUpdatePending : 1;
- quint32 dirtyChildrenBoundingRect : 1;
// Packed 32 bits
- quint32 flags : 19;
+ quint32 flags : 20;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
@@ -571,9 +571,9 @@ public:
quint32 filtersDescendantEvents : 1;
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
- quint32 notifyInvalidated : 1;
// New 32 bits
+ quint32 notifyInvalidated : 1;
quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
@@ -585,7 +585,8 @@ public:
quint32 mayHaveChildWithGraphicsEffect : 1;
quint32 isDeclarativeItem : 1;
quint32 sendParentChangeNotification : 1;
- quint32 padding : 21;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 padding : 19;
// Optional stacking order
int globalStackingOrder;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index bccdb1fbaa..1cd162e6bb 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -299,6 +299,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
painterStateProtection(true),
sortCacheEnabled(false),
allItemsIgnoreTouchEvents(true),
+ minimumRenderSize(0.0),
selectionChanging(0),
rectAdjust(2),
focusItem(0),
@@ -4716,19 +4717,40 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
wasDirtyParentSceneTransform = true;
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool drawItem = itemHasContents && !itemIsFullyTransparent;
- if (drawItem) {
+ if (drawItem || minimumRenderSize > 0.0) {
const QRectF brect = adjustedItemEffectiveBoundingRect(item);
ENSURE_TRANSFORM_PTR
- QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
- : transformPtr->mapRect(brect).toAlignedRect();
- viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
- if (widget)
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
- drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
- : !viewBoundingRect.normalized().isEmpty();
- if (!drawItem) {
+ QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
+ : transformPtr->mapRect(brect);
+
+ bool itemIsTooSmallToRender = false;
+ if (minimumRenderSize > 0.0
+ && (preciseViewBoundingRect.width() < minimumRenderSize
+ || preciseViewBoundingRect.height() < minimumRenderSize)) {
+ itemIsTooSmallToRender = true;
+ drawItem = false;
+ }
+
+ bool itemIsOutsideVisibleRect = false;
+ if (drawItem) {
+ QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
+ viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
+ if (widget)
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
+ : !viewBoundingRect.normalized().isEmpty();
+ itemIsOutsideVisibleRect = !drawItem;
+ }
+
+ if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
+ // We cannot simply use !drawItem here. If we did it is possible
+ // to enter the outter if statement with drawItem == false and minimumRenderSize > 0
+ // and finally end up inside this inner if, even though none of the above two
+ // conditions are met. In that case we should not return from this function
+ // but call draw() instead.
if (!itemHasChildren)
return;
if (itemClipsChildrenToShape) {
@@ -5200,7 +5222,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
// Process children.
if (itemHasChildren && item->d_ptr->dirtyChildren) {
- const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
// Items with no content are threated as 'dummy' items which means they are never drawn and
// 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
// such an item changes geometry, its children have to take care of the update regardless
@@ -5729,6 +5752,49 @@ bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
return d->sendEvent(item, event);
}
+/*!
+ \property QGraphicsScene::minimumRenderSize
+ \since 5.4
+ \brief the minimal view-transformed size an item must have to be drawn
+
+ When the scene is rendered, any item whose width or height, transformed
+ to the target view, is smaller that minimumRenderSize(), will not be
+ rendered. If an item is not rendered and it clips its children items
+ they will also not be rendered. Set this value to speed up rendering
+ of scenes with many objects rendered on a zoomed out view.
+
+ The default value is 0. If unset, or if set to 0 or a negative value,
+ all items will always be rendered.
+
+ For example, setting this property can be especially useful if a scene
+ is rendered by multiple views, one of which serves as an overview which
+ always displays all items. In scenes with many items, such a view will
+ use a high scaling factor so that all items can be shown. Due to the
+ scaling, smaller items will only make an insignificant contribution to
+ the final rendered scene. To avoid drawing these items and reduce the
+ time necessary to render the scene, you can call setMinimumRenderSize()
+ with a non-negative value.
+
+ \note Items that are not drawn as a result of being too small, are still
+ returned by methods such as items() and itemAt(), and participate in
+ collision detection and interactions. It is recommended that you set
+ minimumRenderSize() to a value less than or equal to 1 in order to
+ avoid large unrendered items that are interactive.
+
+ \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform()
+*/
+qreal QGraphicsScene::minimumRenderSize() const
+{
+ Q_D(const QGraphicsScene);
+ return d->minimumRenderSize;
+}
+void QGraphicsScene::setMinimumRenderSize(qreal minSize)
+{
+ Q_D(QGraphicsScene);
+ d->minimumRenderSize = minSize;
+ update();
+}
+
void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
views << view;
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index cde0eda125..ba47d45d63 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -107,6 +107,7 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
+ Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
public:
enum ItemIndexMethod {
@@ -249,6 +250,9 @@ public:
bool sendEvent(QGraphicsItem *item, QEvent *event);
+ qreal minimumRenderSize() const;
+ void setMinimumRenderSize(qreal minSize);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index 9e5bcec488..9f50dcfea7 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -117,6 +117,8 @@ public:
quint32 allItemsIgnoreTouchEvents : 1;
quint32 padding : 15;
+ qreal minimumRenderSize;
+
QRectF growingItemsBoundingRect;
void _q_emitUpdated();
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
index 7598163f2d..50f17ab73f 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -169,7 +169,8 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
untransformableItems << item;
continue;
}
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)
continue;
bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect());
@@ -351,7 +352,8 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec
// Avoid virtual function calls from the destructor.
purgePending = true;
removedItems << item;
- } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect());
}
} else {
@@ -510,7 +512,8 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *
return;
if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
- || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
return; // Item is not in BSP tree; nothing to do.
}
@@ -641,8 +644,10 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value);
bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations;
- bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
- bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
+ bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape
+ || newFlags & QGraphicsItem::ItemContainsChildrenInShape;
if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
@@ -663,10 +668,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
bool ignoredTransform = item->d_ptr->itemIsUntransformable();
bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations)
|| (newParent && newParent->d_ptr->itemIsUntransformable());
- bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren;
+ bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren;
bool ancestorWillClipChildren = newParent
- && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
+ && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || newParent->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren));
if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
diff --git a/src/widgets/graphicsview/qgraphicssceneindex.cpp b/src/widgets/graphicsview/qgraphicssceneindex.cpp
index 40f63937f4..d06c5523ca 100644
--- a/src/widgets/graphicsview/qgraphicssceneindex.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneindex.cpp
@@ -278,7 +278,8 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
Q_ASSERT(!item->d_ptr->dirtySceneTransform);
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool processItem = !itemIsFullyTransparent;
if (processItem) {
processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index ed376fe923..8d0a51606e 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -77,6 +77,7 @@
#endif
#include "private/qkeymapper_p.h"
+#include "private/qaccessiblewidgetfactory_p.h"
#include <qthread.h>
#include <private/qthread_p.h>
@@ -557,6 +558,11 @@ void QApplicationPrivate::construct()
qt_gui_eval_init(application_type);
#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // factory for accessible interfaces for widgets shipped with Qt
+ QAccessible::installFactory(&qAccessibleFactory);
+#endif
+
#ifndef QT_NO_LIBRARY
if(load_testability) {
QLibrary testLib(QLatin1String("qttestability"));
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index c68bcc773f..ccd6c2b03c 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -149,6 +149,11 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
return;
QWidget *tlw = qt_tlw_for_window(wnd);
QApplication::setActiveWindow(tlw);
+ // QTBUG-37126, Active X controls may set the focus on native child widgets.
+ if (wnd && tlw && wnd != tlw->windowHandle()) {
+ if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd))
+ widgetWindow->widget()->setFocus(Qt::ActiveWindowFocusReason);
+ }
}
static void ungrabKeyboardForPopup(QWidget *popup)
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7eecd3d84d..926db7febf 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1065,7 +1065,11 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
// interpret WindowSystemMenuHint as a close button and we can't change that behavior
// we can't just add this in.
#ifndef Q_WS_MAC
- if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) {
+ if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
+# ifdef Q_OS_WIN
+ && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
+# endif
+ ) {
flags |= Qt::WindowSystemMenuHint;
#else
if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
@@ -8209,6 +8213,7 @@ bool QWidget::event(QEvent *event)
case QEvent::MacSizeChange:
case QEvent::ContentsRectChange:
case QEvent::ThemeChange:
+ case QEvent::ReadOnlyChange:
changeEvent(event);
break;
@@ -8382,7 +8387,7 @@ bool QWidget::event(QEvent *event)
QEvent::ModifiedChange, QEvent::MouseTrackingChange,
QEvent::ParentChange, QEvent::WindowStateChange,
QEvent::LanguageChange, QEvent::LocaleChange,
- QEvent::LayoutDirectionChange.
+ QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
*/
void QWidget::changeEvent(QEvent * event)
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index f1cf46169a..4a9852108c 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -4923,6 +4923,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = hint.toChar().unicode();
break;
}
+ case SH_LineEdit_PasswordMaskDelay:
+ ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ break;
case SH_ToolBox_SelectedPageTitleBold:
ret = 1;
break;
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 4c5c7cd17e..8774d71c0c 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1784,6 +1784,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_LineEdit_PasswordCharacter The Unicode character to be
used for passwords.
+ \value SH_LineEdit_PasswordMaskDelay Determines the delay before visible character is masked
+ with password character, in milliseconds. This enum value was added in Qt 5.4.
+
\value SH_Table_GridLineColor The RGB value of the grid for a table.
\value SH_UnderlineShortcut Whether shortcuts are underlined.
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index 136daa9abd..ea012faf46 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -703,6 +703,7 @@ public:
SH_Widget_Animate,
SH_Splitter_OpaqueResize,
SH_ComboBox_UseNativePopup,
+ SH_LineEdit_PasswordMaskDelay,
// Add new style hint values here
SH_CustomBase = 0xf0000000
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 5913b2f261..f642a05d13 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -3702,6 +3702,8 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
of the painter used to draw the item. By default, if no
transformations are applied, its value is 1. If zoomed out 1:2, the level
of detail will be 0.5, and if zoomed in 2:1, its value is 2.
+
+ \sa QGraphicsScene::minimumRenderSize()
*/
qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform)
{
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 94f8e36235..5eea903773 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -645,6 +645,7 @@ static const char *knownStyleHints[] = {
"icon-size",
"leftarrow-icon",
"lineedit-password-character",
+ "lineedit-password-mask-delay",
"mdi-fill-space-on-maximize",
"menu-scrollable",
"menubar-altkey-navigation",
@@ -5142,6 +5143,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
QString s;
switch (sh) {
case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break;
+ case SH_LineEdit_PasswordMaskDelay: s = QLatin1String("lineedit-password-mask-delay"); break;
case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break;
case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break;
case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break;
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index 9c3e1eac99..1d75894cd6 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -1421,15 +1421,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
break;
case CE_DockWidgetTitle:
- if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) {
+ if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
+ const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget);
QRect rect = option->rect;
- if (dockWidget->isFloating()) {
+ if (dockWidget && dockWidget->isFloating()) {
QWindowsXPStyle::drawControl(element, option, painter, widget);
break; //otherwise fall through
}
- if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
-
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
@@ -1490,7 +1489,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
}
break;
- }
#ifndef QT_NO_ITEMVIEWS
case CE_ItemViewItem:
{
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index f1a69e6b36..fa318f3233 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -672,6 +672,74 @@ void QBalloonTip::timerEvent(QTimerEvent *e)
QWidget::timerEvent(e);
}
+//////////////////////////////////////////////////////////////////////
+void QSystemTrayIconPrivate::install_sys_qpa()
+{
+ qpa_sys->init();
+ QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
+ q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
+ QObject::connect(qpa_sys, &QPlatformSystemTrayIcon::messageClicked,
+ q_func(), &QSystemTrayIcon::messageClicked);
+ updateMenu_sys();
+ updateIcon_sys();
+ updateToolTip_sys();
+}
+
+void QSystemTrayIconPrivate::remove_sys_qpa()
+{
+ qpa_sys->cleanup();
+}
+
+QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
+{
+ return qpa_sys->geometry();
+}
+
+void QSystemTrayIconPrivate::updateIcon_sys_qpa()
+{
+ qpa_sys->updateIcon(icon);
+}
+
+void QSystemTrayIconPrivate::updateMenu_sys_qpa()
+{
+ if (menu) {
+ if (!menu->platformMenu()) {
+ QPlatformMenu *platformMenu = qpa_sys->createMenu();
+ if (platformMenu)
+ menu->setPlatformMenu(platformMenu);
+ }
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
+}
+
+void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
+{
+ qpa_sys->updateToolTip(toolTip);
+}
+
+void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &message,
+ const QString &title,
+ QSystemTrayIcon::MessageIcon icon,
+ int msecs)
+{
+ QIcon notificationIcon;
+ switch (icon) {
+ case QSystemTrayIcon::Information:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
+ break;
+ case QSystemTrayIcon::Warning:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
+ break;
+ case QSystemTrayIcon::Critical:
+ notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
+ break;
+ default:
+ break;
+ }
+ qpa_sys->showMessage(message, title, notificationIcon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 211ef308f1..317664a365 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -98,6 +98,15 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
+
+private:
+ void install_sys_qpa();
+ void remove_sys_qpa();
+ void updateIcon_sys_qpa();
+ void updateToolTip_sys_qpa();
+ void updateMenu_sys_qpa();
+ QRect geometry_sys_qpa() const;
+ void showMessage_sys_qpa(const QString &msg, const QString &title, QSystemTrayIcon::MessageIcon icon, int secs);
};
class QBalloonTip : public QWidget
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index f98aeaf678..045641c509 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -65,28 +65,20 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
- if (qpa_sys) {
- qpa_sys->init();
- QObject::connect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
- q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
- QObject::connect(qpa_sys, SIGNAL(messageClicked()),
- q_func(), SIGNAL(messageClicked()));
- updateMenu_sys();
- updateIcon_sys();
- updateToolTip_sys();
- }
+ if (qpa_sys)
+ install_sys_qpa();
}
void QSystemTrayIconPrivate::remove_sys()
{
if (qpa_sys)
- qpa_sys->cleanup();
+ remove_sys_qpa();
}
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return qpa_sys->geometry();
+ return geometry_sys_qpa();
else
return QRect();
}
@@ -94,25 +86,19 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys)
- qpa_sys->updateIcon(icon);
+ updateIcon_sys_qpa();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys && menu) {
- if (!menu->platformMenu()) {
- QPlatformMenu *platformMenu = qpa_sys->createMenu();
- if (platformMenu)
- menu->setPlatformMenu(platformMenu);
- }
- qpa_sys->updateMenu(menu->platformMenu());
- }
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys)
- qpa_sys->updateToolTip(toolTip);
+ updateToolTip_sys_qpa();
}
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
@@ -138,25 +124,8 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &message,
QSystemTrayIcon::MessageIcon icon,
int msecs)
{
- if (!qpa_sys)
- return;
-
- QIcon notificationIcon;
- switch (icon) {
- case QSystemTrayIcon::Information:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::Warning:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- default:
- break;
- }
- qpa_sys->showMessage(message, title, notificationIcon,
- static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
+ if (qpa_sys)
+ showMessage_sys_qpa(message, title, icon, msecs);
}
QT_END_NAMESPACE
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 347e5701c0..27d0418dff 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -55,6 +55,9 @@
#include <qscreen.h>
#include <qbackingstore.h>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformsystemtrayicon.h>
+#include <qpa/qplatformtheme.h>
+#include <private/qguiapplication_p.h>
#include <qdebug.h>
#ifndef QT_NO_SYSTEMTRAYICON
@@ -209,16 +212,22 @@ void QSystemTrayIconSys::paintEvent(QPaintEvent *)
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
+ qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
visible(false)
{
}
QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
{
+ delete qpa_sys;
}
void QSystemTrayIconPrivate::install_sys()
{
+ if (qpa_sys) {
+ install_sys_qpa();
+ return;
+ }
Q_Q(QSystemTrayIcon);
if (!sys && locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
@@ -229,6 +238,8 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
+ if (qpa_sys)
+ return geometry_sys_qpa();
if (!sys)
return QRect();
return sys->globalGeometry();
@@ -236,6 +247,10 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::remove_sys()
{
+ if (qpa_sys) {
+ remove_sys_qpa();
+ return;
+ }
if (!sys)
return;
QBalloonTip::hideBalloon();
@@ -246,17 +261,26 @@ void QSystemTrayIconPrivate::remove_sys()
void QSystemTrayIconPrivate::updateIcon_sys()
{
+ if (qpa_sys) {
+ updateIcon_sys_qpa();
+ return;
+ }
if (sys)
sys->updateIcon();
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
-
+ if (qpa_sys)
+ updateMenu_sys_qpa();
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
+ if (qpa_sys) {
+ updateToolTip_sys_qpa();
+ return;
+ }
if (!sys)
return;
#ifndef QT_NO_TOOLTIP
@@ -266,6 +290,11 @@ void QSystemTrayIconPrivate::updateToolTip_sys()
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->isSystemTrayAvailable();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
const QString platform = QGuiApplication::platformName();
if (platform.compare(QStringLiteral("xcb"), Qt::CaseInsensitive) == 0)
return locateSystemTray();
@@ -274,12 +303,21 @@ bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
bool QSystemTrayIconPrivate::supportsMessages_sys()
{
+ QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
+ if (sys)
+ return sys->supportsMessages();
+
+ // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
return true;
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title,
QSystemTrayIcon::MessageIcon icon, int msecs)
{
+ if (qpa_sys) {
+ showMessage_sys_qpa(message, title, icon, msecs);
+ return;
+ }
if (!sys)
return;
const QPoint g = sys->globalGeometry().topLeft();
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index 0b289c75ae..c2cf4b7dfe 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -8,9 +8,6 @@ DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
-MODULE_PLUGIN_TYPES += \
- accessible/libqtaccessiblewidgets.so
-
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf
load(qt_module)
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 92af91b66e..43f5d6fd31 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -315,6 +315,8 @@ void QAbstractSpinBox::setReadOnly(bool enable)
Q_D(QAbstractSpinBox);
d->readOnly = enable;
d->edit->setReadOnly(enable);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
update();
}
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index ba4dbcc878..b6b7ffb1a2 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1348,6 +1348,8 @@ void QLineEdit::setReadOnly(bool enable)
#ifndef QT_NO_CURSOR
setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
+ QEvent event(QEvent::ReadOnlyChange);
+ QCoreApplication::sendEvent(this, &event);
update();
}
}
@@ -2188,6 +2190,7 @@ void QLineEdit::changeEvent(QEvent *ev)
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
+ d->control->setPasswordMaskDelay(style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, this));
}
d->m_iconSize = QSize();
update();
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 10689b2fc3..adec9cae18 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -205,6 +205,7 @@ void QLineEditPrivate::init(const QString& txt)
QStyleOptionFrameV2 opt;
q->initStyleOption(&opt);
control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q));
+ control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
#ifndef QT_NO_CURSOR
q->setCursor(Qt::IBeamCursor);
#endif
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 600d9b536f..d0488d5955 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -169,7 +169,7 @@
#include <QResizeEvent>
#include <QScrollBar>
#include <QtAlgorithms>
-#include <QMutableListIterator>
+#include <QMutableVectorIterator>
#include <QPainter>
#include <QFontMetrics>
#include <QStyleOption>
@@ -413,7 +413,7 @@ void IconTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const
\internal
Calculates the accumulated overlap (intersection area) between 'source' and 'rects'.
*/
-int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect> &rects)
+int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRect> &rects)
{
int accOverlap = 0;
foreach (const QRect &rect, rects) {
@@ -429,7 +429,7 @@ int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect>
Finds among 'source' the rectangle with the minimum accumulated overlap with the
rectangles in 'rects'.
*/
-QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects)
+QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects)
{
int minAccOverlap = -1;
QRect minAccOverlapRect;
@@ -447,28 +447,37 @@ QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QLi
\internal
Gets candidates for the final placement.
*/
-void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRect> &rects,
- const QRect &domain,QList<QRect> &candidates)
+QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QVector<QRect> &rects,
+ const QRect &domain)
{
- QSet<int> xset;
- QSet<int> yset;
- xset << domain.left() << domain.right() - size.width() + 1;
- yset << domain.top();
+ QVector<QRect> result;
+
+ QVector<int> xlist;
+ xlist.reserve(2 + rects.size());
+ xlist << domain.left() << domain.right() - size.width() + 1;
+
+ QVector<int> ylist;
+ ylist.reserve(2 + rects.size());
+ ylist << domain.top();
if (domain.bottom() - size.height() + 1 >= 0)
- yset << domain.bottom() - size.height() + 1;
+ ylist << domain.bottom() - size.height() + 1;
+
foreach (const QRect &rect, rects) {
- xset << rect.right() + 1;
- yset << rect.bottom() + 1;
+ xlist << rect.right() + 1;
+ ylist << rect.bottom() + 1;
}
- QList<int> xlist = xset.values();
std::sort(xlist.begin(), xlist.end());
- QList<int> ylist = yset.values();
+ xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());
+
std::sort(ylist.begin(), ylist.end());
+ ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());
+ result.reserve(ylist.size() * xlist.size());
foreach (int y, ylist)
foreach (int x, xlist)
- candidates << QRect(QPoint(x, y), size);
+ result << QRect(QPoint(x, y), size);
+ return result;
}
/*!
@@ -476,10 +485,12 @@ void MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRe
Finds all rectangles in 'source' not completely inside 'domain'. The result is stored
in 'result' and also removed from 'source'.
*/
-void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)
{
- QMutableListIterator<QRect> it(source);
+ QVector<QRect> result;
+ result.reserve(source.size());
+
+ QMutableVectorIterator<QRect> it(source);
while (it.hasNext()) {
const QRect srcRect = it.next();
if (!domain.contains(srcRect)) {
@@ -487,6 +498,8 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
it.remove();
}
}
+
+ return result;
}
/*!
@@ -494,9 +507,11 @@ void MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source
Finds all rectangles in 'source' that overlaps 'domain' by the maximum overlap area
between 'domain' and any rectangle in 'source'. The result is stored in 'result'.
*/
-void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect> &source,
- QList<QRect> &result)
+QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QVector<QRect> &source)
{
+ QVector<QRect> result;
+ result.reserve(source.size());
+
int maxOverlap = -1;
foreach (const QRect &srcRect, source) {
QRect intersection = domain.intersected(srcRect);
@@ -509,6 +524,8 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
result << srcRect;
}
}
+
+ return result;
}
/*!
@@ -517,17 +534,15 @@ void MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect
placement that overlaps the rectangles in 'rects' as little as possible while at the
same time being as much as possible inside 'domain'.
*/
-QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRect> &rects,
- QList<QRect> &source)
+QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QRect> &rects,
+ QVector<QRect> &source)
{
- QList<QRect> nonInsiders;
- findNonInsiders(domain, source, nonInsiders);
+ const QVector<QRect> nonInsiders = findNonInsiders(domain, source);
if (!source.empty())
return findMinOverlapRect(source, rects).topLeft();
- QList<QRect> maxOverlappers;
- findMaxOverlappers(domain, nonInsiders, maxOverlappers);
+ QVector<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);
return findMinOverlapRect(maxOverlappers, rects).topLeft();
}
@@ -538,7 +553,7 @@ QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRec
overlaps 'rects' as little as possible and 'domain' as much as possible.
Returns the position of the resulting rectangle.
*/
-QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
+QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,
const QRect &domain) const
{
if (size.isEmpty() || !domain.isValid())
@@ -548,8 +563,7 @@ QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
return QPoint();
}
- QList<QRect> candidates;
- getCandidatePlacements(size, rects, domain, candidates);
+ QVector<QRect> candidates = getCandidatePlacements(size, rects, domain);
return findBestPlacement(domain, rects, candidates);
}
@@ -882,7 +896,8 @@ void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child)
return;
}
- QList<QRect> rects;
+ QVector<QRect> rects;
+ rects.reserve(childWindows.size());
QRect parentRect = q->rect();
foreach (QMdiSubWindow *window, childWindows) {
if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q)
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 90db55438a..360ed2508c 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -59,6 +59,7 @@
#ifndef QT_NO_MDIAREA
#include <QList>
+#include <QVector>
#include <QRect>
#include <QPoint>
#include <QtWidgets/qapplication.h>
@@ -116,24 +117,19 @@ public:
// Places the rectangle defined by 'size' relative to 'rects' and 'domain'.
// Returns the position of the resulting rectangle.
virtual QPoint place(
- const QSize &size, const QList<QRect> &rects, const QRect &domain) const = 0;
+ const QSize &size, const QVector<QRect> &rects, const QRect &domain) const = 0;
virtual ~Placer() {}
};
class MinOverlapPlacer : public Placer
{
- QPoint place(const QSize &size, const QList<QRect> &rects, const QRect &domain) const;
- static int accumulatedOverlap(const QRect &source, const QList<QRect> &rects);
- static QRect findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects);
- static void getCandidatePlacements(
- const QSize &size, const QList<QRect> &rects, const QRect &domain,
- QList<QRect> &candidates);
- static QPoint findBestPlacement(
- const QRect &domain, const QList<QRect> &rects, QList<QRect> &source);
- static void findNonInsiders(
- const QRect &domain, QList<QRect> &source, QList<QRect> &result);
- static void findMaxOverlappers(
- const QRect &domain, const QList<QRect> &source, QList<QRect> &result);
+ QPoint place(const QSize &size, const QVector<QRect> &rects, const QRect &domain) const;
+ static int accumulatedOverlap(const QRect &source, const QVector<QRect> &rects);
+ static QRect findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects);
+ static QVector<QRect> getCandidatePlacements(const QSize &size, const QVector<QRect> &rects, const QRect &domain);
+ static QPoint findBestPlacement(const QRect &domain, const QVector<QRect> &rects, QVector<QRect> &source);
+ static QVector<QRect> findNonInsiders(const QRect &domain, QVector<QRect> &source);
+ static QVector<QRect> findMaxOverlappers(const QRect &domain, const QVector<QRect> &source);
};
} // namespace QMdi
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 6ed1aeff72..e41cb64463 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2536,6 +2536,8 @@ void QPlainTextEdit::setReadOnly(bool ro)
}
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index a33ac0817f..f106b70c12 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -2122,6 +2122,8 @@ void QTextEdit::setReadOnly(bool ro)
}
d->control->setTextInteractionFlags(flags);
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ QEvent event(QEvent::ReadOnlyChange);
+ QApplication::sendEvent(this, &event);
}
/*!
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index b16477246f..1f70dd719b 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -355,8 +355,10 @@ void QWidgetLineControl::init(const QString &txt)
m_text = txt;
updateDisplayText();
m_cursor = m_text.length();
- if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
m_keyboardScheme = theme->themeHint(QPlatformTheme::KeyboardScheme).toInt();
+ m_passwordMaskDelay = theme->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
+ }
// Generalize for X11
if (m_keyboardScheme == QPlatformTheme::KdeKeyboardScheme
|| m_keyboardScheme == QPlatformTheme::GnomeKeyboardScheme
@@ -787,7 +789,7 @@ void QWidgetLineControl::internalInsert(const QString &s)
if (m_echoMode == QLineEdit::Password) {
if (m_passwordEchoTimer != 0)
killTimer(m_passwordEchoTimer);
- int delay = qGuiApp->styleHints()->passwordMaskDelay();
+ int delay = m_passwordMaskDelay;
#ifdef QT_BUILD_INTERNAL
if (m_passwordMaskDelayOverride >= 0)
delay = m_passwordMaskDelayOverride;
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index 1cee67bfd2..ba73e9e25e 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -90,6 +90,7 @@ public:
m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
, m_passwordEchoTimer(0)
+ , m_passwordMaskDelay(-1)
#if defined(Q_WS_MAC)
, m_threadChecks(false)
, m_textLayoutThread(0)
@@ -313,6 +314,9 @@ public:
QChar passwordCharacter() const { return m_passwordCharacter; }
void setPasswordCharacter(QChar character) { m_passwordCharacter = character; updateDisplayText(); }
+ int passwordMaskDelay() const { return m_passwordMaskDelay; }
+ void setPasswordMaskDelay(int delay) { m_passwordMaskDelay = delay; }
+
Qt::LayoutDirection layoutDirection() const {
if (m_layoutDirection == Qt::LayoutDirectionAuto) {
if (m_text.isEmpty())
@@ -481,6 +485,7 @@ private:
bool m_passwordEchoEditing;
QChar m_passwordCharacter;
int m_passwordEchoTimer;
+ int m_passwordMaskDelay;
void cancelPasswordEchoTimer()
{
if (m_passwordEchoTimer != 0) {