diff options
Diffstat (limited to 'tools')
157 files changed, 4847 insertions, 1810 deletions
diff --git a/tools/activeqt/dumpcpp/main.cpp b/tools/activeqt/dumpcpp/main.cpp index 0a4aa06..de3ec57 100644 --- a/tools/activeqt/dumpcpp/main.cpp +++ b/tools/activeqt/dumpcpp/main.cpp @@ -969,7 +969,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O QString libName; BSTR nameString; typelib->GetDocumentation(-1, &nameString, 0, 0, 0); - libName = QString::fromUtf16((const ushort *)nameString); + libName = QString::fromWCharArray(nameString); SysFreeString(nameString); if (!nameSpace.isEmpty()) libName = QString(nameSpace); @@ -1086,7 +1086,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O BSTR bstr; if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0)) break; - className = QString::fromUtf16((const ushort *)bstr).toLatin1(); + className = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); switch (typekind) { case TKIND_RECORD: @@ -1227,7 +1227,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O BSTR bstr; if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0)) break; - className = QString::fromUtf16((const ushort *)bstr).toLatin1(); + className = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); declOut << "// stub for vtable-only interface" << endl; diff --git a/tools/assistant/lib/lib.pro b/tools/assistant/lib/lib.pro index bd9ed53..5d6d436 100644 --- a/tools/assistant/lib/lib.pro +++ b/tools/assistant/lib/lib.pro @@ -1,65 +1,71 @@ -QT += sql xml network +QT += sql \ + xml \ + network TEMPLATE = lib TARGET = QtHelp -DEFINES += QHELP_LIB QT_CLUCENE_SUPPORT -CONFIG += qt warn_on - +DEFINES += QHELP_LIB \ + QT_CLUCENE_SUPPORT +CONFIG += qt \ + warn_on include(../../../src/qbase.pri) - QMAKE_TARGET_PRODUCT = Help -QMAKE_TARGET_DESCRIPTION = Help application framework. +QMAKE_TARGET_DESCRIPTION = Help \ + application \ + framework. DEFINES -= QT_ASCII_CAST_WARNINGS - qclucene = QtCLucene$${QT_LIBINFIX} -if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { +if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { mac:qclucene = $${qclucene}_debug win32:qclucene = $${qclucene}d } linux-lsb-g++:LIBS += --lsb-shared-libs=$$qclucene -unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork QtSql QtXml +unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork \ + QtSql \ + QtXml LIBS += -l$$qclucene -unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork QtSql QtXml - +unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork \ + QtSql \ + QtXml RESOURCES += helpsystem.qrc - SOURCES += qhelpenginecore.cpp \ - qhelpengine.cpp \ - qhelpdbreader.cpp \ - qhelpcontentwidget.cpp \ - qhelpindexwidget.cpp \ - qhelpgenerator.cpp \ - qhelpdatainterface.cpp \ - qhelpprojectdata.cpp \ - qhelpcollectionhandler.cpp \ - qhelpsearchengine.cpp \ - qhelpsearchquerywidget.cpp \ - qhelpsearchresultwidget.cpp \ - qhelpsearchindex_default.cpp \ - qhelpsearchindexwriter_default.cpp \ - qhelpsearchindexreader_default.cpp + qhelpengine.cpp \ + qhelpdbreader.cpp \ + qhelpcontentwidget.cpp \ + qhelpindexwidget.cpp \ + qhelpgenerator.cpp \ + qhelpdatainterface.cpp \ + qhelpprojectdata.cpp \ + qhelpcollectionhandler.cpp \ + qhelpsearchengine.cpp \ + qhelpsearchquerywidget.cpp \ + qhelpsearchresultwidget.cpp \ + qhelpsearchindex_default.cpp \ + qhelpsearchindexwriter_default.cpp \ + qhelpsearchindexreader_default.cpp \ + qhelpsearchindexreader.cpp # access to clucene SOURCES += qhelpsearchindexwriter_clucene.cpp \ - qhelpsearchindexreader_clucene.cpp - + qhelpsearchindexreader_clucene.cpp HEADERS += qhelpenginecore.h \ - qhelpengine.h \ - qhelpengine_p.h \ - qhelp_global.h \ - qhelpdbreader_p.h \ - qhelpcontentwidget.h \ - qhelpindexwidget.h \ - qhelpgenerator_p.h \ - qhelpdatainterface_p.h \ - qhelpprojectdata_p.h \ - qhelpcollectionhandler_p.h \ - qhelpsearchengine.h \ - qhelpsearchquerywidget.h \ - qhelpsearchresultwidget.h \ - qhelpsearchindex_default_p.h \ - qhelpsearchindexwriter_default_p.h \ - qhelpsearchindexreader_default_p.h + qhelpengine.h \ + qhelpengine_p.h \ + qhelp_global.h \ + qhelpdbreader_p.h \ + qhelpcontentwidget.h \ + qhelpindexwidget.h \ + qhelpgenerator_p.h \ + qhelpdatainterface_p.h \ + qhelpprojectdata_p.h \ + qhelpcollectionhandler_p.h \ + qhelpsearchengine.h \ + qhelpsearchquerywidget.h \ + qhelpsearchresultwidget.h \ + qhelpsearchindex_default_p.h \ + qhelpsearchindexwriter_default_p.h \ + qhelpsearchindexreader_default_p.h \ + qhelpsearchindexreader_p.h # access to clucene HEADERS += qhelpsearchindexwriter_clucene_p.h \ - qhelpsearchindexreader_clucene_p.h + qhelpsearchindexreader_clucene_p.h diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp index 8947a36..9412f1c 100644 --- a/tools/assistant/lib/qhelpprojectdata.cpp +++ b/tools/assistant/lib/qhelpprojectdata.cpp @@ -41,9 +41,11 @@ #include "qhelpprojectdata_p.h" +#include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QStack> #include <QtCore/QMap> +#include <QtCore/QRegExp> #include <QtCore/QVariant> #include <QtXml/QXmlStreamReader> @@ -73,6 +75,9 @@ private: void readKeywords(); void readFiles(); void raiseUnknownTokenError(); + void addMatchingFiles(const QString &pattern); + + QMap<QString, QStringList> dirEntriesCache; }; void QHelpProjectDataPrivate::raiseUnknownTokenError() @@ -161,7 +166,7 @@ void QHelpProjectDataPrivate::readFilterSection() readNext(); if (isStartElement()) { if (name() == QLatin1String("filterAttribute")) - filterSectionList.last().addFilterAttribute(readElementText()); + filterSectionList.last().addFilterAttribute(readElementText()); else if (name() == QLatin1String("toc")) readTOC(); else if (name() == QLatin1String("keywords")) @@ -244,7 +249,7 @@ void QHelpProjectDataPrivate::readFiles() readNext(); if (isStartElement()) { if (name() == QLatin1String("file")) - filterSectionList.last().addFile(readElementText()); + addMatchingFiles(readElementText()); else raiseUnknownTokenError(); } else if (isEndElement()) { @@ -258,7 +263,47 @@ void QHelpProjectDataPrivate::readFiles() } } +// Expand file pattern and add matches into list. If the pattern does not match +// any files, insert the pattern itself so the QHelpGenerator will emit a +// meaningful warning later. +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(']')) { + filterSectionList.last().addFile(pattern); + return; + } + QFileInfo fileInfo(rootPath + '/' + pattern); + const QDir &dir = fileInfo.dir(); + const QString &path = dir.canonicalPath(); + + // QDir::entryList() is expensive, so we cache the results. + QMap<QString, QStringList>::ConstIterator it = dirEntriesCache.find(path); + const QStringList &entries = it != dirEntriesCache.constEnd() ? + it.value() : dir.entryList(QDir::Files); + if (it == dirEntriesCache.constEnd()) + dirEntriesCache.insert(path, entries); + + bool matchFound = false; +#ifdef Q_OS_WIN + Qt::CaseSensitivity cs = Qt::CaseInsensitive; +#else + Qt::CaseSensitivity cs = Qt::CaseSensitive; +#endif + QRegExp regExp(fileInfo.fileName(), cs, QRegExp::Wildcard); + foreach (const QString &file, entries) { + if (regExp.exactMatch(file)) { + matchFound = true; + filterSectionList.last(). + addFile(QFileInfo(pattern).dir().path() + '/' + file); + } + } + if (!matchFound) + filterSectionList.last().addFile(pattern); +} /*! \internal diff --git a/tools/assistant/lib/qhelpsearchengine.cpp b/tools/assistant/lib/qhelpsearchengine.cpp index 2a41d04..94c5f7e 100644 --- a/tools/assistant/lib/qhelpsearchengine.cpp +++ b/tools/assistant/lib/qhelpsearchengine.cpp @@ -44,6 +44,7 @@ #include "qhelpsearchquerywidget.h" #include "qhelpsearchresultwidget.h" +#include "qhelpsearchindexreader_p.h" #if defined(QT_CLUCENE_SUPPORT) # include "qhelpsearchindexreader_clucene_p.h" # include "qhelpsearchindexwriter_clucene_p.h" @@ -147,8 +148,11 @@ private: return; if (!indexReader) { - indexReader = new QHelpSearchIndexReader(); - +#if defined(QT_CLUCENE_SUPPORT) + indexReader = new QHelpSearchIndexReaderClucene(); +#else + indexReader = new QHelpSearchIndexReaderDefault(); +#endif // QT_CLUCENE_SUPPORT connect(indexReader, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted())); connect(indexReader, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int))); } @@ -181,7 +185,7 @@ private slots: { #if defined(QT_CLUCENE_SUPPORT) if (indexWriter && !helpEngine.isNull()) { - indexWriter->optimizeIndex(); + indexWriter->optimizeIndex(); } #endif } @@ -192,7 +196,7 @@ private: QHelpSearchQueryWidget *queryWidget; QHelpSearchResultWidget *resultWidget; - QHelpSearchIndexReader *indexReader; + qt::fulltextsearch::QHelpSearchIndexReader *indexReader; QHelpSearchIndexWriter *indexWriter; QPointer<QHelpEngineCore> helpEngine; @@ -321,7 +325,7 @@ QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *paren : QObject(parent) { d = new QHelpSearchEnginePrivate(helpEngine); - + connect(helpEngine, SIGNAL(setupFinished()), this, SLOT(indexDocumentation())); connect(d, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted())); diff --git a/tools/assistant/lib/qhelpsearchindexreader.cpp b/tools/assistant/lib/qhelpsearchindexreader.cpp new file mode 100644 index 0000000..a0fcbe5 --- /dev/null +++ b/tools/assistant/lib/qhelpsearchindexreader.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchindexreader_p.h" + +QT_BEGIN_NAMESPACE + +namespace qt { + namespace fulltextsearch { + +QHelpSearchIndexReader::QHelpSearchIndexReader() + : QThread() + , m_cancel(false) +{ + // nothing todo +} + +QHelpSearchIndexReader::~QHelpSearchIndexReader() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); + + wait(); +} + +void QHelpSearchIndexReader::cancelSearching() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); +} + +void QHelpSearchIndexReader::search(const QString &collectionFile, const QString &indexFilesFolder, + const QList<QHelpSearchQuery> &queryList) +{ + wait(); + + this->hitList.clear(); + this->m_cancel = false; + this->m_query = queryList; + this->m_collectionFile = collectionFile; + this->m_indexFilesFolder = indexFilesFolder; + + start(QThread::NormalPriority); +} + +int QHelpSearchIndexReader::hitsCount() const +{ + QMutexLocker lock(&mutex); + return hitList.count(); +} + +QList<QHelpSearchEngine::SearchHit> QHelpSearchIndexReader::hits(int start, + int end) const +{ + QList<QHelpSearchEngine::SearchHit> hits; + QMutexLocker lock(&mutex); + for (int i = start; i < end && i < hitList.count(); ++i) + hits.append(hitList.at(i)); + return hits; +} + + + } // namespace fulltextsearch +} // namespace qt + +QT_END_NAMESPACE diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp index 89d6040..b417078 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp @@ -59,60 +59,18 @@ namespace qt { namespace fulltextsearch { namespace clucene { -QHelpSearchIndexReader::QHelpSearchIndexReader() - : QThread() - , m_cancel(false) +QHelpSearchIndexReaderClucene::QHelpSearchIndexReaderClucene() + : QHelpSearchIndexReader() { // nothing todo } -QHelpSearchIndexReader::~QHelpSearchIndexReader() +QHelpSearchIndexReaderClucene::~QHelpSearchIndexReaderClucene() { - mutex.lock(); - this->m_cancel = true; - mutex.unlock(); - - wait(); } -void QHelpSearchIndexReader::cancelSearching() -{ - mutex.lock(); - this->m_cancel = true; - mutex.unlock(); -} -void QHelpSearchIndexReader::search(const QString &collectionFile, const QString &indexFilesFolder, - const QList<QHelpSearchQuery> &queryList) -{ - wait(); - - this->hitList.clear(); - this->m_cancel = false; - this->m_query = queryList; - this->m_collectionFile = collectionFile; - this->m_indexFilesFolder = indexFilesFolder; - - start(QThread::NormalPriority); -} - -int QHelpSearchIndexReader::hitsCount() const -{ - QMutexLocker lock(&mutex); - return hitList.count(); -} - -QList<QHelpSearchEngine::SearchHit> QHelpSearchIndexReader::hits(int start, - int end) const -{ - QList<QHelpSearchEngine::SearchHit> hits; - QMutexLocker lock(&mutex); - for (int i = start; i < end && i < hitList.count(); ++i) - hits.append(hitList.at(i)); - return hits; -} - -void QHelpSearchIndexReader::run() +void QHelpSearchIndexReaderClucene::run() { mutex.lock(); @@ -140,7 +98,7 @@ void QHelpSearchIndexReader::run() if(QCLuceneIndexReader::indexExists(indexPath)) { mutex.lock(); if (m_cancel) { - mutex.unlock(); + mutex.unlock(); return; } mutex.unlock(); @@ -227,7 +185,7 @@ void QHelpSearchIndexReader::run() } } -bool QHelpSearchIndexReader::defaultQuery(const QString &term, QCLuceneBooleanQuery &booleanQuery, +bool QHelpSearchIndexReaderClucene::defaultQuery(const QString &term, QCLuceneBooleanQuery &booleanQuery, QCLuceneStandardAnalyzer &analyzer) { const QLatin1String c("content"); @@ -244,7 +202,7 @@ bool QHelpSearchIndexReader::defaultQuery(const QString &term, QCLuceneBooleanQu return false; } -bool QHelpSearchIndexReader::buildQuery(QCLuceneBooleanQuery &booleanQuery, +bool QHelpSearchIndexReaderClucene::buildQuery(QCLuceneBooleanQuery &booleanQuery, const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer) { foreach (const QHelpSearchQuery query, queryList) { @@ -344,7 +302,7 @@ bool QHelpSearchIndexReader::buildQuery(QCLuceneBooleanQuery &booleanQuery, return true; } -bool QHelpSearchIndexReader::buildTryHarderQuery(QCLuceneBooleanQuery &booleanQuery, +bool QHelpSearchIndexReaderClucene::buildTryHarderQuery(QCLuceneBooleanQuery &booleanQuery, const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer) { bool retVal = false; @@ -367,7 +325,7 @@ bool QHelpSearchIndexReader::buildTryHarderQuery(QCLuceneBooleanQuery &booleanQu return retVal; } -void QHelpSearchIndexReader::boostSearchHits(const QHelpEngineCore &engine, +void QHelpSearchIndexReaderClucene::boostSearchHits(const QHelpEngineCore &engine, QList<QHelpSearchEngine::SearchHit> &hitList, const QList<QHelpSearchQuery> &queryList) { foreach (const QHelpSearchQuery query, queryList) { diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h index 8876d80..93ac6a8 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h @@ -53,44 +53,24 @@ // We mean it. // -#include "qhelpsearchengine.h" +#include "qhelpsearchindexreader_p.h" #include "fulltextsearch/qanalyzer_p.h" #include "fulltextsearch/qquery_p.h" -#include <QtCore/QList> -#include <QtCore/QMutex> -#include <QtCore/QObject> -#include <QtCore/QString> -#include <QtCore/QThread> -#include <QtCore/QWaitCondition> - -class QHelpEngineCore; - QT_BEGIN_NAMESPACE namespace qt { namespace fulltextsearch { namespace clucene { -class QHelpSearchIndexReader : public QThread +class QHelpSearchIndexReaderClucene : public QHelpSearchIndexReader { Q_OBJECT public: - QHelpSearchIndexReader(); - ~QHelpSearchIndexReader(); - - void cancelSearching(); - void search(const QString &collectionFile, - const QString &indexFilesFolder, - const QList<QHelpSearchQuery> &queryList); - int hitsCount() const; - QList<QHelpSearchEngine::SearchHit> hits(int start, int end) const; - -signals: - void searchingStarted(); - void searchingFinished(int hits); + QHelpSearchIndexReaderClucene(); + ~QHelpSearchIndexReaderClucene(); private: void run(); @@ -102,14 +82,6 @@ private: const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer); void boostSearchHits(const QHelpEngineCore &engine, QList<QHelpSearchEngine::SearchHit> &hitList, const QList<QHelpSearchQuery> &queryList); - -private: - mutable QMutex mutex; - QList<QHelpSearchEngine::SearchHit> hitList; - bool m_cancel; - QString m_collectionFile; - QList<QHelpSearchQuery> m_query; - QString m_indexFilesFolder; }; } // namespace clucene diff --git a/tools/assistant/lib/qhelpsearchindexreader_default.cpp b/tools/assistant/lib/qhelpsearchindexreader_default.cpp index 91af925..fbf8a09 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_default.cpp +++ b/tools/assistant/lib/qhelpsearchindexreader_default.cpp @@ -492,56 +492,17 @@ void Reader::cleanupIndex(EntryTable &entryTable) } -QHelpSearchIndexReader::QHelpSearchIndexReader() - : QThread() - , m_cancel(false) +QHelpSearchIndexReaderDefault::QHelpSearchIndexReaderDefault() + : QHelpSearchIndexReader() { // nothing todo } -QHelpSearchIndexReader::~QHelpSearchIndexReader() +QHelpSearchIndexReaderDefault::~QHelpSearchIndexReaderDefault() { - mutex.lock(); - this->m_cancel = true; - waitCondition.wakeOne(); - mutex.unlock(); - - wait(); -} - -void QHelpSearchIndexReader::cancelSearching() -{ - mutex.lock(); - this->m_cancel = true; - mutex.unlock(); -} - -void QHelpSearchIndexReader::search(const QString &collectionFile, - const QString &indexFilesFolder, - const QList<QHelpSearchQuery> &queryList) -{ - QMutexLocker lock(&mutex); - - this->hitList.clear(); - this->m_cancel = false; - this->m_query = queryList; - this->m_collectionFile = collectionFile; - this->m_indexFilesFolder = indexFilesFolder; - - start(QThread::NormalPriority); -} - -int QHelpSearchIndexReader::hitsCount() const -{ - return hitList.count(); } -QHelpSearchEngine::SearchHit QHelpSearchIndexReader::hit(int index) const -{ - return hitList.at(index); -} - -void QHelpSearchIndexReader::run() +void QHelpSearchIndexReaderDefault::run() { mutex.lock(); @@ -571,7 +532,7 @@ void QHelpSearchIndexReader::run() QHelpEngineCore engine(collectionFile, 0); if (!engine.setupData()) return; - + const QStringList registeredDocs = engine.registeredDocumentations(); const QStringList indexedNamespaces = engine.customValue(key).toString(). split(QLatin1String("|"), QString::SkipEmptyParts); diff --git a/tools/assistant/lib/qhelpsearchindexreader_default_p.h b/tools/assistant/lib/qhelpsearchindexreader_default_p.h index f0e59b4..d21fc08 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_default_p.h +++ b/tools/assistant/lib/qhelpsearchindexreader_default_p.h @@ -54,19 +54,10 @@ // #include "qhelpsearchindex_default_p.h" -#include "qhelpsearchengine.h" +#include "qhelpsearchindexreader_p.h" #include <QtCore/QHash> #include <QtCore/QPair> -#include <QtCore/QList> -#include <QtCore/QMutex> -#include <QtCore/QString> -#include <QtCore/QThread> -#include <QtCore/QObject> -#include <QtCore/QVector> -#include <QtCore/QByteArray> -#include <QtCore/QStringList> -#include <QtCore/QWaitCondition> QT_BEGIN_NAMESPACE @@ -121,39 +112,19 @@ private: }; -class QHelpSearchIndexReader : public QThread +class QHelpSearchIndexReaderDefault : public QHelpSearchIndexReader { Q_OBJECT public: - QHelpSearchIndexReader(); - ~QHelpSearchIndexReader(); - - void cancelSearching(); - void search(const QString &collectionFile, - const QString &indexFilesFolder, - const QList<QHelpSearchQuery> &queryList); - - int hitsCount() const; - QHelpSearchEngine::SearchHit hit(int index) const; - -signals: - void searchingStarted(); - void searchingFinished(int hits); + QHelpSearchIndexReaderDefault(); + ~QHelpSearchIndexReaderDefault(); private: void run(); private: - QMutex mutex; Reader m_reader; - QWaitCondition waitCondition; - QList<QHelpSearchEngine::SearchHit> hitList; - - bool m_cancel; - QList<QHelpSearchQuery> m_query; - QString m_collectionFile; - QString m_indexFilesFolder; }; } // namespace std diff --git a/tools/assistant/lib/qhelpsearchindexreader_p.h b/tools/assistant/lib/qhelpsearchindexreader_p.h new file mode 100644 index 0000000..c8f2b44 --- /dev/null +++ b/tools/assistant/lib/qhelpsearchindexreader_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXREADER_H +#define QHELPSEARCHINDEXREADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelpsearchengine.h" + +#include <QtCore/QList> +#include <QtCore/QMutex> +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtCore/QThread> +#include <QtCore/QWaitCondition> + +QT_BEGIN_NAMESPACE + +class QHelpEngineCore; + +namespace qt { + namespace fulltextsearch { + +class QHelpSearchIndexReader : public QThread +{ + Q_OBJECT + +public: + QHelpSearchIndexReader(); + ~QHelpSearchIndexReader(); + + void cancelSearching(); + void search(const QString &collectionFile, + const QString &indexFilesFolder, + const QList<QHelpSearchQuery> &queryList); + int hitsCount() const; + QList<QHelpSearchEngine::SearchHit> hits(int start, int end) const; + +signals: + void searchingStarted(); + void searchingFinished(int hits); + +protected: + mutable QMutex mutex; + QList<QHelpSearchEngine::SearchHit> hitList; + bool m_cancel; + QString m_collectionFile; + QList<QHelpSearchQuery> m_query; + QString m_indexFilesFolder; + +private: + virtual void run()=0; +}; + + } // namespace fulltextsearch +} // namespace qt + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXREADER_H diff --git a/tools/assistant/lib/qhelpsearchquerywidget.cpp b/tools/assistant/lib/qhelpsearchquerywidget.cpp index 00444b1..110df4f 100644 --- a/tools/assistant/lib/qhelpsearchquerywidget.cpp +++ b/tools/assistant/lib/qhelpsearchquerywidget.cpp @@ -43,9 +43,12 @@ #include <QtCore/QDebug> +#include <QtCore/QAbstractListModel> #include <QtCore/QObject> #include <QtCore/QStringList> +#include <QtCore/QtGlobal> +#include <QtGui/QCompleter> #include <QtGui/QLabel> #include <QtGui/QLayout> #include <QtGui/QLineEdit> @@ -60,8 +63,46 @@ class QHelpSearchQueryWidgetPrivate : public QObject Q_OBJECT private: + struct QueryHistory { + explicit QueryHistory() : curQuery(-1) {} + QList<QList<QHelpSearchQuery> > queries; + int curQuery; + }; + + class CompleterModel : public QAbstractListModel + { + public: + explicit CompleterModel(QObject *parent) + : QAbstractListModel(parent) {} + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + return parent.isValid() ? 0 : termList.size(); + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + if (!index.isValid() || index.row() >= termList.count()|| + (role != Qt::EditRole && role != Qt::DisplayRole)) + return QVariant(); + return termList.at(index.row()); + } + + void addTerm(const QString &term) + { + if (!termList.contains(term)) { + termList.append(term); + reset(); + } + } + + private: + QStringList termList; + }; + QHelpSearchQueryWidgetPrivate() - : QObject() + : QObject(), simpleSearch(true), + searchCompleter(new CompleterModel(this), this) { searchButton = 0; advancedSearchWidget = 0; @@ -136,11 +177,102 @@ private: return wordList; } + void saveQuery(const QList<QHelpSearchQuery> &query, QueryHistory &queryHist) + { + // We only add the query to the list if it is different from the last one. + bool insert = false; + if (queryHist.queries.empty()) + insert = true; + else { + const QList<QHelpSearchQuery> &lastQuery = queryHist.queries.last(); + if (lastQuery.size() != query.size()) { + insert = true; + } else { + for (int i = 0; i < query.size(); ++i) { + if (query.at(i).fieldName != lastQuery.at(i).fieldName + || query.at(i).wordList != lastQuery.at(i).wordList) { + insert = true; + break; + } + } + } + } + if (insert) { + queryHist.queries.append(query); + foreach (const QHelpSearchQuery &queryPart, query) { + static_cast<CompleterModel *>(searchCompleter.model())-> + addTerm(queryPart.wordList.join(" ")); + } + } + } + + void nextOrPrevQuery(int maxOrMinIndex, int addend, + QToolButton *thisButton, QToolButton *otherButton) + { + QueryHistory *queryHist; + QList<QLineEdit *> lineEdits; + if (simpleSearch) { + queryHist = &simpleQueries; + lineEdits << defaultQuery; + } else { + queryHist = &complexQueries; + lineEdits << allQuery << atLeastQuery << similarQuery + << withoutQuery << exactQuery; + } + foreach (QLineEdit *lineEdit, lineEdits) + lineEdit->clear(); + + // Otherwise, the respective button would be disabled. + Q_ASSERT(queryHist->curQuery != maxOrMinIndex); + + queryHist->curQuery += addend; + const QList<QHelpSearchQuery> &query = + queryHist->queries.at(queryHist->curQuery); + foreach (const QHelpSearchQuery &queryPart, query) { + QLineEdit *lineEdit; + switch (queryPart.fieldName) { + case QHelpSearchQuery::DEFAULT: + lineEdit = defaultQuery; + break; + case QHelpSearchQuery::ALL: + lineEdit = allQuery; + break; + case QHelpSearchQuery::ATLEAST: + lineEdit = atLeastQuery; + break; + case QHelpSearchQuery::FUZZY: + lineEdit = similarQuery; + break; + case QHelpSearchQuery::WITHOUT: + lineEdit = withoutQuery; + break; + case QHelpSearchQuery::PHRASE: + lineEdit = exactQuery; + break; + default: + Q_ASSERT(0); + } + lineEdit->setText(queryPart.wordList.join(" ")); + } + + if (queryHist->curQuery == maxOrMinIndex) + thisButton->setEnabled(false); + otherButton->setEnabled(true); + } + + void enableOrDisableToolButtons() + { + const QueryHistory &queryHist = + simpleSearch ? simpleQueries : complexQueries; + prevQueryButton->setEnabled(queryHist.curQuery > 0); + nextQueryButton->setEnabled(queryHist.curQuery < + queryHist.queries.size() - 1); + } + private slots: void showHideAdvancedSearch() { - bool hidden = advancedSearchWidget->isHidden(); - if (hidden) { + if (simpleSearch) { advancedSearchWidget->show(); showHideAdvancedSearchButton->setText((QLatin1String("-"))); } else { @@ -148,12 +280,86 @@ private slots: showHideAdvancedSearchButton->setText((QLatin1String("+"))); } - defaultQuery->setEnabled(!hidden); + simpleSearch = !simpleSearch; + defaultQuery->setEnabled(simpleSearch); + enableOrDisableToolButtons(); + } + + void searchRequested() + { + QList<QHelpSearchQuery> queryList; +#if !defined(QT_CLUCENE_SUPPORT) + queryList.append(QHelSearchQuery(QHelpSearchQuery::DEFAULT, + QStringList(defaultQuery->text()))); + +#else + if (defaultQuery->isEnabled()) { + queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, + buildTermList(escapeString(defaultQuery->text())))); + } else { + const QRegExp exp(QLatin1String("\\s+")); + QStringList lst = similarQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList fuzzy; + foreach (const QString term, lst) + fuzzy += buildTermList(escapeString(term)); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy)); + } + + lst = withoutQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList without; + foreach (const QString term, lst) + without.append(escapeString(term)); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without)); + } + + if (!exactQuery->text().isEmpty()) { + QString phrase = exactQuery->text().remove(QLatin1Char('\"')); + phrase = escapeString(phrase.simplified()); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase))); + } + + lst = allQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList all; + foreach (const QString term, lst) + all.append(escapeString(term)); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all)); + } + + lst = atLeastQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList atLeast; + foreach (const QString term, lst) + atLeast += buildTermList(escapeString(term)); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast)); + } + } +#endif + QueryHistory &queryHist = simpleSearch ? simpleQueries : complexQueries; + saveQuery(queryList, queryHist); + queryHist.curQuery = queryHist.queries.size() - 1; + if (queryHist.curQuery > 0) + prevQueryButton->setEnabled(true); + nextQueryButton->setEnabled(false); + } + + void nextQuery() + { + nextOrPrevQuery((simpleSearch ? simpleQueries : complexQueries).queries.size() - 1, + 1, nextQueryButton, prevQueryButton); + } + + void prevQuery() + { + nextOrPrevQuery(0, -1, prevQueryButton, nextQueryButton); } private: friend class QHelpSearchQueryWidget; + bool simpleSearch; QPushButton *searchButton; QWidget* advancedSearchWidget; QToolButton *showHideAdvancedSearchButton; @@ -163,6 +369,11 @@ private: QLineEdit *withoutQuery; QLineEdit *allQuery; QLineEdit *atLeastQuery; + QToolButton *nextQueryButton; + QToolButton *prevQueryButton; + QueryHistory simpleQueries; + QueryHistory complexQueries; + QCompleter searchCompleter; }; #include "qhelpsearchquerywidget.moc" @@ -199,13 +410,26 @@ QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) QHBoxLayout* hBoxLayout = new QHBoxLayout(); QLabel *label = new QLabel(tr("Search for:"), this); d->defaultQuery = new QLineEdit(this); + d->defaultQuery->setCompleter(&d->searchCompleter); + d->prevQueryButton = new QToolButton(this); + d->prevQueryButton->setArrowType(Qt::LeftArrow); + d->prevQueryButton->setToolTip(tr("Previous search")); + d->prevQueryButton->setEnabled(false); + d->nextQueryButton = new QToolButton(this); + d->nextQueryButton->setArrowType(Qt::RightArrow); + d->nextQueryButton->setToolTip(tr("Next search")); + d->nextQueryButton->setEnabled(false); d->searchButton = new QPushButton(tr("Search"), this); hBoxLayout->addWidget(label); hBoxLayout->addWidget(d->defaultQuery); + hBoxLayout->addWidget(d->prevQueryButton); + hBoxLayout->addWidget(d->nextQueryButton); hBoxLayout->addWidget(d->searchButton); vLayout->addLayout(hBoxLayout); + connect(d->prevQueryButton, SIGNAL(clicked()), d, SLOT(prevQuery())); + connect(d->nextQueryButton, SIGNAL(clicked()), d, SLOT(nextQuery())); connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search())); connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); @@ -236,26 +460,31 @@ QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) label = new QLabel(tr("words <B>similar</B> to:"), this); gLayout->addWidget(label, 0, 0); d->similarQuery = new QLineEdit(this); + d->similarQuery->setCompleter(&d->searchCompleter); gLayout->addWidget(d->similarQuery, 0, 1); label = new QLabel(tr("<B>without</B> the words:"), this); gLayout->addWidget(label, 1, 0); d->withoutQuery = new QLineEdit(this); + d->withoutQuery->setCompleter(&d->searchCompleter); gLayout->addWidget(d->withoutQuery, 1, 1); label = new QLabel(tr("with <B>exact phrase</B>:"), this); gLayout->addWidget(label, 2, 0); d->exactQuery = new QLineEdit(this); + d->exactQuery->setCompleter(&d->searchCompleter); gLayout->addWidget(d->exactQuery, 2, 1); label = new QLabel(tr("with <B>all</B> of the words:"), this); gLayout->addWidget(label, 3, 0); d->allQuery = new QLineEdit(this); + d->allQuery->setCompleter(&d->searchCompleter); gLayout->addWidget(d->allQuery, 3, 1); label = new QLabel(tr("with <B>at least one</B> of the words:"), this); gLayout->addWidget(label, 4, 0); d->atLeastQuery = new QLineEdit(this); + d->atLeastQuery->setCompleter(&d->searchCompleter); gLayout->addWidget(d->atLeastQuery, 4, 1); vLayout->addWidget(d->advancedSearchWidget); @@ -269,6 +498,7 @@ QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()), d, SLOT(showHideAdvancedSearch())); #endif + connect(this, SIGNAL(search()), d, SLOT(searchRequested())); } /*! @@ -285,59 +515,10 @@ QHelpSearchQueryWidget::~QHelpSearchQueryWidget() */ QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const { -#if !defined(QT_CLUCENE_SUPPORT) - QList<QHelpSearchQuery> queryList; - queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - QStringList(d->defaultQuery->text()))); - - return queryList; -#else - QList<QHelpSearchQuery> queryList; - if (d->defaultQuery->isEnabled()) { - queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - d->buildTermList(d->escapeString(d->defaultQuery->text())))); - } else { - const QRegExp exp(QLatin1String("\\s+")); - QStringList lst = d->similarQuery->text().split(exp, QString::SkipEmptyParts); - if (!lst.isEmpty()) { - QStringList fuzzy; - foreach (const QString term, lst) - fuzzy += d->buildTermList(d->escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy)); - } - - lst = d->withoutQuery->text().split(exp, QString::SkipEmptyParts); - if (!lst.isEmpty()) { - QStringList without; - foreach (const QString term, lst) - without.append(d->escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without)); - } - - if (!d->exactQuery->text().isEmpty()) { - QString phrase = d->exactQuery->text().remove(QLatin1Char('\"')); - phrase = d->escapeString(phrase.simplified()); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase))); - } - - lst = d->allQuery->text().split(exp, QString::SkipEmptyParts); - if (!lst.isEmpty()) { - QStringList all; - foreach (const QString term, lst) - all.append(d->escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all)); - } - - lst = d->atLeastQuery->text().split(exp, QString::SkipEmptyParts); - if (!lst.isEmpty()) { - QStringList atLeast; - foreach (const QString term, lst) - atLeast += d->buildTermList(d->escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast)); - } - } - return queryList; -#endif + const QHelpSearchQueryWidgetPrivate::QueryHistory &queryHist = + d->simpleSearch ? d->simpleQueries : d->complexQueries; + return queryHist.queries.isEmpty() ? + QList<QHelpSearchQuery>() : queryHist.queries.last(); } /*! \reimp diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch Binary files differindex 99687ed..3e66bd9 100644 --- a/tools/assistant/tools/assistant/assistant.qch +++ b/tools/assistant/tools/assistant/assistant.qch diff --git a/tools/assistant/tools/assistant/assistant.rc b/tools/assistant/tools/assistant/assistant.rc index b4786ce..deaf40c 100644 --- a/tools/assistant/tools/assistant/assistant.rc +++ b/tools/assistant/tools/assistant/assistant.rc @@ -1 +1,32 @@ +#include "winver.h" + IDI_ICON1 ICON DISCARDABLE "assistant.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGS 0x0L + FILEFLAGSMASK 0x3fL + FILEOS 0x00040004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)" + VALUE "FileDescription", "Qt Assistant" + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)." + VALUE "InternalName", "assistant.exe" + VALUE "OriginalFilename", "assistant.exe" + VALUE "ProductName", "Qt Assistant" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index a384544..23562db 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -43,6 +43,7 @@ #include "helpviewer.h" #include "searchwidget.h" #include "mainwindow.h" +#include "preferencesdialog.h" #include <QtCore/QDir> #include <QtCore/QEvent> @@ -423,6 +424,27 @@ void CentralWidget::setSource(const QUrl &url) tabWidget->setTabText(lastTabPage, quoteTabTitle(viewer->documentTitle())); } +void CentralWidget::setupWidget() +{ + int option = helpEngine->customValue(QLatin1String("StartOption"), + ShowLastPages).toInt(); + + if (option != ShowLastPages) { + QString homePage; + if (option == ShowHomePage) { + homePage = helpEngine->customValue(QLatin1String("defaultHomepage"), + QLatin1String("help")).toString(); + homePage = helpEngine->customValue(QLatin1String("homepage"), + homePage).toString(); + } + if (option == ShowBlankPage) + homePage = QLatin1String("about:blank"); + setSource(homePage); + } else { + setLastShownPages(); + } +} + void CentralWidget::setLastShownPages() { const QLatin1String key("LastShownPages"); @@ -739,8 +761,10 @@ void CentralWidget::setTabTitle(const QUrl &url) QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); for (int tab = 0; tab < tabBar->count(); ++tab) { HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(tab)); - if (viewer) - tabWidget->setTabText(tab, viewer->documentTitle().trimmed()); + if (viewer) { + tabWidget->setTabText(tab, + quoteTabTitle(viewer->documentTitle().trimmed())); + } } #else HelpViewer *viewer = currentHelpViewer(); diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h index ca9caaf..f7ce1d5 100644 --- a/tools/assistant/tools/assistant/centralwidget.h +++ b/tools/assistant/tools/assistant/centralwidget.h @@ -111,7 +111,7 @@ public: CentralWidget(QHelpEngine *engine, MainWindow *parent); ~CentralWidget(); - void setLastShownPages(); + void setupWidget(); bool hasSelection() const; QUrl currentSource() const; QString currentTitle() const; @@ -188,6 +188,7 @@ private: void initPrinter(); QString quoteTabTitle(const QString &title) const; void highlightSearchTerms(); + void setLastShownPages(); private: int lastTabPage; diff --git a/tools/assistant/tools/assistant/doc/assistant.qhp b/tools/assistant/tools/assistant/doc/assistant.qhp index 7a26101..7ea4cdd 100644 --- a/tools/assistant/tools/assistant/doc/assistant.qhp +++ b/tools/assistant/tools/assistant/doc/assistant.qhp @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <QtHelpProject version="1.0"> <virtualFolder>assistant</virtualFolder> - <namespace>com.trolltech.com.assistantinternal_1.0.0</namespace> + <namespace>com.trolltech.com.assistantinternal-1.0.0</namespace> <filterSection> <files> <file>assistant.html</file> diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index 6799db3..5422bf46 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -306,7 +306,7 @@ void HelpViewer::setSource(const QUrl &url) loadFinished = false; if (url.toString() == QLatin1String("help")) { load(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal_1.0.0/assistant/assistant.html"))); + "assistantinternal-1.0.0/assistant/assistant.html"))); } else { load(url); } @@ -425,7 +425,7 @@ void HelpViewer::setSource(const QUrl &url) if (help) { QTextBrowser::setSource(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal_1.0.0/assistant/assistant.html"))); + "assistantinternal-1.0.0/assistant/assistant.html"))); } else { QTextBrowser::setSource(url); setHtml(tr("<title>Error 404...</title><div align=\"center\"><br><br>" diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp index 05355d9..4af2570 100644 --- a/tools/assistant/tools/assistant/main.cpp +++ b/tools/assistant/tools/assistant/main.cpp @@ -181,7 +181,21 @@ QString indexFilesFolder(const QString &collectionFile) int main(int argc, char *argv[]) { - QApplication a(argc, argv); + // First do a quick search for arguments that imply command-line mode. + const char * cmdModeArgs[] = { + "-help", "-register", "-unregister", "-remove-search-index" + }; + bool useGui = true; + for (int i = 1; i < argc; ++i) { + for (size_t j = 0; j < sizeof cmdModeArgs/sizeof *cmdModeArgs; ++j) { + if(strcmp(argv[i], cmdModeArgs[j]) == 0) { + useGui = false; + break; + } + } + } + + QApplication a(argc, argv, useGui); a.addLibraryPath(a.applicationDirPath() + QLatin1String("/plugins")); CmdLineParser cmd; @@ -306,7 +320,7 @@ int main(int argc, char *argv[]) } } - QLatin1String intern("com.trolltech.com.assistantinternal_"); + QLatin1String intern("com.trolltech.com.assistantinternal-"); foreach (const QString &doc, userDocs) { if (!callerDocs.contains(doc) && !doc.startsWith(intern)) user.unregisterDocumentation(doc); diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index 617ac4d..bc73b80 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -93,6 +93,8 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) , m_qtDocInstaller(0) , m_connectedInitSignals(false) { + setToolButtonStyle(Qt::ToolButtonFollowStyle); + if (usesDefaultCollection()) { MainWindow::collectionFileDirectory(true); m_helpEngine = new QHelpEngine(MainWindow::defaultHelpCollectionFileName(), @@ -272,7 +274,7 @@ bool MainWindow::initHelpDB() return false; bool assistantInternalDocRegistered = false; - QString intern(QLatin1String("com.trolltech.com.assistantinternal_")); + QString intern(QLatin1String("com.trolltech.com.assistantinternal-")); foreach (const QString &ns, m_helpEngine->registeredDocumentations()) { if (ns.startsWith(intern)) { intern = ns; @@ -405,7 +407,7 @@ void MainWindow::insertLastPages() if (m_cmdLine->url().isValid()) m_centralWidget->setSource(m_cmdLine->url()); else - m_centralWidget->setLastShownPages(); + m_centralWidget->setupWidget(); if (m_cmdLine->search() == CmdLineParser::Activate) showSearch(); @@ -429,6 +431,7 @@ void MainWindow::setupActions() SLOT(printPreview())); m_printAction = menu->addAction(tr("&Print..."), m_centralWidget, SLOT(print())); + m_printAction->setPriority(QAction::LowPriority); m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); m_printAction->setShortcut(QKeySequence::Print); @@ -448,12 +451,15 @@ void MainWindow::setupActions() menu = menuBar()->addMenu(tr("&Edit")); m_copyAction = menu->addAction(tr("&Copy selected Text"), m_centralWidget, SLOT(copySelection())); + m_copyAction->setPriority(QAction::LowPriority); + m_copyAction->setIconText("&Copy"); m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); m_copyAction->setShortcuts(QKeySequence::Copy); m_copyAction->setEnabled(false); m_findAction = menu->addAction(tr("&Find in Text..."), m_centralWidget, SLOT(showTextSearch())); + m_findAction->setIconText("&Find"); m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png"))); m_findAction->setShortcuts(QKeySequence::Find); @@ -472,16 +478,19 @@ void MainWindow::setupActions() m_viewMenu = menuBar()->addMenu(tr("&View")); m_zoomInAction = m_viewMenu->addAction(tr("Zoom &in"), m_centralWidget, SLOT(zoomIn())); + m_zoomInAction->setPriority(QAction::LowPriority); m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); m_zoomInAction->setShortcut(QKeySequence::ZoomIn); m_zoomOutAction = m_viewMenu->addAction(tr("Zoom &out"), m_centralWidget, SLOT(zoomOut())); + m_zoomOutAction->setPriority(QAction::LowPriority); m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"), m_centralWidget, SLOT(resetZoom())); + m_resetZoomAction->setPriority(QAction::LowPriority); m_resetZoomAction->setIcon(QIcon(resourcePath + QLatin1String("/resetzoom.png"))); m_resetZoomAction->setShortcut(tr("Ctrl+0")); @@ -507,12 +516,14 @@ void MainWindow::setupActions() m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); m_nextAction = menu->addAction(tr("&Forward"), m_centralWidget, SLOT(forward())); + m_nextAction->setPriority(QAction::LowPriority); m_nextAction->setEnabled(false); m_nextAction->setShortcuts(QKeySequence::Forward); m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); m_syncAction = menu->addAction(tr("Sync with Table of Contents"), this, SLOT(syncContents())); + m_syncAction->setIconText("Sync"); m_syncAction->setIcon(QIcon(resourcePath + QLatin1String("/synctoc.png"))); menu->addSeparator(); diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp index fa70196..2b58c64 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.cpp +++ b/tools/assistant/tools/assistant/preferencesdialog.cpp @@ -146,10 +146,13 @@ PreferencesDialog::~PreferencesDialog() emit updateBrowserFont(); } - if (!m_ui.homePageLineEdit->text().isEmpty()) { - key = QLatin1String("homepage"); - m_helpEngine->setCustomValue(key, m_ui.homePageLineEdit->text()); - } + QString homePage = m_ui.homePageLineEdit->text(); + if (homePage.isEmpty()) + homePage = QLatin1String("help"); + m_helpEngine->setCustomValue(QLatin1String("homepage"), homePage); + + int option = m_ui.helpStartComboBox->currentIndex(); + m_helpEngine->setCustomValue(QLatin1String("StartOption"), option); } void PreferencesDialog::showDialog() @@ -379,6 +382,8 @@ void PreferencesDialog::applyChanges() CentralWidget* widget = CentralWidget::instance(); for (int i = m_TabsToClose.count(); --i >= 0;) widget->closeTabAt(m_TabsToClose.at(i)); + if (widget->availableHelpViewer()== 0) + widget->setSource(QUrl(QLatin1String("about:blank"))); if (m_unregDocs.count()) { foreach (const QString &doc, m_unregDocs) @@ -483,22 +488,23 @@ void PreferencesDialog::updateOptionsPage() homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"), QLatin1String("help")).toString(); } - m_ui.homePageLineEdit->setText(homepage); - connect(m_ui.currentPageButton, SIGNAL(pressed()), this, - SLOT(currentHomepageChanged())); - connect(m_ui.restoreDefaultHomePageButton, SIGNAL(pressed()), this, - SLOT(restoreDefaultHomepage())); + + int option = m_helpEngine->customValue(QLatin1String("StartOption"), + ShowLastPages).toInt(); + m_ui.helpStartComboBox->setCurrentIndex(option); + + connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage())); + connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage())); + connect(m_ui.defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage())); } -void PreferencesDialog::restoreDefaultHomepage() +void PreferencesDialog::setBlankPage() { - QString homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - m_ui.homePageLineEdit->setText(homepage); + m_ui.homePageLineEdit->setText(QLatin1String("about:blank")); } -void PreferencesDialog::currentHomepageChanged() +void PreferencesDialog::setCurrentPage() { QString homepage = CentralWidget::instance()->currentSource().toString(); if (homepage.isEmpty()) @@ -507,4 +513,11 @@ void PreferencesDialog::currentHomepageChanged() m_ui.homePageLineEdit->setText(homepage); } +void PreferencesDialog::setDefaultPage() +{ + QString homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"), + QLatin1String("help")).toString(); + m_ui.homePageLineEdit->setText(homepage); +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/preferencesdialog.h b/tools/assistant/tools/assistant/preferencesdialog.h index 5b8ffe8..4471b5f 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.h +++ b/tools/assistant/tools/assistant/preferencesdialog.h @@ -50,6 +50,12 @@ QT_BEGIN_NAMESPACE class FontPanel; class QHelpEngineCore; +enum { + ShowHomePage = 0, + ShowBlankPage = 1, + ShowLastPages = 2 +}; + class PreferencesDialog : public QDialog { Q_OBJECT @@ -72,8 +78,10 @@ private slots: void appFontSettingChanged(int index); void browserFontSettingToggled(bool on); void browserFontSettingChanged(int index); - void restoreDefaultHomepage(); - void currentHomepageChanged(); + + void setBlankPage(); + void setCurrentPage(); + void setDefaultPage(); signals: void updateBrowserFont(); diff --git a/tools/assistant/tools/assistant/preferencesdialog.ui b/tools/assistant/tools/assistant/preferencesdialog.ui index d848b49..279084d 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.ui +++ b/tools/assistant/tools/assistant/preferencesdialog.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>359</width> + <width>375</width> <height>266</height> </rect> </property> @@ -187,19 +187,90 @@ <attribute name="title"> <string>Options</string> </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="QGroupBox" name="groupBox"> + <widget class="QGroupBox" name="groupBox_2"> <property name="title"> - <string>Homepage</string> + <string/> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QLineEdit" name="homePageLineEdit"/> + <widget class="QLabel" name="label_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>On help start:</string> + </property> + </widget> </item> <item> + <widget class="QComboBox" name="helpStartComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Show my home page</string> + </property> + </item> + <item> + <property name="text"> + <string>Show a blank page</string> + </property> + </item> + <item> + <property name="text"> + <string>Show my tabs from last session</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>54</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string/> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Homepage</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="homePageLineEdit"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -213,22 +284,25 @@ </spacer> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="currentPageButton"> - <property name="text"> - <string>Current Page</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="restoreDefaultHomePageButton"> - <property name="text"> - <string>Restore to default</string> - </property> - </widget> - </item> - </layout> + <widget class="QPushButton" name="currentPageButton"> + <property name="text"> + <string>Current Page</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="blankPageButton"> + <property name="text"> + <string>Blank Page</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="defaultPageButton"> + <property name="text"> + <string>Restore to default</string> + </property> + </widget> </item> </layout> </item> diff --git a/tools/assistant/tools/qhelpconverter/adpreader.cpp b/tools/assistant/tools/qhelpconverter/adpreader.cpp index 35f8878..c427038 100644 --- a/tools/assistant/tools/qhelpconverter/adpreader.cpp +++ b/tools/assistant/tools/qhelpconverter/adpreader.cpp @@ -39,8 +39,16 @@ ** ****************************************************************************/ +#include <QRegExp> + #include "adpreader.h" +static bool versionIsAtLeast320(const QString &version) +{ + return QRegExp("\\d.\\d\\.\\d").exactMatch(version) + && (version[0] > '3' || (version[0] == '3' && version[2] >= '2')); +} + QT_BEGIN_NAMESPACE void AdpReader::readData(const QByteArray &contents) @@ -51,11 +59,11 @@ void AdpReader::readData(const QByteArray &contents) m_properties.clear(); m_files.clear(); addData(contents); - while (!atEnd()) { - readNext(); - if (isStartElement()) { + while (!atEnd()) { + readNext(); + if (isStartElement()) { if (name().toString().toLower() == QLatin1String("assistantconfig") - && attributes().value(QLatin1String("version")) == QLatin1String("3.2.0")) { + && versionIsAtLeast320(attributes().value(QLatin1String("version")).toString())) { readProject(); } else if (name().toString().toLower() == QLatin1String("dcf")) { QString ref = attributes().value(QLatin1String("ref")).toString(); @@ -66,8 +74,8 @@ void AdpReader::readData(const QByteArray &contents) } else { raiseError(); } - } - } + } + } } QList<ContentItem> AdpReader::contents() const diff --git a/tools/assistant/tools/qhelpconverter/adpreader.h b/tools/assistant/tools/qhelpconverter/adpreader.h index f2e7509..740a462 100644 --- a/tools/assistant/tools/qhelpconverter/adpreader.h +++ b/tools/assistant/tools/qhelpconverter/adpreader.h @@ -50,15 +50,15 @@ QT_BEGIN_NAMESPACE struct ContentItem { ContentItem(const QString &t, const QString &r, int d) - : title(t), reference(r), depth(d) {} + : title(t), reference(r), depth(d) {} QString title; QString reference; - int depth; + int depth; }; struct KeywordItem { KeywordItem(const QString &k, const QString &r) - : keyword(k), reference(r) {} + : keyword(k), reference(r) {} QString keyword; QString reference; }; diff --git a/tools/checksdk/cesdkhandler.cpp b/tools/checksdk/cesdkhandler.cpp index 48452a3..677d003 100644 --- a/tools/checksdk/cesdkhandler.cpp +++ b/tools/checksdk/cesdkhandler.cpp @@ -71,15 +71,15 @@ bool CeSdkHandler::parse() // look at the file at %VCInstallDir%/vcpackages/WCE.VCPlatform.config // and scan through all installed sdks... m_list.clear(); - VCInstallDir = qgetenv("VCInstallDir"); + VCInstallDir = QString::fromLatin1(qgetenv("VCInstallDir")); VCInstallDir += QLatin1String("\\"); - VSInstallDir = qgetenv("VSInstallDir"); + VSInstallDir = QString::fromLatin1(qgetenv("VSInstallDir")); VSInstallDir += QLatin1String("\\"); if (VCInstallDir.isEmpty() || VSInstallDir.isEmpty()) return false; QDir vStudioDir(VCInstallDir); - if (!vStudioDir.cd("vcpackages")) + if (!vStudioDir.cd(QLatin1String("vcpackages"))) return false; QFile configFile(vStudioDir.absoluteFilePath(QLatin1String("WCE.VCPlatform.config"))); @@ -118,6 +118,7 @@ bool CeSdkHandler::parse() qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString(); return false; } + return m_list.size() > 0 ? true : false; } diff --git a/tools/checksdk/cesdkhandler.h b/tools/checksdk/cesdkhandler.h index 04d3bdf..6ec26db 100644 --- a/tools/checksdk/cesdkhandler.h +++ b/tools/checksdk/cesdkhandler.h @@ -102,8 +102,8 @@ inline QList<CeSdkInfo> CeSdkHandler::listAll() const inline QString CeSdkHandler::fixPaths(QString path) const { - QString str = QDir::toNativeSeparators(QDir::cleanPath(path.replace(VCINSTALL_MACRO, VCInstallDir).replace(VSINSTALL_MACRO, VSInstallDir).replace(QLatin1String("$(PATH)"), QLatin1String("%PATH%")))); - if (str.endsWith(';')) + QString str = QDir::toNativeSeparators(QDir::cleanPath(path.replace(QLatin1String(VCINSTALL_MACRO), VCInstallDir).replace(QLatin1String(VSINSTALL_MACRO), VSInstallDir).replace(QLatin1String("$(PATH)"), QLatin1String("%PATH%")))); + if (str.endsWith(QLatin1Char(';'))) str.truncate(str.length() - 1); return str; } diff --git a/tools/checksdk/checksdk.pro b/tools/checksdk/checksdk.pro index e364f26..a513981 100644 --- a/tools/checksdk/checksdk.pro +++ b/tools/checksdk/checksdk.pro @@ -32,40 +32,5 @@ SOURCES += \ HEADERS += \ cesdkhandler.h -# Bootstrapped Input -SOURCES += \ - $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \ - $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qlistdata.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \ - $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \ - $$QT_SOURCE_TREE/src/corelib/global/qmalloc.cpp \ - $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \ - $$QT_SOURCE_TREE/src/corelib/xml/qxmlstream.cpp \ - $$QT_SOURCE_TREE/src/corelib/xml/qxmlutils.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \ - $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \ - $$QT_BUILD_TREE/src/corelib/global/qconfig.cpp +include(../../src/tools/bootstrap/bootstrap.pri) + diff --git a/tools/checksdk/main.cpp b/tools/checksdk/main.cpp index 2dd7214..6322eb7 100644 --- a/tools/checksdk/main.cpp +++ b/tools/checksdk/main.cpp @@ -46,17 +46,17 @@ void usage() { - qDebug() << "SDK Scanner - Convenience Tool to setup your environment"; - qDebug() << " for crosscompilation to Windows CE"; - qDebug() << "Options:"; - qDebug() << "-help This output"; - qDebug() << "-list List all available SDKs"; - qDebug() << "-sdk <name> Select specified SDK."; - qDebug() << " Note: SDK names with spaces need to be"; - qDebug() << " specified in parenthesis"; - qDebug() << " default: Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"; - qDebug() << "-script <file> Create a script file which can be launched"; - qDebug() << " to setup your environment for specified SDK"; + printf("SDK Scanner - Convenience Tool to setup your environment\n"); + printf(" for crosscompilation to Windows CE\n"); + printf("Options:\n"); + printf("-help This output\n"); + printf("-list List all available SDKs\n"); + printf("-sdk <name> Select specified SDK.\n"); + printf(" Note: SDK names with spaces need to be\n"); + printf(" specified in parenthesis\n"); + printf(" default: Windows Mobile 5.0 Pocket PC SDK (ARMV4I)\n"); + printf("-script <file> Create a script file which can be launched\n"); + printf(" to setup your environment for specified SDK\n"); } int main(int argc, char **argv) @@ -106,9 +106,12 @@ int main(int argc, char **argv) QList<CeSdkInfo> list = handler.listAll(); if (operationList) { - qDebug() << "Available SDKs:"; - for (QList<CeSdkInfo>::iterator it = list.begin(); it != list.end(); ++it) - qDebug() << "SDK Name:" << it->name(); + printf("Available SDKs:\n"); + for (QList<CeSdkInfo>::iterator it = list.begin(); it != list.end(); ++it) { + printf("SDK Name: "); + printf(qPrintable(it->name())); + printf("\n"); + } return 0; } @@ -132,10 +135,13 @@ int main(int argc, char **argv) includePath = QString::fromLatin1("INCLUDE=") + it->includePath(); libPath = QString::fromLatin1("LIB=") + it->libPath(); if (scriptFile.isEmpty()) { - qDebug() << "Please set up your environment with the following paths:"; - qDebug() << qPrintable(binPath); - qDebug() << qPrintable(includePath); - qDebug() << qPrintable(libPath); + printf("Please set up your environment with the following paths:\n"); + printf(qPrintable(binPath)); + printf("\n"); + printf(qPrintable(includePath)); + printf("\n"); + printf(qPrintable(libPath)); + printf("\n"); return 0; } else { QFile file(scriptFile); diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index b82104e..14a5a95 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -3,7 +3,7 @@ DESTDIR = ../.. CONFIG += console flat CONFIG -= moc qt -DEFINES = QT_NODLL QT_NO_CODECS QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_LITE_COMPONENT QT_NO_STL QT_NO_COMPRESS QT_BUILD_QMAKE QT_NO_THREAD QT_NO_QOBJECT _CRT_SECURE_NO_DEPRECATE +DEFINES = UNICODE QT_NODLL QT_NO_CODECS QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_LITE_COMPONENT QT_NO_STL QT_NO_COMPRESS QT_BUILD_QMAKE QT_NO_THREAD QT_NO_QOBJECT _CRT_SECURE_NO_DEPRECATE win32 : !win32-mwc : LIBS += -lole32 -ladvapi32 @@ -35,6 +35,7 @@ HEADERS = configureapp.h environment.h tools.h\ $$QT_SOURCE_TREE/src/corelib/tools/qlist.h \ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.h \ $$QT_SOURCE_TREE/src/corelib/tools/qvector.h \ + $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec_p.h \ $$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.h \ $$QT_SOURCE_TREE/src/corelib/global/qglobal.h \ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.h \ @@ -67,6 +68,7 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qlistdata.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \ + $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec.cpp \ $$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.cpp \ $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index a50019f..b87e8bb 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -116,16 +116,9 @@ Configure::Configure( int& argc, char** argv ) // Get the path to the executable - QFileInfo sourcePathInfo; - QT_WA({ - unsigned short module_name[256]; - GetModuleFileNameW(0, reinterpret_cast<wchar_t *>(module_name), sizeof(module_name)); - sourcePathInfo = QString::fromUtf16(module_name); - }, { - char module_name[256]; - GetModuleFileNameA(0, module_name, sizeof(module_name)); - sourcePathInfo = QString::fromLocal8Bit(module_name); - }); + wchar_t module_name[MAX_PATH]; + GetModuleFileName(0, module_name, sizeof(module_name) / sizeof(wchar_t)); + QFileInfo sourcePathInfo = QString::fromWCharArray(module_name); sourcePath = sourcePathInfo.absolutePath(); sourceDir = sourcePathInfo.dir(); buildPath = QDir::currentPath(); @@ -252,6 +245,7 @@ Configure::Configure( int& argc, char** argv ) dictionary[ "XMLPATTERNS" ] = "auto"; dictionary[ "PHONON" ] = "auto"; dictionary[ "PHONON_BACKEND" ] = "yes"; + dictionary[ "MULTIMEDIA" ] = "yes"; dictionary[ "DIRECTSHOW" ] = "no"; dictionary[ "WEBKIT" ] = "auto"; dictionary[ "PLUGIN_MANIFESTS" ] = "yes"; @@ -615,10 +609,13 @@ void Configure::parseCmdLine() // cetest --------------------------------------------------- else if (configCmdLine.at(i) == "-no-cetest") { dictionary[ "CETEST" ] = "no"; + dictionary[ "CETEST_REQUESTED" ] = "no"; } else if (configCmdLine.at(i) == "-cetest") { // although specified to use it, we stay at "auto" state // this is because checkAvailability() adds variables - // we need for crosscompilation + // we need for crosscompilation; but remember if we asked + // for it. + dictionary[ "CETEST_REQUESTED" ] = "yes"; } // Qt/CE - signing tool ------------------------------------- else if( configCmdLine.at(i) == "-signature") { @@ -885,6 +882,10 @@ void Configure::parseCmdLine() dictionary[ "XMLPATTERNS" ] = "no"; } else if( configCmdLine.at(i) == "-xmlpatterns" ) { dictionary[ "XMLPATTERNS" ] = "yes"; + } else if( configCmdLine.at(i) == "-no-multimedia" ) { + dictionary[ "MULTIMEDIA" ] = "no"; + } else if( configCmdLine.at(i) == "-multimedia" ) { + dictionary[ "MULTIMEDIA" ] = "yes"; } else if( configCmdLine.at(i) == "-no-phonon" ) { dictionary[ "PHONON" ] = "no"; } else if( configCmdLine.at(i) == "-phonon" ) { @@ -1202,6 +1203,10 @@ void Configure::parseCmdLine() useUnixSeparators = (dictionary["QMAKESPEC"] == "win32-g++"); + // Allow tests for private classes to be compiled against internal builds + if (dictionary["BUILDDEV"] == "yes") + qtConfig += "private_tests"; + #if !defined(EVAL) for( QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis ) { @@ -1548,6 +1553,7 @@ bool Configure::displayHelp() "[-no-openssl] [-no-dbus] [-dbus] [-dbus-linked] [-platform <spec>]\n" "[-qtnamespace <namespace>] [-qtlibinfix <infix>] [-no-phonon]\n" "[-phonon] [-no-phonon-backend] [-phonon-backend]\n" + "[-no-multimedia] [-multimedia]\n" "[-no-webkit] [-webkit]\n" "[-no-scripttools] [-scripttools]\n" "[-graphicssystem raster|opengl|openvg]\n\n", 0, 7); @@ -1728,6 +1734,8 @@ bool Configure::displayHelp() desc("PHONON", "yes", "-phonon", "Compile the Phonon module (Phonon is built if a decent C++ compiler is used.)"); desc("PHONON_BACKEND","no", "-no-phonon-backend","Do not compile the platform-specific Phonon backend-plugin"); desc("PHONON_BACKEND","yes","-phonon-backend", "Compile in the platform-specific Phonon backend-plugin"); + desc("MULTIMEDIA", "no", "-no-multimedia", "Do not compile the multimedia module"); + desc("MULTIMEDIA", "yes","-multimedia", "Compile in multimedia module"); desc("WEBKIT", "no", "-no-webkit", "Do not compile in the WebKit module"); desc("WEBKIT", "yes", "-webkit", "Compile in the WebKit module (WebKit is built if a decent C++ compiler is used.)"); desc("SCRIPTTOOLS", "no", "-no-scripttools", "Do not build the QtScriptTools module."); @@ -1794,39 +1802,49 @@ bool Configure::displayHelp() return false; } -bool Configure::findFileInPaths(const QString &fileName, const QStringList &paths) +QString Configure::findFileInPaths(const QString &fileName, const QString &paths) { +#if defined(Q_OS_WIN32) + QRegExp splitReg("[;,]"); +#else + QRegExp splitReg("[:]"); +#endif + QStringList pathList = paths.split(splitReg, QString::SkipEmptyParts); QDir d; - for( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) { + for( QStringList::ConstIterator it = pathList.begin(); it != pathList.end(); ++it ) { // Remove any leading or trailing ", this is commonly used in the environment // variables QString path = (*it); - if ( path.startsWith( "\"" ) ) + if ( path.startsWith( '\"' ) ) path = path.right( path.length() - 1 ); - if ( path.endsWith( "\"" ) ) + if ( path.endsWith( '\"' ) ) path = path.left( path.length() - 1 ); if( d.exists( path + QDir::separator() + fileName ) ) - return true; + return path; } - return false; + return QString(); } bool Configure::findFile( const QString &fileName ) { - QString file = fileName.toLower(); - QStringList paths; -#if defined(Q_OS_WIN32) - QRegExp splitReg("[;,]"); -#else - QRegExp splitReg("[:]"); -#endif - if (file.endsWith(".h")) - paths = QString::fromLocal8Bit(getenv("INCLUDE")).split(splitReg, QString::SkipEmptyParts); - else if ( file.endsWith( ".lib" ) ) - paths = QString::fromLocal8Bit(getenv("LIB")).split(splitReg, QString::SkipEmptyParts); - else - paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts); - return findFileInPaths(file, paths); + const QString file = fileName.toLower(); + const QString pathEnvVar = QString::fromLocal8Bit(getenv("PATH")); + const QString mingwPath = dictionary["QMAKESPEC"].endsWith("-g++") ? + findFileInPaths("mingw32-g++.exe", pathEnvVar) : QString(); + + QString paths; + if (file.endsWith(".h")) { + if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../include")).isNull()) + return true; + paths = QString::fromLocal8Bit(getenv("INCLUDE")); + } else if ( file.endsWith( ".lib" ) || file.endsWith( ".a" ) ) { + if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../lib")).isNull()) + return true; + paths = QString::fromLocal8Bit(getenv("LIB")); + } else { + paths = pathEnvVar; + } + return !findFileInPaths(file, paths).isNull(); } /*! @@ -1896,7 +1914,7 @@ bool Configure::checkAvailability(const QString &part) { bool available = false; if (part == "STYLE_WINDOWSXP") - available = (dictionary.value("QMAKESPEC") == "win32-g++" || findFile("uxtheme.h")); + available = (findFile("uxtheme.h")); else if (part == "ZLIB") available = findFile("zlib.h"); @@ -1971,6 +1989,11 @@ bool Configure::checkAvailability(const QString &part) dictionary[ "QT_CE_RAPI_INC" ] += QLatin1String("\"") + rapiHeader + QLatin1String("\""); dictionary[ "QT_CE_RAPI_LIB" ] += QLatin1String("\"") + rapiLib + QLatin1String("\""); } + else if (dictionary[ "CETEST_REQUESTED" ] == "yes") { + cout << "cetest could not be enabled: rapi.h and rapi.lib could not be found." << endl; + cout << "Make sure the environment is set up for compiling with ActiveSync." << endl; + dictionary[ "DONE" ] = "error"; + } } else if (part == "INCREDIBUILD_XGE") available = findFile("BuildConsole.exe") && findFile("xgConsole.exe"); @@ -1982,14 +2005,25 @@ bool Configure::checkAvailability(const QString &part) && dictionary.value("QMAKESPEC") != "win32-msvc2002" && dictionary.value("EXCEPTIONS") == "yes"; } else if (part == "PHONON") { - available = findFile("vmr9.h") && findFile("dshow.h") && findFile("strmiids.lib") && - findFile("dmoguids.lib") && findFile("msdmo.lib") && findFile("d3d9.h"); + available = findFile("vmr9.h") && findFile("dshow.h") && findFile("dmo.h") && findFile("dmodshow.h") + && (findFile("strmiids.lib") || findFile("libstrmiids.a")) + && (findFile("dmoguids.lib") || findFile("libdmoguids.a")) + && (findFile("msdmo.lib") || findFile("libmsdmo.a")) + && findFile("d3d9.h"); if (!available) { cout << "All the required DirectShow/Direct3D files couldn't be found." << endl - << "Make sure you have either the platform SDK AND the DirectX SDK or the Windows SDK installed." << endl - << "If you have the DirectX SDK installed, please make sure that you have run the <path to SDK>\\SetEnv.Cmd script." << endl; - } + << "Make sure you have either the platform SDK AND the DirectShow SDK or the Windows SDK installed." << endl + << "If you have the DirectShow SDK installed, please make sure that you have run the <path to SDK>\\SetEnv.Cmd script." << endl; + if (!findFile("vmr9.h")) cout << "vmr9.h not found" << endl; + if (!findFile("dshow.h")) cout << "dshow.h not found" << endl; + if (!findFile("strmiids.lib")) cout << "strmiids.lib not found" << endl; + if (!findFile("dmoguids.lib")) cout << "dmoguids.lib not found" << endl; + if (!findFile("msdmo.lib")) cout << "msdmo.lib not found" << endl; + if (!findFile("d3d9.h")) cout << "d3d9.h not found" << endl; + } + } else if (part == "MULTIMEDIA") { + available = true; } else if (part == "WEBKIT") { available = (dictionary.value("QMAKESPEC") == "win32-msvc2005") || (dictionary.value("QMAKESPEC") == "win32-msvc2008") || (dictionary.value("QMAKESPEC") == "win32-g++"); } else if (part == "SCRIPTTOOLS") { @@ -2152,7 +2186,6 @@ bool Configure::verifyConfiguration() no-gif gif dll staticlib - internal nocrosscompiler GNUmake largefile @@ -2178,8 +2211,6 @@ void Configure::generateBuildKey() QStringList build_options; if (!dictionary["QCONFIG"].isEmpty()) build_options += dictionary["QCONFIG"] + "-config "; - if (dictionary["STL"] == "no") - build_options += "no-stl"; build_options.sort(); // Sorted defines that start with QT_NO_ @@ -2453,6 +2484,9 @@ void Configure::generateOutputVars() qtConfig += "phonon-backend"; } + if (dictionary["MULTIMEDIA"] == "yes") + qtConfig += "multimedia"; + if (dictionary["WEBKIT"] == "yes") qtConfig += "webkit"; @@ -2837,6 +2871,7 @@ void Configure::generateConfigfiles() if(dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6"; if(dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT"; if(dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON"; + if(dictionary["MULTIMEDIA"] == "no") qconfigList += "QT_NO_MULTIMEDIA"; if(dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS"; if(dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS"; if(dictionary["FREETYPE"] == "no") qconfigList += "QT_NO_FREETYPE"; @@ -2928,7 +2963,7 @@ void Configure::generateConfigfiles() tmpFile.flush(); // Replace old qconfig.h with new one - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL); QFile::remove(outName); tmpFile.copy(outName); tmpFile.close(); @@ -2964,7 +2999,7 @@ void Configure::generateConfigfiles() } outName = defSpec + "/qmake.conf"; - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); QFile qmakeConfFile(outName); if (qmakeConfFile.open(QFile::Append | QFile::WriteOnly | QFile::Text)) { QTextStream qmakeConfStream; @@ -3032,7 +3067,7 @@ void Configure::generateConfigfiles() tmpFile2.flush(); // Replace old qconfig.cpp with new one - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); QFile::remove( outName ); tmpFile2.copy(outName); tmpFile2.close(); @@ -3103,6 +3138,7 @@ void Configure::displayConfig() cout << "QtDBus support.............." << dictionary[ "DBUS" ] << endl; cout << "QtXmlPatterns support......." << dictionary[ "XMLPATTERNS" ] << endl; cout << "Phonon support.............." << dictionary[ "PHONON" ] << endl; + cout << "Multimedia support.........." << dictionary[ "MULTIMEDIA" ] << endl; cout << "WebKit support.............." << dictionary[ "WEBKIT" ] << endl; cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl; cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl; @@ -3296,6 +3332,9 @@ void Configure::buildQmake() void Configure::buildHostTools() { + if (dictionary[ "NOPROCESS" ] == "yes") + dictionary[ "DONE" ] = "yes"; + if (!dictionary.contains("XQMAKESPEC")) return; @@ -3521,15 +3560,26 @@ void Configure::generateMakefiles() } else { cout << "Processing of project files have been disabled." << endl; cout << "Only use this option if you really know what you're doing." << endl << endl; - dictionary[ "DONE" ] = "yes"; return; } } void Configure::showSummary() { - cout << endl << endl << "Qt is now configured for building. Just run '" << qPrintable(dictionary["QTBUILDINSTRUCTION"]) << "'." << endl + QString make = dictionary[ "MAKE" ]; + if (!dictionary.contains("XQMAKESPEC")) { + cout << endl << endl << "Qt is now configured for building. Just run " << qPrintable(make) << "." << endl; + cout << "To reconfigure, run " << qPrintable(make) << " confclean and configure." << endl << endl; + } else if(dictionary.value("QMAKESPEC").startsWith("wince")) { + // we are cross compiling for Windows CE + cout << endl << endl << "Qt is now configured for building. To start the build run:" << endl + << "\tsetcepaths " << dictionary.value("XQMAKESPEC") << endl + << "\t" << qPrintable(make) << endl + << "To reconfigure, run " << qPrintable(make) << " confclean and configure." << endl << endl; + } else { // Compiling for Symbian OS + cout << endl << endl << "Qt is now configured for building. To start the build run:" << qPrintable(dictionary["QTBUILDINSTRUCTION"]) << "." << endl << "To reconfigure, run '" << qPrintable(dictionary["CONFCLEANINSTRUCTION"]) << "' and configure." << endl; + } } Configure::ProjectType Configure::projectType( const QString& proFileName ) diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index dc22ac9..03df28e 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -150,8 +150,8 @@ private: QString fixSeparators(QString somePath); bool filesDiffer(const QString &file1, const QString &file2); - static bool findFile(const QString &fileName); - static bool findFileInPaths(const QString &fileName, const QStringList &paths); + bool findFile(const QString &fileName); + static QString findFileInPaths(const QString &fileName, const QString &paths); #if !defined(EVAL) void reloadCmdLine(); void saveCmdLine(); diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 6dc8940..b4c61f8 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -146,26 +146,14 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) QString rSubkeyPath = keyPath(rSubkey); HKEY handle = 0; - LONG res; - QT_WA( { - res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(), - 0, KEY_READ, &handle); - } , { - res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(), - 0, KEY_READ, &handle); - } ); - + LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle); if (res != ERROR_SUCCESS) return QString(); // get the size and type of the value DWORD dataType; DWORD dataSize; - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -173,13 +161,8 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) // get the value QByteArray data(dataSize, 0); - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0, - reinterpret_cast<unsigned char*>(data.data()), &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0, - reinterpret_cast<unsigned char*>(data.data()), &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0, + reinterpret_cast<unsigned char*>(data.data()), &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -189,11 +172,7 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) switch (dataType) { case REG_EXPAND_SZ: case REG_SZ: { - QT_WA( { - result = QString::fromUtf16(((const ushort*)data.constData())); - }, { - result = QString::fromLatin1(data.constData()); - } ); + result = QString::fromWCharArray(((const wchar_t *)data.constData())); break; } @@ -201,29 +180,20 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) QStringList l; int i = 0; for (;;) { - QString s; - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData() + i); - }, { - s = QString::fromLatin1(data.constData() + i); - } ); + QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i); i += s.length() + 1; if (s.isEmpty()) break; l.append(s); } - result = l.join(", "); + result = l.join(", "); break; } case REG_NONE: case REG_BINARY: { - QT_WA( { - result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2); - }, { - result = QString::fromLatin1(data.constData(), data.size()); - } ); + result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2); break; } @@ -232,7 +202,7 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) Q_ASSERT(data.size() == sizeof(int)); int i; memcpy((char*)&i, data.constData(), sizeof(int)); - result = QString::number(i); + result = QString::number(i); break; } @@ -350,29 +320,14 @@ bool Environment::detectExecutable(const QString &executable) PROCESS_INFORMATION procInfo; memset(&procInfo, 0, sizeof(procInfo)); - bool couldExecute; - QT_WA({ - // Unicode version - STARTUPINFOW startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); - - couldExecute = CreateProcessW(0, (WCHAR*)executable.utf16(), - 0, 0, false, - CREATE_NO_WINDOW | CREATE_SUSPENDED, - 0, 0, &startInfo, &procInfo); - - }, { - // Ansi version - STARTUPINFOA startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); + STARTUPINFO startInfo; + memset(&startInfo, 0, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); - couldExecute = CreateProcessA(0, executable.toLocal8Bit().data(), + bool couldExecute = CreateProcess(0, (wchar_t*)executable.utf16(), 0, 0, false, CREATE_NO_WINDOW | CREATE_SUSPENDED, 0, 0, &startInfo, &procInfo); - }) if (couldExecute) { CloseHandle(procInfo.hThread); @@ -421,61 +376,38 @@ static QString qt_create_commandline(const QString &program, const QStringList & } /*! - Creates a QByteArray of the \a environment in either UNICODE or - ansi representation. + Creates a QByteArray of the \a environment. */ static QByteArray qt_create_environment(const QStringList &environment) { QByteArray envlist; - if (!environment.isEmpty()) { - int pos = 0; - // add PATH if necessary (for DLL loading) - QByteArray path = qgetenv("PATH"); - QT_WA({ - if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() - && !path.isNull()) { - QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)); - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize(envlist.size() + tmpSize ); - memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); - pos += tmpSize; - } - // add the user environment - for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) { - QString tmp = *it; - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); - pos += tmpSize; - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - }, { - if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) { - QByteArray tmp = QString("PATH=%1").arg(QString::fromLocal8Bit(path)).toLocal8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the user environment - for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++) { - QByteArray tmp = (*it).toLocal8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the terminating 0 (actually 2, just to be on the safe side) - envlist.resize(envlist.size()+2); - envlist[pos++] = 0; - envlist[pos++] = 0; - }) + if (environment.isEmpty()) + return envlist; + + int pos = 0; + // add PATH if necessary (for DLL loading) + QByteArray path = qgetenv("PATH"); + if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) { + QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)); + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize(envlist.size() + tmpSize); + memcpy(envlist.data() + pos, tmp.utf16(), tmpSize); + pos += tmpSize; } + // add the user environment + for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) { + QString tmp = *it; + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize(envlist.size() + tmpSize); + memcpy(envlist.data() + pos, tmp.utf16(), tmpSize); + pos += tmpSize; + } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize(envlist.size() + 4); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; return envlist; } @@ -501,46 +433,24 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv qDebug() << " " << additionalEnv; qDebug() << " " << removeEnv; #endif -// GetEnvironmentStrings is defined to GetEnvironmentStringsW when -// UNICODE is defined. We cannot use that, since we need to -// destinguish between unicode and ansi versions of the functions. -#if defined(UNICODE) && defined(GetEnvironmentStrings) -#undef GetEnvironmentStrings -#endif - // Create the full environment from the current environment and // the additionalEnv strings, then remove all variables defined // in removeEnv QMap<QString, QString> fullEnvMap; - QT_WA({ - LPWSTR envStrings = GetEnvironmentStringsW(); - if (envStrings) { - int strLen = 0; - for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) { - strLen = wcslen(envString); - QString str = QString((const QChar*)envString, strLen); - if (!str.startsWith("=")) { // These are added by the system - int sepIndex = str.indexOf('='); - fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); - } - } - } - FreeEnvironmentStringsW(envStrings); - }, { - LPSTR envStrings = GetEnvironmentStrings(); - if (envStrings) { - int strLen = 0; - for (LPSTR envString = envStrings; *(envString); envString += strLen + 1) { - strLen = strlen(envString); - QString str = QLatin1String(envString); - if (!str.startsWith("=")) { // These are added by the system - int sepIndex = str.indexOf('='); - fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); - } + LPWSTR envStrings = GetEnvironmentStrings(); + if (envStrings) { + int strLen = 0; + for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) { + strLen = wcslen(envString); + QString str = QString((const QChar*)envString, strLen); + if (!str.startsWith("=")) { // These are added by the system + int sepIndex = str.indexOf('='); + fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); } } - FreeEnvironmentStringsA(envStrings); - }) + } + FreeEnvironmentStrings(envStrings); + // Add additionalEnv variables for (int i = 0; i < additionalEnv.count(); ++i) { const QString &str = additionalEnv.at(i); @@ -569,28 +479,14 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv PROCESS_INFORMATION procInfo; memset(&procInfo, 0, sizeof(procInfo)); - bool couldExecute; - QT_WA({ - // Unicode version - STARTUPINFOW startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); + STARTUPINFO startInfo; + memset(&startInfo, 0, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); - couldExecute = CreateProcessW(0, (WCHAR*)args.utf16(), + bool couldExecute = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, true, CREATE_UNICODE_ENVIRONMENT, envlist.isEmpty() ? 0 : envlist.data(), 0, &startInfo, &procInfo); - }, { - // Ansi version - STARTUPINFOA startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); - - couldExecute = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, true, 0, - envlist.isEmpty() ? 0 : envlist.data(), - 0, &startInfo, &procInfo); - }) if (couldExecute) { WaitForSingleObject(procInfo.hProcess, INFINITE); @@ -654,7 +550,7 @@ bool Environment::cpdir(const QString &srcDir, const QString &destDir) #endif QFile::remove(destFile); intermediate = QFile::copy(entry.absoluteFilePath(), destFile); - SetFileAttributesA(destFile.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL); + SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL); } if(!intermediate) { qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir(); diff --git a/tools/configure/main.cpp b/tools/configure/main.cpp index 0e13c7a..e5c04cc 100644 --- a/tools/configure/main.cpp +++ b/tools/configure/main.cpp @@ -95,7 +95,7 @@ int runConfigure( int argc, char** argv ) #endif if( !app.isDone() ) app.generateMakefiles(); - if( !app.isDone() && app.isOk() ) + if( !app.isDone() ) app.buildHostTools(); if( !app.isDone() ) app.showSummary(); diff --git a/tools/configure/tools.cpp b/tools/configure/tools.cpp index f60f72c..708a537 100644 --- a/tools/configure/tools.cpp +++ b/tools/configure/tools.cpp @@ -201,8 +201,8 @@ void Tools::checkLicense(QMap<QString,QString> &dictionary, QMap<QString,QString if (licenseFeatures == '5') //Floating dictionary["METERED LICENSE"] = "true"; - if (!CopyFileA(QDir::toNativeSeparators(fromLicenseFile).toLocal8Bit(), - QDir::toNativeSeparators(toLicenseFile).toLocal8Bit(), FALSE)) { + if (!CopyFile((wchar_t*)QDir::toNativeSeparators(fromLicenseFile).utf16(), + (wchar_t*)QDir::toNativeSeparators(toLicenseFile).utf16(), FALSE)) { cout << "Failed to copy license file (" << fromLicenseFile << ")"; dictionary["DONE"] = "error"; return; diff --git a/tools/designer/data/generate_shared.xsl b/tools/designer/data/generate_shared.xsl index f7859cd..ec95fe2 100644 --- a/tools/designer/data/generate_shared.xsl +++ b/tools/designer/data/generate_shared.xsl @@ -6,8 +6,8 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- Hack to make names camel case - All names in ui files are lowercase, while the element names are - capital case. To make the ui files conforming to the xsd file + keep + All names in UI files are lowercase, while the element names are + capital case. To make the UI files conforming to the XSD file + keep the DOM interface we rename them here --> <xsl:template name="camel-case"> <xsl:param name="text"/> diff --git a/tools/designer/src/components/formeditor/brushmanagerproxy.h b/tools/designer/src/components/formeditor/brushmanagerproxy.h index 9314120..bfd95e5 100644 --- a/tools/designer/src/components/formeditor/brushmanagerproxy.h +++ b/tools/designer/src/components/formeditor/brushmanagerproxy.h @@ -64,7 +64,7 @@ public: private: QScopedPointer<BrushManagerProxyPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(BrushManagerProxy) + Q_DECLARE_PRIVATE(BrushManagerProxy) Q_DISABLE_COPY(BrushManagerProxy) Q_PRIVATE_SLOT(d_func(), void brushAdded(const QString &, const QBrush &)) Q_PRIVATE_SLOT(d_func(), void brushRemoved(const QString &name)) diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp index de4b57b..ac03909 100644 --- a/tools/designer/src/components/formeditor/qdesigner_resource.cpp +++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp @@ -631,13 +631,13 @@ static bool readUiAttributes(QIODevice *dev, QString *errorMessage, *language = attributes.value(languageAttribute).toString(); return true; } else { - *errorMessage = QCoreApplication::translate("Designer", "Invalid ui file: The root element <ui> is missing."); + *errorMessage = QCoreApplication::translate("Designer", "Invalid UI file: The root element <ui> is missing."); return false; } } } - *errorMessage = QCoreApplication::translate("Designer", "An error has occurred while reading the ui file at line %1, column %2: %3") + *errorMessage = QCoreApplication::translate("Designer", "An error has occurred while reading the UI file at line %1, column %2: %3") .arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()); return false; } @@ -756,7 +756,7 @@ void QDesignerResource::setSaveRelative(bool relative) QWidget *QDesignerResource::create(DomUI *ui, QWidget *parentWidget) { // Load extra info extension. This is used by Jambi for preventing - // C++ ui files from being loaded + // C++ UI files from being loaded if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core())) { if (!extra->loadUiExtraInfo(ui)) { const QString errorMessage = QApplication::translate("Designer", "This file cannot be read because the extra info extension failed to load."); diff --git a/tools/designer/src/components/formeditor/qtbrushmanager.h b/tools/designer/src/components/formeditor/qtbrushmanager.h index e6ced60..4884c577 100644 --- a/tools/designer/src/components/formeditor/qtbrushmanager.h +++ b/tools/designer/src/components/formeditor/qtbrushmanager.h @@ -78,7 +78,7 @@ signals: private: QScopedPointer<QtBrushManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtBrushManager) + Q_DECLARE_PRIVATE(QtBrushManager) Q_DISABLE_COPY(QtBrushManager) }; diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp index fb1a5bb..ca55b15 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp @@ -254,8 +254,11 @@ void TextEditor::resourceActionActivated() { QString oldPath = m_editor->text(); if (oldPath.startsWith(QLatin1String("qrc:"))) - oldPath = oldPath.mid(4); - const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + oldPath.remove(0, 4); + // returns ':/file' + QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + if (newPath.startsWith(QLatin1Char(':'))) + newPath.remove(0, 1); if (newPath.isEmpty() || newPath == oldPath) return; const QString newText = QLatin1String("qrc:") + newPath; diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.ui b/tools/designer/src/components/signalsloteditor/connectdialog.ui index bd062eb..568516a 100644 --- a/tools/designer/src/components/signalsloteditor/connectdialog.ui +++ b/tools/designer/src/components/signalsloteditor/connectdialog.ui @@ -13,7 +13,7 @@ <string>Configure Connection</string> </property> <layout class="QGridLayout" > - <item row="0" column="0" colspan="2" > + <item row="0" column="0" > <widget class="QGroupBox" name="signalGroupBox" > <property name="title" > <string>GroupBox</string> @@ -53,7 +53,7 @@ </layout> </widget> </item> - <item row="0" column="2" > + <item row="0" column="1" > <widget class="QGroupBox" name="slotGroupBox" > <property name="title" > <string>GroupBox</string> @@ -93,14 +93,14 @@ </layout> </widget> </item> - <item row="1" column="0" > + <item row="1" column="0" colspan="2" > <widget class="QCheckBox" name="showAllCheckBox" > <property name="text" > <string>Show signals and slots inherited from QWidget</string> </property> </widget> </item> - <item row="2" column="1" colspan="2" > + <item row="2" column="0" colspan="2" > <widget class="QDialogButtonBox" name="buttonBox" > <property name="orientation" > <enum>Qt::Horizontal</enum> diff --git a/tools/designer/src/designer/Info_mac.plist b/tools/designer/src/designer/Info_mac.plist index 8632a6d..f19176f 100644 --- a/tools/designer/src/designer/Info_mac.plist +++ b/tools/designer/src/designer/Info_mac.plist @@ -22,7 +22,7 @@ <string>ui</string> </array> <key>CFBundleTypeIconFile</key> - <string>@ICON@</string> + <string>uifile.icns</string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>LSIsAppleDefaultForType</key> diff --git a/tools/designer/src/designer/designer.pro b/tools/designer/src/designer/designer.pro index e7fa038..aa6850c 100644 --- a/tools/designer/src/designer/designer.pro +++ b/tools/designer/src/designer/designer.pro @@ -78,6 +78,9 @@ mac { ICON = designer.icns QMAKE_INFO_PLIST = Info_mac.plist TARGET = Designer + FILETYPES.files = uifile.icns + FILETYPES.path = Contents/Resources + QMAKE_BUNDLE_DATA += FILETYPES } target.path=$$[QT_INSTALL_BINS] diff --git a/tools/designer/src/designer/designer.rc b/tools/designer/src/designer/designer.rc index 4b6324b..1f8bc0a 100644 --- a/tools/designer/src/designer/designer.rc +++ b/tools/designer/src/designer/designer.rc @@ -1,2 +1,32 @@ +#include "winver.h" + IDI_ICON1 ICON DISCARDABLE "designer.ico" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGS 0x0L + FILEFLAGSMASK 0x3fL + FILEOS 0x00040004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)" + VALUE "FileDescription", "Qt Designer" + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)." + VALUE "InternalName", "designer" + VALUE "OriginalFilename", "designer.exe" + VALUE "ProductName", "Qt Designer" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/tools/designer/src/designer/mainwindow.cpp b/tools/designer/src/designer/mainwindow.cpp index b72a790..a3ca234 100644 --- a/tools/designer/src/designer/mainwindow.cpp +++ b/tools/designer/src/designer/mainwindow.cpp @@ -155,7 +155,7 @@ DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) : QStringList DockedMdiArea::uiFiles(const QMimeData *d) const { - // Extract dropped ui files from Mime data. + // Extract dropped UI files from Mime data. QStringList rc; if (!d->hasFormat(QLatin1String(uriListMimeFormatC))) return rc; diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp index 923687a2..2ac9e1f 100644 --- a/tools/designer/src/designer/qdesigner_workbench.cpp +++ b/tools/designer/src/designer/qdesigner_workbench.cpp @@ -410,6 +410,12 @@ void QDesignerWorkbench::switchToDockedMode() switchToNeutralMode(); +#ifndef Q_WS_MAC + QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); + widgetBoxWrapper->action()->setVisible(true); + widgetBoxWrapper->setWindowTitle(tr("Widget Box")); +#endif + m_mode = DockedMode; const QDesignerSettings settings(m_core); m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows); @@ -462,8 +468,6 @@ void QDesignerWorkbench::switchToTopLevelMode() // make sure that the widgetbox is visible if it is different from neutral. QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); Q_ASSERT(widgetBoxWrapper); - if (!widgetBoxWrapper->action()->isChecked()) - widgetBoxWrapper->action()->trigger(); switchToNeutralMode(); const QPoint desktopOffset = desktopGeometry().topLeft(); @@ -502,9 +506,6 @@ void QDesignerWorkbench::switchToTopLevelMode() found_visible_window |= tw->isVisible(); } - if (!widgetBoxWrapper->action()->isChecked()) - widgetBoxWrapper->action()->trigger(); - if (!m_toolWindows.isEmpty() && !found_visible_window) m_toolWindows.first()->show(); @@ -960,7 +961,7 @@ QDesignerFormWindow * QDesignerWorkbench::loadForm(const QString &fileName, removeFormWindow(formWindow); formWindowManager->removeFormWindow(editor); m_core->metaDataBase()->remove(editor); - *errorMessage = tr("The file <b>%1</b> is not a valid Designer ui file.").arg(file.fileName()); + *errorMessage = tr("The file <b>%1</b> is not a valid Designer UI file.").arg(file.fileName()); return 0; } *uic3Converted = editor->fileName().isEmpty(); diff --git a/tools/designer/src/designer/uifile.icns b/tools/designer/src/designer/uifile.icns Binary files differnew file mode 100644 index 0000000..2473ea4 --- /dev/null +++ b/tools/designer/src/designer/uifile.icns diff --git a/tools/designer/src/lib/sdk/abstractformwindow.cpp b/tools/designer/src/lib/sdk/abstractformwindow.cpp index 89c1015..313b324 100644 --- a/tools/designer/src/lib/sdk/abstractformwindow.cpp +++ b/tools/designer/src/lib/sdk/abstractformwindow.cpp @@ -247,7 +247,7 @@ QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QObje /*! \fn virtual QString QDesignerFormWindowInterface::fileName() const - Returns the file name of the .ui file that describes the form + Returns the file name of the UI file that describes the form currently being shown. \sa setFileName() @@ -399,11 +399,11 @@ QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QObje \fn virtual QStringList QDesignerFormWindowInterface::includeHints() const Returns a list of the header files that will be included in the - form window's associated \c .ui file. + form window's associated UI file. Header files may be local, i.e. relative to the project's - directory,\c "mywidget.h", or global, i.e. part of Qt or the - compilers standard libraries:\c <QtGui/QWidget>. + directory, \c "mywidget.h", or global, i.e. part of Qt or the + compilers standard libraries: \c <QtGui/QWidget>. \sa setIncludeHints() */ @@ -412,11 +412,11 @@ QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QObje \fn virtual void QDesignerFormWindowInterface::setIncludeHints(const QStringList &includeHints) Sets the header files that will be included in the form window's - associated \c .ui file to the specified \a includeHints. + associated UI file to the specified \a includeHints. Header files may be local, i.e. relative to the project's - directory,\c "mywidget.h", or global, i.e. part of Qt or the - compilers standard libraries:\c <QtGui/QWidget>. + directory, \c "mywidget.h", or global, i.e. part of Qt or the + compilers standard libraries: \c <QtGui/QWidget>. \sa includeHints() */ diff --git a/tools/designer/src/lib/sdk/script.cpp b/tools/designer/src/lib/sdk/script.cpp index 90b4c73..2eda3d1 100644 --- a/tools/designer/src/lib/sdk/script.cpp +++ b/tools/designer/src/lib/sdk/script.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE \since 4.3 On saving the form, the extension is queried for a script snippet - to be associated with the widget while saving the \c .ui file. + to be associated with the widget while saving the UI file. This script is then run after creating the widget by \l uic or QUiLoader. @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE for which an editor is provided by the QDesignerTaskMenuExtension. While saving the form, the state is serialized as a QVariantMap of - \QD-supported properties, which is stored in the \c .ui file. This is + \QD-supported properties, which is stored in the UI file. This is handled by data() and setData(). For item view contents, there might be for example a key that determines @@ -97,7 +97,7 @@ QDesignerScriptExtension::~QDesignerScriptExtension() \fn virtual QVariantMap QDesignerScriptExtension::data() const Returns a map of variants describing the internal state to be - stored in the \c .ui file. + stored in the UI file. */ /*! diff --git a/tools/designer/src/lib/shared/iconselector_p.h b/tools/designer/src/lib/shared/iconselector_p.h index e91a21e..9190d54 100644 --- a/tools/designer/src/lib/shared/iconselector_p.h +++ b/tools/designer/src/lib/shared/iconselector_p.h @@ -88,7 +88,7 @@ public: private: QScopedPointer<class LanguageResourceDialogPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(LanguageResourceDialog) + Q_DECLARE_PRIVATE(LanguageResourceDialog) Q_DISABLE_COPY(LanguageResourceDialog) Q_PRIVATE_SLOT(d_func(), void slotAccepted()) Q_PRIVATE_SLOT(d_func(), void slotPathChanged(QString)) @@ -121,7 +121,7 @@ signals: void iconChanged(const PropertySheetIconValue &icon); private: QScopedPointer<class IconSelectorPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(IconSelector) + Q_DECLARE_PRIVATE(IconSelector) Q_DISABLE_COPY(IconSelector) Q_PRIVATE_SLOT(d_func(), void slotStateActivated()) diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp index f43b527..5b22a86 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp @@ -1381,6 +1381,24 @@ bool QDesignerPropertySheet::isFakeLayoutProperty(int index) const return false; } +// Determine the "designable" state of a property. Properties, which have +// a per-object boolean test function that returns false are shown in +// disabled state ("checked" depending on "checkable", etc.) +// Properties, which are generally not designable independent +// of the object are not shown at all. +enum DesignableState { PropertyIsDesignable, + // Object has a Designable test function that returns false. + PropertyOfObjectNotDesignable, + PropertyNotDesignable }; + +static inline DesignableState designableState(const QDesignerMetaPropertyInterface *p, const QObject *object) +{ + if (p->attributes(object) & QDesignerMetaPropertyInterface::DesignableAttribute) + return PropertyIsDesignable; + return (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute) ? + PropertyOfObjectNotDesignable : PropertyNotDesignable; +} + bool QDesignerPropertySheet::isVisible(int index) const { if (d->invalidIndex(Q_FUNC_INFO, index)) @@ -1450,9 +1468,8 @@ bool QDesignerPropertySheet::isVisible(int index) const if (!(p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess)) return false; - // Enabled handling - return (p->attributes(d->m_object) & QDesignerMetaPropertyInterface::DesignableAttribute) || - (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute); + // Enabled handling: Hide only statically not designable properties + return designableState(p, d->m_object) != PropertyNotDesignable; } void QDesignerPropertySheet::setVisible(int index, bool visible) @@ -1482,9 +1499,12 @@ bool QDesignerPropertySheet::isEnabled(int index) const if (d->m_info.value(index).visible == true) // Sun CC 5.5 oddity, wants true return true; + // Enable setting of properties for statically non-designable properties + // as this might be done via TaskMenu/Cursor::setProperty. Note that those + // properties are not visible. const QDesignerMetaPropertyInterface *p = d->m_meta->property(index); return (p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess) && - (p->attributes(d->m_object) & QDesignerMetaPropertyInterface::DesignableAttribute); + designableState(p, d->m_object) != PropertyOfObjectNotDesignable; } bool QDesignerPropertySheet::isAttribute(int index) const diff --git a/tools/designer/src/lib/shared/qtresourceeditordialog_p.h b/tools/designer/src/lib/shared/qtresourceeditordialog_p.h index 59c5ca6..6eac2b8 100644 --- a/tools/designer/src/lib/shared/qtresourceeditordialog_p.h +++ b/tools/designer/src/lib/shared/qtresourceeditordialog_p.h @@ -85,7 +85,7 @@ private: ~QtResourceEditorDialog(); QScopedPointer<class QtResourceEditorDialogPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtResourceEditorDialog) + Q_DECLARE_PRIVATE(QtResourceEditorDialog) Q_DISABLE_COPY(QtResourceEditorDialog) Q_PRIVATE_SLOT(d_func(), void slotQrcFileInserted(QtQrcFile *)) diff --git a/tools/designer/src/lib/shared/qtresourcemodel_p.h b/tools/designer/src/lib/shared/qtresourcemodel_p.h index 22e98bb..e9f1c93 100644 --- a/tools/designer/src/lib/shared/qtresourcemodel_p.h +++ b/tools/designer/src/lib/shared/qtresourcemodel_p.h @@ -89,7 +89,7 @@ private: friend class QtResourceModel; QScopedPointer<class QtResourceSetPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtResourceSet) + Q_DECLARE_PRIVATE(QtResourceSet) Q_DISABLE_COPY(QtResourceSet) }; @@ -134,7 +134,7 @@ private: friend class QtResourceSet; QScopedPointer<class QtResourceModelPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtResourceModel) + Q_DECLARE_PRIVATE(QtResourceModel) Q_DISABLE_COPY(QtResourceModel) Q_PRIVATE_SLOT(d_func(), void slotFileChanged(const QString &)) diff --git a/tools/designer/src/lib/shared/qtresourceview_p.h b/tools/designer/src/lib/shared/qtresourceview_p.h index 82bb8d8..0484686 100644 --- a/tools/designer/src/lib/shared/qtresourceview_p.h +++ b/tools/designer/src/lib/shared/qtresourceview_p.h @@ -103,7 +103,7 @@ protected: private: QScopedPointer<class QtResourceViewPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtResourceView) + Q_DECLARE_PRIVATE(QtResourceView) Q_DISABLE_COPY(QtResourceView) Q_PRIVATE_SLOT(d_func(), void slotResourceSetActivated(QtResourceSet *)) Q_PRIVATE_SLOT(d_func(), void slotCurrentPathChanged(QTreeWidgetItem *)) @@ -131,7 +131,7 @@ public: private: QScopedPointer<class QtResourceViewDialogPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtResourceViewDialog) + Q_DECLARE_PRIVATE(QtResourceViewDialog) Q_DISABLE_COPY(QtResourceViewDialog) Q_PRIVATE_SLOT(d_func(), void slotResourceSelected(const QString &)) }; diff --git a/tools/designer/src/lib/shared/widgetfactory.cpp b/tools/designer/src/lib/shared/widgetfactory.cpp index 6c45daf..7080ed3 100644 --- a/tools/designer/src/lib/shared/widgetfactory.cpp +++ b/tools/designer/src/lib/shared/widgetfactory.cpp @@ -834,9 +834,11 @@ bool WidgetFactory::isPassiveInteractor(QWidget *widget) if (isTabBarInteractor(tabBar)) m_lastWasAPassiveInteractor = true; return m_lastWasAPassiveInteractor; - } else if (qobject_cast<QSizeGrip*>(widget)) +#ifndef QT_NO_SIZEGRIP + } else if (qobject_cast<QSizeGrip*>(widget)) { return (m_lastWasAPassiveInteractor = true); - else if (qobject_cast<QMdiSubWindow*>(widget)) +#endif + } else if (qobject_cast<QMdiSubWindow*>(widget)) return (m_lastWasAPassiveInteractor = true); else if (qobject_cast<QAbstractButton*>(widget) && (qobject_cast<QTabBar*>(widget->parent()) || qobject_cast<QToolBox*>(widget->parent()))) return (m_lastWasAPassiveInteractor = true); diff --git a/tools/designer/src/lib/uilib/abstractformbuilder.cpp b/tools/designer/src/lib/uilib/abstractformbuilder.cpp index 5a6e1f5..1711d43 100644 --- a/tools/designer/src/lib/uilib/abstractformbuilder.cpp +++ b/tools/designer/src/lib/uilib/abstractformbuilder.cpp @@ -135,7 +135,7 @@ public: QAbstractFormBuilder provides a standard interface and a default implementation for constructing forms from user interface files. It is not intended to be instantiated directly. Use the - QFormBuilder class to create user interfaces from \c{.ui} files at + QFormBuilder class to create user interfaces from UI files at run-time. For example: \snippet doc/src/snippets/code/tools_designer_src_lib_uilib_abstractformbuilder.cpp 0 @@ -145,10 +145,10 @@ public: functions: \list - \o load() handles reading of \c{.ui} format files from arbitrary + \o load() handles reading of UI format files from arbitrary QIODevices, and construction of widgets from the XML data that they contain. - \o save() handles saving of widget details in \c{.ui} format to + \o save() handles saving of widget details in UI format to arbitrary QIODevices. \o workingDirectory() and setWorkingDirectory() control the directory in which forms are held. The form builder looks for @@ -208,13 +208,13 @@ QWidget *QAbstractFormBuilder::load(QIODevice *dev, QWidget *parentWidget) } } if (reader.hasError()) { - uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "An error has occurred while reading the ui file at line %1, column %2: %3") + uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "An error has occurred while reading the UI file at line %1, column %2: %3") .arg(reader.lineNumber()).arg(reader.columnNumber()) .arg(reader.errorString())); return 0; } if (!initialized) { - uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Invalid ui file: The root element <ui> is missing.")); + uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Invalid UI file: The root element <ui> is missing.")); return 0; } @@ -657,7 +657,7 @@ void QAbstractFormBuilder::layoutInfo(DomLayout *ui_layout, QObject *parent, int spac = p->elementNumber(); #ifdef Q_OS_MAC - // here we recognize ui file < 4.3 (no we don't store margin property) + // here we recognize UI file < 4.3 (no we don't store margin property) if (mar != INT_MIN) { const int defaultMargin = parent->inherits("QLayoutWidget") ? 0 : 9; if (mar == defaultMargin) @@ -1202,7 +1202,7 @@ QActionGroup *QAbstractFormBuilder::createActionGroup(QObject *parent, const QSt \fn void QAbstractFormBuilder::save(QIODevice *device, QWidget *widget) Saves an XML representation of the given \a widget to the - specified \a device in the standard \c{.ui} file format. + specified \a device in the standard UI file format. \sa load()*/ void QAbstractFormBuilder::save(QIODevice *dev, QWidget *widget) diff --git a/tools/designer/src/lib/uilib/formbuilder.cpp b/tools/designer/src/lib/uilib/formbuilder.cpp index 043991e..f737311 100644 --- a/tools/designer/src/lib/uilib/formbuilder.cpp +++ b/tools/designer/src/lib/uilib/formbuilder.cpp @@ -57,12 +57,12 @@ namespace QFormInternal { \class QFormBuilder \brief The QFormBuilder class is used to dynamically construct - user interfaces from .ui files at run-time. + user interfaces from UI files at run-time. \inmodule QtDesigner The QFormBuilder class provides a mechanism for dynamically - creating user interfaces at run-time, based on \c{.ui} files + creating user interfaces at run-time, based on UI files created with \QD. For example: \snippet doc/src/snippets/code/tools_designer_src_lib_uilib_formbuilder.cpp 0 diff --git a/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp index 1158e35..1cbf1c1 100644 --- a/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp +++ b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp @@ -162,7 +162,7 @@ void QAxWidgetTaskMenu::setActiveXControl() tr("The control requires a design-time license")); clsid = QUuid(); } else { - key = QString::fromUtf16((ushort *)bKey); + key = QString::fromWCharArray(bKey); } cf2->Release(); diff --git a/tools/designer/src/uitools/quiloader.cpp b/tools/designer/src/uitools/quiloader.cpp index 83d3089..260e9bd 100644 --- a/tools/designer/src/uitools/quiloader.cpp +++ b/tools/designer/src/uitools/quiloader.cpp @@ -574,20 +574,20 @@ void QUiLoaderPrivate::setupWidgetMap() const \brief The QUiLoader class enables standalone applications to dynamically create user interfaces at run-time using the - information stored in .ui files or specified in plugin paths. + information stored in UI files or specified in plugin paths. In addition, you can customize or create your own user interface by deriving your own loader class. If you have a custom component or an application that embeds \QD, you can also use the QFormBuilder class provided by the QtDesigner module to create - user interfaces from \c{.ui} files. + user interfaces from UI files. The QUiLoader class provides a collection of functions allowing you to - create widgets based on the information stored in \c .ui files (created + create widgets based on the information stored in UI files (created with \QD) or available in the specified plugin paths. The specified plugin paths can be retrieved using the pluginPaths() function. Similarly, the - contents of a \c{.ui} file can be retrieved using the load() function. For + contents of a UI file can be retrieved using the load() function. For example: \snippet doc/src/snippets/quiloader/mywidget.cpp 0 diff --git a/tools/designer/src/uitools/quiloader.h b/tools/designer/src/uitools/quiloader.h index 7f718a6..40b5010 100644 --- a/tools/designer/src/uitools/quiloader.h +++ b/tools/designer/src/uitools/quiloader.h @@ -92,7 +92,7 @@ public: private: QScopedPointer<QUiLoaderPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QUiLoader) + Q_DECLARE_PRIVATE(QUiLoader) Q_DISABLE_COPY(QUiLoader) }; diff --git a/tools/linguist/lconvert/main.cpp b/tools/linguist/lconvert/main.cpp index 534bc11..1381595 100644 --- a/tools/linguist/lconvert/main.cpp +++ b/tools/linguist/lconvert/main.cpp @@ -81,10 +81,13 @@ static int usage(const QStringList &args) " --output-format <outformat>\n" " Specify output format. See -if.\n\n" " --input-codec <codec>\n" - " Specify encoding for .qm input files. Default is 'Latin1'.\n" - " UTF-8 is always tried as well, corresponding to the trUtf8() function.\n\n" + " Specify encoding for QM and PO input files. Default is 'Latin1'\n" + " for QM and 'UTF-8' for PO files. UTF-8 is always tried as well for\n" + " QM, corresponding to the possible use of the trUtf8() function.\n\n" + " --output-codec <codec>\n" + " Specify encoding for PO output files. Default is 'UTF-8'.\n\n" " --drop-tags <regexp>\n" - " Drop named extra tags when writing 'ts' or 'xlf' files.\n" + " Drop named extra tags when writing TS or XLIFF files.\n" " May be specified repeatedly.\n\n" " --drop-translations\n" " Drop existing translations and reset the status to 'unfinished'.\n" @@ -101,10 +104,10 @@ static int usage(const QStringList &args) " --no-finished\n" " Drop finished messages.\n\n" " --locations {absolute|relative|none}\n" - " Override how source code references are saved in ts files.\n" + " Override how source code references are saved in TS files.\n" " Default is absolute.\n\n" " --no-ui-lines\n" - " Drop line numbers from references to .ui files.\n\n" + " Drop line numbers from references to UI files.\n\n" " --verbose\n" " be a bit more verbose\n\n" "Long options can be specified with only one leading dash, too.\n\n" @@ -141,7 +144,6 @@ int main(int argc, char *argv[]) Translator::LocationsType locations = Translator::DefaultLocations; ConversionData cd; - cd.m_codecForSource = "Latin1"; Translator tr; for (int i = 1; i < args.size(); ++i) { @@ -174,6 +176,10 @@ int main(int argc, char *argv[]) if (++i >= args.size()) return usage(args); cd.m_codecForSource = args[i].toLatin1(); + } else if (args[i] == QLatin1String("-output-codec")) { + if (++i >= args.size()) + return usage(args); + cd.m_outputCodec = args[i].toLatin1(); } else if (args[i] == QLatin1String("-drop-tag")) { if (++i >= args.size()) return usage(args); @@ -257,6 +263,11 @@ int main(int argc, char *argv[]) if (locations != Translator::DefaultLocations) tr.setLocationsType(locations); + tr.normalizeTranslations(cd); + if (!cd.errors().isEmpty()) { + qWarning("%s", qPrintable(cd.error())); + cd.clearErrors(); + } if (!tr.save(outFileName, cd, outFormat)) { qWarning("%s", qPrintable(cd.error())); return 3; diff --git a/tools/linguist/linguist/linguist.rc b/tools/linguist/linguist/linguist.rc index 865e021..5ff37ca 100644 --- a/tools/linguist/linguist/linguist.rc +++ b/tools/linguist/linguist/linguist.rc @@ -1 +1,32 @@ +#include "winver.h" + IDI_ICON1 ICON DISCARDABLE "linguist.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGS 0x0L + FILEFLAGSMASK 0x3fL + FILEOS 0x00040004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)" + VALUE "FileDescription", "Qt Linguist" + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)." + VALUE "InternalName", "linguist" + VALUE "OriginalFilename", "linguist.exe" + VALUE "ProductName", "Qt Linguist" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp index 2b1df39..bb79b19 100644 --- a/tools/linguist/linguist/mainwindow.cpp +++ b/tools/linguist/linguist/mainwindow.cpp @@ -82,6 +82,7 @@ #include <QMenuBar> #include <QMessageBox> #include <QPrintDialog> +#include <QPrinter> #include <QProcess> #include <QRegExp> #include <QSettings> @@ -257,6 +258,7 @@ bool FocusWatcher::eventFilter(QObject *, QEvent *event) MainWindow::MainWindow() : QMainWindow(0, Qt::Window), m_assistantProcess(0), + m_printer(0), m_findMatchCase(Qt::CaseInsensitive), m_findIgnoreAccelerators(true), m_findWhere(DataModel::NoLocation), @@ -503,6 +505,7 @@ MainWindow::~MainWindow() qDeleteAll(m_phraseBooks); delete m_dataModel; delete m_statistics; + delete m_printer; } void MainWindow::modelCountChanged() @@ -870,15 +873,22 @@ void MainWindow::releaseAll() releaseInternal(i); } +QPrinter *MainWindow::printer() +{ + if (!m_printer) + m_printer = new QPrinter; + return m_printer; +} + void MainWindow::print() { int pageNum = 0; - QPrintDialog dlg(&m_printer, this); + QPrintDialog dlg(printer(), this); if (dlg.exec()) { QApplication::setOverrideCursor(Qt::WaitCursor); - m_printer.setDocName(m_dataModel->condensedSrcFileNames(true)); + printer()->setDocName(m_dataModel->condensedSrcFileNames(true)); statusBar()->showMessage(tr("Printing...")); - PrintOut pout(&m_printer); + PrintOut pout(printer()); for (int i = 0; i < m_dataModel->contextCount(); ++i) { MultiContextItem *mc = m_dataModel->multiContextItem(i); @@ -1229,11 +1239,11 @@ void MainWindow::printPhraseBook(QAction *action) int pageNum = 0; - QPrintDialog dlg(&m_printer, this); + QPrintDialog dlg(printer(), this); if (dlg.exec()) { - m_printer.setDocName(phraseBook->fileName()); + printer()->setDocName(phraseBook->fileName()); statusBar()->showMessage(tr("Printing...")); - PrintOut pout(&m_printer); + PrintOut pout(printer()); pout.setRule(PrintOut::ThinRule); foreach (const Phrase *p, phraseBook->phrases()) { pout.setGuide(p->source()); diff --git a/tools/linguist/linguist/mainwindow.h b/tools/linguist/linguist/mainwindow.h index 167dfe4..3dedcb5 100644 --- a/tools/linguist/linguist/mainwindow.h +++ b/tools/linguist/linguist/mainwindow.h @@ -51,7 +51,6 @@ #include <QtCore/QLocale> #include <QtGui/QMainWindow> -#include <QtGui/QPrinter> QT_BEGIN_NAMESPACE @@ -60,6 +59,7 @@ class QAction; class QDialog; class QLabel; class QMenu; +class QPrinter; class QProcess; class QIcon; class QSortFilterProxyModel; @@ -200,6 +200,8 @@ private: void releaseInternal(int model); void saveInternal(int model); + QPrinter *printer(); + // FIXME: move to DataModel void updateDanger(const MultiDataIndex &index, bool verbose); @@ -226,7 +228,7 @@ private: QList<QHash<QString, QList<Phrase *> > > m_phraseDict; QList<PhraseBook *> m_phraseBooks; QMap<QAction *, PhraseBook *> m_phraseBookMenu[3]; - QPrinter m_printer; + QPrinter *m_printer; FindDialog *m_findDialog; QString m_findText; diff --git a/tools/linguist/linguist/mainwindow.ui b/tools/linguist/linguist/mainwindow.ui index 4f66f31..613241b 100644 --- a/tools/linguist/linguist/mainwindow.ui +++ b/tools/linguist/linguist/mainwindow.ui @@ -747,7 +747,7 @@ <string>Release As...</string> </property> <property name="whatsThis"> - <string>Create a Qt message file suitable for released applications from the current message file. The filename will automatically be determined from the name of the .ts file.</string> + <string>Create a Qt message file suitable for released applications from the current message file. The filename will automatically be determined from the name of the TS file.</string> </property> </action> <action name="actionFile"> diff --git a/tools/linguist/linguist/messagemodel.cpp b/tools/linguist/linguist/messagemodel.cpp index 6bbf6f3..9995220 100644 --- a/tools/linguist/linguist/messagemodel.cpp +++ b/tools/linguist/linguist/messagemodel.cpp @@ -139,7 +139,7 @@ DataModel::DataModel(QObject *parent) QStringList DataModel::normalizedTranslations(const MessageItem &m) const { - return Translator::normalizedTranslations(m.message(), m_language, m_country); + return Translator::normalizedTranslations(m.message(), m_numerusForms.count()); } ContextItem *DataModel::contextItem(int context) const diff --git a/tools/linguist/lrelease/lrelease.1 b/tools/linguist/lrelease/lrelease.1 index 9e77504..8dd14b2 100644 --- a/tools/linguist/lrelease/lrelease.1 +++ b/tools/linguist/lrelease/lrelease.1 @@ -51,10 +51,10 @@ This page documents the tool for the Qt GUI toolkit. .B Lrelease reads a qmake/tmake project file (.pro file) and converts the -translation files (.ts files) specified in it into Qt message files -(.qm files) used by the application to translate. +translation files (TS files) specified in it into Qt message files +(QM files) used by the application to translate. .PP -The .qm file format is a compact binary format that provides +The QM file format is a compact binary format that provides extremely fast lookups for translations and that is used by Qt. .SH OPTIONS .TP @@ -62,7 +62,7 @@ extremely fast lookups for translations and that is used by Qt. Display the usage and exit. .TP .I "-compress" -Compress the .qm files. +Compress the QM files. .TP .I "-nounfinished" Do not include unfinished translations. @@ -72,7 +72,7 @@ If the translated text is the same as the source text, do not include the message. .TP .I "-silent" -Don't explain what is being done. +Do not explain what is being done. .TP .I "-version" Display the version of @@ -105,7 +105,7 @@ generated from gnomovision_dk.ts, gnomovision_fi.ts, gnomovision_no.ts and gnomovision_se.ts, respectively. .PP .B Lrelease -can also be invoked with a list of .ts files to convert: +can also be invoked with a list of TS files to convert: .PP .in +4 .nf diff --git a/tools/linguist/lrelease/main.cpp b/tools/linguist/lrelease/main.cpp index 86b7866..5cb9e1a 100644 --- a/tools/linguist/lrelease/main.cpp +++ b/tools/linguist/lrelease/main.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "translator.h" -#include "profileevaluator.h" +#include "proreader.h" #include <QtCore/QCoreApplication> #include <QtCore/QDebug> @@ -66,19 +66,21 @@ static void printUsage() " lrelease [options] project-file\n" " lrelease [options] ts-files [-qm qm-file]\n\n" "lrelease is part of Qt's Linguist tool chain. It can be used as a\n" - "stand-alone tool to convert XML based translations files in the .ts\n" - "format into the 'compiled' .qm format used by QTranslator objects.\n\n" + "stand-alone tool to convert XML-based translations files in the TS\n" + "format into the 'compiled' QM format used by QTranslator objects.\n\n" "Options:\n" " -help Display this information and exit\n" + " -idbased\n" + " Use IDs instead of source strings for message keying\n" " -compress\n" - " Compress the .qm files\n" + " Compress the QM files\n" " -nounfinished\n" " Do not include unfinished translations\n" " -removeidentical\n" " If the translated text is the same as\n" " the source text, do not include the message\n" " -silent\n" - " Don't explain what is being done\n" + " Do not explain what is being done\n" " -version\n" " Display the version of lrelease and exit\n" )); @@ -99,7 +101,7 @@ static bool loadTsFile(Translator &tor, const QString &tsFileName, bool /* verbo static bool releaseTranslator(Translator &tor, const QString &qmFileName, bool verbose, bool ignoreUnfinished, - bool removeIdentical, TranslatorSaveMode mode) + bool removeIdentical, bool idBased, TranslatorSaveMode mode) { Translator::reportDuplicates(tor.resolveDuplicates(), qmFileName, verbose); @@ -119,8 +121,10 @@ static bool releaseTranslator(Translator &tor, const QString &qmFileName, } ConversionData cd; + tor.normalizeTranslations(cd); cd.m_verbose = verbose; cd.m_ignoreUnfinished = ignoreUnfinished; + cd.m_idBased = idBased; cd.m_saveMode = mode; bool ok = tor.release(&file, cd); file.close(); @@ -136,7 +140,7 @@ static bool releaseTranslator(Translator &tor, const QString &qmFileName, } static bool releaseTsFile(const QString& tsFileName, bool verbose, - bool ignoreUnfinished, bool removeIdentical, TranslatorSaveMode mode) + bool ignoreUnfinished, bool removeIdentical, bool idBased, TranslatorSaveMode mode) { Translator tor; if (!loadTsFile(tor, tsFileName, verbose)) @@ -151,7 +155,7 @@ static bool releaseTsFile(const QString& tsFileName, bool verbose, } qmFileName += QLatin1String(".qm"); - return releaseTranslator(tor, qmFileName, verbose, ignoreUnfinished, removeIdentical, mode); + return releaseTranslator(tor, qmFileName, verbose, ignoreUnfinished, removeIdentical, idBased, mode); } int main(int argc, char **argv) @@ -164,6 +168,7 @@ int main(int argc, char **argv) bool verbose = true; // the default is true starting with Qt 4.2 bool ignoreUnfinished = false; + bool idBased = false; // the default mode is SaveEverything starting with Qt 4.2 TranslatorSaveMode mode = SaveEverything; bool removeIdentical = false; @@ -175,6 +180,9 @@ int main(int argc, char **argv) if (args[i] == QLatin1String("-compress")) { mode = SaveStripped; continue; + } else if (args[i] == QLatin1String("-idbased")) { + idBased = true; + continue; } else if (args[i] == QLatin1String("-nocompress")) { mode = SaveEverything; continue; @@ -232,18 +240,18 @@ int main(int argc, char **argv) qPrintable(args[i])); } else { foreach (const QString &trans, translations) - if (!releaseTsFile(trans, verbose, ignoreUnfinished, removeIdentical, mode)) + if (!releaseTsFile(trans, verbose, ignoreUnfinished, removeIdentical, idBased, mode)) return 1; } } else { qWarning("error: lrelease encountered project file functionality that is currently not supported.\n" - "You might want to consider using .ts files as input instead of a project file.\n" + "You might want to consider using TS files as input instead of a project file.\n" "Try the following syntax:\n" " lrelease [options] ts-files [-qm qm-file]\n"); } } else { if (outputFile.isEmpty()) { - if (!releaseTsFile(args[i], verbose, ignoreUnfinished, removeIdentical, mode)) + if (!releaseTsFile(args[i], verbose, ignoreUnfinished, removeIdentical, idBased, mode)) return 1; } else { if (!loadTsFile(tor, args[i], verbose)) @@ -254,7 +262,7 @@ int main(int argc, char **argv) if (!outputFile.isEmpty()) return releaseTranslator(tor, outputFile, verbose, ignoreUnfinished, - removeIdentical, mode) ? 0 : 1; + removeIdentical, idBased, mode) ? 0 : 1; return 0; } diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index eb743c2..21b230e 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -58,10 +58,6 @@ QT_BEGIN_NAMESPACE static const char MagicComment[] = "TRANSLATOR "; -static const int yyIdentMaxLen = 128; -static const int yyCommentMaxLen = 65536; -static const int yyStringMaxLen = 65536; - #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) #define STRING(s) static QString str##s(QLatin1String(STRINGIFY(s))) @@ -180,7 +176,8 @@ private: QString transcode(const QString &str, bool utf8); void recordMessage( int line, const QString &context, const QString &text, const QString &comment, - const QString &extracomment, bool utf8, bool plural); + const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, + bool utf8, bool plural); void processInclude(const QString &file, ConversionData &cd, QSet<QString> &inclusions); @@ -202,7 +199,7 @@ private: enum { Tok_Eof, Tok_class, Tok_friend, Tok_namespace, Tok_using, Tok_return, - Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8, + Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8, Tok_trid, Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS, Tok_Ident, Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, Tok_ColonColon, Tok_Equals, @@ -556,6 +553,8 @@ uint CppParser::getToken() return Tok_Q_DECLARE_TR_FUNCTIONS; if (yyIdent == QLatin1String("QT_TR_NOOP")) return Tok_tr; + if (yyIdent == QLatin1String("QT_TRID_NOOP")) + return Tok_trid; if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP")) return Tok_translate; if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP3")) @@ -591,6 +590,10 @@ uint CppParser::getToken() if (yyIdent == QLatin1String("namespace")) return Tok_namespace; break; + case 'q': + if (yyIdent == QLatin1String("qtTrId")) + return Tok_trid; + break; case 'r': if (yyIdent == QLatin1String("return")) return Tok_return; @@ -667,14 +670,9 @@ uint CppParser::getToken() yyCh = getChar(); if (yyCh == EOF || yyCh == '\n') break; - if (yyString.size() < yyStringMaxLen) { - yyString.append(QLatin1Char('\\')); - yyString.append(yyCh); - } - } else { - if (yyString.size() < yyStringMaxLen) - yyString.append(yyCh); + yyString.append(QLatin1Char('\\')); } + yyString.append(yyCh); yyCh = getChar(); } @@ -1299,13 +1297,16 @@ QString CppParser::transcode(const QString &str, bool utf8) void CppParser::recordMessage( int line, const QString &context, const QString &text, const QString &comment, - const QString &extracomment, bool utf8, bool plural) + const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, + bool utf8, bool plural) { TranslatorMessage msg( transcode(context, utf8), transcode(text, utf8), transcode(comment, utf8), QString(), yyFileName, line, QStringList(), TranslatorMessage::Unfinished, plural); msg.setExtraComment(transcode(extracomment.simplified(), utf8)); + msg.setId(msgid); + msg.setExtras(extra); if ((utf8 || yyForceUtf8) && !yyCodecIsUtf8 && msg.needs8Bit()) msg.setUtf8(true); results->tor->append(msg); @@ -1332,6 +1333,9 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) QString text; QString comment; QString extracomment; + QString msgid; + QString sourcetext; + TranslatorMessage::ExtraData extra; QString prefix; #ifdef DIAGNOSE_RETRANSLATABILITY QString functionName; @@ -1517,6 +1521,9 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) case Tok_trUtf8: if (!results->tor) goto case_default; + if (!sourcetext.isEmpty()) + qWarning("%s:%d: //%% cannot be used with tr() / QT_TR_NOOP(). Ignoring\n", + qPrintable(yyFileName), yyLineNo); utf8 = (yyTok == Tok_trUtf8); line = yyLineNo; yyTok = getToken(); @@ -1604,14 +1611,19 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) prefix.clear(); } - recordMessage(line, context, text, comment, extracomment, utf8, plural); + recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); } extracomment.clear(); + msgid.clear(); + extra.clear(); break; case Tok_translateUtf8: case Tok_translate: if (!results->tor) goto case_default; + if (!sourcetext.isEmpty()) + qWarning("%s:%d: //%% cannot be used with translate() / QT_TRANSLATE_NOOP(). Ignoring\n", + qPrintable(yyFileName), yyLineNo); utf8 = (yyTok == Tok_translateUtf8); line = yyLineNo; yyTok = getToken(); @@ -1655,9 +1667,34 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) break; } } - recordMessage(line, context, text, comment, extracomment, utf8, plural); + recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); + } + extracomment.clear(); + msgid.clear(); + extra.clear(); + break; + case Tok_trid: + if (!results->tor) + goto case_default; + if (sourcetext.isEmpty()) { + yyTok = getToken(); + } else { + if (!msgid.isEmpty()) + qWarning("%s:%d: //= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n", + qPrintable(yyFileName), yyLineNo); + //utf8 = false; // Maybe use //%% or something like that + line = yyLineNo; + yyTok = getToken(); + if (match(Tok_LeftParen) && matchString(&msgid) && !msgid.isEmpty()) { + bool plural = match(Tok_Comma); + recordMessage(line, QString(), sourcetext, QString(), extracomment, + msgid, extra, false, plural); + } + sourcetext.clear(); } extracomment.clear(); + msgid.clear(); + extra.clear(); break; case Tok_Q_DECLARE_TR_FUNCTIONS: case Tok_Q_OBJECT: @@ -1679,6 +1716,49 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) if (yyComment.startsWith(QLatin1Char(':'))) { yyComment.remove(0, 1); extracomment.append(yyComment); + } else if (yyComment.startsWith(QLatin1Char('='))) { + yyComment.remove(0, 1); + msgid = yyComment.simplified(); + } else if (yyComment.startsWith(QLatin1Char('~'))) { + yyComment.remove(0, 1); + yyComment = yyComment.trimmed(); + int k = yyComment.indexOf(QLatin1Char(' ')); + if (k > -1) + extra.insert(yyComment.left(k), yyComment.mid(k + 1).trimmed()); + } else if (yyComment.startsWith(QLatin1Char('%'))) { + int p = 1, c; + forever { + if (p >= yyComment.length()) + break; + c = yyComment.unicode()[p++].unicode(); + if (isspace(c)) + continue; + if (c != '"') { + qWarning("%s:%d: Unexpected character in meta string\n", + qPrintable(yyFileName), yyLineNo); + break; + } + forever { + if (p >= yyComment.length()) { + whoops: + qWarning("%s:%d: Unterminated meta string\n", + qPrintable(yyFileName), yyLineNo); + break; + } + c = yyComment.unicode()[p++].unicode(); + if (c == '"') + break; + if (c == '\\') { + if (p >= yyComment.length()) + goto whoops; + c = yyComment.unicode()[p++].unicode(); + if (c == '\n') + goto whoops; + sourcetext.append(QLatin1Char('\\')); + } + sourcetext.append(c); + } + } } else { comment = yyComment.simplified(); if (comment.startsWith(QLatin1String(MagicComment))) { @@ -1689,7 +1769,11 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) } else { context = comment.left(k); comment.remove(0, k + 1); - recordMessage(yyLineNo, context, QString(), comment, extracomment, false, false); + recordMessage(yyLineNo, context, QString(), comment, extracomment, + QString(), TranslatorMessage::ExtraData(), false, false); + extracomment.clear(); + results->tor->setExtras(extra); + extra.clear(); } } } @@ -1739,6 +1823,8 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions) prospectiveContext.clear(); prefix.clear(); extracomment.clear(); + msgid.clear(); + extra.clear(); yyTokColonSeen = false; yyTok = getToken(); break; @@ -1799,7 +1885,7 @@ void loadCPP(Translator &translator, const QStringList &filenames, ConversionDat ? translator.codecName() : cd.m_codecForSource; QTextCodec *codec = QTextCodec::codecForName(codecName); - foreach (const QString filename, filenames) { + foreach (const QString &filename, filenames) { if (CppFiles::getResults(filename) || CppFiles::isBlacklisted(filename)) continue; diff --git a/tools/linguist/lupdate/lupdate.1 b/tools/linguist/lupdate/lupdate.1 index 68958b9..b37e7b3 100644 --- a/tools/linguist/lupdate/lupdate.1 +++ b/tools/linguist/lupdate/lupdate.1 @@ -52,12 +52,12 @@ tool for the Qt GUI toolkit. .B Lupdate reads a qmake/tmake project file (.pro file), finds the translatable strings in the specified source, header and interface files, and -updates the translation files (.ts files) specified in it. The +updates the translation files (TS files) specified in it. The translation files are given to the translator who uses .B Qt Linguist to read the files and insert the translations. .PP -The .ts file format is a simple human-readable XML format that can be +The TS file format is a simple human-readable XML format that can be used with version control systems if required. .PP .SH OPTIONS @@ -74,7 +74,7 @@ Default: 'ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx'. Display the usage and exit. .TP .I "-locations {absolute|relative|none}" -Specify/override how source code references are saved in ts files. +Specify/override how source code references are saved in TS files. Default is absolute. .TP .I "-no-obsolete" @@ -84,7 +84,7 @@ Drop all obsolete strings. Do not recursively scan the following directories. .TP .I "-no-sort" -Do not sort contexts in .ts files. +Do not sort contexts in TS files. .TP .I "-pluralonly" Only include plural form messages. @@ -97,7 +97,7 @@ file syntax but different file suffix Recursively scan the following directories. .TP .I "-silent" -Don't explain what is being done. +Do not explain what is being done. .TP .I "-source-language <language>[_<region>]" Specify/override the language of the source strings. Defaults to @@ -139,8 +139,8 @@ translations will be reused as far as possible, and translated strings that have vanished from the source files are marked obsolete. .PP .B lupdate -can also be invoked with a list of C++ source files, .ui files -and .ts files: +can also be invoked with a list of C++ source files, UI files +and TS files: .PP .in +4 .nf diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index 18c8932..5a26774 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -43,6 +43,7 @@ #include <translator.h> #include <profileevaluator.h> +#include <proreader.h> #include <QtCore/QCoreApplication> #include <QtCore/QDebug> @@ -103,7 +104,7 @@ static void printUsage() " -silent\n" " Do not explain what is being done.\n" " -no-sort\n" - " Do not sort contexts in .ts files.\n" + " Do not sort contexts in TS files.\n" " -no-recursive\n" " Do not recursively scan the following directories.\n" " -recursive\n" @@ -112,10 +113,10 @@ static void printUsage() " Additional location to look for include files.\n" " May be specified multiple times.\n" " -locations {absolute|relative|none}\n" - " Specify/override how source code references are saved in ts files.\n" + " Specify/override how source code references are saved in TS files.\n" " Default is absolute.\n" " -no-ui-lines\n" - " Do not record line numbers in references to .ui files.\n" + " Do not record line numbers in references to UI files.\n" " -disable-heuristic {sametext|similartext|number}\n" " Disable the named merge heuristic. Can be specified multiple times.\n" " -pro <filename>\n" @@ -182,9 +183,10 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil if (options & Verbose) printOut(QObject::tr("Updating '%1'...\n").arg(fn)); + UpdateOptions theseOptions = options; if (tor.locationsType() == Translator::NoLocations) // Could be set from file - options |= NoLocations; - Translator out = merge(tor, fetchedTor, options, err); + theseOptions |= NoLocations; + Translator out = merge(tor, fetchedTor, theseOptions, err); if (!codecForTr.isEmpty()) out.setCodecName(codecForTr); @@ -201,6 +203,11 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil out.stripObsoleteMessages(); out.stripEmptyContexts(); + out.normalizeTranslations(cd); + if (!cd.errors().isEmpty()) { + printOut(cd.error()); + cd.clearErrors(); + } if (!out.save(fileName, cd, QLatin1String("auto"))) { printOut(cd.error()); *fail = true; @@ -487,7 +494,7 @@ int main(int argc, char **argv) cd.m_includePath += visitor.values(QLatin1String("INCLUDEPATH")); - evaluateProFile(visitor, &variables); + evaluateProFile(visitor, &variables, pfi.absolutePath()); sourceFiles = variables.value("SOURCES"); @@ -513,7 +520,8 @@ int main(int argc, char **argv) for (QStringList::iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) { if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive)) loadJava(fetchedTor, *it, cd); - else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)) + else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive) + || it->endsWith(QLatin1String(".jui"), Qt::CaseInsensitive)) loadUI(fetchedTor, *it, cd); else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive) || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive)) diff --git a/tools/linguist/phrasebooks/french.qph b/tools/linguist/phrasebooks/french.qph index f244013..d38da5a 100644 --- a/tools/linguist/phrasebooks/french.qph +++ b/tools/linguist/phrasebooks/french.qph @@ -1,4 +1,5 @@ -<!DOCTYPE QPH><QPH language="fr"> +<!DOCTYPE QPH> +<QPH language="fr"> <phrase> <source>About</source> <target>A propos</target> @@ -1101,4 +1102,228 @@ <source>Yes</source> <target>Oui</target> </phrase> +<phrase> + <source>Split</source> + <target>Scinder</target> +</phrase> +<phrase> + <source>&Edit</source> + <target>&Édition</target> +</phrase> +<phrase> + <source>&Redo</source> + <target>Re&faire</target> +</phrase> +<phrase> + <source>debugger</source> + <target>débogueur</target> +</phrase> +<phrase> + <source>Start Debugger</source> + <target>Lancer le débogueur</target> +</phrase> +<phrase> + <source>Executable:</source> + <target>Exécutable:</target> +</phrase> +<phrase> + <source>Filter:</source> + <target>Filtre:</target> +</phrase> +<phrase> + <source>Clear</source> + <target>Effacer</target> +</phrase> +<phrase> + <source>Host and port:</source> + <target>Hôte et port:</target> +</phrase> +<phrase> + <source>Architecture:</source> + <target>Architecture:</target> +</phrase> +<phrase> + <source>Server start script:</source> + <target>Script de démarrage du serveur:</target> +</phrase> +<phrase> + <source>&Undo</source> + <target>Annu&ler</target> +</phrase> +<phrase> + <source>Add Bookmark</source> + <target>Ajouter un signet</target> +</phrase> +<phrase> + <source>Bookmark:</source> + <target>Signet:</target> +</phrase> +<phrase> + <source>Add in Folder:</source> + <target>Ajouter dans le dossier:</target> +</phrase> +<phrase> + <source>+</source> + <target>+</target> +</phrase> +<phrase> + <source>New Folder</source> + <target>Nouveau dossier</target> +</phrase> +<phrase> + <source>Bookmarks</source> + <target>Signets</target> +</phrase> +<phrase> + <source>Rename Folder</source> + <target>Renommer le dossier</target> +</phrase> +<phrase> + <source>Bookmark</source> + <target>Signet</target> +</phrase> +<phrase> + <source>Remove</source> + <target>Retirer</target> +</phrase> +<phrase> + <source>Delete Folder</source> + <target>Supprimer le dossier</target> +</phrase> +<phrase> + <source>Add</source> + <target>Ajouter</target> +</phrase> +<phrase> + <source>Move Up</source> + <target>Vers le Haut</target> +</phrase> +<phrase> + <source>Move Down</source> + <target>Vers le Bas</target> +</phrase> +<phrase> + <source>Show Bookmark</source> + <target>Afficher le signet</target> +</phrase> +<phrase> + <source>Show Bookmark in New Tab</source> + <target>Afficher le signet dans un nouvel onglet</target> +</phrase> +<phrase> + <source>Delete Bookmark</source> + <target>Supprimer le signet</target> +</phrase> +<phrase> + <source>Rename Bookmark</source> + <target>Renommer le signet</target> +</phrase> +<phrase> + <source>Previous Bookmark</source> + <target>Signet précédent</target> +</phrase> +<phrase> + <source>Next Bookmark</source> + <target>Signet suivant</target> +</phrase> +<phrase> + <source>Condition:</source> + <target>Condition:</target> +</phrase> +<phrase> + <source>Working Directory:</source> + <target>Répertoire de travail:</target> +</phrase> +<phrase> + <source>Environment</source> + <target>Environnement</target> +</phrase> +<phrase> + <source>Arguments</source> + <target>Arguments</target> +</phrase> +<phrase> + <source>Build directory:</source> + <target>Répertoire de compilation:</target> +</phrase> +<phrase> + <source>Path:</source> + <target>Chemin:</target> +</phrase> +<phrase> + <source>General</source> + <target>Général</target> +</phrase> +<phrase> + <source>Username:</source> + <target>Nom d'utilisateur:</target> +</phrase> +<phrase> + <source>User interface</source> + <target>Interface utilisateur</target> +</phrase> +<phrase> + <source>Open Link</source> + <target>Ouvrir le lien</target> +</phrase> +<phrase> + <source> [read only]</source> + <target> [lecture seule]</target> +</phrase> +<phrase> + <source> [directory]</source> + <target> [répertoire]</target> +</phrase> +<phrase> + <source>Close All</source> + <target>Fermer tout</target> +</phrase> +<phrase> + <source>Failed!</source> + <target>Échec!</target> +</phrase> +<phrase> + <source>Proceed</source> + <target>Continuer</target> +</phrase> +<phrase> + <source>Make writable</source> + <target>Rendre inscriptible</target> +</phrase> +<phrase> + <source>Qt Creator</source> + <target>Qt Creator</target> +</phrase> +<phrase> + <source>&File</source> + <target>&Fichier</target> +</phrase> +<phrase> + <source>Activate %1</source> + <target>Activer %1</target> +</phrase> +<phrase> + <source>New Project</source> + <target>Nouveau projet</target> +</phrase> +<phrase> + <source>Close %1</source> + <target>Fermer %1</target> +</phrase> +<phrase> + <source>*</source> + <target>*</target> +</phrase> +<phrase> + <source>&Change</source> + <target>&Modifier</target> +</phrase> +<phrase> + <source>Close Other Editors</source> + <target>Fermer les autres éditeurs</target> +</phrase> +<phrase> + <source>Close All Except %1</source> + <target>Fermer tout sauf %1</target> +</phrase> </QPH> diff --git a/tools/linguist/shared/abstractproitemvisitor.h b/tools/linguist/shared/abstractproitemvisitor.h index 0691fdc..43e79e0 100644 --- a/tools/linguist/shared/abstractproitemvisitor.h +++ b/tools/linguist/shared/abstractproitemvisitor.h @@ -49,19 +49,23 @@ QT_BEGIN_NAMESPACE struct AbstractProItemVisitor { virtual ~AbstractProItemVisitor() {} - virtual bool visitBeginProBlock(ProBlock *block) = 0; - virtual bool visitEndProBlock(ProBlock *block) = 0; - virtual bool visitBeginProVariable(ProVariable *variable) = 0; - virtual bool visitEndProVariable(ProVariable *variable) = 0; + virtual ProItem::ProItemReturn visitBeginProBlock(ProBlock *block) = 0; + virtual void visitEndProBlock(ProBlock *block) = 0; - virtual bool visitBeginProFile(ProFile *value) = 0; - virtual bool visitEndProFile(ProFile *value) = 0; + virtual ProItem::ProItemReturn visitProLoopIteration() = 0; + virtual void visitProLoopCleanup() = 0; - virtual bool visitProValue(ProValue *value) = 0; - virtual bool visitProFunction(ProFunction *function) = 0; - virtual bool visitProOperator(ProOperator *function) = 0; - virtual bool visitProCondition(ProCondition *function) = 0; + virtual void visitBeginProVariable(ProVariable *variable) = 0; + virtual void visitEndProVariable(ProVariable *variable) = 0; + + virtual ProItem::ProItemReturn visitBeginProFile(ProFile *value) = 0; + virtual ProItem::ProItemReturn visitEndProFile(ProFile *value) = 0; + + virtual void visitProValue(ProValue *value) = 0; + virtual ProItem::ProItemReturn visitProFunction(ProFunction *function) = 0; + virtual void visitProOperator(ProOperator *function) = 0; + virtual void visitProCondition(ProCondition *function) = 0; }; QT_END_NAMESPACE diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp index e22aa7d..a6795cb 100644 --- a/tools/linguist/shared/po.cpp +++ b/tools/linguist/shared/po.cpp @@ -359,6 +359,7 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd) const QChar quote = QLatin1Char('"'); const QChar newline = QLatin1Char('\n'); QTextStream in(&dev); + in.setCodec(cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource); bool error = false; // format of a .po file entry: @@ -554,7 +555,7 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd) { bool ok = true; QTextStream out(&dev); - //qDebug() << "OUT CODEC: " << out.codec()->name(); + out.setCodec(cd.m_outputCodec.isEmpty() ? QByteArray("UTF-8") : cd.m_outputCodec); bool first = true; if (translator.messages().isEmpty() || !translator.messages().first().sourceText().isEmpty()) { @@ -636,7 +637,7 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd) if (plural.isEmpty()) plural = msg.sourceText(); out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural); - QStringList translations = translator.normalizedTranslations(msg, cd, &ok); + const QStringList &translations = msg.translations(); for (int i = 0; i != translations.size(); ++i) { QString str = translations.at(i); str.replace(QChar(Translator::BinaryVariantSeparator), diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index ef59543..5a9095a 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -60,7 +60,7 @@ #ifdef Q_OS_UNIX #include <unistd.h> #include <sys/utsname.h> -#elif defined(Q_OS_WIN32) +#else #include <Windows.h> #endif #include <stdio.h> @@ -68,8 +68,10 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_PCLOSE pclose #endif QT_BEGIN_NAMESPACE @@ -169,16 +171,18 @@ public: /////////////// Evaluating pro file contents // implementation of AbstractProItemVisitor - bool visitBeginProBlock(ProBlock *block); - bool visitEndProBlock(ProBlock *block); - bool visitBeginProVariable(ProVariable *variable); - bool visitEndProVariable(ProVariable *variable); - bool visitBeginProFile(ProFile *value); - bool visitEndProFile(ProFile *value); - bool visitProValue(ProValue *value); - bool visitProFunction(ProFunction *function); - bool visitProOperator(ProOperator *oper); - bool visitProCondition(ProCondition *condition); + ProItem::ProItemReturn visitBeginProBlock(ProBlock *block); + void visitEndProBlock(ProBlock *block); + ProItem::ProItemReturn visitProLoopIteration(); + void visitProLoopCleanup(); + void visitBeginProVariable(ProVariable *variable); + void visitEndProVariable(ProVariable *variable); + ProItem::ProItemReturn visitBeginProFile(ProFile *value); + ProItem::ProItemReturn visitEndProFile(ProFile *value); + void visitProValue(ProValue *value); + ProItem::ProItemReturn visitProFunction(ProFunction *function); + void visitProOperator(ProOperator *oper); + void visitProCondition(ProCondition *condition); QStringList valuesDirect(const QString &variableName) const { return m_valuemap[variableName]; } QStringList values(const QString &variableName) const; @@ -188,10 +192,8 @@ public: QString propertyValue(const QString &val) const; bool isActiveConfig(const QString &config, bool regex = false); - QStringList expandPattern(const QString &pattern); - void expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out); QStringList expandVariableReferences(const QString &value); + void doVariableReplace(QString *str); QStringList evaluateExpandFunction(const QString &function, const QString &arguments); QString format(const char *format) const; @@ -199,17 +201,22 @@ public: QString currentDirectory() const; ProFile *currentProFile() const; - bool evaluateConditionalFunction(const QString &function, const QString &arguments, bool *result); - bool evaluateFile(const QString &fileName, bool *result); - bool evaluateFeatureFile(const QString &fileName, bool *result); + ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments); + bool evaluateFile(const QString &fileName); + bool evaluateFeatureFile(const QString &fileName); + + static inline ProItem::ProItemReturn returnBool(bool b) + { return b ? ProItem::ReturnTrue : ProItem::ReturnFalse; } + + QStringList evaluateFunction(ProBlock *funcPtr, const QStringList &argumentsList, bool *ok); QStringList qmakeFeaturePaths(); - enum { ConditionTrue, ConditionFalse, ConditionElse }; - int m_condition; - int m_prevCondition; - bool m_updateCondition; - bool m_invertNext; + struct State { + bool condition; + bool prevCondition; + } m_sts; + bool m_invertNext; // Short-lived, so not in State int m_skipLevel; bool m_cumulative; bool m_isFirstVariableValue; @@ -218,6 +225,14 @@ public: QString m_origfile; QString m_oldPath; // To restore the current path to the path QStack<ProFile*> m_profileStack; // To handle 'include(a.pri), so we can track back to 'a.pro' when finished with 'a.pri' + struct ProLoop { + QString variable; + QStringList oldVarVal; + QStringList list; + int index; + bool infinite; + }; + QStack<ProLoop> m_loopStack; // we need the following two variables for handling // CONFIG = foo bar $$CONFIG @@ -229,10 +244,23 @@ public: QHash<QString, QString> m_properties; QString m_outputDir; + bool m_definingTest; + QString m_definingFunc; + QHash<QString, ProBlock *> m_testFunctions; + QHash<QString, ProBlock *> m_replaceFunctions; + QStringList m_returnValue; + QStack<QHash<QString, QStringList> > m_valuemapStack; + QStack<QHash<const ProFile*, QHash<QString, QStringList> > > m_filevaluemapStack; + int m_prevLineNo; // Checking whether we're assigning the same TARGET ProFile *m_prevProFile; // See m_prevLineNo }; +#if (!defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) && !defined(__SUNPRO_CC) +Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::State, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::ProLoop, Q_MOVABLE_TYPE); +#endif + ProFileEvaluator::Private::Private(ProFileEvaluator *q_) : q(q_) { @@ -245,11 +273,12 @@ ProFileEvaluator::Private::Private(ProFileEvaluator *q_) m_cumulative = true; // Evaluator state - m_updateCondition = false; - m_condition = ConditionFalse; + m_sts.condition = false; + m_sts.prevCondition = false; m_invertNext = false; m_skipLevel = 0; m_isFirstVariableValue = true; + m_definingFunc.clear(); } bool ProFileEvaluator::Private::read(ProFile *pro) @@ -561,91 +590,125 @@ void ProFileEvaluator::Private::updateItem() } -bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) +ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) { - if (block->blockKind() == ProBlock::ScopeKind) { - m_updateCondition = true; + if (block->blockKind() & ProBlock::ScopeContentsKind) { + if (!m_definingFunc.isEmpty()) { + if (!m_skipLevel || m_cumulative) { + QHash<QString, ProBlock *> *hash = + (m_definingTest ? &m_testFunctions : &m_replaceFunctions); + if (ProBlock *def = hash->value(m_definingFunc)) + def->deref(); + hash->insert(m_definingFunc, block); + block->ref(); + block->setBlockKind(block->blockKind() | ProBlock::FunctionBodyKind); + } + m_definingFunc.clear(); + return ProItem::ReturnSkip; + } else if (!(block->blockKind() & ProBlock::FunctionBodyKind)) { + if (!m_sts.condition) + ++m_skipLevel; + else + Q_ASSERT(!m_skipLevel); + } + } else { if (!m_skipLevel) { - m_prevCondition = m_condition; - m_condition = ConditionFalse; + if (m_sts.condition) { + m_sts.prevCondition = true; + m_sts.condition = false; + } } else { - Q_ASSERT(m_condition != ConditionTrue); + Q_ASSERT(!m_sts.condition); } - } else if (block->blockKind() & ProBlock::ScopeContentsKind) { - m_updateCondition = false; - if (m_condition != ConditionTrue) - ++m_skipLevel; - else - Q_ASSERT(!m_skipLevel); } - return true; + return ProItem::ReturnTrue; } -bool ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) +void ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) { - if (block->blockKind() & ProBlock::ScopeContentsKind) { + if ((block->blockKind() & ProBlock::ScopeContentsKind) + && !(block->blockKind() & ProBlock::FunctionBodyKind)) { if (m_skipLevel) { - Q_ASSERT(m_condition != ConditionTrue); + Q_ASSERT(!m_sts.condition); --m_skipLevel; - } else { + } else if (!(block->blockKind() & ProBlock::SingleLine)) { // Conditionals contained inside this block may have changed the state. // So we reset it here to make an else following us do the right thing. - m_condition = ConditionTrue; + m_sts.condition = true; } } - return true; } -bool ProFileEvaluator::Private::visitBeginProVariable(ProVariable *variable) +ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoopIteration() +{ + ProLoop &loop = m_loopStack.top(); + + if (loop.infinite) { + if (!loop.variable.isEmpty()) + m_valuemap[loop.variable] = QStringList(QString::number(loop.index++)); + if (loop.index > 1000) { + q->errorMessage(format("ran into infinite loop (> 1000 iterations).")); + return ProItem::ReturnFalse; + } + } else { + QString val; + do { + if (loop.index >= loop.list.count()) + return ProItem::ReturnFalse; + val = loop.list.at(loop.index++); + } while (val.isEmpty()); // stupid, but qmake is like that + m_valuemap[loop.variable] = QStringList(val); + } + return ProItem::ReturnTrue; +} + +void ProFileEvaluator::Private::visitProLoopCleanup() +{ + ProLoop &loop = m_loopStack.top(); + m_valuemap[loop.variable] = loop.oldVarVal; + m_loopStack.pop_back(); +} + +void ProFileEvaluator::Private::visitBeginProVariable(ProVariable *variable) { m_lastVarName = variable->variable(); m_variableOperator = variable->variableOperator(); m_isFirstVariableValue = true; m_tempValuemap = m_valuemap; m_tempFilevaluemap = m_filevaluemap; - return true; } -bool ProFileEvaluator::Private::visitEndProVariable(ProVariable *variable) +void ProFileEvaluator::Private::visitEndProVariable(ProVariable *variable) { Q_UNUSED(variable); m_valuemap = m_tempValuemap; m_filevaluemap = m_tempFilevaluemap; m_lastVarName.clear(); - return true; } -bool ProFileEvaluator::Private::visitProOperator(ProOperator *oper) +void ProFileEvaluator::Private::visitProOperator(ProOperator *oper) { m_invertNext = (oper->operatorKind() == ProOperator::NotOperator); - return true; } -bool ProFileEvaluator::Private::visitProCondition(ProCondition *cond) +void ProFileEvaluator::Private::visitProCondition(ProCondition *cond) { if (!m_skipLevel) { - if (cond->text().toLower() == QLatin1String("else")) { - // The state ConditionElse makes sure that subsequential elses are ignored. - // That's braindead, but qmake is like that. - if (m_prevCondition == ConditionTrue) - m_condition = ConditionElse; - else if (m_prevCondition == ConditionFalse) - m_condition = ConditionTrue; - } else if (m_condition == ConditionFalse) { - if (isActiveConfig(cond->text(), true) ^ m_invertNext) - m_condition = ConditionTrue; + if (!cond->text().compare(QLatin1String("else"), Qt::CaseInsensitive)) { + m_sts.condition = !m_sts.prevCondition; + } else { + m_sts.prevCondition = false; + if (!m_sts.condition && isActiveConfig(cond->text(), true) ^ m_invertNext) + m_sts.condition = true; } } m_invertNext = false; - return true; } -bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) +ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) { PRE(pro); - bool ok = true; m_lineNo = pro->lineNumber(); - if (m_origfile.isEmpty()) m_origfile = pro->fileName(); if (m_oldPath.isEmpty()) { @@ -663,21 +726,20 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) m_cumulative = false; // This is what qmake does, everything set in the mkspec is also set // But this also creates a lot of problems - evaluateFile(mkspecDirectory + QLatin1String("/default/qmake.conf"), &ok); - evaluateFile(mkspecDirectory + QLatin1String("/features/default_pre.prf"), &ok); + evaluateFile(mkspecDirectory + QLatin1String("/default/qmake.conf")); + evaluateFile(mkspecDirectory + QLatin1String("/features/default_pre.prf")); m_cumulative = cumulative; } - ok = QDir::setCurrent(pro->directoryName()); + return returnBool(QDir::setCurrent(pro->directoryName())); } - return ok; + return ProItem::ReturnTrue; } -bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro) +ProItem::ProItemReturn ProFileEvaluator::Private::visitEndProFile(ProFile * pro) { PRE(pro); - bool ok = true; m_lineNo = pro->lineNumber(); if (m_profileStack.count() == 1 && !m_oldPath.isEmpty()) { const QString &mkspecDirectory = propertyValue(QLatin1String("QMAKE_MKSPECS")); @@ -685,7 +747,7 @@ bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro) bool cumulative = m_cumulative; m_cumulative = false; - evaluateFile(mkspecDirectory + QLatin1String("/features/default_post.prf"), &ok); + evaluateFile(mkspecDirectory + QLatin1String("/features/default_post.prf")); QSet<QString> processed; forever { @@ -695,9 +757,8 @@ bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro) const QString config = configs[i].toLower(); if (!processed.contains(config)) { processed.insert(config); - evaluateFile(mkspecDirectory + QLatin1String("/features/") - + config + QLatin1String(".prf"), &ok); - if (ok) { + if (evaluateFile(mkspecDirectory + QLatin1String("/features/") + + config + QLatin1String(".prf"))) { finished = false; break; } @@ -707,13 +768,21 @@ bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro) break; } + foreach (ProBlock *itm, m_replaceFunctions) + itm->deref(); + m_replaceFunctions.clear(); + foreach (ProBlock *itm, m_testFunctions) + itm->deref(); + m_testFunctions.clear(); + m_cumulative = cumulative; } m_profileStack.pop(); - ok = QDir::setCurrent(m_oldPath); + return returnBool(QDir::setCurrent(m_oldPath)); } - return ok; + + return ProItem::ReturnTrue; } static void replaceInList(QStringList *varlist, @@ -734,7 +803,7 @@ static void replaceInList(QStringList *varlist, } } -bool ProFileEvaluator::Private::visitProValue(ProValue *value) +void ProFileEvaluator::Private::visitProValue(ProValue *value) { PRE(value); m_lineNo = value->lineNumber(); @@ -761,29 +830,6 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) m_prevLineNo = m_lineNo; m_prevProFile = currentProFile(); - // The following two blocks fix bug 180128 by making all "interesting" - // file name absolute in each .pro file, not just the top most one - if (varName == QLatin1String("SOURCES") - || varName == QLatin1String("HEADERS") - || varName == QLatin1String("INTERFACES") - || varName == QLatin1String("FORMS") - || varName == QLatin1String("FORMS3") - || varName == QLatin1String("RESOURCES")) { - // matches only existent files, expand certain(?) patterns - QStringList vv; - for (int i = v.count(); --i >= 0; ) - vv << expandPattern(v[i]); - v = vv; - } - - if (varName == QLatin1String("TRANSLATIONS")) { - // also matches non-existent files, but does not expand pattern - QString dir = QFileInfo(currentFileName()).absolutePath(); - dir += QLatin1Char('/'); - for (int i = v.count(); --i >= 0; ) - v[i] = QFileInfo(dir, v[i]).absoluteFilePath(); - } - switch (m_variableOperator) { case ProVariable::SetOperator: // = if (!m_cumulative) { @@ -828,16 +874,16 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) { // DEFINES ~= s/a/b/?[gqi] - // FIXME: qmake variable-expands val first. + doVariableReplace(&val); if (val.length() < 4 || val[0] != QLatin1Char('s')) { q->logMessage(format("the ~= operator can handle only the s/// function.")); - return false; + break; } QChar sep = val.at(1); QStringList func = val.split(sep); if (func.count() < 3 || func.count() > 4) { q->logMessage(format("the s/// function expects 3 or 4 arguments.")); - return false; + break; } bool global = false, quote = false, case_sense = false; @@ -864,12 +910,16 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) } m_isFirstVariableValue = false; - return true; } -bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) +ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func) { - if (!m_updateCondition || m_condition == ConditionFalse) { + // Make sure that called subblocks don't inherit & destroy the state + bool invertThis = m_invertNext; + m_invertNext = false; + if (!m_skipLevel) + m_sts.prevCondition = false; + if (m_cumulative || !m_sts.condition) { QString text = func->text(); int lparen = text.indexOf(QLatin1Char('(')); int rparen = text.lastIndexOf(QLatin1Char(')')); @@ -877,16 +927,13 @@ bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) QString arguments = text.mid(lparen + 1, rparen - lparen - 1); QString funcName = text.left(lparen); m_lineNo = func->lineNumber(); - bool result; - if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) { - m_invertNext = false; - return false; - } - if (!m_skipLevel && (result ^ m_invertNext)) - m_condition = ConditionTrue; + ProItem::ProItemReturn result = evaluateConditionalFunction(funcName.trimmed(), arguments); + if (result != ProItem::ReturnFalse && result != ProItem::ReturnTrue) + return result; + if (!m_skipLevel && ((result == ProItem::ReturnTrue) ^ invertThis)) + m_sts.condition = true; } - m_invertNext = false; - return true; + return ProItem::ReturnTrue; } @@ -1012,6 +1059,11 @@ QString ProFileEvaluator::Private::currentDirectory() const return cur->directoryName(); } +void ProFileEvaluator::Private::doVariableReplace(QString *str) +{ + *str = expandVariableReferences(*str).join(QString(Option::field_sep)); +} + QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str) { QStringList ret; @@ -1226,10 +1278,49 @@ bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex return false; } +QStringList ProFileEvaluator::Private::evaluateFunction( + ProBlock *funcPtr, const QStringList &argumentsList, bool *ok) +{ + bool oki; + QStringList ret; + + if (m_valuemapStack.count() >= 100) { + q->errorMessage(format("ran into infinite recursion (depth > 100).")); + oki = false; + } else { + State sts = m_sts; + m_valuemapStack.push(m_valuemap); + m_filevaluemapStack.push(m_filevaluemap); + + QStringList args; + for (int i = 0; i < argumentsList.count(); ++i) { + QStringList theArgs = expandVariableReferences(argumentsList[i]); + args += theArgs; + m_valuemap[QString::number(i+1)] = theArgs; + } + m_valuemap[QLatin1String("ARGS")] = args; + oki = (funcPtr->Accept(this) != ProItem::ReturnFalse); // True || Return + ret = m_returnValue; + m_returnValue.clear(); + + m_valuemap = m_valuemapStack.pop(); + m_filevaluemap = m_filevaluemapStack.pop(); + m_sts = sts; + } + if (ok) + *ok = oki; + if (oki) + return ret; + return QStringList(); +} + QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments) { QStringList argumentsList = split_arg_list(arguments); + if (ProBlock *funcPtr = m_replaceFunctions.value(func, 0)) + return evaluateFunction(funcPtr, argumentsList, 0); + QStringList args; for (int i = 0; i < argumentsList.count(); ++i) args += expandVariableReferences(argumentsList[i]).join(Option::field_sep); @@ -1240,35 +1331,34 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_REPLACE }; - static QHash<QString, int> *expands = 0; - if (!expands) { - expands = new QHash<QString, int>; - expands->insert(QLatin1String("member"), E_MEMBER); - expands->insert(QLatin1String("first"), E_FIRST); - expands->insert(QLatin1String("last"), E_LAST); - expands->insert(QLatin1String("cat"), E_CAT); - expands->insert(QLatin1String("fromfile"), E_FROMFILE); // implementation disabled (see comment below) - expands->insert(QLatin1String("eval"), E_EVAL); - expands->insert(QLatin1String("list"), E_LIST); - expands->insert(QLatin1String("sprintf"), E_SPRINTF); - expands->insert(QLatin1String("join"), E_JOIN); - expands->insert(QLatin1String("split"), E_SPLIT); - expands->insert(QLatin1String("basename"), E_BASENAME); - expands->insert(QLatin1String("dirname"), E_DIRNAME); - expands->insert(QLatin1String("section"), E_SECTION); - expands->insert(QLatin1String("find"), E_FIND); - expands->insert(QLatin1String("system"), E_SYSTEM); - expands->insert(QLatin1String("unique"), E_UNIQUE); - expands->insert(QLatin1String("quote"), E_QUOTE); - expands->insert(QLatin1String("escape_expand"), E_ESCAPE_EXPAND); - expands->insert(QLatin1String("upper"), E_UPPER); - expands->insert(QLatin1String("lower"), E_LOWER); - expands->insert(QLatin1String("re_escape"), E_RE_ESCAPE); - expands->insert(QLatin1String("files"), E_FILES); - expands->insert(QLatin1String("prompt"), E_PROMPT); // interactive, so cannot be implemented - expands->insert(QLatin1String("replace"), E_REPLACE); + static QHash<QString, int> expands; + if (expands.isEmpty()) { + expands.insert(QLatin1String("member"), E_MEMBER); + expands.insert(QLatin1String("first"), E_FIRST); + expands.insert(QLatin1String("last"), E_LAST); + expands.insert(QLatin1String("cat"), E_CAT); + expands.insert(QLatin1String("fromfile"), E_FROMFILE); // implementation disabled (see comment below) + expands.insert(QLatin1String("eval"), E_EVAL); + expands.insert(QLatin1String("list"), E_LIST); + expands.insert(QLatin1String("sprintf"), E_SPRINTF); + expands.insert(QLatin1String("join"), E_JOIN); + expands.insert(QLatin1String("split"), E_SPLIT); + expands.insert(QLatin1String("basename"), E_BASENAME); + expands.insert(QLatin1String("dirname"), E_DIRNAME); + expands.insert(QLatin1String("section"), E_SECTION); + expands.insert(QLatin1String("find"), E_FIND); + expands.insert(QLatin1String("system"), E_SYSTEM); + expands.insert(QLatin1String("unique"), E_UNIQUE); + expands.insert(QLatin1String("quote"), E_QUOTE); + expands.insert(QLatin1String("escape_expand"), E_ESCAPE_EXPAND); + expands.insert(QLatin1String("upper"), E_UPPER); + expands.insert(QLatin1String("lower"), E_LOWER); + expands.insert(QLatin1String("re_escape"), E_RE_ESCAPE); + expands.insert(QLatin1String("files"), E_FILES); + expands.insert(QLatin1String("prompt"), E_PROMPT); // interactive, so cannot be implemented + expands.insert(QLatin1String("replace"), E_REPLACE); } - ExpandFunc func_t = ExpandFunc(expands->value(func.toLower())); + ExpandFunc func_t = ExpandFunc(expands.value(func.toLower())); QStringList ret; @@ -1425,7 +1515,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun bool singleLine = true; if (args.count() > 1) - singleLine = (args[1].toLower() == QLatin1String("true")); + singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive)); QFile qfile(file); if (qfile.open(QIODevice::ReadOnly)) { @@ -1499,7 +1589,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun FILE *proc = QT_POPEN(args[0].toLatin1(), "r"); bool singleLine = true; if (args.count() > 1) - singleLine = (args[1].toLower() == QLatin1String("true")); + singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive)); QString output; while (proc && !feof(proc)) { int read_in = int(fread(buff, 1, 255, proc)); @@ -1513,6 +1603,8 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun output += QLatin1String(buff); } ret += split_value_list(output); + if (proc) + QT_PCLOSE(proc); } } break; @@ -1579,7 +1671,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } else { bool recursive = false; if (args.count() == 2) - recursive = (args[1].toLower() == QLatin1String("true") || args[1].toInt()); + recursive = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive) || args[1].toInt()); QStringList dirs; QString r = Option::fixPathToLocalOS(args[0]); int slash = r.lastIndexOf(QDir::separator()); @@ -1632,13 +1724,40 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun return ret; } -bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &function, - const QString &arguments, bool *result) +ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( + const QString &function, const QString &arguments) { QStringList argumentsList = split_arg_list(arguments); + + if (ProBlock *funcPtr = m_testFunctions.value(function, 0)) { + bool ok; + QStringList ret = evaluateFunction(funcPtr, argumentsList, &ok); + if (ok) { + if (ret.isEmpty()) { + return ProItem::ReturnTrue; + } else { + if (ret.first() != QLatin1String("false")) { + if (ret.first() == QLatin1String("true")) { + return ProItem::ReturnTrue; + } else { + bool ok; + int val = ret.first().toInt(&ok); + if (ok) { + if (val) + return ProItem::ReturnTrue; + } else { + q->logMessage(format("Unexpected return value from test '%1': %2") + .arg(function).arg(ret.join(QLatin1String(" :: ")))); + } + } + } + } + } + return ProItem::ReturnFalse; + } + QString sep; sep.append(Option::field_sep); - QStringList args; for (int i = 0; i < argumentsList.count(); ++i) args += expandVariableReferences(argumentsList[i]).join(sep); @@ -1646,91 +1765,282 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, - T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF }; - - static QHash<QString, int> *functions = 0; - if (!functions) { - functions = new QHash<QString, int>; - functions->insert(QLatin1String("requires"), T_REQUIRES); - functions->insert(QLatin1String("greaterThan"), T_GREATERTHAN); - functions->insert(QLatin1String("lessThan"), T_LESSTHAN); - functions->insert(QLatin1String("equals"), T_EQUALS); - functions->insert(QLatin1String("isEqual"), T_EQUALS); - functions->insert(QLatin1String("exists"), T_EXISTS); - functions->insert(QLatin1String("export"), T_EXPORT); - functions->insert(QLatin1String("clear"), T_CLEAR); - functions->insert(QLatin1String("unset"), T_UNSET); - functions->insert(QLatin1String("eval"), T_EVAL); - functions->insert(QLatin1String("CONFIG"), T_CONFIG); - functions->insert(QLatin1String("if"), T_IF); - functions->insert(QLatin1String("isActiveConfig"), T_CONFIG); - functions->insert(QLatin1String("system"), T_SYSTEM); - functions->insert(QLatin1String("return"), T_RETURN); - functions->insert(QLatin1String("break"), T_BREAK); - functions->insert(QLatin1String("next"), T_NEXT); - functions->insert(QLatin1String("defined"), T_DEFINED); - functions->insert(QLatin1String("contains"), T_CONTAINS); - functions->insert(QLatin1String("infile"), T_INFILE); - functions->insert(QLatin1String("count"), T_COUNT); - functions->insert(QLatin1String("isEmpty"), T_ISEMPTY); - functions->insert(QLatin1String("load"), T_LOAD); //v - functions->insert(QLatin1String("include"), T_INCLUDE); //v - functions->insert(QLatin1String("debug"), T_DEBUG); - functions->insert(QLatin1String("message"), T_MESSAGE); //v - functions->insert(QLatin1String("warning"), T_MESSAGE); //v - functions->insert(QLatin1String("error"), T_MESSAGE); //v + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF, + T_FOR, T_DEFINE_TEST, T_DEFINE_REPLACE }; + + static QHash<QString, int> functions; + if (functions.isEmpty()) { + functions.insert(QLatin1String("requires"), T_REQUIRES); + functions.insert(QLatin1String("greaterThan"), T_GREATERTHAN); + functions.insert(QLatin1String("lessThan"), T_LESSTHAN); + functions.insert(QLatin1String("equals"), T_EQUALS); + functions.insert(QLatin1String("isEqual"), T_EQUALS); + functions.insert(QLatin1String("exists"), T_EXISTS); + functions.insert(QLatin1String("export"), T_EXPORT); + functions.insert(QLatin1String("clear"), T_CLEAR); + functions.insert(QLatin1String("unset"), T_UNSET); + functions.insert(QLatin1String("eval"), T_EVAL); + functions.insert(QLatin1String("CONFIG"), T_CONFIG); + functions.insert(QLatin1String("if"), T_IF); + functions.insert(QLatin1String("isActiveConfig"), T_CONFIG); + functions.insert(QLatin1String("system"), T_SYSTEM); + functions.insert(QLatin1String("return"), T_RETURN); + functions.insert(QLatin1String("break"), T_BREAK); + functions.insert(QLatin1String("next"), T_NEXT); + functions.insert(QLatin1String("defined"), T_DEFINED); + functions.insert(QLatin1String("contains"), T_CONTAINS); + functions.insert(QLatin1String("infile"), T_INFILE); + functions.insert(QLatin1String("count"), T_COUNT); + functions.insert(QLatin1String("isEmpty"), T_ISEMPTY); + functions.insert(QLatin1String("load"), T_LOAD); //v + functions.insert(QLatin1String("include"), T_INCLUDE); //v + functions.insert(QLatin1String("debug"), T_DEBUG); + functions.insert(QLatin1String("message"), T_MESSAGE); //v + functions.insert(QLatin1String("warning"), T_MESSAGE); //v + functions.insert(QLatin1String("error"), T_MESSAGE); //v + functions.insert(QLatin1String("for"), T_FOR); //v + functions.insert(QLatin1String("defineTest"), T_DEFINE_TEST); //v + functions.insert(QLatin1String("defineReplace"), T_DEFINE_REPLACE); //v } - bool cond = false; - bool ok = true; - - TestFunc func_t = (TestFunc)functions->value(function); + TestFunc func_t = (TestFunc)functions.value(function); switch (func_t) { + case T_DEFINE_TEST: + m_definingTest = true; + goto defineFunc; + case T_DEFINE_REPLACE: + m_definingTest = false; + defineFunc: + if (args.count() != 1) { + q->logMessage(format("%s(function) requires one argument.").arg(function)); + return ProItem::ReturnFalse; + } + m_definingFunc = args.first(); + return ProItem::ReturnTrue; + case T_DEFINED: + if (args.count() < 1 || args.count() > 2) { + q->logMessage(format("defined(function, [\"test\"|\"replace\"])" + " requires one or two arguments.")); + return ProItem::ReturnFalse; + } + if (args.count() > 1) { + if (args[1] == QLatin1String("test")) + return returnBool(m_testFunctions.contains(args[0])); + else if (args[1] == QLatin1String("replace")) + return returnBool(m_replaceFunctions.contains(args[0])); + q->logMessage(format("defined(function, type):" + " unexpected type [%1].\n").arg(args[1])); + return ProItem::ReturnFalse; + } + return returnBool(m_replaceFunctions.contains(args[0]) + || m_testFunctions.contains(args[0])); + case T_RETURN: + m_returnValue = args; + // It is "safe" to ignore returns - due to qmake brokeness + // they cannot be used to terminate loops anyway. + if (m_skipLevel || m_cumulative) + return ProItem::ReturnTrue; + if (m_valuemapStack.isEmpty()) { + q->logMessage(format("unexpected return().")); + return ProItem::ReturnFalse; + } + return ProItem::ReturnReturn; + case T_EXPORT: + if (m_skipLevel && !m_cumulative) + return ProItem::ReturnTrue; + if (args.count() != 1) { + q->logMessage(format("export(variable) requires one argument.")); + return ProItem::ReturnFalse; + } + for (int i = 0; i < m_valuemapStack.size(); ++i) { + m_valuemapStack[i][args[0]] = m_valuemap[args[0]]; + m_filevaluemapStack[i][currentProFile()][args[0]] = + m_filevaluemap[currentProFile()][args[0]]; + } + return ProItem::ReturnTrue; #if 0 case T_INFILE: case T_REQUIRES: - case T_GREATERTHAN: - case T_LESSTHAN: - case T_EQUALS: - case T_EXPORT: - case T_CLEAR: - case T_UNSET: case T_EVAL: - case T_IF: - case T_RETURN: +#endif + case T_FOR: { + if (m_cumulative) // This is a no-win situation, so just pretend it's no loop + return ProItem::ReturnTrue; + if (m_skipLevel) + return ProItem::ReturnFalse; + if (args.count() > 2 || args.count() < 1) { + q->logMessage(format("for({var, list|var, forever|ever})" + " requires one or two arguments.")); + return ProItem::ReturnFalse; + } + ProLoop loop; + loop.infinite = false; + loop.index = 0; + QString it_list; + if (args.count() == 1) { + doVariableReplace(&args[0]); + it_list = args[0]; + if (args[0] != QLatin1String("ever")) { + q->logMessage(format("for({var, list|var, forever|ever})" + " requires one or two arguments.")); + return ProItem::ReturnFalse; + } + it_list = QLatin1String("forever"); + } else { + loop.variable = args[0]; + loop.oldVarVal = m_valuemap.value(loop.variable); + doVariableReplace(&args[1]); + it_list = args[1]; + } + loop.list = m_valuemap[it_list]; + if (loop.list.isEmpty()) { + if (it_list == QLatin1String("forever")) { + loop.infinite = true; + } else { + int dotdot = it_list.indexOf(QLatin1String("..")); + if (dotdot != -1) { + bool ok; + int start = it_list.left(dotdot).toInt(&ok); + if (ok) { + int end = it_list.mid(dotdot+2).toInt(&ok); + if (ok) { + if (start < end) { + for (int i = start; i <= end; i++) + loop.list << QString::number(i); + } else { + for (int i = start; i >= end; i--) + loop.list << QString::number(i); + } + } + } + } + } + } + m_loopStack.push(loop); + m_sts.condition = true; + return ProItem::ReturnLoop; + } case T_BREAK: + if (m_skipLevel) + return ProItem::ReturnFalse; + if (!m_loopStack.isEmpty()) + return ProItem::ReturnBreak; + // ### missing: breaking out of multiline blocks + q->logMessage(format("unexpected break().")); + return ProItem::ReturnFalse; case T_NEXT: - case T_DEFINED: -#endif + if (m_skipLevel) + return ProItem::ReturnFalse; + if (!m_loopStack.isEmpty()) + return ProItem::ReturnNext; + q->logMessage(format("unexpected next().")); + return ProItem::ReturnFalse; + case T_IF: { + if (args.count() != 1) { + q->logMessage(format("if(condition) requires one argument.")); + return ProItem::ReturnFalse; + } + QString cond = args.first(); + bool escaped = false; // This is more than qmake does + bool quoted = false; + bool ret = true; + bool orOp = false; + bool invert = false; + bool isFunc = false; + int parens = 0; + QString test; + test.reserve(20); + QString args; + args.reserve(50); + const QChar *d = cond.unicode(); + const QChar *ed = d + cond.length(); + while (d < ed) { + ushort c = (d++)->unicode(); + if (!escaped) { + if (c == '\\') { + escaped = true; + args += c; // Assume no-one quotes the test name + continue; + } else if (c == '"') { + quoted = !quoted; + args += c; // Ditto + continue; + } + } else { + escaped = false; + } + if (quoted) { + args += c; // Ditto + } else { + bool isOp = false; + if (c == '(') { + isFunc = true; + if (parens) + args += c; + ++parens; + } else if (c == ')') { + --parens; + if (parens) + args += c; + } else if (!parens) { + if (c == ':' || c == '|') + isOp = true; + else if (c == '!') + invert = true; + else + test += c; + } else { + args += c; + } + if (!parens && (isOp || d == ed)) { + // Yes, qmake doesn't shortcut evaluations here. We can't, either, + // as some test functions have side effects. + bool success; + if (isFunc) { + success = evaluateConditionalFunction(test, args); + } else { + success = isActiveConfig(test, true); + } + success ^= invert; + if (orOp) + ret |= success; + else + ret &= success; + orOp = (c == '|'); + invert = false; + isFunc = false; + test.clear(); + args.clear(); + } + } + } + return returnBool(ret); + } case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { q->logMessage(format("CONFIG(config) requires one or two arguments.")); - ok = false; - break; + return ProItem::ReturnFalse; } if (args.count() == 1) { //cond = isActiveConfig(args.first()); XXX - break; + return ProItem::ReturnFalse; } const QStringList mutuals = args[1].split(QLatin1Char('|')); const QStringList &configs = valuesDirect(QLatin1String("CONFIG")); for (int i = configs.size() - 1; i >= 0; i--) { for (int mut = 0; mut < mutuals.count(); mut++) { if (configs[i] == mutuals[mut].trimmed()) { - cond = (configs[i] == args[0]); - goto done_T_CONFIG; + return returnBool(configs[i] == args[0]); } } } - done_T_CONFIG: - break; + return ProItem::ReturnFalse; } case T_CONTAINS: { if (args.count() < 2 || args.count() > 3) { q->logMessage(format("contains(var, val) requires two or three arguments.")); - ok = false; - break; + return ProItem::ReturnFalse; } QRegExp regx(args[1]); @@ -1739,8 +2049,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct for (int i = 0; i < l.size(); ++i) { const QString val = l[i]; if (regx.exactMatch(val) || val == args[1]) { - cond = true; - break; + return ProItem::ReturnTrue; } } } else { @@ -1749,140 +2058,172 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct const QString val = l[i]; for (int mut = 0; mut < mutuals.count(); mut++) { if (val == mutuals[mut].trimmed()) { - cond = (regx.exactMatch(val) || val == args[1]); - goto done_T_CONTAINS; + return returnBool(regx.exactMatch(val) || val == args[1]); } } } } - done_T_CONTAINS: - break; + return ProItem::ReturnFalse; } case T_COUNT: { if (args.count() != 2 && args.count() != 3) { q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); - ok = false; - break; + return ProItem::ReturnFalse; } if (args.count() == 3) { QString comp = args[2]; if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) { - cond = values(args.first()).count() > args[1].toInt(); + return returnBool(values(args.first()).count() > args[1].toInt()); } else if (comp == QLatin1String(">=")) { - cond = values(args.first()).count() >= args[1].toInt(); + return returnBool(values(args.first()).count() >= args[1].toInt()); } else if (comp == QLatin1String("<") || comp == QLatin1String("lessThan")) { - cond = values(args.first()).count() < args[1].toInt(); + return returnBool(values(args.first()).count() < args[1].toInt()); } else if (comp == QLatin1String("<=")) { - cond = values(args.first()).count() <= args[1].toInt(); - } else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual") || comp == QLatin1String("=") || comp == QLatin1String("==")) { - cond = values(args.first()).count() == args[1].toInt(); + return returnBool(values(args.first()).count() <= args[1].toInt()); + } else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual") + || comp == QLatin1String("=") || comp == QLatin1String("==")) { + return returnBool(values(args.first()).count() == args[1].toInt()); } else { - ok = false; q->logMessage(format("unexpected modifier to count(%2)").arg(comp)); + return ProItem::ReturnFalse; } - break; } - cond = values(args.first()).count() == args[1].toInt(); - break; + return returnBool(values(args.first()).count() == args[1].toInt()); + } + case T_GREATERTHAN: + case T_LESSTHAN: { + if (args.count() != 2) { + q->logMessage(format("%1(variable, value) requires two arguments.").arg(function)); + return ProItem::ReturnFalse; + } + QString rhs(args[1]), lhs(values(args[0]).join(QString(Option::field_sep))); + bool ok; + int rhs_int = rhs.toInt(&ok); + if (ok) { // do integer compare + int lhs_int = lhs.toInt(&ok); + if (ok) { + if (func_t == T_GREATERTHAN) + return returnBool(lhs_int > rhs_int); + return returnBool(lhs_int < rhs_int); + } + } + if (func_t == T_GREATERTHAN) + return returnBool(lhs > rhs); + return returnBool(lhs < rhs); + } + case T_EQUALS: + if (args.count() != 2) { + q->logMessage(format("%1(variable, value) requires two arguments.").arg(function)); + return ProItem::ReturnFalse; + } + return returnBool(values(args[0]).join(QString(Option::field_sep)) == args[1]); + case T_CLEAR: { + if (m_skipLevel && !m_cumulative) + return ProItem::ReturnFalse; + if (args.count() != 1) { + q->logMessage(format("%1(variable) requires one argument.").arg(function)); + return ProItem::ReturnFalse; + } + QHash<QString, QStringList>::Iterator it = m_valuemap.find(args[0]); + if (it == m_valuemap.end()) + return ProItem::ReturnFalse; + it->clear(); + return ProItem::ReturnTrue; + } + case T_UNSET: { + if (m_skipLevel && !m_cumulative) + return ProItem::ReturnFalse; + if (args.count() != 1) { + q->logMessage(format("%1(variable) requires one argument.").arg(function)); + return ProItem::ReturnFalse; + } + QHash<QString, QStringList>::Iterator it = m_valuemap.find(args[0]); + if (it == m_valuemap.end()) + return ProItem::ReturnFalse; + m_valuemap.erase(it); + return ProItem::ReturnTrue; } case T_INCLUDE: { if (m_skipLevel && !m_cumulative) - break; + return ProItem::ReturnFalse; QString parseInto; if (args.count() == 2) { parseInto = args[1]; } else if (args.count() != 1) { q->logMessage(format("include(file) requires one or two arguments.")); - ok = false; - break; + return ProItem::ReturnFalse; } QString fileName = args.first(); // ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style. QDir currentProPath(currentDirectory()); fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName)); - ok = evaluateFile(fileName, &ok); - break; + State sts = m_sts; + bool ok = evaluateFile(fileName); + m_sts = sts; + return returnBool(ok); } case T_LOAD: { if (m_skipLevel && !m_cumulative) - break; + return ProItem::ReturnFalse; QString parseInto; bool ignore_error = false; if (args.count() == 2) { QString sarg = args[1]; - ignore_error = (sarg.toLower() == QLatin1String("true") || sarg.toInt()); + ignore_error = (!sarg.compare(QLatin1String("true"), Qt::CaseInsensitive) || sarg.toInt()); } else if (args.count() != 1) { q->logMessage(format("load(feature) requires one or two arguments.")); - ok = false; - break; + return ProItem::ReturnFalse; } - ok = evaluateFeatureFile( args.first(), &cond); - break; + // XXX ignore_error unused + return returnBool(evaluateFeatureFile(args.first())); } case T_DEBUG: // Yup - do nothing. Nothing is going to enable debug output anyway. - break; + return ProItem::ReturnFalse; case T_MESSAGE: { if (args.count() != 1) { q->logMessage(format("%1(message) requires one argument.").arg(function)); - ok = false; - break; + return ProItem::ReturnFalse; } QString msg = fixEnvVariables(args.first()); - if (function == QLatin1String("error")) { - QStringList parents; - foreach (ProFile *proFile, m_profileStack) - parents.append(proFile->fileName()); - if (!parents.isEmpty()) - parents.takeLast(); - if (parents.isEmpty()) - q->fileMessage(format("Project ERROR: %1").arg(msg)); - else - q->fileMessage(format("Project ERROR: %1. File was included from: '%2'") - .arg(msg).arg(parents.join(QLatin1String("', '")))); - } else { - q->fileMessage(format("Project MESSAGE: %1").arg(msg)); - } - break; + q->fileMessage(QString::fromLatin1("Project %1: %2").arg(function.toUpper(), msg)); + // ### Consider real termination in non-cumulative mode + return returnBool(function != QLatin1String("error")); } #if 0 // Way too dangerous to enable. case T_SYSTEM: { if (args.count() != 1) { q->logMessage(format("system(exec) requires one argument.")); - ok = false; - break; + ProItem::ReturnFalse; } - ok = system(args.first().toLatin1().constData()) == 0; - break; + return returnBool(system(args.first().toLatin1().constData()) == 0); } #endif case T_ISEMPTY: { if (args.count() != 1) { q->logMessage(format("isEmpty(var) requires one argument.")); - ok = false; - break; + return ProItem::ReturnFalse; } QStringList sl = values(args.first()); if (sl.count() == 0) { - cond = true; + return ProItem::ReturnTrue; } else if (sl.count() > 0) { QString var = sl.first(); - cond = (var.isEmpty()); + if (var.isEmpty()) + return ProItem::ReturnTrue; } - break; + return ProItem::ReturnFalse; } case T_EXISTS: { if (args.count() != 1) { q->logMessage(format("exists(file) requires one argument.")); - ok = false; - break; + return ProItem::ReturnFalse; } QString file = args.first(); file = Option::fixPathToLocalOS(file); if (QFile::exists(file)) { - cond = true; - break; + return ProItem::ReturnTrue; } //regular expression I guess QString dirstr = currentDirectory(); @@ -1892,23 +2233,18 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct file = file.right(file.length() - slsh - 1); } if (file.contains(QLatin1Char('*')) || file.contains(QLatin1Char('?'))) - cond = QDir(dirstr).entryList(QStringList(file)).count(); + if (!QDir(dirstr).entryList(QStringList(file)).isEmpty()) + return ProItem::ReturnTrue; - break; + return ProItem::ReturnFalse; } case 0: - // This is too chatty currently (missing defineTest and defineReplace) - //q->logMessage(format("'%1' is not a recognized test function").arg(function)); - break; + q->logMessage(format("'%1' is not a recognized test function").arg(function)); + return ProItem::ReturnFalse; default: q->logMessage(format("Function '%1' is not implemented").arg(function)); - break; + return ProItem::ReturnFalse; } - - if (result) - *result = cond; - - return ok; } QStringList ProFileEvaluator::Private::values(const QString &variableName, @@ -1949,9 +2285,9 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, ret = QLatin1String("Windows"); } else if (type == QLatin1String("name")) { DWORD name_length = 1024; - TCHAR name[1024]; + wchar_t name[1024]; if (GetComputerName(name, &name_length)) - ret = QString::fromUtf16((ushort*)name, name_length); + ret = QString::fromWCharArray(name); } else if (type == QLatin1String("version") || type == QLatin1String("version_string")) { QSysInfo::WinVersion ver = QSysInfo::WindowsVersion; if (type == QLatin1String("version")) @@ -2061,37 +2397,21 @@ void ProFileEvaluator::releaseParsedProFile(ProFile *proFile) delete proFile; } -bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *result) +bool ProFileEvaluator::Private::evaluateFile(const QString &fileName) { - bool ok = true; ProFile *pro = q->parsedProFile(fileName); if (pro) { m_profileStack.push(pro); - ok = (currentProFile() ? pro->Accept(this) : false); + bool ok = (pro->Accept(this) == ProItem::ReturnTrue); m_profileStack.pop(); q->releaseParsedProFile(pro); - - if (result) - *result = true; + return ok; } else { - if (result) - *result = false; + return false; } -/* if (ok && readFeatures) { - QStringList configs = values("CONFIG"); - QSet<QString> processed; - foreach (const QString &fn, configs) { - if (!processed.contains(fn)) { - processed.insert(fn); - evaluateFeatureFile(fn, 0); - } - } - } */ - - return ok; } -bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, bool *result) +bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName) { QString fn; foreach (const QString &path, qmakeFeaturePaths()) { @@ -2110,87 +2430,11 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo return false; bool cumulative = m_cumulative; m_cumulative = false; - bool ok = evaluateFile(fn, result); + bool ok = evaluateFile(fn); m_cumulative = cumulative; return ok; } -void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out) -{ - const QStringList vpaths = values(QLatin1String("VPATH")) - + values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH")) - + values(QLatin1String("DEPENDPATH")) - + values(QLatin1String("VPATH_SOURCES")); - - QFileInfo fi(absName); - bool found = fi.exists(); - // Search in all vpaths - if (!found) { - foreach (const QString &vpath, vpaths) { - fi.setFile(vpath + QDir::separator() + relName); - if (fi.exists()) { - found = true; - break; - } - } - } - - if (found) { - sources_out += fi.absoluteFilePath(); // Not resolving symlinks - } else { - QString val = relName; - QString dir; - QString wildcard = val; - QString real_dir; - if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) { - dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1); - real_dir = dir; - wildcard = wildcard.right(wildcard.length() - dir.length()); - } - - if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) { - QStringList files = QDir(real_dir).entryList(QStringList(wildcard)); - if (files.isEmpty()) { - q->logMessage(format("Failure to find %1").arg(val)); - } else { - QString a; - for (int i = files.count() - 1; i >= 0; --i) { - if (files[i] == QLatin1String(".") || files[i] == QLatin1String("..")) - continue; - a = dir + files[i]; - sources_out += a; - } - } - } else { - q->logMessage(format("Cannot match %1/%2, as %3 does not exist.") - .arg(real_dir).arg(wildcard).arg(real_dir)); - } - } -} - - -/* - * Lookup of files are done in this order: - * 1. look in pwd - * 2. look in vpaths - * 3. expand wild card files relative from the profiles folder - **/ - -// FIXME: This code supports something that I'd consider a flaw in .pro file syntax -// which is not even documented. So arguably this can be ditched completely... -QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern) -{ - if (!currentProFile()) - return QStringList(); - - QStringList sources_out; - const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern)); - - expandPatternHelper(pattern, absName, sources_out); - return sources_out; -} - QString ProFileEvaluator::Private::format(const char *fmt) const { ProFile *pro = currentProFile(); @@ -2241,18 +2485,71 @@ QStringList ProFileEvaluator::values(const QString &variableName, const ProFile return fixEnvVariables(d->values(variableName, pro)); } +QStringList ProFileEvaluator::absolutePathValues( + const QString &variable, const QString &baseDirectory) const +{ + QStringList result; + foreach (const QString &el, values(variable)) { + const QFileInfo info = QFileInfo(baseDirectory, el); + if (info.isDir()) + result << QDir::cleanPath(info.absoluteFilePath()); + } + return result; +} + +QStringList ProFileEvaluator::absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const +{ + QStringList result; + foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { + QFileInfo info(el); + if (info.isAbsolute()) { + if (info.exists()) { + result << QDir::cleanPath(el); + goto next; + } + } else { + foreach (const QString &dir, searchDirs) { + QFileInfo info(dir, el); + if (info.isFile()) { + result << QDir::cleanPath(info.filePath()); + goto next; + } + } + if (baseDirectory.isEmpty()) + goto next; + info = QFileInfo(baseDirectory, el); + } + { + QFileInfo baseInfo(info.absolutePath()); + if (baseInfo.exists()) { + QString wildcard = info.fileName(); + if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { + QDir theDir(QDir::cleanPath(baseInfo.filePath())); + foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) + if (fn != QLatin1String(".") && fn != QLatin1String("..")) + result << theDir.absoluteFilePath(fn); + } + } + } + next: ; + } + return result; +} + ProFileEvaluator::TemplateType ProFileEvaluator::templateType() { QStringList templ = values(QLatin1String("TEMPLATE")); if (templ.count() >= 1) { - QString t = templ.last().toLower(); - if (t == QLatin1String("app")) + const QString &t = templ.last(); + if (!t.compare(QLatin1String("app"), Qt::CaseInsensitive)) return TT_Application; - if (t == QLatin1String("lib")) + if (!t.compare(QLatin1String("lib"), Qt::CaseInsensitive)) return TT_Library; - if (t == QLatin1String("script")) + if (!t.compare(QLatin1String("script"), Qt::CaseInsensitive)) return TT_Script; - if (t == QLatin1String("subdirs")) + if (!t.compare(QLatin1String("subdirs"), Qt::CaseInsensitive)) return TT_Subdirs; } return TT_Unknown; @@ -2327,64 +2624,4 @@ void ProFileEvaluator::setOutputDir(const QString &dir) d->m_outputDir = dir; } -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap) -{ - QStringList sourceFiles; - QString codecForTr; - QString codecForSource; - QStringList tsFileNames; - - // app/lib template - sourceFiles += visitor.values(QLatin1String("SOURCES")); - sourceFiles += visitor.values(QLatin1String("HEADERS")); - tsFileNames = visitor.values(QLatin1String("TRANSLATIONS")); - - QStringList trcodec = visitor.values(QLatin1String("CODEC")) - + visitor.values(QLatin1String("DEFAULTCODEC")) - + visitor.values(QLatin1String("CODECFORTR")); - if (!trcodec.isEmpty()) - codecForTr = trcodec.last(); - - QStringList srccodec = visitor.values(QLatin1String("CODECFORSRC")); - if (!srccodec.isEmpty()) - codecForSource = srccodec.last(); - - QStringList forms = visitor.values(QLatin1String("INTERFACES")) - + visitor.values(QLatin1String("FORMS")) - + visitor.values(QLatin1String("FORMS3")); - sourceFiles << forms; - - sourceFiles.sort(); - sourceFiles.removeDuplicates(); - tsFileNames.sort(); - tsFileNames.removeDuplicates(); - - varMap->insert("SOURCES", sourceFiles); - varMap->insert("CODECFORTR", QStringList() << codecForTr); - varMap->insert("CODECFORSRC", QStringList() << codecForSource); - varMap->insert("TRANSLATIONS", tsFileNames); -} - -bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap) -{ - QFileInfo fi(fileName); - if (!fi.exists()) - return false; - - ProFile pro(fi.absoluteFilePath()); - - ProFileEvaluator visitor; - visitor.setVerbose(verbose); - - if (!visitor.queryProFile(&pro)) - return false; - - if (!visitor.accept(&pro)) - return false; - - evaluateProFile(visitor, varMap); - - return true; -} - QT_END_NAMESPACE diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h index 69f47f5..f3498c1 100644 --- a/tools/linguist/shared/profileevaluator.h +++ b/tools/linguist/shared/profileevaluator.h @@ -52,12 +52,6 @@ QT_BEGIN_NAMESPACE -class ProFile; -class ProFileEvaluator; - -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap); -bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap); - class ProFileEvaluator { public: @@ -85,6 +79,10 @@ public: void addProperties(const QHash<QString, QString> &properties); QStringList values(const QString &variableName) const; QStringList values(const QString &variableName, const ProFile *pro) const; + QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; + QStringList absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const; QString propertyValue(const QString &val) const; // for our descendents @@ -97,6 +95,9 @@ public: private: class Private; Private *d; + + // This doesn't help gcc 3.3 and sunpro ... + template<typename T> friend class QTypeInfo; }; QT_END_NAMESPACE diff --git a/tools/linguist/shared/proitems.cpp b/tools/linguist/shared/proitems.cpp index 471417e..905c67e 100644 --- a/tools/linguist/shared/proitems.cpp +++ b/tools/linguist/shared/proitems.cpp @@ -58,15 +58,21 @@ QString ProItem::comment() const } // --------------- ProBlock ---------------- + ProBlock::ProBlock(ProBlock *parent) { m_blockKind = 0; m_parent = parent; + m_refCount = 1; } ProBlock::~ProBlock() { - qDeleteAll(m_proitems); + foreach (ProItem *itm, m_proitems) + if (itm->kind() == BlockKind) + static_cast<ProBlock *>(itm)->deref(); + else + delete itm; } void ProBlock::appendItem(ProItem *proitem) @@ -109,14 +115,37 @@ ProItem::ProItemKind ProBlock::kind() const return ProItem::BlockKind; } -bool ProBlock::Accept(AbstractProItemVisitor *visitor) -{ - visitor->visitBeginProBlock(this); - foreach (ProItem *item, m_proitems) { - if (!item->Accept(visitor)) - return false; +ProItem::ProItemReturn ProBlock::Accept(AbstractProItemVisitor *visitor) +{ + if (visitor->visitBeginProBlock(this) == ReturnSkip) + return ReturnTrue; + ProItemReturn rt = ReturnTrue; + for (int i = 0; i < m_proitems.count(); ++i) { + rt = m_proitems.at(i)->Accept(visitor); + if (rt != ReturnTrue && rt != ReturnFalse) { + if (rt == ReturnLoop) { + rt = ReturnTrue; + while (visitor->visitProLoopIteration()) + for (int j = i; ++j < m_proitems.count(); ) { + rt = m_proitems.at(j)->Accept(visitor); + if (rt != ReturnTrue && rt != ReturnFalse) { + if (rt == ReturnNext) { + rt = ReturnTrue; + break; + } + if (rt == ReturnBreak) + rt = ReturnTrue; + goto do_break; + } + } + do_break: + visitor->visitProLoopCleanup(); + } + break; + } } - return visitor->visitEndProBlock(this); + visitor->visitEndProBlock(this); + return rt; } // --------------- ProVariable ---------------- @@ -148,14 +177,13 @@ QString ProVariable::variable() const return m_variable; } -bool ProVariable::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor) { visitor->visitBeginProVariable(this); - foreach (ProItem *item, m_proitems) { - if (!item->Accept(visitor)) - return false; - } - return visitor->visitEndProVariable(this); + foreach (ProItem *item, m_proitems) + item->Accept(visitor); // cannot fail + visitor->visitEndProVariable(this); + return ReturnTrue; } // --------------- ProValue ---------------- @@ -190,9 +218,10 @@ ProItem::ProItemKind ProValue::kind() const return ProItem::ValueKind; } -bool ProValue::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProValue::Accept(AbstractProItemVisitor *visitor) { - return visitor->visitProValue(this); + visitor->visitProValue(this); + return ReturnTrue; } // --------------- ProFunction ---------------- @@ -216,7 +245,7 @@ ProItem::ProItemKind ProFunction::kind() const return ProItem::FunctionKind; } -bool ProFunction::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProFunction::Accept(AbstractProItemVisitor *visitor) { return visitor->visitProFunction(this); } @@ -242,9 +271,10 @@ ProItem::ProItemKind ProCondition::kind() const return ProItem::ConditionKind; } -bool ProCondition::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProCondition::Accept(AbstractProItemVisitor *visitor) { - return visitor->visitProCondition(this); + visitor->visitProCondition(this); + return ReturnTrue; } // --------------- ProOperator ---------------- @@ -268,9 +298,10 @@ ProItem::ProItemKind ProOperator::kind() const return ProItem::OperatorKind; } -bool ProOperator::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProOperator::Accept(AbstractProItemVisitor *visitor) { - return visitor->visitProOperator(this); + visitor->visitProOperator(this); + return ReturnTrue; } // --------------- ProFile ---------------- @@ -315,13 +346,12 @@ bool ProFile::isModified() const return m_modified; } -bool ProFile::Accept(AbstractProItemVisitor *visitor) +ProItem::ProItemReturn ProFile::Accept(AbstractProItemVisitor *visitor) { - visitor->visitBeginProFile(this); - foreach (ProItem *item, m_proitems) { - if (!item->Accept(visitor)) - return false; - } + ProItemReturn rt; + if ((rt = visitor->visitBeginProFile(this)) != ReturnTrue) + return rt; + ProBlock::Accept(visitor); // cannot fail return visitor->visitEndProFile(this); } diff --git a/tools/linguist/shared/proitems.h b/tools/linguist/shared/proitems.h index aad0ba2..7833be1 100644 --- a/tools/linguist/shared/proitems.h +++ b/tools/linguist/shared/proitems.h @@ -60,6 +60,16 @@ public: BlockKind }; + enum ProItemReturn { + ReturnFalse, + ReturnTrue, + ReturnBreak, + ReturnNext, + ReturnLoop, + ReturnSkip, + ReturnReturn + }; + ProItem() : m_lineNumber(0) {} virtual ~ProItem() {} @@ -68,7 +78,7 @@ public: void setComment(const QString &comment); QString comment() const; - virtual bool Accept(AbstractProItemVisitor *visitor) = 0; + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor) = 0; int lineNumber() const { return m_lineNumber; } void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; } @@ -86,7 +96,8 @@ public: ScopeContentsKind = 0x02, VariableKind = 0x04, ProFileKind = 0x08, - SingleLine = 0x10 + FunctionBodyKind = 0x10, + SingleLine = 0x80 }; ProBlock(ProBlock *parent); @@ -102,14 +113,18 @@ public: void setParent(ProBlock *parent); ProBlock *parent() const; + void ref() { ++m_refCount; } + void deref() { if (!--m_refCount) delete this; } + ProItem::ProItemKind kind() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); protected: QList<ProItem *> m_proitems; private: ProBlock *m_parent; int m_blockKind; + int m_refCount; }; class ProVariable : public ProBlock @@ -131,7 +146,7 @@ public: void setVariable(const QString &name); QString variable() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: VariableOperator m_variableKind; QString m_variable; @@ -150,7 +165,7 @@ public: ProItem::ProItemKind kind() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: QString m_value; ProVariable *m_variable; @@ -166,7 +181,7 @@ public: ProItem::ProItemKind kind() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: QString m_text; }; @@ -181,7 +196,7 @@ public: ProItem::ProItemKind kind() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: QString m_text; }; @@ -201,7 +216,7 @@ public: ProItem::ProItemKind kind() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: OperatorKind m_operatorKind; }; @@ -219,7 +234,7 @@ public: void setModified(bool modified); bool isModified() const; - virtual bool Accept(AbstractProItemVisitor *visitor); + virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: QString m_fileName; diff --git a/tools/linguist/shared/proparser.pri b/tools/linguist/shared/proparser.pri index 372247e..99d32e7 100644 --- a/tools/linguist/shared/proparser.pri +++ b/tools/linguist/shared/proparser.pri @@ -2,11 +2,13 @@ INCLUDEPATH *= $$PWD HEADERS += \ + $$PWD/proreader.h \ $$PWD/abstractproitemvisitor.h \ $$PWD/proitems.h \ $$PWD/profileevaluator.h \ $$PWD/proparserutils.h SOURCES += \ + $$PWD/proreader.cpp \ $$PWD/proitems.cpp \ $$PWD/profileevaluator.cpp diff --git a/tools/linguist/shared/proreader.cpp b/tools/linguist/shared/proreader.cpp new file mode 100644 index 0000000..3400f20 --- /dev/null +++ b/tools/linguist/shared/proreader.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "profileevaluator.h" + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> + +QT_BEGIN_NAMESPACE + +static QStringList getSources(const char *var, const char *vvar, const QStringList &baseVPaths, + const QString &projectDir, const ProFileEvaluator &visitor) +{ + QStringList vPaths = + visitor.absolutePathValues(QLatin1String(vvar), projectDir); + vPaths += baseVPaths; + vPaths.removeDuplicates(); + return visitor.absoluteFileValues(QLatin1String(var), projectDir, vPaths, 0); +} + +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir) +{ + QStringList baseVPaths; + baseVPaths += visitor.absolutePathValues(QLatin1String("VPATH"), projectDir); + baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH + baseVPaths += visitor.absolutePathValues(QLatin1String("DEPENDPATH"), projectDir); + baseVPaths.removeDuplicates(); + + QStringList sourceFiles; + QString codecForTr; + QString codecForSource; + QStringList tsFileNames; + + // app/lib template + sourceFiles += getSources("SOURCES", "VPATH_SOURCES", baseVPaths, projectDir, visitor); + + sourceFiles += getSources("FORMS", "VPATH_FORMS", baseVPaths, projectDir, visitor); + sourceFiles += getSources("FORMS3", "VPATH_FORMS3", baseVPaths, projectDir, visitor); + + QStringList vPathsInc = baseVPaths; + vPathsInc += visitor.absolutePathValues(QLatin1String("INCLUDEPATH"), projectDir); + vPathsInc.removeDuplicates(); + sourceFiles += visitor.absoluteFileValues(QLatin1String("HEADERS"), projectDir, vPathsInc, 0); + + QDir proDir(projectDir); + foreach (const QString &tsFile, visitor.values(QLatin1String("TRANSLATIONS"))) + tsFileNames << QFileInfo(proDir, tsFile).filePath(); + + QStringList trcodec = visitor.values(QLatin1String("CODEC")) + + visitor.values(QLatin1String("DEFAULTCODEC")) + + visitor.values(QLatin1String("CODECFORTR")); + if (!trcodec.isEmpty()) + codecForTr = trcodec.last(); + + QStringList srccodec = visitor.values(QLatin1String("CODECFORSRC")); + if (!srccodec.isEmpty()) + codecForSource = srccodec.last(); + + sourceFiles.sort(); + sourceFiles.removeDuplicates(); + tsFileNames.sort(); + tsFileNames.removeDuplicates(); + + varMap->insert("SOURCES", sourceFiles); + varMap->insert("CODECFORTR", QStringList() << codecForTr); + varMap->insert("CODECFORSRC", QStringList() << codecForSource); + varMap->insert("TRANSLATIONS", tsFileNames); +} + +bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap) +{ + QFileInfo fi(fileName); + if (!fi.exists()) + return false; + + ProFile pro(fi.absoluteFilePath()); + + ProFileEvaluator visitor; + visitor.setVerbose(verbose); + + if (!visitor.queryProFile(&pro)) + return false; + + if (!visitor.accept(&pro)) + return false; + + evaluateProFile(visitor, varMap, fi.absolutePath()); + + return true; +} + +QT_END_NAMESPACE diff --git a/tools/linguist/shared/proreader.h b/tools/linguist/shared/proreader.h new file mode 100644 index 0000000..f663e23 --- /dev/null +++ b/tools/linguist/shared/proreader.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROREADER_H +#define PROREADER_H + +#include <QtCore/QHash> + +QT_BEGIN_NAMESPACE + +class ProFileEvaluator; + +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir); +bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap); + +QT_END_NAMESPACE + +#endif // PROREADER_H diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp index ec61cb6..dc681f5 100644 --- a/tools/linguist/shared/qm.cpp +++ b/tools/linguist/shared/qm.cpp @@ -173,6 +173,7 @@ public: bool save(QIODevice *iod); void insert(const TranslatorMessage &msg, bool forceComment); + void insertIdBased(const TranslatorMessage &message); void squeeze(TranslatorSaveMode mode); @@ -244,7 +245,7 @@ void Releaser::writeMessage(const ByteTranslatorMessage &msg, QDataStream &strea if (mode == SaveEverything) prefix = HashContextSourceTextComment; - // lrelease produces "wrong" .qm files for QByteArrays that are .isNull(). + // lrelease produces "wrong" QM files for QByteArrays that are .isNull(). switch (prefix) { default: case HashContextSourceTextComment: @@ -436,6 +437,16 @@ void Releaser::insert(const TranslatorMessage &message, bool forceComment) insertInternal(message, forceComment, false); } +void Releaser::insertIdBased(const TranslatorMessage &message) +{ + QStringList tlns = message.translations(); + for (int i = 0; i < tlns.size(); ++i) + if (tlns.at(i).isEmpty()) + tlns[i] = message.sourceText(); + ByteTranslatorMessage bmsg("", originalBytes(message.id(), false), "", tlns); + m_messages.insert(bmsg, 0); +} + void Releaser::setNumerusRules(const QByteArray &rules) { m_numerusRules = rules; @@ -541,7 +552,8 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) size_t numItems = offsetLength / (2 * sizeof(quint32)); //qDebug() << "NUMITEMS: " << numItems; - QTextCodec *codec = QTextCodec::codecForName(cd.m_codecForSource); + QTextCodec *codec = QTextCodec::codecForName( + cd.m_codecForSource.isEmpty() ? QByteArray("Latin1") : cd.m_codecForSource); QTextCodec *utf8Codec = 0; if (codec->name() != "UTF-8") utf8Codec = QTextCodec::codecForName("UTF-8"); @@ -689,11 +701,17 @@ static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData int finished = 0; int unfinished = 0; int untranslated = 0; + int missingIds = 0; + int droppedData = 0; for (int i = 0; i != translator.messageCount(); ++i) { const TranslatorMessage &msg = translator.message(i); TranslatorMessage::Type typ = msg.type(); if (typ != TranslatorMessage::Obsolete) { + if (cd.m_idBased && msg.id().isEmpty()) { + ++missingIds; + continue; + } if (typ == TranslatorMessage::Unfinished) { if (msg.translation().isEmpty()) { ++untranslated; @@ -706,19 +724,34 @@ static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData } else { ++finished; } - // Drop the comment in (context, sourceText, comment), - // unless the context is empty, - // unless (context, sourceText, "") already exists or - // unless we already dropped the comment of (context, - // sourceText, comment0). - bool forceComment = - msg.comment().isEmpty() - || msg.context().isEmpty() - || translator.contains(msg.context(), msg.sourceText(), QString()); - releaser.insert(msg, forceComment); + if (cd.m_idBased) { + if (!msg.context().isEmpty() || !msg.comment().isEmpty()) + ++droppedData; + releaser.insertIdBased(msg); + } else { + // Drop the comment in (context, sourceText, comment), + // unless the context is empty, + // unless (context, sourceText, "") already exists or + // unless we already dropped the comment of (context, + // sourceText, comment0). + bool forceComment = + msg.comment().isEmpty() + || msg.context().isEmpty() + || translator.contains(msg.context(), msg.sourceText(), QString()); + releaser.insert(msg, forceComment); + } } } + if (missingIds) + cd.appendError(QCoreApplication::translate("LRelease", + "Dropped %n message(s) which had no ID.", 0, + QCoreApplication::CodecForTr, missingIds)); + if (droppedData) + cd.appendError(QCoreApplication::translate("LRelease", + "Excess context/disambiguation dropped from %n message(s).", 0, + QCoreApplication::CodecForTr, droppedData)); + releaser.squeeze(cd.m_saveMode); bool saved = releaser.save(&dev); if (saved && cd.isVerbose()) { diff --git a/tools/linguist/shared/translator.cpp b/tools/linguist/shared/translator.cpp index 305681d..62f4d10 100644 --- a/tools/linguist/shared/translator.cpp +++ b/tools/linguist/shared/translator.cpp @@ -517,16 +517,10 @@ QList<TranslatorMessage> Translator::translatedMessages() const return result; } -QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, - QLocale::Language language, QLocale::Country country) +QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, int numPlurals) { QStringList translations = msg.translations(); - int numTranslations = 1; - if (msg.isPlural() && language != QLocale::C) { - QStringList forms; - if (getNumerusInfo(language, country, 0, &forms)) - numTranslations = forms.count(); // includes singular - } + int numTranslations = msg.isPlural() ? numPlurals : 1; // make sure that the stringlist always have the size of the // language's current numerus, or 1 if its not plural @@ -540,21 +534,39 @@ QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, return translations; } -QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, - ConversionData &cd, bool *ok) const +void Translator::normalizeTranslations(ConversionData &cd) { + bool truncated = false; QLocale::Language l; QLocale::Country c; languageAndCountry(languageCode(), &l, &c); - QStringList translns = normalizedTranslations(msg, l, c); - if (msg.translations().size() > translns.size() && ok) { + int numPlurals = 1; + if (l != QLocale::C) { + QStringList forms; + if (getNumerusInfo(l, c, 0, &forms)) + numPlurals = forms.count(); // includes singular + } + for (int i = 0; i < m_messages.count(); ++i) { + const TranslatorMessage &msg = m_messages.at(i); + QStringList tlns = msg.translations(); + int ccnt = msg.isPlural() ? numPlurals : 1; + if (tlns.count() != ccnt) { + while (tlns.count() < ccnt) + tlns.append(QString()); + while (tlns.count() > ccnt) { + tlns.removeLast(); + truncated = true; + } + TranslatorMessage msg2(msg); + msg2.setTranslations(tlns); + m_messages[i] = msg2; + } + } + if (truncated) cd.appendError(QLatin1String( "Removed plural forms as the target language has less " "forms.\nIf this sounds wrong, possibly the target language is " "not set or recognized.\n")); - *ok = false; - } - return translns; } QString Translator::guessLanguageCodeFromFileName(const QString &filename) diff --git a/tools/linguist/shared/translator.h b/tools/linguist/shared/translator.h index ac824f3..d0903a9 100644 --- a/tools/linguist/shared/translator.h +++ b/tools/linguist/shared/translator.h @@ -65,6 +65,7 @@ public: m_ignoreUnfinished(false), m_sortContexts(false), m_noUiLines(false), + m_idBased(false), m_saveMode(SaveEverything) {} @@ -83,7 +84,8 @@ public: public: QString m_defaultContext; - QByteArray m_codecForSource; // CPP specific + QByteArray m_codecForSource; // CPP, PO & QM specific + QByteArray m_outputCodec; // PO specific QString m_sourceFileName; QString m_targetFileName; QDir m_sourceDir; @@ -97,6 +99,7 @@ public: bool m_ignoreUnfinished; bool m_sortContexts; bool m_noUiLines; + bool m_idBased; TranslatorSaveMode m_saveMode; }; @@ -156,8 +159,8 @@ public: static QString guessLanguageCodeFromFileName(const QString &fileName); QList<TranslatorMessage> messages() const; QList<TranslatorMessage> translatedMessages() const; - static QStringList normalizedTranslations(const TranslatorMessage &m, - QLocale::Language lang, QLocale::Country country); + static QStringList normalizedTranslations(const TranslatorMessage &m, int numPlurals); + void normalizeTranslations(ConversionData &cd); QStringList normalizedTranslations(const TranslatorMessage &m, ConversionData &cd, bool *ok) const; int messageCount() const { return m_messages.size(); } diff --git a/tools/linguist/shared/ts.cpp b/tools/linguist/shared/ts.cpp index 3efce15..5884997 100644 --- a/tools/linguist/shared/ts.cpp +++ b/tools/linguist/shared/ts.cpp @@ -693,8 +693,8 @@ bool saveTS(const Translator &translator, QIODevice &dev, ConversionData &cd, in t << " type=\"obsolete\""; if (msg.isPlural()) { t << ">"; - QStringList translns = translator.normalizedTranslations(msg, cd, &result); - for (int j = 0; j < qMax(1, translns.count()); ++j) { + const QStringList &translns = msg.translations(); + for (int j = 0; j < translns.count(); ++j) { t << "\n <numerusform"; writeVariants(t, " ", translns[j]); t << "</numerusform>"; diff --git a/tools/linguist/shared/ts.dtd b/tools/linguist/shared/ts.dtd index ab77f64..4d2cdeb 100644 --- a/tools/linguist/shared/ts.dtd +++ b/tools/linguist/shared/ts.dtd @@ -34,7 +34,7 @@ version CDATA #IMPLIED sourcelanguage CDATA #IMPLIED language CDATA #IMPLIED> -<!-- The encoding to use in the .qm file by default. Default is ISO-8859-1. --> +<!-- The encoding to use in the QM file by default. Default is ISO-8859-1. --> <!ELEMENT defaultcodec (#PCDATA) > <!ELEMENT context (name?, comment?, (context|message)+) > <!ATTLIST context @@ -54,7 +54,7 @@ <!ELEMENT message (location*, source?, oldsource?, comment?, oldcomment?, extracomment?, translatorcomment?, translation?, userdata?, extra-**) > <!-- ! If utf8 is true, the defaultcodec is overridden and the message is encoded - ! in UTF-8 in the .qm file. + ! in UTF-8 in the QM file. --> <!ATTLIST message id CDATA #IMPLIED @@ -70,7 +70,7 @@ ! is omitted, the "current" one is used. For the 1st location in a message, ! "current" is the filename used for the 1st location of the previous message. ! For subsequent locations, it is the filename used for the previous location. - ! A single .ts file has either all absolute or all relative locations. + ! A single TS file has either all absolute or all relative locations. --> <!ATTLIST location filename CDATA #IMPLIED @@ -106,7 +106,7 @@ <!-- ! The translation variants have a priority between 1 ("highest") and 9 ("lowest") ! Typically longer translations get a higher priority. - ! If omitted, the order of appearance of the variants in the .ts files is used. + ! If omitted, the order of appearance of the variants in the TS files is used. --> <!ATTLIST lengthvariant priority (1|2|3|4|5|6|7|8|9) #IMPLIED> diff --git a/tools/linguist/shared/xliff.cpp b/tools/linguist/shared/xliff.cpp index 1313172..c222b8d 100644 --- a/tools/linguist/shared/xliff.cpp +++ b/tools/linguist/shared/xliff.cpp @@ -243,13 +243,12 @@ static void writeComment(QTextStream &ts, const TranslatorMessage &msg, const QR } } -static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent, - const Translator &translator, ConversionData &cd, bool *ok) +static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent) { static int msgid; QString msgidstr = !msg.id().isEmpty() ? msg.id() : QString::fromAscii("_msg%1").arg(++msgid); - QStringList translns = translator.normalizedTranslations(msg, cd, ok); + QStringList translns = msg.translations(); QHash<QString, QString>::const_iterator it; QString pluralStr; QStringList sources(msg.sourceText()); @@ -349,8 +348,7 @@ static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const } } -static void writeMessage(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent, - const Translator &translator, ConversionData &cd, bool *ok) +static void writeMessage(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent) { if (msg.isPlural()) { writeIndent(ts, indent); @@ -364,12 +362,12 @@ static void writeMessage(QTextStream &ts, const TranslatorMessage &msg, const QR writeLineNumber(ts, msg, indent); writeComment(ts, msg, drops, indent); - writeTransUnits(ts, msg, drops, indent, translator, cd, ok); + writeTransUnits(ts, msg, drops, indent); --indent; writeIndent(ts, indent); ts << "</group>\n"; } else { - writeTransUnits(ts, msg, drops, indent, translator, cd, ok); + writeTransUnits(ts, msg, drops, indent); } } @@ -795,7 +793,7 @@ bool saveXLIFF(const Translator &translator, QIODevice &dev, ConversionData &cd) } foreach (const TranslatorMessage &msg, messageOrder[fn][ctx]) - writeMessage(ts, msg, drops, indent, translator, cd, &ok); + writeMessage(ts, msg, drops, indent); if (!ctx.isEmpty()) { --indent; diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp index 5d1ac32..b8b9338 100644 --- a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -613,18 +613,15 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << endl; - if (type != "QVariant") - hs << " { return qvariant_cast< " << type << " >(internalPropGet(\"" - << property.name << "\")); }" << endl; - else - hs << " { return internalPropGet(\"" << property.name << "\"); }" << endl; + hs << " inline " << type << " " << getter << "() const" << endl + << " { return qvariant_cast< " << type << " >(property(\"" + << property.name << "\")); }" << endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl - << " { internalPropSet(\"" << property.name + << " { setProperty(\"" << property.name << "\", qVariantFromValue(value)); }" << endl; } diff --git a/tools/qdoc3/atom.cpp b/tools/qdoc3/atom.cpp index a82a783..da32735 100644 --- a/tools/qdoc3/atom.cpp +++ b/tools/qdoc3/atom.cpp @@ -93,6 +93,7 @@ QString Atom::UPPERROMAN_ ("upperroman"); \value AbstractLeft \value AbstractRight + \value AnnotatedList \value AutoLink \value BaseName \value BriefLeft @@ -163,6 +164,7 @@ static const struct { } atms[] = { { "AbstractLeft", Atom::AbstractLeft }, { "AbstractRight", Atom::AbstractRight }, + { "AnnotatedList", Atom::AnnotatedList }, { "AutoLink", Atom::AutoLink }, { "BaseName", Atom::BaseName }, { "BriefLeft", Atom::BriefLeft }, diff --git a/tools/qdoc3/atom.h b/tools/qdoc3/atom.h index 6d5af0a..941ac70 100644 --- a/tools/qdoc3/atom.h +++ b/tools/qdoc3/atom.h @@ -58,6 +58,7 @@ class Atom enum Type { AbstractLeft, AbstractRight, + AnnotatedList, AutoLink, BaseName, BriefLeft, diff --git a/tools/qdoc3/codemarker.cpp b/tools/qdoc3/codemarker.cpp index e95153d..4c018d1 100644 --- a/tools/qdoc3/codemarker.cpp +++ b/tools/qdoc3/codemarker.cpp @@ -168,7 +168,8 @@ const Node *CodeMarker::nodeForString(const QString& string) { if (sizeof(const Node *) == sizeof(uint)) { return reinterpret_cast<const Node *>(string.toUInt()); - } else { + } + else { return reinterpret_cast<const Node *>(string.toULongLong()); } } @@ -177,7 +178,8 @@ QString CodeMarker::stringForNode(const Node *node) { if (sizeof(const Node *) == sizeof(ulong)) { return QString::number(reinterpret_cast<ulong>(node)); - } else { + } + else { return QString::number(reinterpret_cast<qulonglong>(node)); } } @@ -220,7 +222,8 @@ QString CodeMarker::typified(const QString &string) || ch.digitValue() >= 0 || ch == QLatin1Char('_') || ch == QLatin1Char(':')) { pendingWord += ch; - } else { + } + else { if (!pendingWord.isEmpty()) { bool isProbablyType = (pendingWord != QLatin1String("const")); if (isProbablyType) @@ -251,7 +254,7 @@ QString CodeMarker::typified(const QString &string) return result; } -QString CodeMarker::taggedNode(const Node *node) +QString CodeMarker::taggedNode(const Node* node) { QString tag; @@ -276,10 +279,34 @@ QString CodeMarker::taggedNode(const Node *node) break; default: tag = QLatin1String("@unknown"); + break; + } + return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name()) + + QLatin1String("</") + tag + QLatin1Char('>'); +} + +#ifdef QDOC_QML +QString CodeMarker::taggedQmlNode(const Node* node) +{ + QString tag; + switch (node->type()) { + case Node::QmlProperty: + tag = QLatin1String("@property"); + break; + case Node::QmlSignal: + tag = QLatin1String("@signal"); + break; + case Node::QmlMethod: + tag = QLatin1String("@method"); + break; + default: + tag = QLatin1String("@unknown"); + break; } return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name()) + QLatin1String("</") + tag + QLatin1Char('>'); } +#endif QString CodeMarker::linkTag(const Node *node, const QString& body) { @@ -308,9 +335,11 @@ QString CodeMarker::sortName(const Node *node) QString sortNo; if (func->metaness() == FunctionNode::Ctor) { sortNo = QLatin1String("C"); - } else if (func->metaness() == FunctionNode::Dtor) { + } + else if (func->metaness() == FunctionNode::Dtor) { sortNo = QLatin1String("D"); - } else { + } + else { if (nodeName.startsWith(QLatin1String("operator")) && nodeName.length() > 8 && !nodeName[8].isLetterOrNumber()) @@ -336,9 +365,14 @@ void CodeMarker::insert(FastSection &fastSection, SynopsisStyle style, Status status) { - bool inheritedMember = (!node->relates() && - (node->parent() != (const InnerNode *)fastSection.innerNode)); bool irrelevant = false; + bool inheritedMember = false; + if (!node->relates()) { + if (node->parent() != (const InnerNode*)fastSection.innerNode) { + if (node->type() != Node::QmlProperty) + inheritedMember = true; + } + } if (node->access() == Node::Private) { irrelevant = true; @@ -462,7 +496,8 @@ QStringList CodeMarker::macRefsForNode(const Node *node) #if 0 if (!classe->templateStuff().isEmpty()) { result += QLatin1String("tmplt/"); - } else + } + else #endif { result += QLatin1String("cl/"); @@ -499,14 +534,18 @@ QStringList CodeMarker::macRefsForNode(const Node *node) result += QLatin1String("macro/"); isMacro = true; #if 0 - } else if (!func->templateStuff().isEmpty()) { + } + else if (!func->templateStuff().isEmpty()) { result += QLatin1String("ftmplt/"); #endif - } else if (func->isStatic()) { + } + else if (func->isStatic()) { result += QLatin1String("clm/"); - } else if (!func->parent()->name().isEmpty()) { + } + else if (!func->parent()->name().isEmpty()) { result += QLatin1String("instm/"); - } else { + } + else { result += QLatin1String("func/"); } @@ -520,7 +559,8 @@ QStringList CodeMarker::macRefsForNode(const Node *node) result += "/" + QLatin1String(QMetaObject::normalizedSignature(func->returnType().toLatin1().constData())) + "/("; const QList<Parameter> ¶ms = func->parameters(); for (int i = 0; i < params.count(); ++i) { - QString type = params.at(i).leftType() + params.at(i).rightType(); + QString type = params.at(i).leftType() + + params.at(i).rightType(); type = QLatin1String(QMetaObject::normalizedSignature(type.toLatin1().constData())); if (i != 0) result += ","; @@ -563,10 +603,21 @@ QString CodeMarker::macName(const Node *node, const QString &name) if (node->name().isEmpty()) { return QLatin1Char('/') + myName; - } else { + } + else { return plainFullName(node) + QLatin1Char('/') + myName; } } +#ifdef QDOC_QML +/*! + Get the list of documentation sections for the children of + the specified QmlClassNode. + */ +QList<Section> CodeMarker::qmlSections(const QmlClassNode* , SynopsisStyle ) +{ + return QList<Section>(); +} +#endif QT_END_NAMESPACE diff --git a/tools/qdoc3/codemarker.h b/tools/qdoc3/codemarker.h index 67b1064..91dc8b0 100644 --- a/tools/qdoc3/codemarker.h +++ b/tools/qdoc3/codemarker.h @@ -121,6 +121,9 @@ class CodeMarker virtual QString markedUpSynopsis(const Node *node, const Node *relative, SynopsisStyle style) = 0; +#ifdef QDOC_QML + virtual QString markedUpQmlItem(const Node* , bool) { return QString(); } +#endif virtual QString markedUpName(const Node *node) = 0; virtual QString markedUpFullName(const Node *node, const Node *relative = 0) = 0; @@ -132,6 +135,10 @@ class CodeMarker virtual QList<Section> sections(const InnerNode *inner, SynopsisStyle style, Status status) = 0; +#ifdef QDOC_QML + virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style); +#endif virtual const Node *resolveTarget(const QString& target, const Tree *tree, const Node *relative) = 0; @@ -151,7 +158,10 @@ class CodeMarker virtual QString sortName(const Node *node); QString protect(const QString &string); QString typified(const QString &string); - QString taggedNode(const Node *node); + QString taggedNode(const Node* node); +#ifdef QDOC_QML + QString taggedQmlNode(const Node* node); +#endif QString linkTag(const Node *node, const QString& body); void insert(FastSection &fastSection, Node *node, diff --git a/tools/qdoc3/command.cpp b/tools/qdoc3/command.cpp index e51e235..bce262b 100644 --- a/tools/qdoc3/command.cpp +++ b/tools/qdoc3/command.cpp @@ -49,44 +49,46 @@ QT_BEGIN_NAMESPACE -void executeCommand( const Location& location, const QString& format, - const QStringList& args ) +void executeCommand(const Location& location, + const QString& format, + const QStringList& args) { QString actualCommand; - for ( int i = 0; i < (int) format.length(); i++ ) { + for (int i = 0; i < (int) format.length(); i++) { int ch = format[i].unicode(); - if ( ch > 0 && ch < 8 ) { + if (ch > 0 && ch < 8) { actualCommand += args[ch - 1]; - } else { + } + else { actualCommand += format[i]; } } QString toolName = actualCommand; - int space = toolName.indexOf( QLatin1Char(' ') ); - if ( space != -1 ) - toolName.truncate( space ); + int space = toolName.indexOf(QLatin1Char(' ')); + if (space != -1) + toolName.truncate(space); QProcess process; process.start(QLatin1String("sh"), - QStringList() << QLatin1String("-c") << actualCommand ); + QStringList() << QLatin1String("-c") << actualCommand); process.waitForFinished(); if (process.exitCode() == 127) - location.fatal( tr("Couldn't launch the '%1' tool") - .arg(toolName), - tr("Make sure the tool is installed and in the" - " path.") ); + location.fatal(tr("Couldn't launch the '%1' tool") + .arg(toolName), + tr("Make sure the tool is installed and in the" + " path.")); QString errors = QString::fromLocal8Bit(process.readAllStandardError()); - while ( errors.endsWith(QLatin1Char('\n')) ) - errors.truncate( errors.length() - 1 ); - if ( !errors.isEmpty() ) - location.fatal( tr("The '%1' tool encountered some problems") - .arg(toolName), - tr("The tool was invoked like this:\n%1\n" - "It emitted these errors:\n%2") - .arg(actualCommand).arg(errors) ); + while (errors.endsWith(QLatin1Char('\n'))) + errors.truncate(errors.length() - 1); + if (!errors.isEmpty()) + location.fatal(tr("The '%1' tool encountered some problems") + .arg(toolName), + tr("The tool was invoked like this:\n%1\n" + "It emitted these errors:\n%2") + .arg(actualCommand).arg(errors)); } QT_END_NAMESPACE diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h index 4e97d9f..22cb671 100644 --- a/tools/qdoc3/config.h +++ b/tools/qdoc3/config.h @@ -140,6 +140,7 @@ class Config #define CONFIG_INDEXES "indexes" #define CONFIG_LANGUAGE "language" #define CONFIG_MACRO "macro" +#define CONFIG_OBSOLETELINKS "obsoletelinks" #define CONFIG_OUTPUTDIR "outputdir" #define CONFIG_OUTPUTLANGUAGE "outputlanguage" #define CONFIG_OUTPUTFORMATS "outputformats" diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index f807609..0f8d1b7 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -284,7 +284,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, } else { for (int i = 0; i < documentedItems.size(); ++i) { - if (i < MaxEnumValues - 2 || i == documentedItems.size() - 1) { + if (i < MaxEnumValues-2 || i == documentedItems.size()-1) { if (i != 0) synopsis += ", "; synopsis += documentedItems.at(i); @@ -345,6 +345,43 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, return synopsis + extra; } +#ifdef QDOC_QML +/*! + */ +QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) +{ + QString name = taggedQmlNode(node); + if (summary) { + name = linkTag(node,name); + } + name = "<@name>" + name + "</@name>"; + QString synopsis = name; + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node); + synopsis += " : " + typified(pn->dataType()); + } + + QString extra; + if (summary) { + if (node->status() == Node::Preliminary) { + extra += " (preliminary)"; + } + else if (node->status() == Node::Deprecated) { + extra += " (deprecated)"; + } + else if (node->status() == Node::Obsolete) { + extra += " (obsolete)"; + } + } + + if (!extra.isEmpty()) { + extra.prepend("<@extra>"); + extra.append("</@extra>"); + } + return synopsis + extra; +} +#endif + QString CppCodeMarker::markedUpName(const Node *node) { QString name = linkTag(node, taggedNode(node)); @@ -537,7 +574,7 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner, else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) - insert(staticPublicMembers, *c, style, status); + insert(staticPublicMembers,*c,style,status); } else if ((*c)->type() == Node::Property) { insert(properties, *c, style, status); @@ -561,11 +598,11 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner, else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) - insert(staticProtectedMembers, *c, style, status); + insert(staticProtectedMembers,*c,style,status); } else if ((*c)->type() == Node::Variable) { if (!(*c)->doc().isEmpty()) - insert(protectedVariables, *c, style, status); + insert(protectedVariables,*c,style,status); } else if ((*c)->type() == Node::Function) { if (!insertReimpFunc(protectedFunctions,*c,status)) @@ -582,14 +619,14 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner, else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) - insert(staticPrivateMembers, *c, style, status); + insert(staticPrivateMembers,*c,style,status); } else if ((*c)->type() == Node::Function) { if (!insertReimpFunc(privateFunctions,*c,status)) insert(privateFunctions, *c, style, status); } else { - insert(privateTypes, *c, style, status); + insert(privateTypes,*c,style,status); } } ++c; @@ -706,17 +743,23 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner, "Namespaces", "namespace", "namespaces"); - FastSection classes(inner, "Classes", "class", "classes"); + FastSection classes(inner, + "Classes", + "class", + "classes"); FastSection types(inner, - style == Summary ? "Types" : "Type Documentation", + style == Summary ? + "Types" : "Type Documentation", "type", "types"); FastSection functions(inner, - style == Summary ? "Functions" : "Function Documentation", + style == Summary ? + "Functions" : "Function Documentation", "function", "functions"); FastSection macros(inner, - style == Summary ? "Macros" : "Macro Documentation", + style == Summary ? + "Macros" : "Macro Documentation", "macro", "macros"); @@ -1051,4 +1094,82 @@ QString CppCodeMarker::addMarkUp(const QString& protectedCode, return result; } +#ifdef QDOC_QML +/*! + This function is for documenting QML properties. It returns + the list of documentation sections for the children of the + \a qmlClassNode. + + Currently, it only handles QML property groups. + */ +QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style) +{ + QList<Section> sections; + if (qmlClassNode) { + if (style == Summary) { + FastSection qmlproperties(qmlClassNode, + "QML Properties", + "property", + "properties"); + FastSection qmlsignals(qmlClassNode, + "QML Signals", + "signal", + "signals"); + FastSection qmlmethods(qmlClassNode, + "QML Methods", + "method", + "methods"); + + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c); + NodeList::ConstIterator p = qpgn->childNodes().begin(); + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + insert(qmlproperties,*p,style,Okay); + } + ++p; + } + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + else if (style == Detailed) { + FastSection qmlproperties(qmlClassNode,"QML Property Documentation"); + FastSection qmlsignals(qmlClassNode,"QML Signal Documentation"); + FastSection qmlmethods(qmlClassNode,"QML Method Documentation"); + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + insert(qmlproperties,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + } + + return sections; +} +#endif + QT_END_NAMESPACE diff --git a/tools/qdoc3/cppcodemarker.h b/tools/qdoc3/cppcodemarker.h index 2967dfe..fa3cb78 100644 --- a/tools/qdoc3/cppcodemarker.h +++ b/tools/qdoc3/cppcodemarker.h @@ -67,6 +67,9 @@ class CppCodeMarker : public CodeMarker QString markedUpSynopsis(const Node *node, const Node *relative, SynopsisStyle style); +#ifdef QDOC_QML + QString markedUpQmlItem(const Node *node, bool summary); +#endif QString markedUpName(const Node *node); QString markedUpFullName(const Node *node, const Node *relative); QString markedUpEnumValue(const QString &enumValue, const Node *relative); @@ -76,6 +79,8 @@ class CppCodeMarker : public CodeMarker QList<Section> sections(const InnerNode *innerNode, SynopsisStyle style, Status status); + QList<Section> qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style); const Node *resolveTarget(const QString& target, const Tree *tree, const Node *relative); diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp index 792190d..562684b 100644 --- a/tools/qdoc3/cppcodeparser.cpp +++ b/tools/qdoc3/cppcodeparser.cpp @@ -87,6 +87,10 @@ QT_BEGIN_NAMESPACE #ifdef QDOC_QML #define COMMAND_QMLCLASS Doc::alias("qmlclass") #define COMMAND_QMLPROPERTY Doc::alias("qmlproperty") +#define COMMAND_QMLINHERITS Doc::alias("inherits") +#define COMMAND_QMLSIGNAL Doc::alias("qmlsignal") +#define COMMAND_QMLMETHOD Doc::alias("qmlmethod") +#define COMMAND_QMLDEFAULT Doc::alias("default") #endif QStringList CppCodeParser::exampleFiles; @@ -109,7 +113,8 @@ static void extractPageLinkAndDesc(const QString &arg, if (arg.contains(".html") && spaceAt != -1) { *link = arg.left(spaceAt).trimmed(); *desc = arg.mid(spaceAt).trimmed(); - } else { + } + else { *link = arg; *desc = arg; } @@ -202,11 +207,6 @@ void CppCodeParser::initializeParser(const Config &config) nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property); nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable); -#ifdef QDOC_QML - // nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class); - nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property); -#endif - exampleFiles = config.getStringList(CONFIG_EXAMPLES); exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS); QStringList exampleFilePatterns = config.getStringList( @@ -477,13 +477,15 @@ QSet<QString> CppCodeParser::topicCommands() << COMMAND_PROPERTY << COMMAND_SERVICE << COMMAND_TYPEDEF -#ifdef QDOC_QML +#ifdef QDOC_QML << COMMAND_VARIABLE << COMMAND_QMLCLASS - << COMMAND_QMLPROPERTY; -#else + << COMMAND_QMLPROPERTY + << COMMAND_QMLSIGNAL + << COMMAND_QMLMETHOD; +#else << COMMAND_VARIABLE; -#endif +#endif } /*! @@ -587,7 +589,7 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc, The command was neither "fn" nor "macro" . */ // ### split(" ") hack is there to support header file syntax - QStringList paths = arg.split(" "); + QStringList paths = arg.split(" "); QStringList path = paths[0].split("::"); Node *node = 0; if (!usedNamespaces.isEmpty()) { @@ -627,49 +629,169 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc, } } + if (command == COMMAND_CLASS) { + if (paths.size() > 1) { + if (!paths[1].endsWith(".h")) { + ClassNode*cnode = static_cast<ClassNode*>(node); + cnode->setQmlElement(paths[1]); + } + } + } return node; } else if (command == COMMAND_EXAMPLE) { - FakeNode *fake = new FakeNode(tre->root(), arg, FakeNode::Example); + FakeNode *fake = new FakeNode(tre->root(), arg, Node::Example); createExampleFileNodes(fake); return fake; } else if (command == COMMAND_EXTERNALPAGE) { - return new FakeNode(tre->root(), arg, FakeNode::ExternalPage); + return new FakeNode(tre->root(), arg, Node::ExternalPage); } else if (command == COMMAND_FILE) { - return new FakeNode(tre->root(), arg, FakeNode::File); + return new FakeNode(tre->root(), arg, Node::File); } else if (command == COMMAND_GROUP) { - return new FakeNode(tre->root(), arg, FakeNode::Group); + return new FakeNode(tre->root(), arg, Node::Group); } else if (command == COMMAND_HEADERFILE) { - return new FakeNode(tre->root(), arg, FakeNode::HeaderFile); + return new FakeNode(tre->root(), arg, Node::HeaderFile); } else if (command == COMMAND_MODULE) { - return new FakeNode(tre->root(), arg, FakeNode::Module); + return new FakeNode(tre->root(), arg, Node::Module); } else if (command == COMMAND_PAGE) { - return new FakeNode(tre->root(), arg, FakeNode::Page); + return new FakeNode(tre->root(), arg, Node::Page); } -#ifdef QDOC_QML +#ifdef QDOC_QML else if (command == COMMAND_QMLCLASS) { const ClassNode* classNode = 0; - QStringList names = arg.split(" "); - //qDebug() << "QMLCLASS" << names; + QStringList names = arg.split(" "); if (names.size() > 1) { Node* n = tre->findNode(names[1].split("::"),Node::Class); - if (n) { + if (n) classNode = static_cast<const ClassNode*>(n); - //qDebug() << "FOUND IT!" << classNode->name(); + } + return new QmlClassNode(tre->root(), names[0], classNode); + } + else if ((command == COMMAND_QMLSIGNAL) || + (command == COMMAND_QMLMETHOD)) { + QString element; + QString name; + QmlClassNode* qmlClass = 0; + if (splitQmlArg(doc,arg,element,name)) { + Node* n = tre->findNode(QStringList(element),Node::Fake); + if (n && n->subType() == Node::QmlClass) { + qmlClass = static_cast<QmlClassNode*>(n); + if (command == COMMAND_QMLSIGNAL) + return new QmlSignalNode(qmlClass,name); + else + return new QmlMethodNode(qmlClass,name); } } - return new QmlNode(tre->root(), names[0], classNode); } -#endif +#endif return 0; } +#ifdef QDOC_QML + +/*! + A QML property argument has the form... + + <type> <element>::<name> + + This function splits the argument into those three + parts, sets \a type, \a element, and \a property, + and returns true. If any of the parts isn't found, + a debug message is output and false is returned. + */ +bool CppCodeParser::splitQmlPropertyArg(const Doc& doc, + const QString& arg, + QString& type, + QString& element, + QString& property) +{ + QStringList blankSplit = arg.split(" "); + if (blankSplit.size() > 1) { + type = blankSplit[0]; + QStringList colonSplit(blankSplit[1].split("::")); + if (colonSplit.size() > 1) { + element = colonSplit[0]; + property = colonSplit[1]; + return true; + } + else + doc.location().warning(tr("Missing QML element name or property name")); + } + else + doc.location().warning(tr("Missing QML property type or property path")); + return false; +} + +/*! + A QML signal or method argument has the form... + + <element>::<name> + + This function splits the argument into those two + parts, sets \a element, and \a name, and returns + true. If either of the parts isn't found, a debug + message is output and false is returned. + */ +bool CppCodeParser::splitQmlArg(const Doc& doc, + const QString& arg, + QString& element, + QString& name) +{ + QStringList colonSplit(arg.split("::")); + if (colonSplit.size() > 1) { + element = colonSplit[0]; + name = colonSplit[1]; + return true; + } + else + doc.location().warning(tr("Missing QML element name or signal/method name")); + return false; +} + +/*! + Process the topic \a command group with arguments \a args. + + Currently, this function is called only for \e{qmlproperty}. + */ +Node *CppCodeParser::processTopicCommandGroup(const Doc& doc, + const QString& command, + const QStringList& args) +{ + QmlPropGroupNode* qmlPropGroup = 0; + if (command == COMMAND_QMLPROPERTY) { + QString type; + QString element; + QString property; + QStringList::ConstIterator arg = args.begin(); + if (splitQmlPropertyArg(doc,(*arg),type,element,property)) { + Node* n = tre->findNode(QStringList(element),Node::Fake); + if (n && n->subType() == Node::QmlClass) { + QmlClassNode* qmlClass = static_cast<QmlClassNode*>(n); + if (qmlClass) + qmlPropGroup = new QmlPropGroupNode(qmlClass,property); + } + } + if (qmlPropGroup) { + new QmlPropertyNode(qmlPropGroup,property,type); + ++arg; + while (arg != args.end()) { + if (splitQmlPropertyArg(doc,(*arg),type,element,property)) { + new QmlPropertyNode(qmlPropGroup,property,type); + } + ++arg; + } + } + } + return qmlPropGroup; +} +#endif + /*! Returns the set of strings representing the common metacommands plus some other metacommands. @@ -684,7 +806,13 @@ QSet<QString> CppCodeParser::otherMetaCommands() << COMMAND_NEXTPAGE << COMMAND_PREVIOUSPAGE << COMMAND_INDEXPAGE +#ifdef QDOC_QML + << COMMAND_STARTPAGE + << COMMAND_QMLINHERITS + << COMMAND_QMLDEFAULT; +#else << COMMAND_STARTPAGE; +#endif } /*! @@ -726,24 +854,29 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, tr("The function either doesn't exist in any base class " "with the same signature or it exists but isn't virtual.")); } -#if 0 // Ideally, we would enable this check to warn whenever \reimp is used - // incorrectly, and only make the node internal if the function is a - // reimplementation of another function in a base class. + /* + Ideally, we would enable this check to warn whenever + \reimp is used incorrectly, and only make the node + internal if the function is a reimplementation of + another function in a base class. + */ else if (from->access() == Node::Private || from->parent()->access() == Node::Private) { - doc.location().warning( - tr("Base function for '\\%1' in %2() is private or internal") + doc.location().warning(tr("'\\%1' in %2() should be '\\internal' because its base function is private or internal") .arg(COMMAND_REIMP).arg(node->name())); } -#endif - // Note: Setting the access to Private hides the documentation, - // but setting the status to Internal makes the node available - // in the XML output when the WebXMLGenerator is used. + #if 0 // Reimplemented functions now reported in separate sections. + /* + Note: Setting the access to Private hides the documentation, + but setting the status to Internal makes the node available + in the XML output when the WebXMLGenerator is used. + */ func->setAccess(Node::Private); func->setStatus(Node::Internal); -#endif +#endif + func->setReimp(true); } else { doc.location().warning(tr("Ignored '\\%1' in %2") @@ -754,14 +887,19 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, else if (command == COMMAND_RELATES) { InnerNode *pseudoParent; if (arg.startsWith("<") || arg.startsWith("\"")) { - pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(arg), Node::Fake)); + pseudoParent = + static_cast<InnerNode *>(tre->findNode(QStringList(arg), + Node::Fake)); } else { QStringList newPath = arg.split("::"); - pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath), Node::Class)); + pseudoParent = + static_cast<InnerNode*>(tre->findNode(QStringList(newPath), + Node::Class)); if (!pseudoParent) - pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath), - Node::Namespace)); + pseudoParent = + static_cast<InnerNode*>(tre->findNode(QStringList(newPath), + Node::Namespace)); } if (!pseudoParent) { doc.location().warning(tr("Cannot find '%1' in '\\%2'") @@ -786,6 +924,15 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, else if (command == COMMAND_STARTPAGE) { setLink(node, Node::StartLink, arg); } +#ifdef QDOC_QML + else if (command == COMMAND_QMLINHERITS) { + setLink(node, Node::InheritsLink, arg); + } + else if (command == COMMAND_QMLDEFAULT) { + QmlPropGroupNode* qpgn = static_cast<QmlPropGroupNode*>(node); + qpgn->setDefault(); + } +#endif else { processCommonMetaCommand(doc.location(),command,arg,node,tre); } @@ -865,9 +1012,8 @@ bool CppCodeParser::match(int target) readToken(); return true; } - else { + else return false; - } } /*! @@ -902,11 +1048,14 @@ bool CppCodeParser::matchTemplateAngles(CodeChunk *dataType) do { if (tok == Tok_LeftAngle) { leftAngleDepth++; - } else if (tok == Tok_RightAngle) { + } + else if (tok == Tok_RightAngle) { leftAngleDepth--; - } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { + } + else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { ++parenAndBraceDepth; - } else if (tok == Tok_RightParen || tok == Tok_RightBrace) { + } + else if (tok == Tok_RightParen || tok == Tok_RightBrace) { if (--parenAndBraceDepth < 0) return false; } @@ -969,7 +1118,8 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var) dataType->append(previousLexeme()); else return false; - } else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) { + } + else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) { dataType->append(previousLexeme()); } @@ -1069,8 +1219,10 @@ bool CppCodeParser::matchParameter(FunctionNode *func) readToken(); } } - func->addParameter(Parameter(dataType.toString(), "", name, - defaultValue.toString())); // ### + func->addParameter(Parameter(dataType.toString(), + "", + name, + defaultValue.toString())); // ### return true; } @@ -1118,7 +1270,8 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent, compat = true; if (tok == Tok_operator && - (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) { + (returnType.toString().isEmpty() || + returnType.toString().endsWith("::"))) { // 'QString::operator const char *()' parentPath = returnType.toString().split(sep); parentPath.removeAll(QString()); @@ -1154,11 +1307,10 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent, name = previousLexeme(); matchTemplateAngles(); - if (match(Tok_Gulbrandsen)) { + if (match(Tok_Gulbrandsen)) parentPath.append(name); - } else { + else break; - } } if (tok == Tok_operator) { @@ -1171,7 +1323,9 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent, break; } } - if (parent && (tok == Tok_Semicolon || tok == Tok_LeftBracket || tok == Tok_Colon) + if (parent && (tok == Tok_Semicolon || + tok == Tok_LeftBracket || + tok == Tok_Colon) && access != Node::Private) { if (tok == Tok_LeftBracket) { returnType.appendHotspot(); @@ -1185,7 +1339,8 @@ bool CppCodeParser::matchFunctionDecl(InnerNode *parent, } if (tok != Tok_Semicolon) return false; - } else if (tok == Tok_Colon) { + } + else if (tok == Tok_Colon) { returnType.appendHotspot(); while (tok != Tok_Semicolon && tok != Tok_Eoi) { @@ -1377,7 +1532,7 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent) QString namespaceName = previousLexeme(); NamespaceNode *namespasse = 0; if (parent) - namespasse = static_cast<NamespaceNode *>(parent->findNode(namespaceName, Node::Namespace)); + namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace)); if (!namespasse) { namespasse = new NamespaceNode(parent, namespaceName); namespasse->setAccess(access); @@ -1443,7 +1598,8 @@ bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume) if (strVal.isEmpty()) { if (enume->items().isEmpty()) { strVal = "0"; - } else { + } + else { QString last = enume->items().last().value(); bool ok; int n = last.toInt(&ok); @@ -1453,15 +1609,16 @@ bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume) strVal = last.left(2) + QString::number(n + 1, 16); else strVal = "0" + QString::number(n + 1, 8); - } else { - strVal = QString::number(n + 1); } + else + strVal = QString::number(n + 1); } } } enume->addItem(EnumItem(name, strVal)); - } else { + } + else { VariableNode *var = new VariableNode(parent, name); var->setAccess(access); var->setLocation(location()); @@ -1549,7 +1706,8 @@ bool CppCodeParser::matchProperty(InnerNode *parent) if (match(Tok_Ident)) { value = previousLexeme(); - } else if (match(Tok_LeftParen)) { + } + else if (match(Tok_LeftParen)) { int depth = 1; while (tok != Tok_Eoi) { if (tok == Tok_LeftParen) { @@ -1566,6 +1724,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent) value = "?"; } + /* + Task 259071 requires work here. See gui/widgets/qdatetime.h, for example. + */ if (key == "READ") tre->addPropertyFunction(property, value, PropertyNode::Getter); else if (key == "WRITE") @@ -1802,6 +1963,28 @@ bool CppCodeParser::matchDocsAndStuff() /* There is a topic command. Process it. */ +#ifdef QDOC_QML + if (topic == COMMAND_QMLPROPERTY) { + Doc nodeDoc = doc; + Node *node = processTopicCommandGroup(nodeDoc,topic,args); + if (node != 0) { + nodes.append(node); + docs.append(nodeDoc); + } + } + else { + QStringList::ConstIterator a = args.begin(); + while (a != args.end()) { + Doc nodeDoc = doc; + Node *node = processTopicCommand(nodeDoc,topic,*a); + if (node != 0) { + nodes.append(node); + docs.append(nodeDoc); + } + ++a; + } + } +#else QStringList::ConstIterator a = args.begin(); while (a != args.end()) { Doc nodeDoc = doc; @@ -1812,6 +1995,7 @@ bool CppCodeParser::matchDocsAndStuff() } ++a; } +#endif } NodeList::Iterator n = nodes.begin(); @@ -1819,7 +2003,8 @@ bool CppCodeParser::matchDocsAndStuff() while (n != nodes.end()) { processOtherMetaCommands(*d, *n); (*n)->setDoc(*d); - if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { + if ((*n)->isInnerNode() && + ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast<InnerNode *>(*n); while (m->parent() != tre->root()) m = m->parent(); @@ -1907,7 +2092,8 @@ void CppCodeParser::parseQiteratorDotH(const Location &location, mutableSequentialIteratorDefinition = lines[1]; associativeIteratorDefinition = lines[2]; mutableAssociativeIteratorDefinition = lines[3]; - } else { + } + else { location.warning(tr("The qiterator.h hack failed")); } } @@ -1989,7 +2175,7 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake) foreach (const QString &exampleFile, exampleFiles) (void) new FakeNode(fake, exampleFile.mid(sizeOfBoringPartOfName), - FakeNode::File); + Node::File); } QT_END_NAMESPACE diff --git a/tools/qdoc3/cppcodeparser.h b/tools/qdoc3/cppcodeparser.h index 1f41318..cbb0149 100644 --- a/tools/qdoc3/cppcodeparser.h +++ b/tools/qdoc3/cppcodeparser.h @@ -90,6 +90,21 @@ class CppCodeParser : public CodeParser virtual Node *processTopicCommand(const Doc& doc, const QString& command, const QString& arg); +#ifdef QDOC_QML + // might need to implement this in QsCodeParser as well. + virtual Node *processTopicCommandGroup(const Doc& doc, + const QString& command, + const QStringList& args); + bool splitQmlPropertyArg(const Doc& doc, + const QString& arg, + QString& type, + QString& element, + QString& property); + bool splitQmlArg(const Doc& doc, + const QString& arg, + QString& element, + QString& name); +#endif virtual QSet<QString> otherMetaCommands(); virtual void processOtherMetaCommand(const Doc& doc, const QString& command, diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 222b9a1..e2f3525 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -73,20 +73,20 @@ struct Macro }; enum { - CMD_A, CMD_ABSTRACT, CMD_BADCODE, CMD_BASENAME, CMD_BOLD, - CMD_BRIEF, CMD_C, CMD_CAPTION, CMD_CHAPTER, CMD_CODE, - CMD_CODELINE, CMD_DOTS, CMD_ELSE, CMD_ENDABSTRACT, - CMD_ENDCHAPTER, CMD_ENDCODE, CMD_ENDFOOTNOTE, CMD_ENDIF, - CMD_ENDLEGALESE, CMD_ENDLINK, CMD_ENDLIST, CMD_ENDOMIT, - CMD_ENDPART, CMD_ENDQUOTATION, CMD_ENDRAW, CMD_ENDSECTION1, - CMD_ENDSECTION2, CMD_ENDSECTION3, CMD_ENDSECTION4, - CMD_ENDSIDEBAR, CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE, - CMD_GENERATELIST, CMD_GRANULARITY, CMD_HEADER, CMD_I, - CMD_IF, CMD_IMAGE, CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX, - CMD_KEYWORD, CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST, - CMD_META, CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT, - CMD_OMITVALUE, CMD_OVERLOAD, - CMD_PART, CMD_PRINTLINE, CMD_PRINTTO, + CMD_A, CMD_ABSTRACT, CMD_ANNOTATEDLIST, CMD_BADCODE, + CMD_BASENAME, CMD_BOLD, CMD_BRIEF, CMD_C, CMD_CAPTION, + CMD_CHAPTER, CMD_CODE, CMD_CODELINE, CMD_DOTS, CMD_ELSE, + CMD_ENDABSTRACT, CMD_ENDCHAPTER, CMD_ENDCODE, + CMD_ENDFOOTNOTE, CMD_ENDIF, CMD_ENDLEGALESE, CMD_ENDLINK, + CMD_ENDLIST, CMD_ENDOMIT, CMD_ENDPART, CMD_ENDQUOTATION, + CMD_ENDRAW, CMD_ENDSECTION1, CMD_ENDSECTION2, + CMD_ENDSECTION3, CMD_ENDSECTION4, CMD_ENDSIDEBAR, + CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE, CMD_GENERATELIST, + CMD_GRANULARITY, CMD_HEADER, CMD_I, CMD_IF, CMD_IMAGE, + CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX, CMD_KEYWORD, + CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST, CMD_META, + CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT, CMD_OMITVALUE, + CMD_OVERLOAD, CMD_PART, CMD_PRINTLINE, CMD_PRINTTO, CMD_PRINTUNTIL, CMD_QUOTATION, CMD_QUOTEFILE, CMD_QUOTEFROMFILE, CMD_QUOTEFUNCTION, CMD_RAW, CMD_ROW, CMD_SA, CMD_SECTION1, CMD_SECTION2, CMD_SECTION3, @@ -108,6 +108,7 @@ static struct { } cmds[] = { { "a", CMD_A, 0 }, { "abstract", CMD_ABSTRACT, 0 }, + { "annotatedlist", CMD_ANNOTATEDLIST, 0 }, { "badcode", CMD_BADCODE, 0 }, { "basename", CMD_BASENAME, 0 }, // ### don't document for now { "bold", CMD_BOLD, 0 }, @@ -723,6 +724,9 @@ void DocParser::parse(const QString& source, paraState = OutsidePara; // ### } break; + case CMD_ANNOTATEDLIST: + append(Atom::AnnotatedList, getArgument()); + break; case CMD_GENERATELIST: append(Atom::GeneratedList, getArgument()); break; @@ -1677,10 +1681,13 @@ void DocParser::startSection(Doc::SectioningUnit unit, int cmd) leavePara(); if (currentSectioningUnit == Doc::Book) { +#if 0 + // mws didn't think this was necessary. if (unit > Doc::Section1) location().warning(tr("Unexpected '\\%1' without '\\%2'") .arg(cmdName(cmd)) .arg(cmdName(CMD_SECTION1))); +#endif currentSectioningUnit = (Doc::SectioningUnit) (unit - 1); priv->constructExtra(); priv->extra->sectioningUnit = currentSectioningUnit; diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp index fa55b8a..e92f53b 100644 --- a/tools/qdoc3/generator.cpp +++ b/tools/qdoc3/generator.cpp @@ -42,7 +42,7 @@ /* generator.cpp */ - +#include <QtCore> #include <qdir.h> #include <qdebug.h> #include "codemarker.h" @@ -68,14 +68,20 @@ QStringList Generator::imageDirs; QString Generator::outDir; QString Generator::project; -static Text stockLink(const QString &target) +static void singularPlural(Text& text, const NodeList& nodes) { - return Text() << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) - << target << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + if (nodes.count() == 1) + text << " is"; + else + text << " are"; } Generator::Generator() - : amp("&"), lt("<"), gt(">"), quot("""), tag("</?@[^>]*>") + : amp("&"), + lt("<"), + gt(">"), + quot("""), + tag("</?@[^>]*>") { generators.prepend(this); } @@ -123,7 +129,8 @@ void Generator::initialize(const Config &config) QSet<QString> formats = config.subVars(imagesDotFileExtensions); QSet<QString>::ConstIterator f = formats.begin(); while (f != formats.end()) { - imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + Config::dot + *f); + imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + + Config::dot + *f); ++f; } @@ -131,16 +138,22 @@ void Generator::initialize(const Config &config) while (g != generators.end()) { if (outputFormats.contains((*g)->format())) { (*g)->initializeGenerator(config); - QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + Config::dot - + (*g)->format()); + QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + + Config::dot + + (*g)->format()); QStringList::ConstIterator e = extraImages.begin(); while (e != extraImages.end()) { QString userFriendlyFilePath; - QString filePath = Config::findFile(config.lastLocation(), imageFiles, imageDirs, *e, - imgFileExts[(*g)->format()], userFriendlyFilePath); + QString filePath = Config::findFile(config.lastLocation(), + imageFiles, imageDirs, *e, + imgFileExts[(*g)->format()], + userFriendlyFilePath); if (!filePath.isEmpty()) - Config::copyFile(config.lastLocation(), filePath, userFriendlyFilePath, - (*g)->outputDir() + "/images"); + Config::copyFile(config.lastLocation(), + filePath, + userFriendlyFilePath, + (*g)->outputDir() + + "/images"); ++e; } } @@ -156,20 +169,23 @@ void Generator::initialize(const Config &config) QSet<QString> formats = config.subVars(formattingDotName); QSet<QString>::ConstIterator f = formats.begin(); while (f != formats.end()) { - QString def = config.getString(formattingDotName + Config::dot + - *f); + QString def = config.getString(formattingDotName + + Config::dot + *f); if (!def.isEmpty()) { int numParams = Config::numParams(def); int numOccs = def.count("\1"); if (numParams != 1) { - config.lastLocation().warning(tr("Formatting '%1' must have exactly one" - " parameter (found %2)") - .arg(*n).arg(numParams)); + config.lastLocation().warning(tr("Formatting '%1' must " + "have exactly one " + "parameter (found %2)") + .arg(*n).arg(numParams)); } else if (numOccs > 1) { - config.lastLocation().fatal(tr("Formatting '%1' must contain exactly one" - " occurrence of '\\1' (found %2)") + config.lastLocation().fatal(tr("Formatting '%1' must " + "contain exactly one " + "occurrence of '\\1' " + "(found %2)") .arg(*n).arg(numOccs)); } else { @@ -241,7 +257,7 @@ void Generator::generateFakeNode(const FakeNode * /* fake */, { } -void Generator::generateText(const Text& text, +bool Generator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { @@ -254,31 +270,40 @@ void Generator::generateText(const Text& text, true, numAtoms); endText(relative, marker); + return true; } + return false; } #ifdef QDOC_QML -void Generator::generateQmlText(const Text& text, +/*! + Extract sections of markup text surrounded by \e qmltext + and \e endqmltext and output them. + */ +bool Generator::generateQmlText(const Text& text, const Node *relative, - CodeMarker *marker) + CodeMarker *marker, + const QString& qmlName) { - if (text.firstAtom() != 0) { - startText(relative, marker); - const Atom *atom = text.firstAtom(); - while (atom) { - if (atom->type() != Atom::QmlText) - atom = atom->next(); - else { - atom = atom->next(); - while (atom && (atom->type() != Atom::EndQmlText)) { - int n = 1 + generateAtom(atom, relative, marker); - while (n-- > 0) - atom = atom->next(); - } + const Atom* atom = text.firstAtom(); + if (atom == 0) + return false; + + startText(relative, marker); + while (atom) { + if (atom->type() != Atom::QmlText) + atom = atom->next(); + else { + atom = atom->next(); + while (atom && (atom->type() != Atom::EndQmlText)) { + int n = 1 + generateAtom(atom, relative, marker); + while (n-- > 0) + atom = atom->next(); } } - endText(relative, marker); } + endText(relative, marker); + return true; } #endif @@ -295,14 +320,14 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } else if (node->type() == Node::Fake) { const FakeNode *fake = static_cast<const FakeNode *>(node); - if (fake->subType() == FakeNode::Example) + if (fake->subType() == Node::Example) generateExampleFiles(fake, marker); - else if (fake->subType() == FakeNode::File) + else if (fake->subType() == Node::File) quiet = true; } if (node->doc().isEmpty()) { - if (!quiet) // ### might be unnecessary + if (!quiet && !node->isReimp()) // ### might be unnecessary node->location().warning(tr("No documentation for '%1'") .arg(marker->plainFullName(node))); } @@ -313,7 +338,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) generateReimplementedFrom(func, marker); } - generateText(node->doc().body(), node, marker); + if (!generateText(node->doc().body(), node, marker)) + if (node->isReimp()) + return; if (node->type() == Node::Enum) { const EnumNode *enume = (const EnumNode *) node; @@ -387,7 +414,8 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name()); if (primaryFunc) { - foreach (const Parameter ¶m, primaryFunc->parameters()) { + foreach (const Parameter ¶m, + primaryFunc->parameters()) { if (param.name() == *a) { needWarning = false; break; @@ -395,9 +423,10 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } } } - if (needWarning) + if (needWarning && !func->isReimp()) node->doc().location().warning( - tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node))); + tr("Undocumented parameter '%1' in %2") + .arg(*a).arg(marker->plainFullName(node))); } ++a; } @@ -419,7 +448,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) if (node->type() == Node::Fake) { const FakeNode *fake = static_cast<const FakeNode *>(node); - if (fake->subType() == FakeNode::File) { + if (fake->subType() == Node::File) { Text text; Quoter quoter; Doc::quoteFromFile(fake->doc().location(), quoter, fake->name()); @@ -466,7 +495,8 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker) if ((*r).access == Node::Protected) { text << " (protected)"; - } else if ((*r).access == Node::Private) { + } + else if ((*r).access == Node::Private) { text << " (private)"; } text << separator(index++, classe->baseClasses().count()); @@ -477,6 +507,15 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker) } } +#ifdef QDOC_QML +/*! + */ +void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* ) +{ + // stub. +} +#endif + void Generator::generateInheritedBy(const ClassNode *classe, CodeMarker *marker) { @@ -504,18 +543,21 @@ void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker) QString exampleFile = child->name(); openedList.next(); text << Atom(Atom::ListItemNumber, openedList.numberString()) - << Atom(Atom::ListItemLeft, openedList.styleString()) << Atom::ParaLeft + << Atom(Atom::ListItemLeft, openedList.styleString()) + << Atom::ParaLeft << Atom(Atom::Link, exampleFile) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << exampleFile << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) - << Atom::ParaRight << Atom(Atom::ListItemRight, openedList.styleString()); + << Atom::ParaRight + << Atom(Atom::ListItemRight, openedList.styleString()); } text << Atom(Atom::ListRight, openedList.styleString()); generateText(text, fake, marker); } -void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marker) +void Generator::generateModuleWarning(const ClassNode *classe, + CodeMarker *marker) { QString module = classe->moduleName(); if (!module.isEmpty()) { @@ -536,8 +578,10 @@ void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marke << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; } - else if (module == "Qt3Support" && Tokenizer::isTrue("defined(opensourceedition)")) { - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) + else if (module == "Qt3Support" && + Tokenizer::isTrue("defined(opensourceedition)")) { + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Note to Qt Desktop Light Edition users:" << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This class is only available in the " @@ -565,10 +609,12 @@ QString Generator::indent(int level, const QString& markedCode) if (markedCode.at(i - 1) == QLatin1Char('>')) break; } - } else { + } + else { if (markedCode.at(i) == QLatin1Char('\n')) { column = 0; - } else { + } + else { if (column == 0) { for (int j = 0; j < level; j++) t += QLatin1Char(' '); @@ -637,7 +683,7 @@ void Generator::setImageFileExtensions(const QStringList& extensions) void Generator::unknownAtom(const Atom *atom) { Location::internalError(tr("unknown atom type '%1' in %2 generator") - .arg(atom->typeString()).arg(format())); + .arg(atom->typeString()).arg(format())); } bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType) @@ -666,7 +712,8 @@ void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList) alternateFunc = func->parent()->findFunctionNode(alternateName); } } - } else if (!func->name().isEmpty()) { + } + else if (!func->name().isEmpty()) { alternateName = "set"; alternateName += func->name()[0].toUpper(); alternateName += func->name().mid(1); @@ -722,9 +769,13 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker) case Node::Main: break; case Node::Preliminary: - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " - << typeString(node) << " is under development and is subject to change." - << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) + << "This " + << typeString(node) + << " is under development and is subject to change." + << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) + << Atom::ParaRight; break; case Node::Deprecated: text << Atom::ParaLeft; @@ -742,16 +793,21 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker) text << "This " << typeString(node) << " is obsolete."; if (node->isInnerNode()) text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); - text << " It is provided to keep old source code working. We strongly advise against " + text << " It is provided to keep old source code working. " + << "We strongly advise against " << "using it in new code." << Atom::ParaRight; break; case Node::Compat: // reimplemented in HtmlGenerator subclass if (node->isInnerNode()) { - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " - << typeString(node) << " is part of the Qt 3 compatibility layer." + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) + << "This " + << typeString(node) + << " is part of the Qt 3 compatibility layer." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) - << " It is provided to keep old source code working. We strongly advise against " + << " It is provided to keep old source code working. " + << "We strongly advise against " << "using it in new code. See " << Atom(Atom::AutoLink, "Porting to Qt 4") << " for more information." @@ -769,71 +825,147 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker) { Text text; Text theStockLink; - Node::ThreadSafeness parent = node->parent()->inheritedThreadSafeness(); + Node::ThreadSafeness threadSafeness = node->threadSafeness(); + + 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 (node->threadSafeness()) { + switch (threadSafeness) { case Node::UnspecifiedSafeness: break; case Node::NonReentrant: - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Warning:" - << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This " - << typeString(node) << " is not " << stockLink("reentrant") << "." << Atom::ParaRight; + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) + << "Warning:" + << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD) + << " This " + << typeString(node) + << " is not " + << rlink + << "." + << Atom::ParaRight; break; case Node::Reentrant: case Node::ThreadSafe: - text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); - if (parent == Node::ThreadSafe) { - text << "Warning:"; - } else { - text << "Note:"; - } - text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " "; - - if (node->threadSafeness() == Node::ThreadSafe) - theStockLink = stockLink("thread-safe"); - else - theStockLink = stockLink("reentrant"); + text << Atom::ParaLeft + << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) + << "Note:" + << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD) + << " "; if (node->isInnerNode()) { - const InnerNode *innerNode = static_cast<const InnerNode *>(node); - text << "All the functions in this " << typeString(node) << " are " - << theStockLink; - - NodeList except; + const InnerNode* innerNode = static_cast<const InnerNode*>(node); + text << "All functions in this " + << typeString(node) + << " are "; + if (threadSafeness == Node::ThreadSafe) + text << tlink; + else + text << rlink; + + bool exceptions = false; + NodeList reentrant; + NodeList threadsafe; + NodeList nonreentrant; NodeList::ConstIterator c = innerNode->childNodes().begin(); while (c != innerNode->childNodes().end()) { - if ((*c)->threadSafeness() != Node::UnspecifiedSafeness) - except.append(*c); + 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 (except.isEmpty()) { + if (!exceptions) text << "."; + else if (threadSafeness == Node::Reentrant) { + if (nonreentrant.isEmpty()) { + if (!threadsafe.isEmpty()) { + text << ", but "; + appendFullNames(text,threadsafe,innerNode,marker); + singularPlural(text,threadsafe); + text << " also " << tlink << "."; + } + else + text << "."; + } + else { + text << ", except for "; + appendFullNames(text,nonreentrant,innerNode,marker); + text << ", which"; + singularPlural(text,nonreentrant); + text << " nonreentrant."; + if (!threadsafe.isEmpty()) { + text << " "; + appendFullNames(text,threadsafe,innerNode,marker); + singularPlural(text,threadsafe); + text << " " << tlink << "."; + } + } } - else { - text << ", except "; - - NodeList::ConstIterator e = except.begin(); - int index = 0; - while (e != except.end()) { - appendFullName(text, *e, innerNode, marker); - text << separator(index++, except.count()); - ++e; + else { // thread-safe + if (!nonreentrant.isEmpty() || !reentrant.isEmpty()) { + text << ", except for "; + if (!reentrant.isEmpty()) { + appendFullNames(text,reentrant,innerNode,marker); + text << ", which"; + singularPlural(text,reentrant); + text << " only " << rlink; + if (!nonreentrant.isEmpty()) + text << ", and "; + } + if (!nonreentrant.isEmpty()) { + appendFullNames(text,nonreentrant,innerNode,marker); + text << ", which"; + singularPlural(text,nonreentrant); + text << " nonreentrant."; + } + text << "."; } } } else { - text << "This " << typeString(node) << " is " << theStockLink << "."; + text << "This " << typeString(node) << " is "; + if (threadSafeness == Node::ThreadSafe) + text << tlink; + else + text << rlink; + text << "."; } text << Atom::ParaRight; } - generateText(text, node, marker); + generateText(text,node,marker); } void Generator::generateSince(const Node *node, CodeMarker *marker) { if (!node->since().isEmpty()) { Text text; - text << Atom::ParaLeft << "This " << typeString(node) + text << Atom::ParaLeft + << "This " + << typeString(node) << " was introduced in "; if (project.isEmpty()) text << "version"; @@ -863,7 +995,8 @@ void Generator::generateReimplementedFrom(const FunctionNode *func, { if (func->reimplementedFrom() != 0) { const FunctionNode *from = func->reimplementedFrom(); - if (from->access() != Node::Private && from->parent()->access() != Node::Private) { + if (from->access() != Node::Private && + from->parent()->access() != Node::Private) { Text text; text << Atom::ParaLeft << "Reimplemented from "; QString fullName = from->parent()->name() + "::" + from->name() + "()"; @@ -905,8 +1038,8 @@ const Atom *Generator::generateAtomList(const Atom *atom, if (atom->type() == Atom::FormatEndif) { if (generate && numAtoms0 == numAtoms) { - relative->location().warning(tr("Output format %1 not handled"). - arg(format())); + relative->location().warning(tr("Output format %1 not handled") + .arg(format())); Atom unhandledFormatAtom(Atom::UnhandledFormat, format()); generateAtomList(&unhandledFormatAtom, relative, @@ -917,7 +1050,8 @@ const Atom *Generator::generateAtomList(const Atom *atom, atom = atom->next(); } } - else if (atom->type() == Atom::FormatElse || atom->type() == Atom::FormatEndif) { + else if (atom->type() == Atom::FormatElse || + atom->type() == Atom::FormatEndif) { return atom; } else { @@ -960,6 +1094,20 @@ void Generator::appendFullName(Text& text, << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); } +void Generator::appendFullNames(Text& text, + const NodeList& nodes, + const Node* relative, + CodeMarker* marker) +{ + NodeList::ConstIterator n = nodes.begin(); + int index = 0; + while (n != nodes.end()) { + appendFullName(text,*n,relative,marker); + text << comma(index++,nodes.count()); + ++n; + } +} + void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes, @@ -971,7 +1119,8 @@ void Generator::appendSortedNames(Text& text, r = classes.begin(); while (r != classes.end()) { - if ((*r).node->access() == Node::Public && (*r).node->status() != Node::Internal + if ((*r).node->access() == Node::Public && + (*r).node->status() != Node::Internal && !(*r).node->doc().isEmpty()) { Text className; appendFullName(className, (*r).node, classe, marker); diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h index 75134d2..8e3c57e 100644 --- a/tools/qdoc3/generator.h +++ b/tools/qdoc3/generator.h @@ -93,13 +93,16 @@ class Generator virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); - virtual void generateText(const Text& text, + virtual bool generateText(const Text& text, const Node *relative, CodeMarker *marker); #ifdef QDOC_QML - virtual void generateQmlText(const Text& text, + virtual bool generateQmlText(const Text& text, const Node *relative, - CodeMarker *marker); + CodeMarker *marker, + const QString& qmlName); + virtual void generateQmlInherits(const QmlClassNode* cn, + CodeMarker* marker); #endif virtual void generateBody(const Node *node, CodeMarker *marker); virtual void generateAlsoList(const Node *node, CodeMarker *marker); @@ -154,6 +157,10 @@ class Generator const Node *apparentNode, const QString& fullName, const Node *actualNode); + void appendFullNames(Text& text, + const NodeList& nodes, + const Node* relative, + CodeMarker* marker); void appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes, diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index cf7c618..f862e55 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -118,16 +118,19 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList typeHash["variable"] = Node::Variable; typeHash["target"] = Node::Target; - QHash<QString, FakeNode::SubType> subTypeHash; - subTypeHash["example"] = FakeNode::Example; - subTypeHash["headerfile"] = FakeNode::HeaderFile; - subTypeHash["file"] = FakeNode::File; - subTypeHash["group"] = FakeNode::Group; - subTypeHash["module"] = FakeNode::Module; - subTypeHash["page"] = FakeNode::Page; - subTypeHash["externalpage"] = FakeNode::ExternalPage; - - QSet<FakeNode::SubType> allSubTypes = QSet<FakeNode::SubType>::fromList(subTypeHash.values()); + QHash<QString, Node::SubType> subTypeHash; + 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; +#ifdef QDOC_QML + subTypeHash["qmlclass"] = Node::QmlClass; +#endif + + QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values()); foreach (const QString &selector, selectors) { QStringList pieces = selector.split(":"); @@ -139,7 +142,7 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList QString lower = pieces[0].toLower(); pieces = pieces[1].split(","); if (typeHash.contains(lower)) { - QSet<FakeNode::SubType> subTypes; + QSet<Node::SubType> subTypes; for (int i = 0; i < pieces.size(); ++i) { QString lower = pieces[i].toLower(); if (subTypeHash.contains(lower)) @@ -235,7 +238,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, // mask. const FakeNode *fakeNode = static_cast<const FakeNode *>(node); if (subproject.selectors[node->type()].contains(fakeNode->subType()) && - fakeNode->subType() != FakeNode::ExternalPage && + fakeNode->subType() != Node::ExternalPage && !fakeNode->fullTitle().isEmpty()) project.subprojects[name].nodes[objName] = node; @@ -324,10 +327,10 @@ bool HelpProjectWriter::generateSection(HelpProject &project, // attributes. case Node::Fake: { const FakeNode *fakeNode = static_cast<const FakeNode*>(node); - if (fakeNode->subType() != FakeNode::ExternalPage && + if (fakeNode->subType() != Node::ExternalPage && !fakeNode->fullTitle().isEmpty()) { - if (fakeNode->subType() != FakeNode::File) { + if (fakeNode->subType() != Node::File) { if (fakeNode->doc().hasKeywords()) { foreach (const Atom *keyword, fakeNode->doc().keywords()) { if (!keyword->string().isEmpty()) { @@ -485,7 +488,7 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer writer.writeAttribute("title", fakeNode->fullTitle()); // qDebug() << "Title:" << fakeNode->fullTitle(); - if (fakeNode->subType() == FakeNode::HeaderFile) { + if (fakeNode->subType() == Node::HeaderFile) { // Write subsections for all members, obsolete members and Qt 3 // members. @@ -609,7 +612,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) while (nextPage) { writeNode(project, writer, nextPage); nextTitle = nextPage->links().value(Node::NextLink).first; - if (nextTitle.isEmpty()) + if(nextTitle.isEmpty()) break; nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle)); } diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index c007b9b..425c50b 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -186,7 +186,7 @@ HtmlGenerator::HtmlGenerator() : helpProjectWriter(0), inLink(false), inContents(false), inSectionHeading(false), inTableHeader(false), numTableRows(0), threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"), - tre(0), slow(false) + tre(0), slow(false), obsoleteLinks(false) { } @@ -215,6 +215,7 @@ void HtmlGenerator::initializeGenerator(const Config &config) }; Generator::initializeGenerator(config); + obsoleteLinks = config.getBool(QLatin1String(CONFIG_OBSOLETELINKS)); setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif"); int i = 0; while (defaults[i].key) { @@ -223,11 +224,21 @@ void HtmlGenerator::initializeGenerator(const Config &config) i++; } - style = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLE); - postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER); - footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER); - address = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_ADDRESS); - pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS); + style = config.getString(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_STYLE); + postHeader = config.getString(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_POSTHEADER); + footer = config.getString(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_FOOTER); + address = config.getString(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_ADDRESS); + pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_GENERATEMACREFS); project = config.getString(CONFIG_PROJECT); @@ -241,10 +252,16 @@ void HtmlGenerator::initializeGenerator(const Config &config) QSet<QString>::ConstIterator edition = editionNames.begin(); while (edition != editionNames.end()) { QString editionName = *edition; - QStringList editionModules = config.getStringList( - CONFIG_EDITION + Config::dot + editionName + Config::dot + "modules"); - QStringList editionGroups = config.getStringList( - CONFIG_EDITION + Config::dot + editionName + Config::dot + "groups"); + QStringList editionModules = config.getStringList(CONFIG_EDITION + + Config::dot + + editionName + + Config::dot + + "modules"); + QStringList editionGroups = config.getStringList(CONFIG_EDITION + + Config::dot + + editionName + + Config::dot + + "groups"); if (!editionModules.isEmpty()) editionModuleMap[editionName] = editionModules; @@ -256,11 +273,17 @@ void HtmlGenerator::initializeGenerator(const Config &config) slow = config.getBool(CONFIG_SLOW); - stylesheets = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLESHEETS); - customHeadElements = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_CUSTOMHEADELEMENTS); + stylesheets = config.getStringList(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_STYLESHEETS); + customHeadElements = config.getStringList(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_CUSTOMHEADELEMENTS); codeIndent = config.getInt(CONFIG_CODEINDENT); - helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp"); + helpProjectWriter = new HelpProjectWriter(config, + project.toLower() + + ".qhp"); } void HtmlGenerator::terminateGenerator() @@ -294,6 +317,7 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) nonCompatClasses.clear(); mainClasses.clear(); compatClasses.clear(); + obsoleteClasses.clear(); moduleClassMap.clear(); moduleNamespaceMap.clear(); funcIndex.clear(); @@ -303,9 +327,9 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) findAllFunctions(tree->root()); findAllLegaleseTexts(tree->root()); findAllNamespaces(tree->root()); -#ifdef ZZZ_QDOC_QML +#ifdef ZZZ_QDOC_QML findAllQmlClasses(tree->root()); -#endif +#endif PageGenerator::generateTree(tree, marker); @@ -381,7 +405,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::AutoLink: if (!inLink && !inContents && !inSectionHeading) { const Node *node = 0; - QString link = getLink(atom, relative, marker, node); + QString link = getLink(atom, relative, marker, &node); if (!link.isEmpty()) { beginLink(link, node, relative, marker); generateLink(atom, relative, marker); @@ -409,7 +433,8 @@ int HtmlGenerator::generateAtom(const Atom *atom, QString str; atom = atom->next(); while (atom != 0 && atom->type() != Atom::BriefRight) { - if (atom->type() == Atom::String || atom->type() == Atom::AutoLink) + if (atom->type() == Atom::String || + atom->type() == Atom::AutoLink) str += atom->string(); skipAhead++; atom = atom->next(); @@ -452,14 +477,14 @@ int HtmlGenerator::generateAtom(const Atom *atom, marker,relative)) << "</pre>\n"; break; -#ifdef QDOC_QML +#ifdef QDOC_QML case Atom::Qml: out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; break; -#endif +#endif case Atom::CodeNew: out() << "<p>you can rewrite it as</p>\n" << "<pre>" @@ -512,6 +537,20 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << formattingRightMap()[atom->string()]; } break; + case Atom::AnnotatedList: + { + const FakeNode *fake = static_cast<const FakeNode *>(relative); + if (fake && !fake->groupMembers().isEmpty()) { + QList<Node*> values = tre->groups().values(atom->string()); + QMap<QString, const Node*> nodeMap; + for (int i = 0; i < values.size(); ++i) { + const Node* n = values.at(i); + nodeMap.insert(n->name(),n); + } + generateAnnotatedList(fake, marker, nodeMap); + } + } + break; case Atom::GeneratedList: if (atom->string() == "annotatedclasses") { generateAnnotatedList(relative, marker, nonCompatClasses); @@ -567,6 +606,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, else if (atom->string() == "compatclasses") { generateCompactList(relative, marker, compatClasses); } + else if (atom->string() == "obsoleteclasses") { + generateCompactList(relative, marker, obsoleteClasses); + } else if (atom->string() == "functionindex") { generateFunctionIndex(relative, marker); } @@ -648,11 +690,12 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::Link: { const Node *node = 0; - QString myLink = getLink(atom, relative, marker, node); - if (myLink.isEmpty()) + QString myLink = getLink(atom, relative, marker, &node); + if (myLink.isEmpty()) { relative->doc().location().warning(tr("Cannot link to '%1' in %2") .arg(atom->string()) .arg(marker->plainFullName(relative))); + } beginLink(myLink, node, relative, marker); skipAhead = 1; } @@ -971,7 +1014,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::EndQmlText: // don't do anything with these. They are just tags. break; -#endif +#endif default: unknownAtom(atom); } @@ -1037,6 +1080,12 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, generateHeader(title, inner, marker, true); generateTitle(title, subtitleText, SmallSubTitle, inner, marker); +#ifdef QDOC_QML + if (classe && !classe->qmlElement().isEmpty()) { + generateInstantiatedBy(classe,marker); + } +#endif + generateBrief(inner, marker); generateIncludes(inner, marker); generateStatus(inner, marker); @@ -1220,16 +1269,19 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) QList<Section>::const_iterator s; QString htmlTitle = fake->fullTitle(); - if (fake->subType() == FakeNode::File && !fake->subTitle().isEmpty()) { + if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) { subTitleSize = SmallSubTitle; htmlTitle += " (" + fake->subTitle() + ")"; } generateHeader(htmlTitle, fake, marker, true); - generateTitle(fake->fullTitle(), Text() << fake->subTitle(), subTitleSize, - fake, marker); + generateTitle(fake->fullTitle(), + Text() << fake->subTitle(), + subTitleSize, + fake, + marker); - if (fake->subType() == FakeNode::Module) { + if (fake->subType() == Node::Module) { // Generate brief text and status for modules. generateBrief(fake, marker); generateStatus(fake, marker); @@ -1243,7 +1295,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]); } } - else if (fake->subType() == FakeNode::HeaderFile) { + else if (fake->subType() == Node::HeaderFile) { // Generate brief text and status for modules. generateBrief(fake, marker); generateStatus(fake, marker); @@ -1290,7 +1342,49 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) appendDcfSubSection(&fakeSection, compatSection); } } +#ifdef QDOC_QML + else if (fake->subType() == Node::QmlClass) { + const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake); + const ClassNode* cn = qml_cn->classNode(); + generateQmlInherits(qml_cn, marker); + generateQmlInstantiates(qml_cn, marker); + generateBrief(qml_cn, marker); + sections = marker->qmlSections(qml_cn,CodeMarker::Summary); + s = sections.begin(); + while (s != sections.end()) { + out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; + out() << "<h2>" << protect((*s).name) << "</h2>\n"; + generateQmlSummary(*s,fake,marker); + ++s; + } + out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + out() << "<h2>" << "Detailed Description" << "</h2>\n"; + generateBody(fake, marker); + if (cn) + generateQmlText(cn->doc().body(), cn, marker, fake->name()); + generateAlsoList(fake, marker); + out() << "<hr />\n"; + + sections = marker->qmlSections(qml_cn,CodeMarker::Detailed); + s = sections.begin(); + while (s != sections.end()) { + out() << "<h2>" << protect((*s).name) << "</h2>\n"; + NodeList::ConstIterator m = (*s).members.begin(); + while (m != (*s).members.end()) { + generateDetailedQmlMember(*m, fake, marker); + out() << "<br />\n"; + fakeSection.keywords += qMakePair((*m)->name(), + linkForNode(*m,0)); + ++m; + } + ++s; + } + generateFooter(fake); + return; + } +#endif + sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { @@ -1301,24 +1395,12 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) } Text brief = fake->doc().briefText(); - if (fake->subType() == FakeNode::Module && !brief.isEmpty()) { + if (fake->subType() == Node::Module && !brief.isEmpty()) { out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; out() << "<h2>" << "Detailed Description" << "</h2>\n"; } generateBody(fake, marker); -#ifdef QDOC_QML - if (fake->subType() == FakeNode::QmlClass) { - //qDebug() << "generateFakeNode(): QML CLASS" << fake->name(); - const QmlNode* qmlNode = static_cast<const QmlNode*>(fake); - const ClassNode* cn = qmlNode->classNode(); - if (cn) { - //qDebug() << " CPP CLASS" << cn->name(); - generateQmlText(cn->doc().body(), cn, marker); - } - } -#endif - generateAlsoList(fake, marker); if (!fake->groupMembers().isEmpty()) { @@ -1348,10 +1430,10 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) } generateFooter(fake); - if (fake->subType() == FakeNode::Example) { + if (fake->subType() == Node::Example) { appendDcfSubSection(&dcfExamplesRoot, fakeSection); } - else if (fake->subType() != FakeNode::File) { + else if (fake->subType() != Node::File) { QString contentsPage = fake->links().value(Node::ContentsLink).first; if (contentsPage == "Qt Designer Manual") { @@ -1638,7 +1720,10 @@ void HtmlGenerator::generateTableOfContents(const Node *node, columnSize = 0; } out() << "<li>"; - out() << "<a href=\"" << nodeName << "#" << Doc::canonicalTitle(headingText.toString()) + out() << "<a href=\"" + << nodeName + << "#" + << Doc::canonicalTitle(headingText.toString()) << "\">"; generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms); out() << "</a></li>\n"; @@ -1688,7 +1773,8 @@ void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, } #endif -QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker) +QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, + CodeMarker *marker) { QList<Section> sections; QList<Section>::ConstIterator s; @@ -1739,7 +1825,8 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, if (status == CodeMarker::Compat) { title = "Qt 3 Support Members for " + inner->name(); fileName = fileBase(inner) + "-qt3." + fileExtension(inner); - } else { + } + else { title = "Obsolete Members for " + inner->name(); fileName = fileBase(inner) + "-obsolete." + fileExtension(inner); } @@ -1753,10 +1840,11 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, "<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> " "They are provided to help you port old code to Qt 4. We advise against " "using them in new code.</p>\n"; - } else { - out() << "<p><b>The following class members are obsolete.</b> They are provided to keep " - "old source code working. We strongly advise against using them in new " - "code.</p>\n"; + } + else { + out() << "<p><b>The following class members are obsolete.</b> " + << "They are provided to keep old source code working. " + << "We strongly advise against using them in new code.</p>\n"; } out() << "<p><ul><li><a href=\"" @@ -1811,8 +1899,10 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, if (stack.top().isEmpty()) { stack.pop(); out() << "</ul>\n"; - } else { - const ClassNode *child = static_cast<const ClassNode *>(*stack.top().begin()); + } + else { + const ClassNode *child = + static_cast<const ClassNode *>(*stack.top().begin()); out() << "<li>"; generateFullName(child, relative, marker); out() << "</li>\n"; @@ -1831,10 +1921,9 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, } } -void -HtmlGenerator::generateAnnotatedList(const Node *relative, - CodeMarker *marker, - const QMap<QString,const Node *>&nodeMap) +void HtmlGenerator::generateAnnotatedList(const Node *relative, + CodeMarker *marker, + const QMap<QString, const Node *> &nodeMap) { out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" " << "cellspacing=\"1\" border=\"0\">\n"; @@ -1843,6 +1932,9 @@ HtmlGenerator::generateAnnotatedList(const Node *relative, foreach (const QString &name, nodeMap.keys()) { const Node *node = nodeMap[name]; + if (node->status() == Node::Obsolete) + continue; + if (++row % 2 == 1) out() << "<tr valign=\"top\" class=\"odd\">"; else @@ -1858,7 +1950,8 @@ HtmlGenerator::generateAnnotatedList(const Node *relative, generateText(brief, node, marker); out() << "</td>"; } - } else { + } + else { out() << "<td>"; out() << protect(node->doc().briefText().toString()); out() << "</td>"; @@ -1868,10 +1961,9 @@ HtmlGenerator::generateAnnotatedList(const Node *relative, out() << "</table></p>\n"; } -void -HtmlGenerator::generateCompactList(const Node *relative, - CodeMarker *marker, - const QMap<QString,const Node*> &classMap) +void HtmlGenerator::generateCompactList(const Node *relative, + CodeMarker *marker, + const QMap<QString, const Node *> &classMap) { const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_' const int NumColumns = 4; // number of columns in the result @@ -1914,8 +2006,9 @@ HtmlGenerator::generateCompactList(const Node *relative, last = classMap.begin().key(); if (classMap.size() > 1) { - while (commonPrefixLen < first.length() + 1 && commonPrefixLen < last.length() + 1 - && first[commonPrefixLen] == last[commonPrefixLen]) + while (commonPrefixLen < first.length() + 1 && + commonPrefixLen < last.length() + 1 && + first[commonPrefixLen] == last[commonPrefixLen]) ++commonPrefixLen; } @@ -1944,7 +2037,8 @@ HtmlGenerator::generateCompactList(const Node *relative, if (key[0].digitValue() != -1) { paragraphNo = key[0].digitValue(); - } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) { + } + else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) { paragraphNo = 10 + key[0].unicode() - 'a'; } @@ -2097,7 +2191,8 @@ void HtmlGenerator::generateFunctionIndex(const Node *relative, #endif } -void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marker) +void HtmlGenerator::generateLegaleseList(const Node *relative, + CodeMarker *marker) { QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin(); while (it != legaleseTexts.end()) { @@ -2115,6 +2210,77 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marke } } +/*void HtmlGenerator::generateSynopsis(const Node *node, + const Node *relative, + CodeMarker *marker, + CodeMarker::SynopsisStyle style) +{ + QString marked = marker->markedUpSynopsis(node, relative, style); + QRegExp templateTag("(<[^@>]*>)"); + if (marked.indexOf(templateTag) != -1) { + QString contents = protect(marked.mid(templateTag.pos(1), + templateTag.cap(1).length())); + marked.replace(templateTag.pos(1), templateTag.cap(1).length(), + contents); + } + marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), + "<i>\\1<sub>\\2</sub></i>"); + marked.replace("<@param>", "<i>"); + marked.replace("</@param>", "</i>"); + + if (style == CodeMarker::Summary) + marked.replace("@name>", "b>"); + + if (style == CodeMarker::SeparateList) { + QRegExp extraRegExp("<@extra>.*</@extra>"); + extraRegExp.setMinimal(true); + marked.replace(extraRegExp, ""); + } + else { + marked.replace("<@extra>", " <tt>"); + marked.replace("</@extra>", "</tt>"); + } + + if (style != CodeMarker::Detailed) { + marked.replace("<@type>", ""); + marked.replace("</@type>", ""); + } + out() << highlightedCode(marked, marker, relative); +}*/ + +#ifdef QDOC_QML +void HtmlGenerator::generateQmlItem(const Node *node, + const Node *relative, + CodeMarker *marker, + bool summary) +{ + QString marked = marker->markedUpQmlItem(node,summary); + QRegExp templateTag("(<[^@>]*>)"); + if (marked.indexOf(templateTag) != -1) { + QString contents = protect(marked.mid(templateTag.pos(1), + templateTag.cap(1).length())); + marked.replace(templateTag.pos(1), templateTag.cap(1).length(), + contents); + } + marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), + "<i>\\1<sub>\\2</sub></i>"); + marked.replace("<@param>", "<i>"); + marked.replace("</@param>", "</i>"); + + if (summary) + marked.replace("@name>", "b>"); + + marked.replace("<@extra>", " <tt>"); + marked.replace("</@extra>", "</tt>"); + + if (summary) { + marked.replace("<@type>", ""); + marked.replace("</@type>", ""); + } + out() << highlightedCode(marked, marker, relative); +} +#endif + void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */) { QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap; @@ -2137,7 +2303,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m } // there are too many examples; they would clutter the list - if (fakeNode->subType() == FakeNode::Example) + if (fakeNode->subType() == Node::Example) continue; // not interested either in individual (Qt Designer etc.) manual chapters @@ -2145,7 +2311,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m continue; // Discard external nodes. - if (fakeNode->subType() == FakeNode::ExternalPage) + if (fakeNode->subType() == Node::ExternalPage) continue; QString sortKey = fakeNode->fullTitle().toLower(); @@ -2170,7 +2336,8 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode); } } - } else if (!isGroupPage) { + } + 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 FakeNode *groupNode = static_cast<const FakeNode *>(tre->root()->findNode(group, Node::Fake)); @@ -2729,8 +2896,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; if (parseArg(src, linkTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); + const Node* node = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(node, relative); addLink(link, arg, &html); } else { @@ -2743,7 +2910,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } } - if (slow) { // is this block ever used at all? // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" @@ -2873,7 +3039,9 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } #endif -void HtmlGenerator::generateLink(const Atom *atom, const Node * /* relative */, CodeMarker *marker) +void HtmlGenerator::generateLink(const Atom* atom, + const Node* /* relative */, + CodeMarker* marker) { static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_"); @@ -3066,10 +3234,9 @@ QString HtmlGenerator::fileBase(const Node *node, QString HtmlGenerator::fileName(const Node *node) { if (node->type() == Node::Fake) { - if (static_cast<const FakeNode *>(node)->subType() == FakeNode::ExternalPage) + if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage) return node->name(); } - return PageGenerator::fileName(node); } @@ -3091,7 +3258,8 @@ QString HtmlGenerator::refForNode(const Node *node) typedeffe = static_cast<const TypedefNode *>(node); if (typedeffe->associatedEnum()) { return refForNode(typedeffe->associatedEnum()); - } else { + } + else { ref = node->name() + "-typedef"; } break; @@ -3099,15 +3267,27 @@ QString HtmlGenerator::refForNode(const Node *node) func = static_cast<const FunctionNode *>(node); if (func->associatedProperty()) { return refForNode(func->associatedProperty()); - } else { + } + else { ref = func->name(); if (func->overloadNumber() != 1) ref += "-" + QString::number(func->overloadNumber()); } break; case Node::Property: +#ifdef QDOC_QML + case Node::QmlProperty: +#endif ref = node->name() + "-prop"; break; +#ifdef QDOC_QML + case Node::QmlSignal: + ref = node->name() + "-signal"; + break; + case Node::QmlMethod: + ref = node->name() + "-method"; + break; +#endif case Node::Variable: ref = node->name() + "-var"; break; @@ -3156,9 +3336,11 @@ QString HtmlGenerator::refForAtom(Atom *atom, const Node * /* node */) { if (atom->type() == Atom::SectionLeft) { return Doc::canonicalTitle(Text::sectionHeading(atom).toString()); - } else if (atom->type() == Atom::Target) { + } + else if (atom->type() == Atom::Target) { return Doc::canonicalTitle(atom->string()); - } else { + } + else { return QString(); } } @@ -3202,7 +3384,10 @@ void HtmlGenerator::generateDetailedMember(const Node *node, out() << "<a name=\"" + refForNode(node) + "\"></a>"; generateSynopsis(enume, relative, marker, CodeMarker::Detailed); out() << "<br />"; - generateSynopsis(enume->flagsType(), relative, marker, CodeMarker::Detailed); + generateSynopsis(enume->flagsType(), + relative, + marker, + CodeMarker::Detailed); out() << "</h3>\n"; } else { @@ -3261,6 +3446,9 @@ void HtmlGenerator::findAllClasses(const InnerNode *node) if ((*c)->status() == Node::Compat) { compatClasses.insert(className, *c); } + else if ((*c)->status() == Node::Obsolete) { + obsoleteClasses.insert(className, *c); + } else { nonCompatClasses.insert(className, *c); if ((*c)->status() == Node::Main) @@ -3351,7 +3539,7 @@ void HtmlGenerator::findAllNamespaces(const InnerNode *node) } } -#ifdef ZZZ_QDOC_QML +#ifdef ZZZ_QDOC_QML /*! This function finds all the qml element nodes and stores them in a map for later use. @@ -3362,24 +3550,16 @@ void HtmlGenerator::findAllQmlClasses(const InnerNode *node) while (c != node->childNodes().constEnd()) { if ((*c)->type() == Node::Fake) { const FakeNode* fakeNode = static_cast<const FakeNode *>(*c); - if (fakeNode->subType() == FakeNode::QmlClass) { - const QmlNode* qmlNode = static_cast<const QmlNode*>(fakeNode); - //qDebug() << "HtmlGenerator: QML CLASS" << qmlNode->name(); + if (fakeNode->subType() == Node::QmlClass) { + const QmlClassNode* qmlNode = + static_cast<const QmlClassNode*>(fakeNode); const Node* n = qmlNode->classNode(); - if (n) - //qDebug() << " FOUND IT!" << n->name(); } qmlClasses.insert(fakeNode->name(),*c); } ++c; } } -#endif - -#if 0 - else if ((*c)->isInnerNode()) { - findAllClasses(static_cast<InnerNode *>(*c)); - } #endif int HtmlGenerator::hOffset(const Node *node) @@ -3457,10 +3637,11 @@ const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node) QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, CodeMarker *marker, - const Node *node) + const Node** node) { QString link; - node = 0; + *node = 0; + inObsoleteLink = false; if (atom->string().contains(":") && (atom->string().startsWith("file:") @@ -3484,40 +3665,86 @@ QString HtmlGenerator::getLink(const Atom *atom, QString first = path.first().trimmed(); if (first.isEmpty()) { - node = relative; + *node = relative; } else if (first.endsWith(".html")) { - node = tre->root()->findNode(first, Node::Fake); + *node = tre->root()->findNode(first, Node::Fake); } else { - node = marker->resolveTarget(first, tre, relative); - if (!node) - node = tre->findFakeNodeByTitle(first); - if (!node) - node = tre->findUnambiguousTarget(first, targetAtom); + *node = marker->resolveTarget(first, tre, relative); + if (!*node) + *node = tre->findFakeNodeByTitle(first); + if (!*node) + *node = tre->findUnambiguousTarget(first, targetAtom); } - if (node) { - if (!node->url().isEmpty()) - return node->url(); + if (*node) { + if (!(*node)->url().isEmpty()) + return (*node)->url(); else path.removeFirst(); } else { - node = relative; + *node = relative; + } + + if (*node) { + if ((*node)->status() == Node::Obsolete) { + if (relative) { + if (relative->parent() != *node) { + if (relative->status() != Node::Obsolete) { + bool porting = false; + if (relative->type() == Node::Fake) { + const FakeNode* fake = static_cast<const FakeNode*>(relative); + if (fake->title().startsWith("Porting")) + porting = true; + } + QString name = marker->plainFullName(relative); + if (!porting && !name.startsWith("Q3")) { + if (obsoleteLinks) { + relative->doc().location().warning(tr("Link to obsolete item '%1' in %2") + .arg(atom->string()) + .arg(name)); + } + inObsoleteLink = true; + } +#if 0 + qDebug() << "Link to Obsolete entity" + << (*node)->name(); + qDebug() << " relative entity" + << relative->name(); +#endif + } + } + } + else { + qDebug() << "Link to Obsolete entity" + << (*node)->name() << "no relative"; + } + } +#if 0 + else if ((*node)->status() == Node::Deprecated) { + qDebug() << "Link to Deprecated entity"; + } + else if ((*node)->status() == Node::Internal) { + qDebug() << "Link to Internal entity"; + } + //else + //qDebug() << "Node Status:" << (*node)->status(); +#endif } while (!path.isEmpty()) { - targetAtom = tre->findTarget(path.first(), node); + targetAtom = tre->findTarget(path.first(), *node); if (targetAtom == 0) break; path.removeFirst(); } if (path.isEmpty()) { - link = linkForNode(node, relative); + link = linkForNode(*node, relative); if (targetAtom) - link += "#" + refForAtom(targetAtom, node); + link += "#" + refForAtom(targetAtom, *node); } } return link; @@ -3636,10 +3863,225 @@ void HtmlGenerator::endLink() out() << "</i>"; } else { + if (inObsoleteLink) { + out() << "<sup>(obsolete)</sup>"; + } out() << "</a>"; } } inLink = false; + inObsoleteLink = false; } QT_END_NAMESPACE + +#ifdef QDOC_QML + +/*! + Generates the summary for for the \a section. Only used for + sections of QML element documentation. + + Currently handles only the QML property group. + */ +void HtmlGenerator::generateQmlSummary(const Section& section, + const Node *relative, + CodeMarker *marker) +{ + if (!section.members.isEmpty()) { + NodeList::ConstIterator m; + int count = section.members.size(); + bool twoColumn = false; + if (section.members.first()->type() == Node::QmlProperty) { + twoColumn = (count >= 5); + } + if (twoColumn) + out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\"" + " cellspacing=\"0\">\n" + << "<tr><td width=\"45%\" valign=\"top\">"; + out() << "<ul>\n"; + + int row = 0; + m = section.members.begin(); + while (m != section.members.end()) { + if (twoColumn && row == (int) (count + 1) / 2) + out() << "</ul></td><td valign=\"top\"><ul>\n"; + out() << "<li><div class=\"fn\"></div>"; + generateQmlItem(*m,relative,marker,true); + out() << "</li>\n"; + row++; + ++m; + } + out() << "</ul>\n"; + if (twoColumn) + out() << "</td></tr>\n</table></p>\n"; + } +} + +/*! + Outputs the html detailed documentation for a section + on a QML element reference page. + */ +void HtmlGenerator::generateDetailedQmlMember(const Node *node, + const InnerNode *relative, + CodeMarker *marker) +{ + const QmlPropertyNode* qpn = 0; + generateMacRef(node, marker); + out() << "<div class=\"qmlitem\">"; + if (node->subType() == Node::QmlPropertyGroup) { + const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); + NodeList::ConstIterator p = qpgn->childNodes().begin(); + out() << "<div class=\"qmlproto\">"; + out() << "<table class=\"qmlname\">"; + + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + qpn = static_cast<const QmlPropertyNode*>(*p); + out() << "<tr><td>"; + out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; + generateQmlItem(qpn, relative, marker, false); + out() << "</td></tr>"; + if (qpgn->isDefault()) { + out() << "</table>" + << "</div></div>" + << "<div class=\"qmlitem\">" + << "<div class=\"qmlproto\">" + << "<table class=\"qmlname\">" + << "<tr><td><font color=\"green\">" + << "default</font></td></tr>"; + } + } + ++p; + } + out() << "</table>"; + out() << "</div>"; + } + else if (node->type() == Node::QmlSignal) { + const QmlSignalNode* qsn = static_cast<const QmlSignalNode*>(node); + out() << "<div class=\"qmlproto\">"; + out() << "<table class=\"qmlname\">"; + out() << "<tr><td>"; + out() << "<a name=\"" + refForNode(qsn) + "\"></a>"; + generateQmlItem(qsn,relative,marker,false); + out() << "</td></tr>"; + out() << "</table>"; + out() << "</div>"; + } + else if (node->type() == Node::QmlMethod) { + const QmlMethodNode* qmn = static_cast<const QmlMethodNode*>(node); + out() << "<div class=\"qmlproto\">"; + out() << "<table class=\"qmlname\">"; + out() << "<tr><td>"; + out() << "<a name=\"" + refForNode(qmn) + "\"></a>"; + generateQmlItem(qmn,relative,marker,false); + out() << "</td></tr>"; + out() << "</table>"; + out() << "</div>"; + } + out() << "<div class=\"qmldoc\">"; + generateStatus(node, marker); + generateBody(node, marker); + generateThreadSafeness(node, marker); + generateSince(node, marker); + generateAlsoList(node, marker); + out() << "</div>"; + out() << "</div>"; +} + +/*! + Output the "Inherits" line for the QML element, + if there should be one. + */ +void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn, + CodeMarker* marker) +{ + if (cn && !cn->links().empty()) { + if (cn->links().contains(Node::InheritsLink)) { + QPair<QString,QString> linkPair; + linkPair = cn->links()[Node::InheritsLink]; + QStringList strList(linkPair.first); + const Node* n = tre->findNode(strList,Node::Fake); + if (n && n->subType() == Node::QmlClass) { + const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n); + out() << "<p style=\"text-align: center\">"; + Text text; + text << "[Inherits "; + text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); + text << Atom(Atom::String, linkPair.second); + text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + text << "]"; + generateText(text, cn, marker); + out() << "</p>"; + } +// else +// qDebug() << "generateQmlInherits(): " +// << "Inherited element not documented -->" +// << linkPair.first; + } + } +} + +/*! + Output the "[Xxx instantiates the C++ class QFxXxx]" + line for the QML element, if there should be one. + + If there is no class node, or if the class node status + is set to Node::Internal, do nothing. + */ +void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, + CodeMarker* marker) +{ + const ClassNode* cn = qcn->classNode(); + if (cn && (cn->status() != Node::Internal)) { + out() << "<p style=\"text-align: center\">"; + Text text; + text << "["; + text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); + text << Atom(Atom::String, qcn->name()); + text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + text << " instantiates the C++ class "; + text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); + text << Atom(Atom::String, cn->name()); + text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + text << "]"; + generateText(text, qcn, marker); + out() << "</p>"; + } +} + +/*! + Output the "[QFxXxx is instantiated by QML element Xxx]" + line for the class, if there should be one. + + If there is no QML element, or if the class node status + is set to Node::Internal, do nothing. + */ +void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, + CodeMarker* marker) +{ + if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) { + const Node* n = tre->root()->findNode(cn->qmlElement(),Node::Fake); + if (n && n->subType() == Node::QmlClass) { + out() << "<p style=\"text-align: center\">"; + Text text; + text << "["; + text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); + text << Atom(Atom::String, cn->name()); + text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + text << " is instantiated by QML element "; + text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n)); + text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); + text << Atom(Atom::String, n->name()); + text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); + text << "]"; + generateText(text, cn, marker); + out() << "</p>"; + } + } +} + +#endif diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index dc5e5cf..c22fe20 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -145,6 +145,21 @@ class HtmlGenerator : public PageGenerator const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style); +#ifdef QDOC_QML + void generateQmlSummary(const Section& section, + const Node *relative, + CodeMarker *marker); + void generateQmlItem(const Node *node, + const Node *relative, + CodeMarker *marker, + bool summary); + void generateDetailedQmlMember(const Node *node, + const InnerNode *relative, + CodeMarker *marker); + void generateQmlInherits(const QmlClassNode* cn, CodeMarker* marker); + void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); + void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); +#endif #ifdef QDOC_NAME_ALIGNMENT void generateSection(const NodeList& nl, const Node *relative, @@ -180,8 +195,12 @@ class HtmlGenerator : public PageGenerator const Node *relative, CodeMarker *marker, const Node *actualNode = 0); - void generateDetailedMember(const Node *node, const InnerNode *relative, CodeMarker *marker); - void generateLink(const Atom *atom, const Node *relative, CodeMarker *marker); + void generateDetailedMember(const Node *node, + const InnerNode *relative, + CodeMarker *marker); + void generateLink(const Atom *atom, + const Node *relative, + CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker); QString registerRef(const QString& ref); @@ -202,7 +221,7 @@ class HtmlGenerator : public PageGenerator virtual QString getLink(const Atom *atom, const Node *relative, CodeMarker *marker, - const Node *node = 0); + const Node** node); virtual void generateDcf(const QString &fileBase, const QString &startPage, const QString &title, DcfSection &dcfRoot); @@ -230,6 +249,7 @@ class HtmlGenerator : public PageGenerator DcfSection dcfQmakeRoot; HelpProjectWriter *helpProjectWriter; bool inLink; + bool inObsoleteLink; bool inContents; bool inSectionHeading; bool inTableHeader; @@ -251,11 +271,13 @@ class HtmlGenerator : public PageGenerator QStringList customHeadElements; const Tree *tre; bool slow; + bool obsoleteLinks; QMap<QString, QMap<QString, const Node *> > moduleClassMap; QMap<QString, QMap<QString, const Node *> > moduleNamespaceMap; QMap<QString, const Node *> nonCompatClasses; QMap<QString, const Node *> mainClasses; QMap<QString, const Node *> compatClasses; + QMap<QString, const Node *> obsoleteClasses; QMap<QString, const Node *> namespaceIndex; QMap<QString, const Node *> serviceClasses; #ifdef QDOC_QML diff --git a/tools/qdoc3/jambiapiparser.cpp b/tools/qdoc3/jambiapiparser.cpp index f981e6d..70e9260 100644 --- a/tools/qdoc3/jambiapiparser.cpp +++ b/tools/qdoc3/jambiapiparser.cpp @@ -234,8 +234,9 @@ void JambiApiParser::doneParsingSourceFiles(Tree * /* tree */) foreach (Node *cppNode, cppTre->root()->childNodes()) { if (cppNode->type() == Node::Fake) { FakeNode *cppFake = static_cast<FakeNode *>(cppNode); - if (cppFake->subType() == FakeNode::Page) { - FakeNode *javaFake = new FakeNode(javaTre->root(), cppFake->name(), + if (cppFake->subType() == Node::Page) { + FakeNode *javaFake = new FakeNode(javaTre->root(), + cppFake->name(), cppFake->subType()); javaFake->setModuleName("com.trolltech.qt"); // ### hard-coded javaFake->setTitle(cppFake->title()); diff --git a/tools/qdoc3/javadocgenerator.cpp b/tools/qdoc3/javadocgenerator.cpp index b32425c..294877b 100644 --- a/tools/qdoc3/javadocgenerator.cpp +++ b/tools/qdoc3/javadocgenerator.cpp @@ -272,9 +272,10 @@ void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker HtmlGenerator::generateFakeNode(fake, marker); } -void JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker) +bool JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { HtmlGenerator::generateText(text, relative, marker); + return true; } void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker) diff --git a/tools/qdoc3/javadocgenerator.h b/tools/qdoc3/javadocgenerator.h index ba9b15d..5431c38 100644 --- a/tools/qdoc3/javadocgenerator.h +++ b/tools/qdoc3/javadocgenerator.h @@ -68,7 +68,7 @@ protected: void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); void generateFakeNode( const FakeNode *fake, CodeMarker *marker ); - void generateText( const Text& text, const Node *relative, CodeMarker *marker ); + bool generateText( const Text& text, const Node *relative, CodeMarker *marker ); void generateBody( const Node *node, CodeMarker *marker ); void generateAlsoList( const Node *node, CodeMarker *marker ); diff --git a/tools/qdoc3/main.cpp b/tools/qdoc3/main.cpp index 5a98275..9338203 100644 --- a/tools/qdoc3/main.cpp +++ b/tools/qdoc3/main.cpp @@ -96,6 +96,7 @@ static const struct { static bool slow = false; static bool showInternal = false; +static bool obsoleteLinks = false; static QStringList defines; static QHash<QString, Tree *> trees; @@ -128,9 +129,11 @@ static void printHelp() " -D<name> " "Define <name> as a macro while parsing sources\n" " -slow " - "Turn on features that slow down qdoc" + "Turn on features that slow down qdoc\n" " -showinternal " - "Include stuff marked internal") ); + "Include stuff marked internal\n" + " -obsoletelinks " + "Report links from obsolete items to non-obsolete items") ); } /*! @@ -165,6 +168,8 @@ static void processQdocconfFile(const QString &fileName) config.setStringList(CONFIG_SLOW, QStringList(slow ? "true" : "false")); config.setStringList(CONFIG_SHOWINTERNAL, QStringList(showInternal ? "true" : "false")); + config.setStringList(CONFIG_OBSOLETELINKS, + QStringList(obsoleteLinks ? "true" : "false")); /* With the default configuration values in place, load @@ -434,6 +439,9 @@ int main(int argc, char **argv) else if (opt == "-showinternal") { showInternal = true; } + else if (opt == "-obsoletelinks") { + obsoleteLinks = true; + } else { qdocFiles.append(opt); } diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 0f9468a..610249d 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -43,6 +43,7 @@ node.cpp */ +#include <QtCore> #include "node.h" QT_BEGIN_NAMESPACE @@ -113,6 +114,9 @@ void Node::setRelates(InnerNode *pseudoParent) } /*! + This function creates a pair that describes a link. + The pair is composed from \a link and \a desc. The + \a linkType is the map index the pair is filed under. */ void Node::setLink(LinkType linkType, const QString &link, const QString &desc) { @@ -623,7 +627,7 @@ void InnerNode::removeRelated(Node *pseudoChild) */ /*! - Returns false because this is an InnerNode. + Returns false because this is a LeafNode. */ bool LeafNode::isInnerNode() const { @@ -713,9 +717,11 @@ void ClassNode::fixBaseClasses() */ /*! + The type of a FakeNode is Fake, and it has a \a subtype, + which specifies the type of FakeNode. */ -FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subType) - : InnerNode(Fake, parent, name), sub(subType) +FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subtype) + : InnerNode(Fake, parent, name), sub(subtype) { } @@ -868,6 +874,18 @@ void FunctionNode::setOverload(bool overlode) } /*! + Sets the function node's reimplementation flag to \a r. + When \a r is true, it is supposed to mean that this function + is a reimplementation of a virtual function in a base class, + but it really just means the \e reimp command was seen in the + qdoc comment. + */ +void FunctionNode::setReimp(bool r) +{ + reimp = r; +} + +/*! */ void FunctionNode::addParameter(const Parameter& parameter) { @@ -1021,4 +1039,98 @@ bool TargetNode::isInnerNode() const return false; } +#ifdef QDOC_QML +/*! + Constructor for the Qml class node. + */ +QmlClassNode::QmlClassNode(InnerNode *parent, + const QString& name, + const ClassNode* cn) + : FakeNode(parent, name, QmlClass), cnode(cn) +{ + setTitle("QML " + name + " Element Reference"); +} + +/*! + The base file name for this kind of node has "qml_" + prepended to it. + + But not yet. Still testing. + */ +QString QmlClassNode::fileBase() const +{ +#if 0 + if (Node::fileBase() == "item") + qDebug() << "FILEBASE: qmlitem" << name(); + return "qml_" + Node::fileBase(); +#endif + return Node::fileBase(); +} + +/*! + Constructor for the Qml property group node. \a parent is + always a QmlClassNode. + */ +QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name) + : FakeNode(parent, name, QmlPropertyGroup), isdefault(false) +{ + // nothing. +} + +/*! + Constructor for the QML property node. + */ +QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent, + const QString& name, + const QString& type) + : LeafNode(QmlProperty, parent, name), + dt(type), + sto(Trool_Default), + des(Trool_Default) +{ + // nothing. +} + +/*! + I don't know what this is. + */ +QmlPropertyNode::Trool QmlPropertyNode::toTrool(bool boolean) +{ + return boolean ? Trool_True : Trool_False; +} + +/*! + I don't know what this is either. + */ +bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue) +{ + switch (troolean) { + case Trool_True: + return true; + case Trool_False: + return false; + default: + return defaultValue; + } +} + +/*! + Constructor for the QML signal node. + */ +QmlSignalNode::QmlSignalNode(QmlClassNode *parent, const QString& name) + : LeafNode(QmlSignal, parent, name) +{ + // nothing. +} + +/*! + Constructor for the QML method node. + */ +QmlMethodNode::QmlMethodNode(QmlClassNode *parent, const QString& name) + : LeafNode(QmlMethod, parent, name) +{ + // nothing. +} +#endif + QT_END_NAMESPACE diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index 0a671b37d..17ec447 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -72,7 +72,31 @@ class Node Function, Property, Variable, +#ifdef QDOC_QML + Target, + QmlProperty, + QmlSignal, + QmlMethod +#else Target +#endif + }; + + enum SubType { + NoSubType, + Example, + HeaderFile, + File, + Group, + Module, + Page, +#ifdef QDOC_QML + ExternalPage, + QmlClass, + QmlPropertyGroup +#else + ExternalPage +#endif }; enum Access { Public, Protected, Private }; @@ -99,7 +123,8 @@ class Node NextLink, PreviousLink, ContentsLink, - IndexLink /*, + IndexLink, + InheritsLink /*, GlossaryLink, CopyrightLink, ChapterLink, @@ -123,7 +148,9 @@ class Node void setTemplateStuff(const QString &templateStuff) { tpl = templateStuff; } virtual bool isInnerNode() const = 0; + virtual bool isReimp() const { return false; } Type type() const { return typ; } + virtual SubType subType() const { return NoSubType; } InnerNode *parent() const { return par; } InnerNode *relates() const { return rel; } const QString& name() const { return nam; } @@ -143,7 +170,7 @@ class Node void clearRelated() { rel = 0; } - QString fileBase() const; + virtual QString fileBase() const; protected: Node(Type type, InnerNode *parent, const QString& name); @@ -180,7 +207,7 @@ typedef QList<Node *> NodeList; class InnerNode : public Node { public: - ~InnerNode(); + virtual ~InnerNode(); Node *findNode(const QString& name); Node *findNode(const QString& name, Type type); @@ -202,6 +229,7 @@ class InnerNode : public Node const EnumNode *findEnumNodeForValue(const QString &enumValue) const; const NodeList & childNodes() const { return children; } const NodeList & relatedNodes() const { return related; } + int count() const { return children.size(); } int overloadNumber(const FunctionNode *func) const; int numOverloads(const QString& funcName) const; NodeList overloads(const QString &funcName) const; @@ -231,17 +259,19 @@ class LeafNode : public Node { public: LeafNode(); + virtual ~LeafNode() { } virtual bool isInnerNode() const; protected: - LeafNode(Type type, InnerNode *parent, const QString& name); + LeafNode(Type type, InnerNode* parent, const QString& name); }; class NamespaceNode : public InnerNode { public: NamespaceNode(InnerNode *parent, const QString& name); + virtual ~NamespaceNode() { } }; class ClassNode; @@ -265,6 +295,7 @@ class ClassNode : public InnerNode { public: ClassNode(InnerNode *parent, const QString& name); + virtual ~ClassNode() { } void addBaseClass(Access access, ClassNode *node, @@ -279,29 +310,23 @@ class ClassNode : public InnerNode QString serviceName() const { return sname; } void setServiceName(const QString& value) { sname = value; } + QString qmlElement() const { return qmlelement; } + void setQmlElement(const QString& value) { qmlelement = value; } private: QList<RelatedClass> bas; QList<RelatedClass> der; bool hidden; QString sname; + QString qmlelement; }; class FakeNode : public InnerNode { public: - enum SubType { - Example, - HeaderFile, - File, - Group, - Module, - Page, - ExternalPage, - QmlClass - }; FakeNode(InnerNode *parent, const QString& name, SubType subType); + virtual ~FakeNode() { } void setTitle(const QString &title) { tle = title; } void setSubTitle(const QString &subTitle) { stle = subTitle; } @@ -320,18 +345,85 @@ class FakeNode : public InnerNode NodeList gr; }; -class QmlNode : public FakeNode +#ifdef QDOC_QML +class QmlClassNode : public FakeNode { public: - QmlNode(InnerNode *parent, const QString& name, const ClassNode* cn) - : FakeNode(parent, name, QmlClass), cnode(cn) { } + QmlClassNode(InnerNode *parent, + const QString& name, + const ClassNode* cn); + virtual ~QmlClassNode() { } const ClassNode* classNode() const { return cnode; } + virtual QString fileBase() const; private: const ClassNode* cnode; }; +class QmlPropGroupNode : public FakeNode +{ + public: + QmlPropGroupNode(QmlClassNode* parent, const QString& name); + virtual ~QmlPropGroupNode() { } + + const QString& element() const { return name(); } + void setDefault() { isdefault = true; } + bool isDefault() const { return isdefault; } + + private: + bool isdefault; +}; + +class QmlPropertyNode : public LeafNode +{ + public: + QmlPropertyNode(QmlPropGroupNode* parent, + const QString& name, + const QString& type); + virtual ~QmlPropertyNode() { } + + void setDataType(const QString& dataType) { dt = dataType; } + void setStored(bool stored) { sto = toTrool(stored); } + void setDesignable(bool designable) { des = toTrool(designable); } + + const QString &dataType() const { return dt; } + QString qualifiedDataType() const { return dt; } + bool isStored() const { return fromTrool(sto,true); } + bool isDesignable() const { return fromTrool(des,false); } + + const QString& element() const { return parent()->name(); } + + private: + enum Trool { Trool_True, Trool_False, Trool_Default }; + + static Trool toTrool(bool boolean); + static bool fromTrool(Trool troolean, bool defaultValue); + + QString dt; + Trool sto; + Trool des; +}; + +class QmlSignalNode : public LeafNode +{ + public: + QmlSignalNode(QmlClassNode* parent, const QString& name); + virtual ~QmlSignalNode() { } + + const QString& element() const { return parent()->name(); } +}; + +class QmlMethodNode : public LeafNode +{ + public: + QmlMethodNode(QmlClassNode* parent, const QString& name); + virtual ~QmlMethodNode() { } + + const QString& element() const { return parent()->name(); } +}; +#endif + class EnumItem { public: @@ -357,6 +449,7 @@ class EnumNode : public LeafNode { public: EnumNode(InnerNode *parent, const QString& name); + virtual ~EnumNode() { } void addItem(const EnumItem& item); void setFlagsType(TypedefNode *typedeff); @@ -377,6 +470,7 @@ class TypedefNode : public LeafNode { public: TypedefNode(InnerNode *parent, const QString& name); + virtual ~TypedefNode() { } const EnumNode *associatedEnum() const { return ae; } @@ -437,6 +531,7 @@ class FunctionNode : public LeafNode enum Virtualness { NonVirtual, ImpureVirtual, PureVirtual }; FunctionNode(InnerNode *parent, const QString &name); + virtual ~FunctionNode() { } void setReturnType(const QString& returnType) { rt = returnType; } void setMetaness(Metaness metaness) { met = metaness; } @@ -444,6 +539,7 @@ class FunctionNode : public LeafNode void setConst(bool conste) { con = conste; } void setStatic(bool statique) { sta = statique; } void setOverload(bool overlode); + void setReimp(bool r); void addParameter(const Parameter& parameter); inline void setParameters(const QList<Parameter>& parameters); void borrowParameterNames(const FunctionNode *source); @@ -458,6 +554,7 @@ class FunctionNode : public LeafNode bool isConst() const { return con; } bool isStatic() const { return sta; } bool isOverload() const { return ove; } + bool isReimp() const { return reimp; } int overloadNumber() const; int numOverloads() const; const QList<Parameter>& parameters() const { return params; } @@ -483,6 +580,7 @@ class FunctionNode : public LeafNode bool con : 1; bool sta : 1; bool ove : 1; + bool reimp: 1; QList<Parameter> params; const FunctionNode *rf; const PropertyNode *ap; @@ -496,6 +594,7 @@ class PropertyNode : public LeafNode enum { NumFunctionRoles = Resetter + 1 }; PropertyNode(InnerNode *parent, const QString& name); + virtual ~PropertyNode() { } void setDataType(const QString& dataType) { dt = dataType; } void addFunction(FunctionNode *function, FunctionRole role); @@ -553,6 +652,7 @@ class VariableNode : public LeafNode { public: VariableNode(InnerNode *parent, const QString &name); + virtual ~VariableNode() { } void setLeftType(const QString &leftType) { lt = leftType; } void setRightType(const QString &rightType) { rt = rightType; } @@ -578,6 +678,7 @@ class TargetNode : public LeafNode { public: TargetNode(InnerNode *parent, const QString& name); + virtual ~TargetNode() { } virtual bool isInnerNode() const; }; diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp index 06ff398..8715f4a 100644 --- a/tools/qdoc3/pagegenerator.cpp +++ b/tools/qdoc3/pagegenerator.cpp @@ -81,30 +81,50 @@ QString PageGenerator::fileBase(const Node *node) { if (node->relates()) node = node->relates(); - else if (!node->isInnerNode()) + else if (!node->isInnerNode()) { node = node->parent(); +#ifdef QDOC_QML + if (node->subType() == Node::QmlPropertyGroup) { + node = node->parent(); + } +#endif + } QString base = node->doc().baseName(); if (!base.isEmpty()) return base; - const Node *p = node; - - forever { - base.prepend(p->name()); + const Node *p = node; + + forever { + base.prepend(p->name()); +#ifdef QDOC_QML + /* + To avoid file name conflicts in the html directory, + we prepend "qml-" to the file name of QML element doc + files. + */ + if ((p->subType() == Node::QmlClass) || + (p->subType() == Node::QmlPropertyGroup)) + base.prepend("qml-"); + else if ((p->type() == Node::QmlProperty) || + (p->type() == Node::QmlSignal) || + (p->type() == Node::QmlMethod)) + base.prepend("qml-"); +#endif const Node *pp = p->parent(); if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake) - break; + break; base.prepend(QLatin1Char('-')); p = pp; - } - - if (node->type() == Node::Fake) { + } + + if (node->type() == Node::Fake) { #ifdef QDOC2_COMPAT - if (base.endsWith(".html")) - base.truncate(base.length() - 5); + if (base.endsWith(".html")) + base.truncate(base.length() - 5); #endif - } + } // the code below is effectively equivalent to: // base.replace(QRegExp("[^A-Za-z0-9]+"), " "); @@ -126,7 +146,8 @@ QString PageGenerator::fileBase(const Node *node) if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) { res += QLatin1Char(u); begun = true; - } else if (begun) { + } + else if (begun) { res += QLatin1Char('-'); begun = false; } @@ -187,8 +208,12 @@ void PageGenerator::generateInnerNode(const InnerNode *node, if (node->type() == Node::Fake) { const FakeNode *fakeNode = static_cast<const FakeNode *>(node); - if (fakeNode->subType() == FakeNode::ExternalPage) + if (fakeNode->subType() == Node::ExternalPage) + return; +#ifdef QDOC_QML + if (fakeNode->subType() == Node::QmlPropertyGroup) return; +#endif } if (node->parent() != 0) { @@ -197,12 +222,6 @@ void PageGenerator::generateInnerNode(const InnerNode *node, generateClassLikeNode(node, marker); } else if (node->type() == Node::Fake) { - const FakeNode* fakeNode = static_cast<const FakeNode *>(node); -#ifdef QDOC_QML - if (fakeNode->subType() == FakeNode::QmlClass) { - //qDebug() << "FILENAME:" << fileName(node); - } -#endif generateFakeNode(static_cast<const FakeNode *>(node), marker); } endSubPage(); diff --git a/tools/qdoc3/qdoc3.pro b/tools/qdoc3/qdoc3.pro index ed27669..49a16e6 100644 --- a/tools/qdoc3/qdoc3.pro +++ b/tools/qdoc3/qdoc3.pro @@ -6,9 +6,12 @@ DEFINES += QT_NO_CAST_TO_ASCII QT = core xml CONFIG += console +CONFIG -= debug_and_release_target +#CONFIG += debug build_all:!build_pass { CONFIG -= build_all CONFIG += release +# CONFIG += debug } mac:CONFIG -= app_bundle HEADERS += apigenerator.h \ diff --git a/tools/qdoc3/separator.cpp b/tools/qdoc3/separator.cpp index 8f27f90..60674be 100644 --- a/tools/qdoc3/separator.cpp +++ b/tools/qdoc3/separator.cpp @@ -48,22 +48,30 @@ QT_BEGIN_NAMESPACE -QString separator( int index, int count ) +QString separator(int index, int count) { - if ( index == count - 1 ) - return tr( ".", "terminator" ); + if (index == count - 1) + return tr(".", "terminator"); + if (count == 2) + return tr(" and ", "separator when N = 2"); + if (index == 0) + return tr(", ", "first separator when N > 2"); + if (index < count - 2) + return tr(", ", "general separator when N > 2"); + return tr(", and ", "last separator when N > 2"); +} - if ( count == 2 ) { - return tr( " and ", "separator when N = 2" ); - } else { - if ( index == 0 ) { - return tr( ", ", "first separator when N > 2" ); - } else if ( index < count - 2 ) { - return tr( ", ", "general separator when N > 2" ); - } else { - return tr( ", and ", "last separator when N > 2" ); - } - } +QString comma(int index, int count) +{ + if (index == count - 1) + return QString(""); + if (count == 2) + return tr(" and ", "separator when N = 2"); + if (index == 0) + return tr(", ", "first separator when N > 2"); + if (index < count - 2) + return tr(", ", "general separator when N > 2"); + return tr(", and ", "last separator when N > 2"); } QT_END_NAMESPACE diff --git a/tools/qdoc3/separator.h b/tools/qdoc3/separator.h index 70ba624..2336d94 100644 --- a/tools/qdoc3/separator.h +++ b/tools/qdoc3/separator.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE QString separator( int index, int count ); +QString comma( int index, int count ); QT_END_NAMESPACE diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf index b82507f..44815ff 100644 --- a/tools/qdoc3/test/assistant.qdocconf +++ b/tools/qdoc3/test/assistant.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Assistant description = Qt Assistant Manual -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Assistant qhp.Assistant.file = assistant.qhp -qhp.Assistant.namespace = com.trolltech.assistant.452 +qhp.Assistant.namespace = com.trolltech.assistant.460 qhp.Assistant.virtualFolder = qdoc qhp.Assistant.indexTitle = Qt Assistant Manual qhp.Assistant.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css index 7f22861..4225a1b 100644 --- a/tools/qdoc3/test/classic.css +++ b/tools/qdoc3/test/classic.css @@ -125,7 +125,7 @@ table.generic, table.annotated } table td.memItemLeft { - width: 160px; + width: 180px; padding: 2px 0px 0px 8px; margin: 4px; border-width: 1px; @@ -225,3 +225,52 @@ span.string,span.char { font-size: 0.65em } + +.qmlitem { + padding: 0; +} + +.qmlname { + white-space: nowrap; + font-weight: bold; + font-size: 125%; +} + +.qmltype { + font-weight: bold; + font-size: 125%; +} + +.qmlproto, .qmldoc { + // border-top: 1px solid #84b0c7; +} + +.qmlproto { + padding: 0; + //background-color: #e4e4e4;//#d5e1e8; + //font-weight: bold; + //-webkit-border-top-left-radius: 8px; + //-webkit-border-top-right-radius: 8px; + //-moz-border-radius-topleft: 8px; + //-moz-border-radius-topright: 8px; +} + +.qmldoc { + border-top: 1px solid #e4e4e4; + //padding: 2px 5px; + //background-color: #eef3f5; + //border-top-width: 0; + //-webkit-border-bottom-left-radius: 8px; + //-webkit-border-bottom-right-radius: 8px; + //-moz-border-radius-bottomleft: 8px; + //-moz-border-radius-bottomright: 8px; +} + +.qmldoc p, .qmldoc dl, .qmldoc ul { + //margin: 6px 0; +} + +*.qmlitem p { + //margin-top: 0px; + //margin-bottom: 0px; +} diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf index 9c0790e..88f8dc9 100644 --- a/tools/qdoc3/test/designer.qdocconf +++ b/tools/qdoc3/test/designer.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Designer description = Qt Designer Manual -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Designer qhp.Designer.file = designer.qhp -qhp.Designer.namespace = com.trolltech.designer.452 +qhp.Designer.namespace = com.trolltech.designer.460 qhp.Designer.virtualFolder = qdoc qhp.Designer.indexTitle = Qt Designer Manual qhp.Designer.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf index da49abe..1c0a585 100644 --- a/tools/qdoc3/test/linguist.qdocconf +++ b/tools/qdoc3/test/linguist.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Linguist description = Qt Linguist Manual -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Linguist qhp.Linguist.file = linguist.qhp -qhp.Linguist.namespace = com.trolltech.linguist.452 +qhp.Linguist.namespace = com.trolltech.linguist.460 qhp.Linguist.virtualFolder = qdoc qhp.Linguist.indexTitle = Qt Linguist Manual qhp.Linguist.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png diff --git a/tools/qdoc3/test/macros.qdocconf b/tools/qdoc3/test/macros.qdocconf index 85fe1db..f7dcdc0 100644 --- a/tools/qdoc3/test/macros.qdocconf +++ b/tools/qdoc3/test/macros.qdocconf @@ -1,14 +1,15 @@ +macro.aacute.HTML = "á" macro.Aring.HTML = "Å" macro.aring.HTML = "å" macro.Auml.HTML = "Ä" macro.author = "\\bold{Author:}" macro.br.HTML = "<br />" macro.BR.HTML = "<br />" -macro.aacute.HTML = "á" +macro.copyright.HTML = "©" macro.eacute.HTML = "é" -macro.iacute.HTML = "í" macro.gui = "\\bold" macro.hr.HTML = "<hr />" +macro.iacute.HTML = "í" macro.key = "\\bold" macro.menu = "\\bold" macro.note = "\\bold{Note:}" diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf index 5e2cac7..0f98132 100644 --- a/tools/qdoc3/test/qmake.qdocconf +++ b/tools/qdoc3/test/qmake.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = QMake description = QMake Manual -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = qmake qhp.qmake.file = qmake.qhp -qhp.qmake.namespace = com.trolltech.qmake.452 +qhp.qmake.namespace = com.trolltech.qmake.460 qhp.qmake.virtualFolder = qdoc qhp.qmake.indexTitle = QMake Manual qhp.qmake.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf index 77b03d2..b4f0c7a 100644 --- a/tools/qdoc3/test/qt-build-docs.qdocconf +++ b/tools/qdoc3/test/qt-build-docs.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ QtXmlPatterns QtTest @@ -20,7 +20,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.452 +qhp.Qt.namespace = com.trolltech.qt.460 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index 9a18abe..709e336 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -68,7 +68,8 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QT_END_NAMESPACE \ QT_END_INCLUDE_NAMESPACE \ PHONON_EXPORT \ - Q_GADGET + Q_GADGET \ + QWEBKIT_EXPORT Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ diff --git a/tools/qdoc3/test/qt-inc.qdocconf b/tools/qdoc3/test/qt-inc.qdocconf index 01b07b3..379511f 100644 --- a/tools/qdoc3/test/qt-inc.qdocconf +++ b/tools/qdoc3/test/qt-inc.qdocconf @@ -3,7 +3,7 @@ include(macros.qdocconf) project = Qt description = Qt Reference Documentation -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 edition.Console = QtCore QtNetwork QtSql QtXml QtScript QtTest edition.Desktop = QtCore QtGui QtNetwork QtOpenGL QtSql QtSvg QtXml QtScript \ @@ -100,7 +100,8 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_TYPENAME \ Q_XML_EXPORT \ QDBUS_EXPORT \ - Q_GADGET + Q_GADGET \ + QWEBKIT_EXPORT Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf index d154254..10e0fcd 100644 --- a/tools/qdoc3/test/qt.qdocconf +++ b/tools/qdoc3/test/qt.qdocconf @@ -8,7 +8,7 @@ project = Qt versionsym = version = %VERSION% description = Qt Reference Documentation -url = http://doc.qtsoftware.com/4.5 +url = http://doc.qtsoftware.com/4.6 edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ QtXmlPatterns QtTest @@ -22,7 +22,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.452 +qhp.Qt.namespace = com.trolltech.qt.460 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index 308ba0e..d75af70 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -176,6 +176,8 @@ const Node *Tree::findNode(const QStringList &path, } /*! + Find the node with the specified \a path name of the + specified \a type. */ Node *Tree::findNode(const QStringList &path, Node::Type type, @@ -189,6 +191,8 @@ Node *Tree::findNode(const QStringList &path, } /*! + Find the node with the specified \a path name of the + specified \a type. */ const Node *Tree::findNode(const QStringList &path, Node::Type type, @@ -208,7 +212,9 @@ FunctionNode *Tree::findFunctionNode(const QStringList& path, int findFlags) { return const_cast<FunctionNode *>( - const_cast<const Tree *>(this)->findFunctionNode(path, relative, findFlags)); + const_cast<const Tree *>(this)->findFunctionNode(path, + relative, + findFlags)); } /*! @@ -233,7 +239,8 @@ const FunctionNode *Tree::findFunctionNode(const QStringList &path, else next = ((InnerNode *) node)->findNode(path.at(i)); - if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) { + if (!next && node->type() == Node::Class && + (findFlags & SearchBaseClasses)) { NodeList baseClasses = allBaseClasses(static_cast<const ClassNode *>(node)); foreach (const Node *baseClass, baseClasses) { if (i == path.size() - 1) @@ -412,6 +419,8 @@ void Tree::addPropertyFunction(PropertyNode *property, } /*! + This function adds the \a node to the \a group. The group + can be listed anywhere using the \e{annotated list} command. */ void Tree::addToGroup(Node *node, const QString &group) { @@ -563,7 +572,7 @@ void Tree::resolveGroups() FakeNode *fake = static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake)); - if (fake && fake->subType() == FakeNode::Group) { + if (fake && fake->subType() == Node::Group) { fake->addGroupMember(i.value()); } else { @@ -770,21 +779,21 @@ void Tree::readIndexSection(const QDomElement &element, } else if (element.nodeName() == "page") { - FakeNode::SubType subtype; + Node::SubType subtype; if (element.attribute("subtype") == "example") - subtype = FakeNode::Example; + subtype = Node::Example; else if (element.attribute("subtype") == "header") - subtype = FakeNode::HeaderFile; + subtype = Node::HeaderFile; else if (element.attribute("subtype") == "file") - subtype = FakeNode::File; + subtype = Node::File; else if (element.attribute("subtype") == "group") - subtype = FakeNode::Group; + subtype = Node::Group; else if (element.attribute("subtype") == "module") - subtype = FakeNode::Module; + subtype = Node::Module; else if (element.attribute("subtype") == "page") - subtype = FakeNode::Page; + subtype = Node::Page; else if (element.attribute("subtype") == "externalpage") - subtype = FakeNode::ExternalPage; + subtype = Node::ExternalPage; else return; @@ -1226,25 +1235,25 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, const FakeNode *fakeNode = static_cast<const FakeNode*>(node); switch (fakeNode->subType()) { - case FakeNode::Example: + case Node::Example: writer.writeAttribute("subtype", "example"); break; - case FakeNode::HeaderFile: + case Node::HeaderFile: writer.writeAttribute("subtype", "header"); break; - case FakeNode::File: + case Node::File: writer.writeAttribute("subtype", "file"); break; - case FakeNode::Group: + case Node::Group: writer.writeAttribute("subtype", "group"); break; - case FakeNode::Module: + case Node::Module: writer.writeAttribute("subtype", "module"); break; - case FakeNode::Page: + case Node::Page: writer.writeAttribute("subtype", "page"); break; - case FakeNode::ExternalPage: + case Node::ExternalPage: writer.writeAttribute("subtype", "externalpage"); break; default: @@ -1383,7 +1392,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, bool external = false; if (inner->type() == Node::Fake) { const FakeNode *fakeNode = static_cast<const FakeNode *>(inner); - if (fakeNode->subType() == FakeNode::ExternalPage) + if (fakeNode->subType() == Node::ExternalPage) external = true; } @@ -1863,7 +1872,7 @@ void Tree::generateTagFile(const QString &fileName) const */ void Tree::addExternalLink(const QString &url, const Node *relative) { - FakeNode *fakeNode = new FakeNode(root(), url, FakeNode::ExternalPage); + FakeNode *fakeNode = new FakeNode(root(), url, Node::ExternalPage); fakeNode->setAccess(Node::Public); // Create some content for the node. @@ -1898,6 +1907,11 @@ QString Tree::fullDocumentLocation(const Node *node) const return ""; } else if (node->type() == Node::Fake) { +#ifdef QDOC_QML + if (node->subType() == Node::QmlClass) + return "qml-" + node->fileBase() + ".html"; + else +#endif parentName = node->fileBase() + ".html"; } else if (node->fileBase().isEmpty()) diff --git a/tools/qdoc3/webxmlgenerator.cpp b/tools/qdoc3/webxmlgenerator.cpp index c5209b8..e87e812 100644 --- a/tools/qdoc3/webxmlgenerator.cpp +++ b/tools/qdoc3/webxmlgenerator.cpp @@ -191,7 +191,7 @@ void WebXMLGenerator::generateIndexSections(QXmlStreamWriter &writer, generateRelations(writer, node, marker); - if (fake->subType() == FakeNode::Module) { + if (fake->subType() == Node::Module) { writer.writeStartElement("generatedlist"); writer.writeAttribute("contents", "classesbymodule"); @@ -264,7 +264,7 @@ void WebXMLGenerator::generateInnerNode(const InnerNode *node, CodeMarker *marke if (node->type() == Node::Fake) { const FakeNode *fakeNode = static_cast<const FakeNode *>(node); - if (fakeNode->subType() == FakeNode::ExternalPage) + if (fakeNode->subType() == Node::ExternalPage) return; } diff --git a/tools/qtconfig/paletteeditoradvanced.cpp b/tools/qtconfig/paletteeditoradvanced.cpp index 45f6a45..36cbd89 100644 --- a/tools/qtconfig/paletteeditoradvanced.cpp +++ b/tools/qtconfig/paletteeditoradvanced.cpp @@ -55,7 +55,7 @@ PaletteEditorAdvanced::PaletteEditorAdvanced( QWidget * parent, const char * name, bool modal, Qt::WindowFlags f ) : PaletteEditorAdvancedBase( parent, name, modal, f ), selectedPalette(0) { - // work around buggy ui file + // work around buggy UI file comboEffect->setEnabled(false); buttonEffect->setEnabled(false); onToggleBuildEffects(true); diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index f047b79..1080477 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -113,6 +113,8 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS CeCloseHandle(deviceHandle); return true; } + } else { + qWarning("Could not open %s: %s", qPrintable(localSource), qPrintable(file.errorString())); } return false; } @@ -120,7 +122,7 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS deleteFile(deviceDest); HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (deviceHandle == INVALID_HANDLE_VALUE) { - debugOutput(QString::fromLatin1(" Could not create target file"), 2); + qWarning("Could not create %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData()); return false; } @@ -144,7 +146,7 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS if (toWrite == 0) break; if (!CeWriteFile(deviceHandle, data.data() , toWrite, &written, NULL)) { - debugOutput(QString::fromLatin1(" Could not write File"), 2); + qWarning("Could not write to %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData()); return false; } currentPos += written; @@ -270,8 +272,8 @@ bool ActiveSyncConnection::copyDirectoryFromDevice(const QString &deviceSource, } do { - QString srcFile = deviceSource + "\\" + QString::fromUtf16(data.cFileName); - QString destFile = localDest + "\\" + QString::fromUtf16(data.cFileName); + QString srcFile = deviceSource + "\\" + QString::fromWCharArray(data.cFileName); + QString destFile = localDest + "\\" + QString::fromWCharArray(data.cFileName); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive && !copyDirectoryFromDevice(srcFile, destFile, recursive)) { wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16()); @@ -306,8 +308,8 @@ bool ActiveSyncConnection::copyDirectory(const QString &srcDirectory, const QStr } do { - QString srcFile = srcDirectory + "\\" + QString::fromUtf16(data.cFileName); - QString destFile = destDirectory + "\\" + QString::fromUtf16(data.cFileName); + QString srcFile = srcDirectory + "\\" + QString::fromWCharArray(data.cFileName); + QString destFile = destDirectory + "\\" + QString::fromWCharArray(data.cFileName); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive && !copyDirectory(srcFile, destFile, recursive)) { wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16()); @@ -341,7 +343,7 @@ bool ActiveSyncConnection::deleteDirectory(const QString &directory, bool recurs return false; do { - QString FileName = directory + "\\" + QString::fromUtf16(FindFileData.cFileName); + QString FileName = directory + "\\" + QString::fromWCharArray(FindFileData.cFileName); if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive) if (!deleteDirectory(FileName, recursive, failIfContentExists)) @@ -380,12 +382,17 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo BYTE* output; IRAPIStream *stream; int returned = 0; + DWORD error = 0; HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0); if (S_OK != res) { - if (S_OK != CeGetLastError()) - debugOutput(QString::fromLatin1("Error: Could not invoke method on QtRemote"),1); - else - debugOutput(QString::fromLatin1("Error: QtRemote return unexpectedly with error Code %1").arg(res), 1); + DWORD ce_error = CeGetLastError(); + if (S_OK != ce_error) { + qWarning("Error invoking %s on %s: %s", qPrintable(functionName), + qPrintable(dllLocation), strwinerror(ce_error).constData()); + } else { + qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName), + qPrintable(dllLocation), res); + } } else { DWORD written; int strSize = program.length(); @@ -414,9 +421,18 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo if (S_OK != stream->Read(&returned, sizeof(returned), &written)) { qWarning(" Could not access return value of process"); } - result = true; - } + if (S_OK != stream->Read(&error, sizeof(error), &written)) { + qWarning(" Could not access error code"); + } + if (error) { + qWarning("Error on target: %s", strwinerror(error).constData()); + result = false; + } + else { + result = true; + } + } if (returnValue) *returnValue = returned; diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri index 39f24c2..a31374e 100644 --- a/tools/qtestlib/wince/cetest/bootstrapped.pri +++ b/tools/qtestlib/wince/cetest/bootstrapped.pri @@ -35,4 +35,5 @@ SOURCES += \ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \ - $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp + $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \ + $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec.cpp diff --git a/tools/qtestlib/wince/cetest/deployment.cpp b/tools/qtestlib/wince/cetest/deployment.cpp index fec2735..68f0197 100644 --- a/tools/qtestlib/wince/cetest/deployment.cpp +++ b/tools/qtestlib/wince/cetest/deployment.cpp @@ -125,13 +125,37 @@ void DeploymentHandler::initQtDeploy(QMakeProject *project, DeploymentList &depl if (!project->values("QMAKE_QT_DLL").isEmpty() && !project->values("QMAKE_LIBDIR").isEmpty()) { QStringList libs = project->values("LIBS"); QStringList qtLibs; + QStringList libPaths; foreach (QString item, libs) { - if (item.startsWith("-lQt")) { - qtLibs += project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + item.mid(2) + QLatin1String("4.dll"); + + if (item.startsWith("-L")) { + // -L -> a directory containing DLLs + libPaths << item.mid(2); + continue; + } + + QStringList libCandidates; + + if (item.startsWith("-l")) { + // -l -> a library located within one of the standard library paths + QString lib = item.mid(2); + + // Check if it's a Qt library first, then check in all paths given with -L. + // Note Qt libraries get a `4' appended to them, others don't. + libCandidates << project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + lib + QLatin1String("4.dll"); + foreach (QString const& libPath, libPaths) { + libCandidates << libPath + QDir::separator() + lib + QLatin1String(".dll"); + } } else { - QFileInfo info(item); - if (info.exists() && info.isAbsolute() && info.fileName().startsWith(QLatin1String("Qt"))) - qtLibs += info.dir().absoluteFilePath(info.fileName().replace(QLatin1String(".lib"), QLatin1String(".dll"))); + libCandidates << item.replace(".lib",".dll"); + } + + foreach (QString const& file, libCandidates) { + QFileInfo info(file); + if (info.exists()) { + qtLibs += info.dir().absoluteFilePath(info.fileName()); + break; + } } } for (QStringList::ConstIterator it = qtLibs.constBegin(); it != qtLibs.constEnd(); ++it) { diff --git a/tools/qtestlib/wince/cetest/main.cpp b/tools/qtestlib/wince/cetest/main.cpp index ba3ef8d..782f6d9 100644 --- a/tools/qtestlib/wince/cetest/main.cpp +++ b/tools/qtestlib/wince/cetest/main.cpp @@ -320,6 +320,7 @@ int main(int argc, char **argv) cout << endl << "Remote Launch:" << qPrintable(TestConfiguration::remoteExecutable) << " " << qPrintable(launchArguments.join(" ")) << endl; if (!connection.execute(TestConfiguration::remoteExecutable, launchArguments.join(" "), timeout)) { cout << "Error: Could not execute target file" << endl; + return -1; } diff --git a/tools/qtestlib/wince/cetest/remoteconnection.cpp b/tools/qtestlib/wince/cetest/remoteconnection.cpp index 547b211..3d0c3f3 100644 --- a/tools/qtestlib/wince/cetest/remoteconnection.cpp +++ b/tools/qtestlib/wince/cetest/remoteconnection.cpp @@ -41,6 +41,38 @@ #include "remoteconnection.h" +QByteArray strwinerror(DWORD errorcode) +{ + QByteArray out(512, 0); + + DWORD ok = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM, + 0, + errorcode, + 0, + out.data(), + out.size(), + 0 + ); + + if (!ok) { + qsnprintf(out.data(), out.size(), + "(error %d; additionally, error %d while looking up error string)", + (int)errorcode, (int)GetLastError()); + } + else { + out.resize(qstrlen(out.constData())); + if (out.endsWith("\r\n")) + out.chop(2); + + /* Append error number to error message for good measure */ + out.append(" (0x"); + out.append(QByteArray::number(uint(errorcode), 16).rightJustified(8, '0')); + out.append(")"); + } + return out; +} + AbstractRemoteConnection::AbstractRemoteConnection() { } diff --git a/tools/qtestlib/wince/cetest/remoteconnection.h b/tools/qtestlib/wince/cetest/remoteconnection.h index 9c3e63d..f517009 100644 --- a/tools/qtestlib/wince/cetest/remoteconnection.h +++ b/tools/qtestlib/wince/cetest/remoteconnection.h @@ -79,4 +79,6 @@ public: virtual bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL) = 0; }; +QByteArray strwinerror(DWORD); + #endif diff --git a/tools/qtestlib/wince/remotelib/commands.cpp b/tools/qtestlib/wince/remotelib/commands.cpp index 3aed2d6..f2176dd 100644 --- a/tools/qtestlib/wince/remotelib/commands.cpp +++ b/tools/qtestlib/wince/remotelib/commands.cpp @@ -56,6 +56,7 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) wchar_t* arguments = 0; int timeout = -1; int returnValue = -2; + DWORD error = 0; if (S_OK != stream->Read(&appLength, sizeof(appLength), &bytesRead)) CLEAN_FAIL(-2); @@ -74,11 +75,13 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) if (S_OK != stream->Read(&timeout, sizeof(timeout), &bytesRead)) CLEAN_FAIL(-2); - bool result = qRemoteExecute(appName, arguments, &returnValue, timeout); + bool result = qRemoteExecute(appName, arguments, &returnValue, &error, timeout); if (timeout != 0) { if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead)) CLEAN_FAIL(-4); + if (S_OK != stream->Write(&error, sizeof(error), &bytesRead)) + CLEAN_FAIL(-5); } delete appName; delete arguments; @@ -90,13 +93,16 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) } -bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, int timeout) +bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, DWORD* error, int timeout) { + *error = 0; + if (!program) return false; PROCESS_INFORMATION pid; if (!CreateProcess(program, arguments, NULL, NULL, false, 0, NULL, NULL, NULL, &pid)) { + *error = GetLastError(); wprintf(L"Could not launch: %s\n", program); return false; } diff --git a/tools/qtestlib/wince/remotelib/commands.h b/tools/qtestlib/wince/remotelib/commands.h index 9f0b2e3..5275f2c 100644 --- a/tools/qtestlib/wince/remotelib/commands.h +++ b/tools/qtestlib/wince/remotelib/commands.h @@ -45,7 +45,7 @@ extern "C" { int __declspec(dllexport) qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream*); - bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , int timeout = -1); + bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , DWORD* error = NULL, int timeout = -1); } #endif diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.h b/tools/shared/qtgradienteditor/qtcolorbutton.h index 5f34815..0348998 100644 --- a/tools/shared/qtgradienteditor/qtcolorbutton.h +++ b/tools/shared/qtgradienteditor/qtcolorbutton.h @@ -76,7 +76,7 @@ protected: #endif private: QScopedPointer<class QtColorButtonPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtColorButton) + Q_DECLARE_PRIVATE(QtColorButton) Q_DISABLE_COPY(QtColorButton) Q_PRIVATE_SLOT(d_func(), void slotEditColor()) }; diff --git a/tools/shared/qtgradienteditor/qtcolorline.h b/tools/shared/qtgradienteditor/qtcolorline.h index f54ec70..ffd3eea 100644 --- a/tools/shared/qtgradienteditor/qtcolorline.h +++ b/tools/shared/qtgradienteditor/qtcolorline.h @@ -115,7 +115,7 @@ protected: private: QScopedPointer<class QtColorLinePrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtColorLine) + Q_DECLARE_PRIVATE(QtColorLine) Q_DISABLE_COPY(QtColorLine) }; diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.h b/tools/shared/qtgradienteditor/qtgradientdialog.h index 6f40794..f293a28 100644 --- a/tools/shared/qtgradienteditor/qtgradientdialog.h +++ b/tools/shared/qtgradienteditor/qtgradientdialog.h @@ -77,7 +77,7 @@ public: private: QScopedPointer<class QtGradientDialogPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientDialog) + Q_DECLARE_PRIVATE(QtGradientDialog) Q_DISABLE_COPY(QtGradientDialog) Q_PRIVATE_SLOT(d_func(), void slotAboutToShowDetails(bool details, int extensionWidthHint)) }; diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.h b/tools/shared/qtgradienteditor/qtgradienteditor.h index b7dcfd3..2d96515 100644 --- a/tools/shared/qtgradienteditor/qtgradienteditor.h +++ b/tools/shared/qtgradienteditor/qtgradienteditor.h @@ -79,7 +79,7 @@ signals: private: QScopedPointer<class QtGradientEditorPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientEditor) + Q_DECLARE_PRIVATE(QtGradientEditor) Q_DISABLE_COPY(QtGradientEditor) Q_PRIVATE_SLOT(d_func(), void slotGradientStopsChanged(const QGradientStops &stops)) Q_PRIVATE_SLOT(d_func(), void slotTypeChanged(int type)) diff --git a/tools/shared/qtgradienteditor/qtgradientstopscontroller.h b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h index 94a5619..7c6a660 100644 --- a/tools/shared/qtgradienteditor/qtgradientstopscontroller.h +++ b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h @@ -71,7 +71,7 @@ signals: private: QScopedPointer<class QtGradientStopsControllerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientStopsController) + Q_DECLARE_PRIVATE(QtGradientStopsController) Q_DISABLE_COPY(QtGradientStopsController) Q_PRIVATE_SLOT(d_func(), void slotHsvClicked()) Q_PRIVATE_SLOT(d_func(), void slotRgbClicked()) diff --git a/tools/shared/qtgradienteditor/qtgradientstopsmodel.h b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h index 8190829..a02ebc5 100644 --- a/tools/shared/qtgradienteditor/qtgradientstopsmodel.h +++ b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h @@ -112,7 +112,7 @@ signals: private: QScopedPointer<class QtGradientStopsModelPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientStopsModel) + Q_DECLARE_PRIVATE(QtGradientStopsModel) Q_DISABLE_COPY(QtGradientStopsModel) }; diff --git a/tools/shared/qtgradienteditor/qtgradientstopswidget.h b/tools/shared/qtgradienteditor/qtgradientstopswidget.h index 7c7c5fc..753d695 100644 --- a/tools/shared/qtgradienteditor/qtgradientstopswidget.h +++ b/tools/shared/qtgradienteditor/qtgradientstopswidget.h @@ -92,7 +92,7 @@ protected: private: QScopedPointer<QtGradientStopsWidgetPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientStopsWidget) + Q_DECLARE_PRIVATE(QtGradientStopsWidget) Q_DISABLE_COPY(QtGradientStopsWidget) Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop)) Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop)) diff --git a/tools/shared/qtgradienteditor/qtgradientwidget.h b/tools/shared/qtgradienteditor/qtgradientwidget.h index 52fdcbb..3e23bf9 100644 --- a/tools/shared/qtgradienteditor/qtgradientwidget.h +++ b/tools/shared/qtgradienteditor/qtgradientwidget.h @@ -111,7 +111,7 @@ protected: private: QScopedPointer<class QtGradientWidgetPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGradientWidget) + Q_DECLARE_PRIVATE(QtGradientWidget) Q_DISABLE_COPY(QtGradientWidget) }; diff --git a/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h index 13d37e2..a558657 100644 --- a/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h +++ b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h @@ -72,7 +72,7 @@ protected: private: QScopedPointer<QtButtonPropertyBrowserPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtButtonPropertyBrowser) + Q_DECLARE_PRIVATE(QtButtonPropertyBrowser) Q_DISABLE_COPY(QtButtonPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotUpdate()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) diff --git a/tools/shared/qtpropertybrowser/qteditorfactory.h b/tools/shared/qtpropertybrowser/qteditorfactory.h index ec30f9d..bad2080 100644 --- a/tools/shared/qtpropertybrowser/qteditorfactory.h +++ b/tools/shared/qtpropertybrowser/qteditorfactory.h @@ -61,7 +61,7 @@ protected: void disconnectPropertyManager(QtIntPropertyManager *manager); private: QScopedPointer<QtSpinBoxFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtSpinBoxFactory) + Q_DECLARE_PRIVATE(QtSpinBoxFactory) Q_DISABLE_COPY(QtSpinBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) @@ -85,7 +85,7 @@ protected: void disconnectPropertyManager(QtIntPropertyManager *manager); private: QScopedPointer<QtSliderFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtSliderFactory) + Q_DECLARE_PRIVATE(QtSliderFactory) Q_DISABLE_COPY(QtSliderFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) @@ -109,7 +109,7 @@ protected: void disconnectPropertyManager(QtIntPropertyManager *manager); private: QScopedPointer<QtScrollBarFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtScrollBarFactory) + Q_DECLARE_PRIVATE(QtScrollBarFactory) Q_DISABLE_COPY(QtScrollBarFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) @@ -133,7 +133,7 @@ protected: void disconnectPropertyManager(QtBoolPropertyManager *manager); private: QScopedPointer<QtCheckBoxFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtCheckBoxFactory) + Q_DECLARE_PRIVATE(QtCheckBoxFactory) Q_DISABLE_COPY(QtCheckBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(bool)) @@ -155,7 +155,7 @@ protected: void disconnectPropertyManager(QtDoublePropertyManager *manager); private: QScopedPointer<QtDoubleSpinBoxFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDoubleSpinBoxFactory) + Q_DECLARE_PRIVATE(QtDoubleSpinBoxFactory) Q_DISABLE_COPY(QtDoubleSpinBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) @@ -180,7 +180,7 @@ protected: void disconnectPropertyManager(QtStringPropertyManager *manager); private: QScopedPointer<QtLineEditFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtLineEditFactory) + Q_DECLARE_PRIVATE(QtLineEditFactory) Q_DISABLE_COPY(QtLineEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &)) Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &)) @@ -203,7 +203,7 @@ protected: void disconnectPropertyManager(QtDatePropertyManager *manager); private: QScopedPointer<QtDateEditFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDateEditFactory) + Q_DECLARE_PRIVATE(QtDateEditFactory) Q_DISABLE_COPY(QtDateEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, @@ -227,7 +227,7 @@ protected: void disconnectPropertyManager(QtTimePropertyManager *manager); private: QScopedPointer<QtTimeEditFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtTimeEditFactory) + Q_DECLARE_PRIVATE(QtTimeEditFactory) Q_DISABLE_COPY(QtTimeEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QTime &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QTime &)) @@ -249,7 +249,7 @@ protected: void disconnectPropertyManager(QtDateTimePropertyManager *manager); private: QScopedPointer<QtDateTimeEditFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDateTimeEditFactory) + Q_DECLARE_PRIVATE(QtDateTimeEditFactory) Q_DISABLE_COPY(QtDateTimeEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDateTime &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDateTime &)) @@ -271,7 +271,7 @@ protected: void disconnectPropertyManager(QtKeySequencePropertyManager *manager); private: QScopedPointer<QtKeySequenceEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtKeySequenceEditorFactory) + Q_DECLARE_PRIVATE(QtKeySequenceEditorFactory) Q_DISABLE_COPY(QtKeySequenceEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QKeySequence &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QKeySequence &)) @@ -293,7 +293,7 @@ protected: void disconnectPropertyManager(QtCharPropertyManager *manager); private: QScopedPointer<QtCharEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtCharEditorFactory) + Q_DECLARE_PRIVATE(QtCharEditorFactory) Q_DISABLE_COPY(QtCharEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QChar &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QChar &)) @@ -315,7 +315,7 @@ protected: void disconnectPropertyManager(QtEnumPropertyManager *manager); private: QScopedPointer<QtEnumEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtEnumEditorFactory) + Q_DECLARE_PRIVATE(QtEnumEditorFactory) Q_DISABLE_COPY(QtEnumEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, @@ -341,7 +341,7 @@ protected: void disconnectPropertyManager(QtCursorPropertyManager *manager); private: QScopedPointer<QtCursorEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtCursorEditorFactory) + Q_DECLARE_PRIVATE(QtCursorEditorFactory) Q_DISABLE_COPY(QtCursorEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QCursor &)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) @@ -363,7 +363,7 @@ protected: void disconnectPropertyManager(QtColorPropertyManager *manager); private: QScopedPointer<QtColorEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtColorEditorFactory) + Q_DECLARE_PRIVATE(QtColorEditorFactory) Q_DISABLE_COPY(QtColorEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QColor &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) @@ -385,7 +385,7 @@ protected: void disconnectPropertyManager(QtFontPropertyManager *manager); private: QScopedPointer<QtFontEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtFontEditorFactory) + Q_DECLARE_PRIVATE(QtFontEditorFactory) Q_DISABLE_COPY(QtFontEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QFont &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) diff --git a/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h index 5124fd5..1cfda63 100644 --- a/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h +++ b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h @@ -64,7 +64,7 @@ protected: private: QScopedPointer<QtGroupBoxPropertyBrowserPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtGroupBoxPropertyBrowser) + Q_DECLARE_PRIVATE(QtGroupBoxPropertyBrowser) Q_DISABLE_COPY(QtGroupBoxPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotUpdate()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowser.h b/tools/shared/qtpropertybrowser/qtpropertybrowser.h index dfcb65a..19996c0 100644 --- a/tools/shared/qtpropertybrowser/qtpropertybrowser.h +++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.h @@ -119,7 +119,7 @@ protected: private: friend class QtProperty; QScopedPointer<QtAbstractPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtAbstractPropertyManager) + Q_DECLARE_PRIVATE(QtAbstractPropertyManager) Q_DISABLE_COPY(QtAbstractPropertyManager) }; @@ -293,7 +293,7 @@ private: QtAbstractEditorFactoryBase *abstractFactory); QScopedPointer<QtAbstractPropertyBrowserPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtAbstractPropertyBrowser) + Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser) Q_DISABLE_COPY(QtAbstractPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) diff --git a/tools/shared/qtpropertybrowser/qtpropertymanager.h b/tools/shared/qtpropertybrowser/qtpropertymanager.h index 14b71fb..31c308e 100644 --- a/tools/shared/qtpropertybrowser/qtpropertymanager.h +++ b/tools/shared/qtpropertybrowser/qtpropertymanager.h @@ -95,7 +95,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtIntPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtIntPropertyManager) + Q_DECLARE_PRIVATE(QtIntPropertyManager) Q_DISABLE_COPY(QtIntPropertyManager) }; @@ -121,7 +121,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtBoolPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtBoolPropertyManager) + Q_DECLARE_PRIVATE(QtBoolPropertyManager) Q_DISABLE_COPY(QtBoolPropertyManager) }; @@ -158,7 +158,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtDoublePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDoublePropertyManager) + Q_DECLARE_PRIVATE(QtDoublePropertyManager) Q_DISABLE_COPY(QtDoublePropertyManager) }; @@ -186,7 +186,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtStringPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtStringPropertyManager) + Q_DECLARE_PRIVATE(QtStringPropertyManager) Q_DISABLE_COPY(QtStringPropertyManager) }; @@ -217,7 +217,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtDatePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDatePropertyManager) + Q_DECLARE_PRIVATE(QtDatePropertyManager) Q_DISABLE_COPY(QtDatePropertyManager) }; @@ -242,7 +242,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtTimePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtTimePropertyManager) + Q_DECLARE_PRIVATE(QtTimePropertyManager) Q_DISABLE_COPY(QtTimePropertyManager) }; @@ -267,7 +267,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtDateTimePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtDateTimePropertyManager) + Q_DECLARE_PRIVATE(QtDateTimePropertyManager) Q_DISABLE_COPY(QtDateTimePropertyManager) }; @@ -292,7 +292,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtKeySequencePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtKeySequencePropertyManager) + Q_DECLARE_PRIVATE(QtKeySequencePropertyManager) Q_DISABLE_COPY(QtKeySequencePropertyManager) }; @@ -317,7 +317,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtCharPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtCharPropertyManager) + Q_DECLARE_PRIVATE(QtCharPropertyManager) Q_DISABLE_COPY(QtCharPropertyManager) }; @@ -345,7 +345,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtLocalePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtLocalePropertyManager) + Q_DECLARE_PRIVATE(QtLocalePropertyManager) Q_DISABLE_COPY(QtLocalePropertyManager) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -374,7 +374,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtPointPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtPointPropertyManager) + Q_DECLARE_PRIVATE(QtPointPropertyManager) Q_DISABLE_COPY(QtPointPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -406,7 +406,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtPointFPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtPointFPropertyManager) + Q_DECLARE_PRIVATE(QtPointFPropertyManager) Q_DISABLE_COPY(QtPointFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -441,7 +441,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtSizePropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtSizePropertyManager) + Q_DECLARE_PRIVATE(QtSizePropertyManager) Q_DISABLE_COPY(QtSizePropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -479,7 +479,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtSizeFPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtSizeFPropertyManager) + Q_DECLARE_PRIVATE(QtSizeFPropertyManager) Q_DISABLE_COPY(QtSizeFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -511,7 +511,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtRectPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtRectPropertyManager) + Q_DECLARE_PRIVATE(QtRectPropertyManager) Q_DISABLE_COPY(QtRectPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -546,7 +546,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtRectFPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtRectFPropertyManager) + Q_DECLARE_PRIVATE(QtRectFPropertyManager) Q_DISABLE_COPY(QtRectFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -580,7 +580,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtEnumPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtEnumPropertyManager) + Q_DECLARE_PRIVATE(QtEnumPropertyManager) Q_DISABLE_COPY(QtEnumPropertyManager) }; @@ -610,7 +610,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtFlagPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtFlagPropertyManager) + Q_DECLARE_PRIVATE(QtFlagPropertyManager) Q_DISABLE_COPY(QtFlagPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -640,7 +640,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtSizePolicyPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtSizePolicyPropertyManager) + Q_DECLARE_PRIVATE(QtSizePolicyPropertyManager) Q_DISABLE_COPY(QtSizePolicyPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) @@ -673,7 +673,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtFontPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtFontPropertyManager) + Q_DECLARE_PRIVATE(QtFontPropertyManager) Q_DISABLE_COPY(QtFontPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) @@ -707,7 +707,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtColorPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtColorPropertyManager) + Q_DECLARE_PRIVATE(QtColorPropertyManager) Q_DISABLE_COPY(QtColorPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) @@ -737,7 +737,7 @@ protected: virtual void uninitializeProperty(QtProperty *property); private: QScopedPointer<QtCursorPropertyManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtCursorPropertyManager) + Q_DECLARE_PRIVATE(QtCursorPropertyManager) Q_DISABLE_COPY(QtCursorPropertyManager) }; diff --git a/tools/shared/qtpropertybrowser/qttreepropertybrowser.h b/tools/shared/qtpropertybrowser/qttreepropertybrowser.h index 4994bfc..ebcf185 100644 --- a/tools/shared/qtpropertybrowser/qttreepropertybrowser.h +++ b/tools/shared/qtpropertybrowser/qttreepropertybrowser.h @@ -119,7 +119,7 @@ protected: private: QScopedPointer<QtTreePropertyBrowserPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtTreePropertyBrowser) + Q_DECLARE_PRIVATE(QtTreePropertyBrowser) Q_DISABLE_COPY(QtTreePropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &)) diff --git a/tools/shared/qtpropertybrowser/qtvariantproperty.h b/tools/shared/qtpropertybrowser/qtvariantproperty.h index f4f45da..4f32c57 100644 --- a/tools/shared/qtpropertybrowser/qtvariantproperty.h +++ b/tools/shared/qtpropertybrowser/qtvariantproperty.h @@ -149,7 +149,7 @@ private: Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *)) - Q_DECLARE_SCOPED_PRIVATE(QtVariantPropertyManager) + Q_DECLARE_PRIVATE(QtVariantPropertyManager) Q_DISABLE_COPY(QtVariantPropertyManager) }; @@ -166,7 +166,7 @@ protected: void disconnectPropertyManager(QtVariantPropertyManager *manager); private: QScopedPointer<class QtVariantEditorFactoryPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtVariantEditorFactory) + Q_DECLARE_PRIVATE(QtVariantEditorFactory) Q_DISABLE_COPY(QtVariantEditorFactory) }; diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.cpp b/tools/shared/qttoolbardialog/qttoolbardialog.cpp index 0c4622f..8ceb582 100644 --- a/tools/shared/qttoolbardialog/qttoolbardialog.cpp +++ b/tools/shared/qttoolbardialog/qttoolbardialog.cpp @@ -120,7 +120,7 @@ signals: private: QScopedPointer<QtFullToolBarManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtFullToolBarManager) + Q_DECLARE_PRIVATE(QtFullToolBarManager) Q_DISABLE_COPY(QtFullToolBarManager) }; diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.h b/tools/shared/qttoolbardialog/qttoolbardialog.h index d3f7396..9227b56 100644 --- a/tools/shared/qttoolbardialog/qttoolbardialog.h +++ b/tools/shared/qttoolbardialog/qttoolbardialog.h @@ -89,7 +89,7 @@ private: friend class QtToolBarDialog; QScopedPointer<QtToolBarManagerPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtToolBarManager) + Q_DECLARE_PRIVATE(QtToolBarManager) Q_DISABLE_COPY(QtToolBarManager) }; @@ -113,7 +113,7 @@ protected: private: QScopedPointer<QtToolBarDialogPrivate> d_ptr; - Q_DECLARE_SCOPED_PRIVATE(QtToolBarDialog) + Q_DECLARE_PRIVATE(QtToolBarDialog) Q_DISABLE_COPY(QtToolBarDialog) Q_PRIVATE_SLOT(d_func(), void newClicked()) diff --git a/tools/tools.pro b/tools/tools.pro index a978227..a602892 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -26,7 +26,7 @@ mac { embedded:SUBDIRS += kmap2qmap contains(QT_CONFIG, dbus):SUBDIRS += qdbus -!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns +!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns xmlpatternsvalidator embedded: SUBDIRS += makeqpf CONFIG+=ordered diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp index a5c2c41..2405d5d 100644 --- a/tools/xmlpatterns/main.cpp +++ b/tools/xmlpatterns/main.cpp @@ -194,7 +194,7 @@ protected: /* If we don't open stdout in "binary" mode on Windows, it will translate * 0xA into 0xD 0xA. See Trolltech task 173619, for an example. */ _setmode(_fileno(stdout), _O_BINARY); - m_stdout = QT_WA_INLINE(_wfdopen(_fileno(stdout), L"wb"),_fdopen(_fileno(stdout), "wb")); + m_stdout = _wfdopen(_fileno(stdout), L"wb"); out->open(m_stdout, QIODevice::WriteOnly); #else out->open(stdout, QIODevice::WriteOnly); diff --git a/tools/xmlpatterns/qcoloringmessagehandler.cpp b/tools/xmlpatterns/qcoloringmessagehandler.cpp index 9616097..0ddb246 100644 --- a/tools/xmlpatterns/qcoloringmessagehandler.cpp +++ b/tools/xmlpatterns/qcoloringmessagehandler.cpp @@ -100,12 +100,18 @@ void ColoringMessageHandler::handleMessage(QtMsgType type, } case QtFatalMsg: { - Q_ASSERT(!sourceLocation.isNull()); const QString errorCode(identifier.fragment()); Q_ASSERT(!errorCode.isEmpty()); QUrl uri(identifier); uri.setFragment(QString()); + QString location; + + if(sourceLocation.isNull()) + location = QXmlPatternistCLI::tr("Unknown location"); + else + location = QString::fromLatin1(sourceLocation.uri().toEncoded()); + QString errorId; /* If it's a standard error code, we don't want to output the * whole URI. */ @@ -117,7 +123,7 @@ void ColoringMessageHandler::handleMessage(QtMsgType type, if(hasLine) { writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2, at line %3, column %4: %5").arg(colorify(errorId, ErrorCode), - colorify(QString::fromLatin1(sourceLocation.uri().toEncoded()), Location), + colorify(location, Location), colorify(QString::number(sourceLocation.line()), Location), colorify(QString::number(sourceLocation.column()), Location), colorifyDescription(description))); @@ -125,7 +131,7 @@ void ColoringMessageHandler::handleMessage(QtMsgType type, else { writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2: %3").arg(colorify(errorId, ErrorCode), - colorify(QString::fromLatin1(sourceLocation.uri().toEncoded()), Location), + colorify(location, Location), colorifyDescription(description))); } break; diff --git a/tools/xmlpatternsvalidator/main.cpp b/tools/xmlpatternsvalidator/main.cpp new file mode 100644 index 0000000..75ea8b4 --- /dev/null +++ b/tools/xmlpatternsvalidator/main.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "main.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QUrl> +#include <QtXmlPatterns/QXmlSchema> +#include <QtXmlPatterns/QXmlSchemaValidator> + +QT_USE_NAMESPACE + +int main(int argc, char **argv) +{ + enum ExitCode + { + Valid = 0, + Invalid, + ParseError + }; + + enum ExecutionMode + { + InvalidMode, + SchemaOnlyMode, + SchemaAndInstanceMode, + InstanceOnlyMode + }; + + const QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName(QLatin1String("xmlpatternsvalidator")); + + if (argc != 2 && argc != 3) { + qDebug() << QXmlPatternistCLI::tr("usage: xmlpatternsvalidator (<schema url> | <instance url> <schema url> | <instance url>)"); + return ParseError; + } + + // parse command line arguments + ExecutionMode mode = InvalidMode; + + if (argc == 2) { + // either it is a schema or instance document + + QString url = QFile::decodeName(argv[1]); + if (url.toLower().endsWith(QLatin1String(".xsd"))) { + mode = SchemaOnlyMode; + } else { + // as we could validate all types of xml documents, don't check the extension here + mode = InstanceOnlyMode; + } + } else if (argc == 3) { + mode = SchemaAndInstanceMode; + } + + // do validation + QXmlSchema schema; + + if (mode == SchemaOnlyMode) { + const QString schemaUri = QFile::decodeName(argv[1]); + + schema.load(QUrl(schemaUri)); + + if (schema.isValid()) + return Valid; + else + return Invalid; + } else if (mode == SchemaAndInstanceMode) { + const QString instanceUri = QFile::decodeName(argv[1]); + const QString schemaUri = QFile::decodeName(argv[2]); + + schema.load(QUrl(schemaUri)); + + if (!schema.isValid()) + return Invalid; + + QXmlSchemaValidator validator(schema); + if (validator.validate(QUrl(instanceUri))) + return Valid; + else + return Invalid; + } else if (mode == InstanceOnlyMode) { + const QString instanceUri = QFile::decodeName(argv[1]); + + QXmlSchemaValidator validator(schema); + if (validator.validate(QUrl(instanceUri))) + return Valid; + else + return Invalid; + } + + Q_ASSERT(false); + + return Invalid; +} diff --git a/tools/xmlpatternsvalidator/main.h b/tools/xmlpatternsvalidator/main.h new file mode 100644 index 0000000..a0eff3b --- /dev/null +++ b/tools/xmlpatternsvalidator/main.h @@ -0,0 +1,76 @@ +/**************************************************************************** + ** + ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: Qt Software Information (qt-info@nokia.com) + ** + ** This file is part of the Patternist project on Trolltech Labs. * ** + ** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef Patternist_main_h +#define Patternist_main_h + +#include <QtCore/QCoreApplication> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlPatternistCLI +{ +public: + Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI) +private: + inline QXmlPatternistCLI(); + Q_DISABLE_COPY(QXmlPatternistCLI) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro new file mode 100644 index 0000000..dd5bd37 --- /dev/null +++ b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +TARGET = xmlpatternsvalidator +DESTDIR = ../../bin +QT -= gui +QT += xmlpatterns + +target.path = $$[QT_INSTALL_BINS] +INSTALLS += target + +# This ensures we get stderr and stdout on Windows. +CONFIG += console + +# This ensures that this is a command-line program on OS X and not a GUI application. +CONFIG -= app_bundle + +SOURCES = main.cpp +HEADERS = main.h + +include(../src/common.pri) |