diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-04-06 12:42:27 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-04-06 12:42:51 +0200 |
commit | 887f86794c24c6e80cf49a2687b669d7530a1944 (patch) | |
tree | 9d08458d66b9621faf2d877879b5e3aa8faa30af | |
parent | 790f59646d80e3b05d03aa8d3e2d9cc52eef68b9 (diff) | |
parent | cf9129f19fb180d24f217897cc660ea7c6861e87 (diff) | |
download | qttools-887f86794c24c6e80cf49a2687b669d7530a1944.tar.gz |
Merge remote-tracking branch 'origin/5.6' into 5.7
Change-Id: I06a1d65d1bcb0cdb0ae6e00e57283333aafbb673
32 files changed, 346 insertions, 152 deletions
diff --git a/src/assistant/assistant/images/darkclosebutton.png b/src/assistant/assistant/images/darkclosebutton.png Binary files differindex 1077663b2..147a954be 100644 --- a/src/assistant/assistant/images/darkclosebutton.png +++ b/src/assistant/assistant/images/darkclosebutton.png diff --git a/src/assistant/assistant/stdinlistener.cpp b/src/assistant/assistant/stdinlistener.cpp index 13059c207..0a4241bce 100644 --- a/src/assistant/assistant/stdinlistener.cpp +++ b/src/assistant/assistant/stdinlistener.cpp @@ -35,6 +35,8 @@ #include "tracer.h" +#include <stdio.h> + QT_BEGIN_NAMESPACE StdInListener::StdInListener(QObject *parent) diff --git a/src/assistant/help/qhelpprojectdata.cpp b/src/assistant/help/qhelpprojectdata.cpp index f48fdea9b..fa084ff3c 100644 --- a/src/assistant/help/qhelpprojectdata.cpp +++ b/src/assistant/help/qhelpprojectdata.cpp @@ -275,13 +275,13 @@ void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern) { // The pattern matching is expensive, so we skip it if no // wildcard symbols occur in the string. - if (!pattern.contains('?') && !pattern.contains('*') - && !pattern.contains('[') && !pattern.contains(']')) { + if (!pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('*')) + && !pattern.contains(QLatin1Char('[')) && !pattern.contains(QLatin1Char(']'))) { filterSectionList.last().addFile(pattern); return; } - QFileInfo fileInfo(rootPath + '/' + pattern); + QFileInfo fileInfo(rootPath + QLatin1Char('/') + pattern); const QDir &dir = fileInfo.dir(); const QString &path = dir.canonicalPath(); @@ -303,7 +303,7 @@ void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern) if (regExp.exactMatch(file)) { matchFound = true; filterSectionList.last(). - addFile(QFileInfo(pattern).dir().path() + '/' + file); + addFile(QFileInfo(pattern).dir().path() + QLatin1Char('/') + file); } } if (!matchFound) diff --git a/src/assistant/help/qhelpsearchindexreader_clucene.cpp b/src/assistant/help/qhelpsearchindexreader_clucene.cpp index 18b128b01..a63128a88 100644 --- a/src/assistant/help/qhelpsearchindexreader_clucene.cpp +++ b/src/assistant/help/qhelpsearchindexreader_clucene.cpp @@ -270,8 +270,8 @@ bool QHelpSearchIndexReaderClucene::buildTryHarderQuery( bool QHelpSearchIndexReaderClucene::isNegativeQuery(const QHelpSearchQuery &query) const { - const QString &search = query.wordList.join(" "); - return search.contains('!') || search.contains('-') + const QString &search = query.wordList.join(QLatin1Char(' ')); + return search.contains(QLatin1Char('!')) || search.contains(QLatin1Char('-')) || search.contains(QLatin1String(" NOT ")); } diff --git a/src/assistant/help/qhelpsearchquerywidget.cpp b/src/assistant/help/qhelpsearchquerywidget.cpp index 46f6fdfbd..e0b481e58 100644 --- a/src/assistant/help/qhelpsearchquerywidget.cpp +++ b/src/assistant/help/qhelpsearchquerywidget.cpp @@ -212,7 +212,7 @@ private: queryHist.queries.append(query); foreach (const QHelpSearchQuery &queryPart, query) { static_cast<CompleterModel *>(searchCompleter.model())-> - addTerm(queryPart.wordList.join(" ")); + addTerm(queryPart.wordList.join(QLatin1Char(' '))); } } } @@ -241,7 +241,7 @@ private: queryHist->queries.at(queryHist->curQuery); foreach (const QHelpSearchQuery &queryPart, query) { if (QLineEdit *lineEdit = lineEditFor(queryPart.fieldName)) - lineEdit->setText(queryPart.wordList.join(" ")); + lineEdit->setText(queryPart.wordList.join(QLatin1Char(' '))); } if (queryHist->curQuery == maxOrMinIndex) diff --git a/src/designer/src/components/formeditor/formwindowmanager.cpp b/src/designer/src/components/formeditor/formwindowmanager.cpp index 386d09f8e..000c9d52f 100644 --- a/src/designer/src/components/formeditor/formwindowmanager.cpp +++ b/src/designer/src/components/formeditor/formwindowmanager.cpp @@ -363,7 +363,8 @@ QWidget *FormWindowManager::findManagedWidget(FormWindow *fw, QWidget *w) void FormWindowManager::setupActions() { #ifndef QT_NO_CLIPBOARD - m_actionCut = new QAction(createIconSet(QStringLiteral("editcut.png")), tr("Cu&t"), this); + const QIcon cutIcon = QIcon::fromTheme(QStringLiteral("edit-cut"), createIconSet(QStringLiteral("editcut.png"))); + m_actionCut = new QAction(cutIcon, tr("Cu&t"), this); m_actionCut->setObjectName(QStringLiteral("__qt_cut_action")); m_actionCut->setShortcut(QKeySequence::Cut); m_actionCut->setStatusTip(tr("Cuts the selected widgets and puts them on the clipboard")); @@ -371,7 +372,8 @@ void FormWindowManager::setupActions() connect(m_actionCut, &QAction::triggered, this, &FormWindowManager::slotActionCutActivated); m_actionCut->setEnabled(false); - m_actionCopy = new QAction(createIconSet(QStringLiteral("editcopy.png")), tr("&Copy"), this); + const QIcon copyIcon = QIcon::fromTheme(QStringLiteral("edit-copy"), createIconSet(QStringLiteral("editcopy.png"))); + m_actionCopy = new QAction(copyIcon, tr("&Copy"), this); m_actionCopy->setObjectName(QStringLiteral("__qt_copy_action")); m_actionCopy->setShortcut(QKeySequence::Copy); m_actionCopy->setStatusTip(tr("Copies the selected widgets to the clipboard")); @@ -379,7 +381,8 @@ void FormWindowManager::setupActions() connect(m_actionCopy, &QAction::triggered, this, &FormWindowManager::slotActionCopyActivated); m_actionCopy->setEnabled(false); - m_actionPaste = new QAction(createIconSet(QStringLiteral("editpaste.png")), tr("&Paste"), this); + const QIcon pasteIcon = QIcon::fromTheme(QStringLiteral("edit-paste"), createIconSet(QStringLiteral("editpaste.png"))); + m_actionPaste = new QAction(pasteIcon, tr("&Paste"), this); m_actionPaste->setObjectName(QStringLiteral("__qt_paste_action")); m_actionPaste->setShortcut(QKeySequence::Paste); m_actionPaste->setStatusTip(tr("Pastes the clipboard's contents")); @@ -388,7 +391,7 @@ void FormWindowManager::setupActions() m_actionPaste->setEnabled(false); #endif - m_actionDelete = new QAction(tr("&Delete"), this); + m_actionDelete = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("&Delete"), this); m_actionDelete->setObjectName(QStringLiteral("__qt_delete_action")); m_actionDelete->setStatusTip(tr("Deletes the selected widgets")); m_actionDelete->setWhatsThis(whatsThisFrom(QStringLiteral("Edit|Delete"))); @@ -523,24 +526,6 @@ void FormWindowManager::setupActions() connect(m_actionShowFormWindowSettingsDialog, &QAction::triggered, this, &FormWindowManager::slotActionShowFormWindowSettingsDialog); m_actionShowFormWindowSettingsDialog->setEnabled(false); - -#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) -#ifndef QT_NO_CLIPBOARD - m_actionCopy->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"), m_actionCopy->icon())); - m_actionCut->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut"), m_actionCut->icon())); - m_actionPaste->setIcon(QIcon::fromTheme(QStringLiteral("edit-paste"), m_actionPaste->icon())); -#endif - m_actionDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"), m_actionDelete->icon())); - - // These do not currently exist, but will allow theme authors to fill in the gaps - m_actionBreakLayout->setIcon(QIcon::fromTheme(QStringLiteral("designer-break-layout"), m_actionBreakLayout->icon())); - m_actionGridLayout->setIcon(QIcon::fromTheme(QStringLiteral("designer-grid-layout"), m_actionGridLayout->icon())); - m_actionHorizontalLayout->setIcon(QIcon::fromTheme(QStringLiteral("designer-horizontal-layout"), m_actionHorizontalLayout->icon())); - m_actionVerticalLayout->setIcon(QIcon::fromTheme(QStringLiteral("designer-vertical-layout"), m_actionVerticalLayout->icon())); - m_actionSplitHorizontal->setIcon(QIcon::fromTheme(QStringLiteral("designer-split-horizontal"), m_actionSplitHorizontal->icon())); - m_actionSplitVertical->setIcon(QIcon::fromTheme(QStringLiteral("designer-split-vertical"), m_actionSplitVertical->icon())); - m_actionAdjustSize->setIcon(QIcon::fromTheme(QStringLiteral("designer-adjust-size"), m_actionAdjustSize->icon())); -#endif } #ifndef QT_NO_CLIPBOARD diff --git a/src/designer/src/components/formeditor/images/cleartext.png b/src/designer/src/components/formeditor/images/cleartext.png Binary files differindex 74133baff..4c7bb13f3 100644 --- a/src/designer/src/components/formeditor/images/cleartext.png +++ b/src/designer/src/components/formeditor/images/cleartext.png diff --git a/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png b/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png Binary files differindex a48e974bf..cdfc086bb 100644 --- a/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png +++ b/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png diff --git a/src/designer/src/components/formeditor/images/righttoleft.png b/src/designer/src/components/formeditor/images/righttoleft.png Binary files differindex 26a69d5ba..759066479 100644 --- a/src/designer/src/components/formeditor/images/righttoleft.png +++ b/src/designer/src/components/formeditor/images/righttoleft.png diff --git a/src/linguist/lupdate/cpp.cpp b/src/linguist/lupdate/cpp.cpp index 0d5a7a8d9..37927c447 100644 --- a/src/linguist/lupdate/cpp.cpp +++ b/src/linguist/lupdate/cpp.cpp @@ -459,6 +459,7 @@ STRING(class); STRING(final); STRING(friend); STRING(namespace); +STRING(nullptr); STRING(operator); STRING(return); STRING(struct); @@ -698,6 +699,8 @@ CppParser::TokenType CppParser::getToken() case 'n': if (yyWord == strnamespace) return Tok_namespace; + if (yyWord == strnullptr) + return Tok_Null; break; case 'o': if (yyWord == stroperator) { diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp index eb88346dc..c68012d2f 100644 --- a/src/qdoc/cppcodemarker.cpp +++ b/src/qdoc/cppcodemarker.cpp @@ -161,10 +161,12 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).dataType(), true); - if (style != Subpage && !(*p).name().isEmpty()) - synopsis += - "<@param>" + protect((*p).name()) + "</@param>"; + bool hasName = !(*p).name().isEmpty(); + if (hasName) + synopsis += typified((*p).dataType(), true); + const QString ¶mName = hasName ? (*p).name() : (*p).dataType(); + if (style != Subpage || !hasName) + synopsis += "<@param>" + protect(paramName) + "</@param>"; synopsis += protect((*p).rightType()); if (style != Subpage && !(*p).defaultValue().isEmpty()) synopsis += " = " + protect((*p).defaultValue()); @@ -342,9 +344,11 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).dataType(), true); - if (!(*p).name().isEmpty()) - synopsis += "<@param>" + protect((*p).name()) + "</@param>"; + bool hasName = !(*p).name().isEmpty(); + if (hasName) + synopsis += typified((*p).dataType(), true); + const QString ¶mName = hasName ? (*p).name() : (*p).dataType(); + synopsis += "<@param>" + protect(paramName) + "</@param>"; synopsis += protect((*p).rightType()); ++p; } diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 0ea135cce..c1295c3a7 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -813,9 +813,11 @@ void CppCodeParser::processQmlProperties(const Doc& doc, bool attached = ((topic == COMMAND_QMLATTACHEDPROPERTY) || (topic == COMMAND_JSATTACHEDPROPERTY)); if (splitQmlPropertyArg(arg, type, module, qmlTypeName, property)) { - qmlType = qdb_->findQmlType(module, qmlTypeName); - if (qmlType) { - if (qmlType->hasQmlProperty(property, attached) != 0) { + Aggregate* aggregate = qdb_->findQmlType(module, qmlTypeName); + if (!aggregate) + aggregate = qdb_->findQmlBasicType(module, qmlTypeName); + if (aggregate) { + if (aggregate->hasQmlProperty(property, attached) != 0) { QString msg = tr("QML property documented multiple times: '%1'").arg(arg); doc.startLocation().warning(msg); } @@ -826,7 +828,7 @@ void CppCodeParser::processQmlProperties(const Doc& doc, qpn->setGenus(Node::JS); } else { - qpn = new QmlPropertyNode(qmlType, property, type, attached); + qpn = new QmlPropertyNode(aggregate, property, type, attached); qpn->setLocation(doc.startLocation()); if (jsProps) qpn->setGenus(Node::JS); @@ -1548,7 +1550,10 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent, VariableNode *var = new VariableNode(parent, name); var->setAccess(access); - var->setLocation(location()); + if (parsingHeaderFile_) + var->setLocation(declLoc()); + else + var->setLocation(location()); var->setLeftType(returnType.left()); var->setRightType(returnType.right()); if (matched_compat) @@ -1638,7 +1643,10 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent, if (matched_friend) access = Node::Public; func->setAccess(access); - func->setLocation(location()); + if (parsingHeaderFile_) + func->setLocation(declLoc()); + else + func->setLocation(location()); func->setReturnType(returnType.toString()); func->setParentPath(parentPath); func->setTemplateStuff(templateStuff); @@ -1790,7 +1798,7 @@ bool CppCodeParser::matchClassDecl(Aggregate *parent, */ ClassNode *classe = new ClassNode(parent, className); classe->setAccess(access); - classe->setLocation(location()); + classe->setLocation(declLoc()); if (compat) classe->setStatus(Node::Compat); if (!physicalModuleName.isEmpty()) @@ -1834,7 +1842,7 @@ bool CppCodeParser::matchNamespaceDecl(Aggregate *parent) if (!ns) { ns = new NamespaceNode(parent, namespaceName); ns->setAccess(access); - ns->setLocation(location()); + ns->setLocation(declLoc()); } readToken(); // skip '{' @@ -1997,7 +2005,7 @@ bool CppCodeParser::matchEnumDecl(Aggregate *parent) if (!name.isEmpty()) { enume = new EnumNode(parent, name); enume->setAccess(access); - enume->setLocation(location()); + enume->setLocation(declLoc()); } readToken(); @@ -2027,7 +2035,7 @@ bool CppCodeParser::matchTypedefDecl(Aggregate *parent) if (parent && !parent->findChildNode(name, Node::Typedef)) { TypedefNode* td = new TypedefNode(parent, name); td->setAccess(access); - td->setLocation(location()); + td->setLocation(declLoc()); } return true; } @@ -2056,7 +2064,7 @@ bool CppCodeParser::matchProperty(Aggregate *parent) PropertyNode *property = new PropertyNode(parent, name); property->setAccess(Node::Public); - property->setLocation(location()); + property->setLocation(declLoc()); property->setDataType(dataType.toString()); while (tok != Tok_RightParen && tok != Tok_Eoi) { @@ -2161,12 +2169,15 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) case Tok_class: case Tok_struct: case Tok_union: + setDeclLoc(); matchClassDecl(parent, templateStuff); break; case Tok_namespace: + setDeclLoc(); matchNamespaceDecl(parent); break; case Tok_using: + setDeclLoc(); matchUsingDecl(parent); break; case Tok_template: @@ -2178,9 +2189,11 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) } continue; case Tok_enum: + setDeclLoc(); matchEnumDecl(parent); break; case Tok_typedef: + setDeclLoc(); matchTypedefDecl(parent); break; case Tok_private: @@ -2216,6 +2229,7 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) case Tok_Q_PROPERTY: case Tok_Q_PRIVATE_PROPERTY: case Tok_QDOC_PROPERTY: + setDeclLoc(); if (!matchProperty(parent)) { location().warning(tr("Failed to parse token %1 in property declaration").arg(lexeme())); skipTo(Tok_RightParen); @@ -2248,13 +2262,14 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) break; case Tok_Q_DECLARE_FLAGS: readToken(); + setDeclLoc(); if (match(Tok_LeftParen) && match(Tok_Ident)) { QString flagsType = previousLexeme(); if (match(Tok_Comma) && match(Tok_Ident)) { QString name = previousLexeme(); TypedefNode *flagsNode = new TypedefNode(parent, flagsType); flagsNode->setAccess(access); - flagsNode->setLocation(location()); + flagsNode->setLocation(declLoc()); EnumNode* en = static_cast<EnumNode*>(parent->findChildNode(name, Node::Enum)); if (en) en->setFlagsType(flagsNode); @@ -2264,6 +2279,7 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) break; case Tok_QT_MODULE: readToken(); + setDeclLoc(); if (match(Tok_LeftParen) && match(Tok_Ident)) physicalModuleName = previousLexeme(); if (!physicalModuleName.startsWith("Qt")) @@ -2271,6 +2287,8 @@ bool CppCodeParser::matchDeclList(Aggregate *parent) match(Tok_RightParen); break; default: + if (parsingHeaderFile_) + setDeclLoc(); if (!matchFunctionDecl(parent, 0, 0, templateStuff, extra)) { while (tok != Tok_Eoi && (tokenizer->braceDepth() > braceDepth0 || diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h index 7c110d2bb..d3a5829e3 100644 --- a/src/qdoc/cppcodeparser.h +++ b/src/qdoc/cppcodeparser.h @@ -76,6 +76,8 @@ public: virtual void doneParsingHeaderFiles() Q_DECL_OVERRIDE; virtual void doneParsingSourceFiles() Q_DECL_OVERRIDE; bool parseParameters(const QString& parameters, QVector<Parameter>& pvect, bool& isQPrivateSignal); + const Location& declLoc() const { return declLoc_; } + void setDeclLoc() { declLoc_ = location(); } protected: const QSet<QString>& topicCommands(); @@ -163,6 +165,7 @@ protected: QStringList lastPath_; QRegExp varComment; QRegExp sep; + Location declLoc_; private: QString sequentialIteratorDefinition; diff --git a/src/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/qdoc/doc/qdoc-manual-markupcmds.qdoc index a8d5e6830..5c997e5b4 100644 --- a/src/qdoc/doc/qdoc-manual-markupcmds.qdoc +++ b/src/qdoc/doc/qdoc-manual-markupcmds.qdoc @@ -1934,7 +1934,7 @@ \c {\l [QML|CPP|DOC|QtModuleName] {link target} {link text}} \endlist - The \e {square bracket} argument is only allowed in the \c {\\l + The \e {square bracket} argument is only allowed in the \c {\l (link)} command. The example above shows how \c QML is used as the \e {square brackets} argument to force qdoc to match a QML target. Most often, this will be a QML type, but it can also be a QML diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp index 0765e8ab7..4286aa692 100644 --- a/src/qdoc/generator.cpp +++ b/src/qdoc/generator.cpp @@ -190,6 +190,41 @@ void Generator::appendFullNames(Text& text, const NodeList& nodes, const Node* r } } +/*! + Append the signature for the function named in \a node to + \a text, so that is is a link to the documentation for that + function. + */ +void Generator::appendSignature(Text& text, const Node* node) +{ + text << Atom(Atom::LinkNode, CodeMarker::stringForNode(node)) + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) + << Atom(Atom::String, node->signature(false, true)) + << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); +} + +/*! + Generate a bullet list of function signatures. The function + nodes are in \a nodes. It uses the \a relative node and the + \a marker for the generation. + */ +void Generator::signatureList(const NodeList& nodes, const Node* relative, CodeMarker* marker) +{ + Text text; + int count = 0; + text << Atom(Atom::ListLeft, QString("bullet")); + NodeList::ConstIterator n = nodes.constBegin(); + while (n != nodes.constEnd()) { + text << Atom(Atom::ListItemNumber, QString::number(++count)); + text << Atom(Atom::ListItemLeft, QString("bullet")); + appendSignature(text, *n); + text << Atom(Atom::ListItemRight, QString("bullet")); + ++n; + } + text << Atom(Atom::ListRight, QString("bullet")); + generateText(text, relative, marker); +} + int Generator::appendSortedNames(Text& text, const ClassNode* cn, const QList<RelatedClass>& rc) { QList<RelatedClass>::ConstIterator r; @@ -1392,24 +1427,83 @@ bool Generator::generateText(const Text& text, return result; } +/* + The node is an aggregate, typically a class node, which has + a threadsafeness level. This function checks all the children + of the node to see if they are exceptions to the node's + threadsafeness. If there are any exceptions, the exceptions + are added to the appropriate set (reentrant, threadsafe, and + nonreentrant, and true is returned. If there are no exceptions, + the three node lists remain empty and false is returned. + */ +static bool hasExceptions(const Node* node, + NodeList& reentrant, + NodeList& threadsafe, + NodeList& nonreentrant) +{ + bool result = false; + Node::ThreadSafeness ts = node->threadSafeness(); + const Aggregate* a = static_cast<const Aggregate*>(node); + NodeList::ConstIterator c = a->childNodes().constBegin(); + while (c != a->childNodes().constEnd()) { + if (!(*c)->isObsolete()){ + switch ((*c)->threadSafeness()) { + case Node::Reentrant: + reentrant.append(*c); + if (ts == Node::ThreadSafe) + result = true; + break; + case Node::ThreadSafe: + threadsafe.append(*c); + if (ts == Node::Reentrant) + result = true; + break; + case Node::NonReentrant: + nonreentrant.append(*c); + result = true; + break; + default: + break; + } + } + ++c; + } + return result; +} + +static void startNote(Text& text) +{ + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) + << "Note:" + << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) + << " "; +} + +/*! + Generates text that explains how threadsafe and/or reentrant + \a node is. + */ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker) { - Text text; - Node::ThreadSafeness threadSafeness = node->threadSafeness(); + Text text, rlink, tlink; + NodeList reentrant; + NodeList threadsafe; + NodeList nonreentrant; + Node::ThreadSafeness ts = node->threadSafeness(); + bool exceptions = false; - Text rlink; rlink << Atom(Atom::Link,"reentrant") << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << "reentrant" << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - Text tlink; tlink << Atom(Atom::Link,"thread-safe") << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << "thread-safe" << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - switch (threadSafeness) { + switch (ts) { case Node::UnspecifiedSafeness: break; case Node::NonReentrant: @@ -1426,110 +1520,76 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker) break; case Node::Reentrant: case Node::ThreadSafe: - text << Atom::ParaLeft - << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) - << "Note:" - << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD) - << " "; - + startNote(text); if (node->isAggregate()) { - const Aggregate* innerNode = static_cast<const Aggregate*>(node); - text << "All functions in this " - << typeString(node) - << " are "; - if (threadSafeness == Node::ThreadSafe) + exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant); + text << "All functions in this " << typeString(node) << " are "; + if (ts == Node::ThreadSafe) text << tlink; else text << rlink; - bool exceptions = false; - NodeList reentrant; - NodeList threadsafe; - NodeList nonreentrant; - NodeList::ConstIterator c = innerNode->childNodes().constBegin(); - while (c != innerNode->childNodes().constEnd()) { - - if ((*c)->status() != Node::Obsolete){ - switch ((*c)->threadSafeness()) { - case Node::Reentrant: - reentrant.append(*c); - if (threadSafeness == Node::ThreadSafe) - exceptions = true; - break; - case Node::ThreadSafe: - threadsafe.append(*c); - if (threadSafeness == Node::Reentrant) - exceptions = true; - break; - case Node::NonReentrant: - nonreentrant.append(*c); - exceptions = true; - break; - default: - break; - } - } - ++c; - } - if (!exceptions) + if (!exceptions || (ts == Node::Reentrant && !threadsafe.isEmpty())) text << "."; - else if (threadSafeness == Node::Reentrant) { - if (nonreentrant.isEmpty()) { - if (!threadsafe.isEmpty()) { - text << ", but "; - appendFullNames(text,threadsafe,innerNode); - singularPlural(text,threadsafe); - text << " also " << tlink << "."; - } - else - text << "."; - } - else { - text << ", except for "; - appendFullNames(text,nonreentrant,innerNode); - text << ", which"; - singularPlural(text,nonreentrant); - text << " nonreentrant."; - if (!threadsafe.isEmpty()) { - text << " "; - appendFullNames(text,threadsafe,innerNode); - singularPlural(text,threadsafe); - text << " " << tlink << "."; - } - } - } - else { // thread-safe - if (!nonreentrant.isEmpty() || !reentrant.isEmpty()) { - text << ", except for "; - if (!reentrant.isEmpty()) { - appendFullNames(text,reentrant,innerNode); - text << ", which"; - singularPlural(text,reentrant); - text << " only " << rlink; - if (!nonreentrant.isEmpty()) - text << ", and "; - } - if (!nonreentrant.isEmpty()) { - appendFullNames(text,nonreentrant,innerNode); - text << ", which"; - singularPlural(text,nonreentrant); - text << " nonreentrant."; - } - text << "."; - } - } + else + text << " with the following exceptions:"; } else { text << "This " << typeString(node) << " is "; - if (threadSafeness == Node::ThreadSafe) + if (ts == Node::ThreadSafe) text << tlink; else text << rlink; - text << "."; } text << Atom::ParaRight; + break; + default: + break; } generateText(text,node,marker); + + if (exceptions) { + text.clear(); + if (ts == Node::Reentrant) { + if (!nonreentrant.isEmpty()) { + startNote(text); + text << "These functions are not " + << rlink + << ":" + << Atom::ParaRight; + signatureList(nonreentrant, node, marker); + } + if (!threadsafe.isEmpty()) { + text.clear(); + startNote(text); + text << "These functions are also " + << tlink + << ":" + << Atom::ParaRight; + generateText(text, node, marker); + signatureList(threadsafe, node, marker); + } + } + else { // thread-safe + if (!reentrant.isEmpty()) { + startNote(text); + text << "These functions are only " + << rlink + << ":" + << Atom::ParaRight; + signatureList(reentrant, node, marker); + } + if (!nonreentrant.isEmpty()) { + text.clear(); + startNote(text); + text << "These functions are not " + << rlink + << ":" + << Atom::ParaRight; + signatureList(nonreentrant, node, marker); + } + } + } } /*! diff --git a/src/qdoc/generator.h b/src/qdoc/generator.h index c0adc1468..5b301f9f1 100644 --- a/src/qdoc/generator.h +++ b/src/qdoc/generator.h @@ -200,6 +200,8 @@ protected: const Node *actualNode); void appendFullNames(Text& text, const NodeList& nodes, const Node* relative); int appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes); + void appendSignature(Text& text, const Node* node); + void signatureList(const NodeList& nodes, const Node* relative, CodeMarker* marker); private: static Generator* currentGenerator_; diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index 0702f0a9b..02384c962 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -1383,7 +1383,6 @@ void HtmlGenerator::generateClassLikeNode(Aggregate* inner, CodeMarker* marker) generateBrief(inner, marker); generateRequisites(inner, marker); generateStatus(inner, marker); - generateThreadSafeness(inner, marker); out() << "<ul>\n"; @@ -1408,6 +1407,7 @@ void HtmlGenerator::generateClassLikeNode(Aggregate* inner, CodeMarker* marker) << "Compatibility members</a></li>\n"; out() << "</ul>\n"; + generateThreadSafeness(inner, marker); bool needOtherSection = false; @@ -2016,10 +2016,12 @@ void HtmlGenerator::generateHeader(const QString& title, out() << " <title>" << protectEnc(title) << divider - << titleSuffix - << QLatin1Char(' ') - << shortVersion - << "</title>\n"; + << titleSuffix; + + if (!shortVersion.isEmpty()) + out() << QLatin1Char(' ') << shortVersion; + + out() << "</title>\n"; // Include style sheet and script links. out() << headerStyles; diff --git a/src/qdoc/jscodemarker.cpp b/src/qdoc/jscodemarker.cpp index 669040da0..496eb8c30 100644 --- a/src/qdoc/jscodemarker.cpp +++ b/src/qdoc/jscodemarker.cpp @@ -44,10 +44,12 @@ #include "tree.h" #include "generator.h" +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsast_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> +#endif QT_BEGIN_NAMESPACE @@ -64,6 +66,7 @@ JsCodeMarker::~JsCodeMarker() */ bool JsCodeMarker::recognizeCode(const QString &code) { +#ifndef QT_NO_DECLARATIVE QQmlJS::Engine engine; QQmlJS::Lexer lexer(&engine); QQmlJS::Parser parser(&engine); @@ -73,6 +76,9 @@ bool JsCodeMarker::recognizeCode(const QString &code) lexer.setCode(newCode, 1); return parser.parseProgram(); +#else + return false; +#endif } /*! @@ -112,6 +118,7 @@ QString JsCodeMarker::addMarkUp(const QString &code, const Node * /* relative */, const Location &location) { +#ifndef QT_NO_DECLARATIVE QQmlJS::Engine engine; QQmlJS::Lexer lexer(&engine); @@ -137,6 +144,10 @@ QString JsCodeMarker::addMarkUp(const QString &code, output = protect(code); } return output; +#else + location.warning("QtDeclarative not installed; cannot parse QML or JS."); + return QString(); +#endif } QT_END_NAMESPACE diff --git a/src/qdoc/node.h b/src/qdoc/node.h index e76d940f9..870a55cdf 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -952,7 +952,7 @@ public: bool hasActiveAssociatedProperty() const; QStringList reconstructParameters(bool values = false) const; - virtual QString signature(bool values, bool noReturnType = false) const; + virtual QString signature(bool values, bool noReturnType = false) const Q_DECL_OVERRIDE; virtual QString element() const Q_DECL_OVERRIDE { return parent()->name(); } virtual bool isAttached() const Q_DECL_OVERRIDE { return attached_; } virtual bool isQtQuickNode() const Q_DECL_OVERRIDE { return parent()->isQtQuickNode(); } diff --git a/src/qdoc/qdoc.pro b/src/qdoc/qdoc.pro index 6333a046e..52b40bccb 100644 --- a/src/qdoc/qdoc.pro +++ b/src/qdoc/qdoc.pro @@ -4,7 +4,12 @@ } option(host_build) -QT = core qmldevtools-private +QT = core +qtHaveModule(qmldevtools-private) { + QT += qmldevtools-private +} else { + DEFINES += QT_NO_DECLARATIVE +} DEFINES += \ QDOC2_COMPAT diff --git a/src/qdoc/qmlcodemarker.cpp b/src/qdoc/qmlcodemarker.cpp index 089e1d1c8..3b76f87da 100644 --- a/src/qdoc/qmlcodemarker.cpp +++ b/src/qdoc/qmlcodemarker.cpp @@ -44,11 +44,13 @@ #include "tree.h" #include "generator.h" +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsast_p.h> #include <private/qqmljsastfwd_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> +#endif QT_BEGIN_NAMESPACE @@ -65,6 +67,7 @@ QmlCodeMarker::~QmlCodeMarker() */ bool QmlCodeMarker::recognizeCode(const QString &code) { +#ifndef QT_NO_DECLARATIVE QQmlJS::Engine engine; QQmlJS::Lexer lexer(&engine); QQmlJS::Parser parser(&engine); @@ -74,6 +77,9 @@ bool QmlCodeMarker::recognizeCode(const QString &code) lexer.setCode(newCode, 1); return parser.parse(); +#else + return false; +#endif } /*! @@ -163,6 +169,7 @@ QString QmlCodeMarker::addMarkUp(const QString &code, const Node * /* relative */, const Location &location) { +#ifndef QT_NO_DECLARATIVE QQmlJS::Engine engine; QQmlJS::Lexer lexer(&engine); @@ -188,8 +195,13 @@ QString QmlCodeMarker::addMarkUp(const QString &code, } return output; +#else + location.warning("QtDeclarative not installed; cannot parse QML or JS."); + return QString(); +#endif } +#ifndef QT_NO_DECLARATIVE /* Copied and pasted from src/declarative/qml/qqmlscriptparser.cpp. @@ -270,5 +282,6 @@ QList<QQmlJS::AST::SourceLocation> QmlCodeMarker::extractPragmas(QString &script } return removed; } +#endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlcodemarker.h b/src/qdoc/qmlcodemarker.h index 96353ebe5..0090350e7 100644 --- a/src/qdoc/qmlcodemarker.h +++ b/src/qdoc/qmlcodemarker.h @@ -40,7 +40,9 @@ #include "cppcodemarker.h" +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsastfwd_p.h> +#endif QT_BEGIN_NAMESPACE @@ -67,7 +69,9 @@ public: virtual QString functionEndRegExp(const QString &funcName) Q_DECL_OVERRIDE; /* Copied from src/declarative/qml/qdeclarativescriptparser.cpp */ +#ifndef QT_NO_DECLARATIVE QList<QQmlJS::AST::SourceLocation> extractPragmas(QString &script); +#endif private: QString addMarkUp(const QString &code, const Node *relative, diff --git a/src/qdoc/qmlcodeparser.cpp b/src/qdoc/qmlcodeparser.cpp index e94df4753..58be80d01 100644 --- a/src/qdoc/qmlcodeparser.cpp +++ b/src/qdoc/qmlcodeparser.cpp @@ -41,8 +41,10 @@ #include "config.h" #include "qmlvisitor.h" +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsast_p.h> #include <private/qqmljsastvisitor_p.h> +#endif #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -97,8 +99,10 @@ QT_BEGIN_NAMESPACE Constructs the QML code parser. */ QmlCodeParser::QmlCodeParser() +#ifndef QT_NO_DECLARATIVE : lexer( 0 ), parser( 0 ) +#endif { } @@ -119,8 +123,10 @@ void QmlCodeParser::initializeParser(const Config &config) { CodeParser::initializeParser(config); +#ifndef QT_NO_DECLARATIVE lexer = new QQmlJS::Lexer(&engine); parser = new QQmlJS::Parser(&engine); +#endif } /*! @@ -129,8 +135,10 @@ void QmlCodeParser::initializeParser(const Config &config) */ void QmlCodeParser::terminateParser() { +#ifndef QT_NO_DECLARATIVE delete lexer; delete parser; +#endif } /*! @@ -167,6 +175,7 @@ void QmlCodeParser::parseSourceFile(const Location& location, const QString& fil return; } +#ifndef QT_NO_DECLARATIVE QString document = in.readAll(); in.close(); @@ -195,6 +204,9 @@ void QmlCodeParser::parseSourceFile(const Location& location, const QString& fil << ": " << qPrintable(msg.message); } currentFile_.clear(); +#else + location.warning("QtDeclarative not installed; cannot parse QML or JS."); +#endif } /*! @@ -265,6 +277,7 @@ const QSet<QString>& QmlCodeParser::otherMetaCommands() return otherMetaCommands_; } +#ifndef QT_NO_DECLARATIVE /*! Copy and paste from src/declarative/qml/qdeclarativescriptparser.cpp. This function blanks out the section of the \a str beginning at \a idx @@ -329,5 +342,6 @@ void QmlCodeParser::extractPragmas(QString &script) } return; } +#endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlcodeparser.h b/src/qdoc/qmlcodeparser.h index 8b5667532..f483b7382 100644 --- a/src/qdoc/qmlcodeparser.h +++ b/src/qdoc/qmlcodeparser.h @@ -41,9 +41,11 @@ #include "codeparser.h" #include <qset.h> +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> +#endif QT_BEGIN_NAMESPACE @@ -66,17 +68,21 @@ public: virtual void parseSourceFile(const Location& location, const QString& filePath) Q_DECL_OVERRIDE; virtual void doneParsingSourceFiles() Q_DECL_OVERRIDE; +#ifndef QT_NO_DECLARATIVE /* Copied from src/declarative/qml/qdeclarativescriptparser.cpp */ void extractPragmas(QString &script); +#endif protected: const QSet<QString>& topicCommands(); const QSet<QString>& otherMetaCommands(); private: +#ifndef QT_NO_DECLARATIVE QQmlJS::Engine engine; QQmlJS::Lexer *lexer; QQmlJS::Parser *parser; +#endif }; QT_END_NAMESPACE diff --git a/src/qdoc/qmlmarkupvisitor.cpp b/src/qdoc/qmlmarkupvisitor.cpp index 17dd99325..122c23040 100644 --- a/src/qdoc/qmlmarkupvisitor.cpp +++ b/src/qdoc/qmlmarkupvisitor.cpp @@ -35,12 +35,15 @@ #include <qstringlist.h> #include <qglobal.h> +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsast_p.h> #include <private/qqmljsastfwd_p.h> #include <private/qqmljsengine_p.h> +#endif QT_BEGIN_NAMESPACE +#ifndef QT_NO_DECLARATIVE QmlMarkupVisitor::QmlMarkupVisitor(const QString &source, const QList<QQmlJS::AST::SourceLocation> &pragmas, QQmlJS::Engine *engine) @@ -840,5 +843,6 @@ bool QmlMarkupVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition) QQmlJS::AST::Node::accept(definition->initializer, this); return false; } +#endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlmarkupvisitor.h b/src/qdoc/qmlmarkupvisitor.h index ab1180fd4..63d6f1bf4 100644 --- a/src/qdoc/qmlmarkupvisitor.h +++ b/src/qdoc/qmlmarkupvisitor.h @@ -38,11 +38,14 @@ #include "tree.h" #include <qstring.h> +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsastvisitor_p.h> #include <private/qqmljsengine_p.h> +#endif QT_BEGIN_NAMESPACE +#ifndef QT_NO_DECLARATIVE class QmlMarkupVisitor : public QQmlJS::AST::Visitor { public: @@ -167,6 +170,7 @@ private: int extraIndex; }; Q_DECLARE_TYPEINFO(QmlMarkupVisitor::ExtraType, Q_PRIMITIVE_TYPE); +#endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlvisitor.cpp b/src/qdoc/qmlvisitor.cpp index 654922929..3fee46932 100644 --- a/src/qdoc/qmlvisitor.cpp +++ b/src/qdoc/qmlvisitor.cpp @@ -42,9 +42,11 @@ #include <qstringlist.h> #include <qglobal.h> #include <qdebug.h> +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsast_p.h> #include <private/qqmljsastfwd_p.h> #include <private/qqmljsengine_p.h> +#endif QT_BEGIN_NAMESPACE @@ -89,6 +91,7 @@ QT_BEGIN_NAMESPACE #define COMMAND_JSATTACHEDMETHOD Doc::alias(QLatin1String("jsattachedmethod")) #define COMMAND_JSBASICTYPE Doc::alias(QLatin1String("jsbasictype")) +#ifndef QT_NO_DECLARATIVE /*! The constructor stores all the parameters in local data members. */ @@ -823,5 +826,6 @@ void QmlDocVisitor::endVisit(QQmlJS::AST::UiQualifiedId* ) { // nothing. } +#endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlvisitor.h b/src/qdoc/qmlvisitor.h index 8a23eef75..bc7a3c003 100644 --- a/src/qdoc/qmlvisitor.h +++ b/src/qdoc/qmlvisitor.h @@ -37,8 +37,10 @@ #include "node.h" #include <qstring.h> +#ifndef QT_NO_DECLARATIVE #include <private/qqmljsastvisitor_p.h> #include <private/qqmljsengine_p.h> +#endif QT_BEGIN_NAMESPACE @@ -57,6 +59,7 @@ struct QmlPropArgs } }; +#ifndef QT_NO_DECLARATIVE class QmlDocVisitor : public QQmlJS::AST::Visitor { Q_DECLARE_TR_FUNCTIONS(QDoc::QmlDocVisitor) @@ -115,6 +118,7 @@ private: QSet<quint32> usedComments; Aggregate *current; }; +#endif QT_END_NAMESPACE diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp index 64f39619d..a29b38bbd 100644 --- a/src/windeployqt/utils.cpp +++ b/src/windeployqt/utils.cpp @@ -45,7 +45,7 @@ #include <QtCore/QStandardPaths> #if defined(Q_OS_WIN) # include <QtCore/qt_windows.h> -# include <Shlwapi.h> +# include <shlwapi.h> # include <delayimp.h> #else // Q_OS_WIN # include <sys/wait.h> diff --git a/src/windeployqt/windeployqt.pro b/src/windeployqt/windeployqt.pro index ef5534a67..4ea703948 100644 --- a/src/windeployqt/windeployqt.pro +++ b/src/windeployqt/windeployqt.pro @@ -7,6 +7,6 @@ HEADERS += utils.h qmlutils.h elfreader.h CONFIG += force_bootstrap -win32: LIBS += -lShlwapi +win32: LIBS += -lshlwapi load(qt_tool) diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp index f4ac1e214..d58ddf9fb 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp @@ -488,3 +488,22 @@ class TernaryClass : public QObject tr("ternary, ddd, false"); } }; + + + +// QTBUG-47467: lupdate confused by nullptr in case of plural forms +void nullptrInPlural() +{ + QObject::tr("%n nullptr(s)", nullptr, 3); + QCoreApplication::translate("Plurals, nullptr", "%n car(s)", nullptr, QCoreApplication::UnicodeUTF8, 1); +} + +class nullptrClass : public QObject +{ + Q_OBJECT + + void f() + { + tr("%n car(s)", nullptr, 2); + } +}; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result index b847f8f89..be9df15ca 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result @@ -235,6 +235,16 @@ backslashed \ stuff.</source> </message> </context> <context> + <name>Plurals, nullptr</name> + <message numerus="yes"> + <location filename="main.cpp" line="498"/> + <source>%n car(s)</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> +</context> +<context> <name>QApplication</name> <message> <location filename="main.cpp" line="43"/> @@ -302,6 +312,13 @@ backslashed \ stuff.</source> <extracomment>comment, bbb, false</extracomment> <translation type="unfinished"></translation> </message> + <message numerus="yes"> + <location filename="main.cpp" line="497"/> + <source>%n nullptr(s)</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> <message> <location filename="included.cpp" line="34"/> <source>message from #included .cpp file</source> @@ -456,6 +473,16 @@ backslashed \ stuff.</source> </message> </context> <context> + <name>nullptrClass</name> + <message numerus="yes"> + <location filename="main.cpp" line="507"/> + <source>%n car(s)</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> +</context> +<context> <name>scope</name> <message numerus="yes"> <location filename="main.cpp" line="179"/> |