qdoc: better copying of .css files
authorMartin Smith <martin.smith@digia.com>
Fri, 16 Nov 2012 10:38:32 +0000 (11:38 +0100)
committerJerome Pasion <jerome.pasion@digia.com>
Fri, 16 Nov 2012 10:43:05 +0000 (11:43 +0100)
This change ignores templatedir for css files.
It assumes that the paths in the stylesheets
variable are relative to the qdocconf file that
contains the stylesheets variable.

Task-number: QTBUG-27878
Change-Id: I2155e58f352e17d710c93ad4e92679beb169d823
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
src/tools/qdoc/config.cpp
src/tools/qdoc/config.h
src/tools/qdoc/ditaxmlgenerator.cpp
src/tools/qdoc/ditaxmlgenerator.h
src/tools/qdoc/generator.cpp
src/tools/qdoc/main.cpp

index 89d4f1a..a378d19 100644 (file)
@@ -156,6 +156,7 @@ QString Config::installDir;
 QSet<QString> Config::overrideOutputFormats;
 QMap<QString, QString> Config::extractedDirs;
 int Config::numInstances;
+QStack<QString> Config::workingDirs_;
 
 /*!
   \class Config
@@ -173,10 +174,10 @@ Config::Config(const QString& programName)
     : prog(programName)
 {
     loc = Location::null;
-    lastLoc = Location::null;
+    lastLocation_ = Location::null;
     locMap.clear();
-    stringValueMap.clear();
-    stringListValueMap.clear();
+    stringPairMap.clear();
+    stringListPairMap.clear();
     numInstances++;
 }
 
@@ -205,7 +206,7 @@ void Config::load(const QString& fileName)
     else {
         loc.setEtc(true);
     }
-    lastLoc = Location::null;
+    lastLocation_ = Location::null;
 }
 
 /*!
@@ -214,9 +215,9 @@ void Config::load(const QString& fileName)
  */
 void Config::unload(const QString& fileName)
 {
-    QStringMultiMap::ConstIterator v = stringValueMap.constBegin();
-    while (v != stringValueMap.constEnd()) {
-        qDebug() << v.key() << " = " << v.value();
+    QStringPairMap::ConstIterator v = stringPairMap.constBegin();
+    while (v != stringPairMap.constEnd()) {
+        qDebug() << v.key() << " = " << v.value().second;
         ++v;
     }
     qDebug() << "fileName:" << fileName;
@@ -231,8 +232,10 @@ void Config::unload(const QString& fileName)
  */
 void Config::setStringList(const QString& var, const QStringList& values)
 {
-    stringValueMap[var] = values.join(QLatin1Char(' '));
-    stringListValueMap[var] = values;
+    stringPairMap[var].first = QDir::currentPath();
+    stringPairMap[var].second = values.join(QLatin1Char(' '));
+    stringListPairMap[var].first = QDir::currentPath();
+    stringListPairMap[var].second = values;
 }
 
 /*!
@@ -292,16 +295,37 @@ QSet<QString> Config::getOutputFormats() const
 /*!
   First, this function looks up the configuration variable \a var
   in the location map and, if found, sets the internal variable
-  \c{lastLoc} to the Location that \a var maps to.
+  \c{lastLocation_} to the Location that \a var maps to.
 
   Then it looks up the configuration variable \a var in the string
-  map, and returns the string that \a var maps to.
+  map and returns the string that \a var maps to.
  */
 QString Config::getString(const QString& var) const
 {
     if (!locMap[var].isEmpty())
-        (Location&) lastLoc = locMap[var];
-    return stringValueMap[var];
+        (Location&) lastLocation_ = locMap[var];
+    return stringPairMap[var].second;
+}
+
+/*!
+  This function looks up the variable \a var in the location map
+  and, if found, sets the internal variable \c{lastLocation_} to the
+  location that \a var maps to.
+
+  Then it looks up \a var in the configuration variable map and,
+  if found, constructs a path from the pair value, which consists
+  of the directory path of the configuration file where the value
+  came from, and the value itself. The constructed path is returned.
+ */
+QString Config::getPath(const QString& var) const
+{
+    if (!locMap[var].isEmpty())
+        (Location&) lastLocation_ = locMap[var];
+    QString path;
+    if (stringPairMap.contains(var)) {
+        path = QDir(stringPairMap[var].first + "/" + stringPairMap[var].second).absolutePath();
+    }
+    return path;
 }
 
 /*!
@@ -317,7 +341,7 @@ QSet<QString> Config::getStringSet(const QString& var) const
 /*!
   First, this function looks up the configuration variable \a var
   in the location map and, if found, sets the internal variable
-  \c{lastLoc} to the Location that \a var maps to.
+  \c{lastLocation_} to the Location that \a var maps to.
 
   Then it looks up the configuration variable \a var in the string
   list map, and returns the string list that \a var maps to.
@@ -325,8 +349,8 @@ QSet<QString> Config::getStringSet(const QString& var) const
 QStringList Config::getStringList(const QString& var) const
 {
     if (!locMap[var].isEmpty())
-        (Location&) lastLoc = locMap[var];
-    return stringListValueMap[var];
+        (Location&) lastLocation_ = locMap[var];
+    return stringListPairMap[var].second;
 }
 
 
@@ -339,11 +363,11 @@ QStringList Config::getStringList(const QString& var) const
 QStringList Config::getCanonicalRelativePathList(const QString& var) const
 {
     if (!locMap[var].isEmpty())
-        (Location&) lastLoc = locMap[var];
+        (Location&) lastLocation_ = locMap[var];
     QStringList t;
-    QMap<QString,QStringList>::const_iterator it = stringListValueMap.constFind(var);
-    if (it != stringListValueMap.constEnd()) {
-        const QStringList& sl = it.value();
+    QStringListPairMap::const_iterator it = stringListPairMap.constFind(var);
+    if (it != stringListPairMap.constEnd()) {
+        const QStringList& sl = it.value().second;
         if (!sl.isEmpty()) {
             t.reserve(sl.size());
             for (int i=0; i<sl.size(); ++i) {
@@ -363,7 +387,7 @@ QStringList Config::getCanonicalRelativePathList(const QString& var) const
 
   First, this function looks up the configuration variable \a var
   in the location map and, if found, sets the internal variable
-  \c{lastLoc} the Location that \a var maps to.
+  \c{lastLocation_} the Location that \a var maps to.
 
   Then it looks up the configuration variable \a var in the string
   list map, which maps to a string list that contains file paths.
@@ -373,11 +397,11 @@ QStringList Config::getCanonicalRelativePathList(const QString& var) const
 QStringList Config::getCleanPathList(const QString& var) const
 {
     if (!locMap[var].isEmpty())
-        (Location&) lastLoc = locMap[var];
+        (Location&) lastLocation_ = locMap[var];
     QStringList t;
-    QMap<QString,QStringList>::const_iterator it = stringListValueMap.constFind(var);
-    if (it != stringListValueMap.constEnd()) {
-        const QStringList& sl = it.value();
+    QStringListPairMap::const_iterator it = stringListPairMap.constFind(var);
+    if (it != stringListPairMap.constEnd()) {
+        const QStringList& sl = it.value().second;
         if (!sl.isEmpty()) {
             t.reserve(sl.size());
             for (int i=0; i<sl.size(); ++i) {
@@ -389,6 +413,47 @@ QStringList Config::getCleanPathList(const QString& var) const
 }
 
 /*!
+  This function should only be called when the configuration
+  variable \a var maps to a string list that contains file paths.
+  It cleans the paths with QDir::cleanPath() before returning
+  them.
+
+  First, this function looks up the configuration variable \a var
+  in the location map and, if found, sets the internal variable
+  \c{lastLocation_} the Location that \a var maps to.
+
+  Then it looks up the configuration variable \a var in the string
+  list map, which maps to a string list that contains file paths.
+  These paths might not be clean, so QDir::cleanPath() is called
+  for each one. The string list returned contains cleaned paths.
+ */
+QStringList Config::getPathList(const QString& var) const
+{
+    if (!locMap[var].isEmpty())
+        (Location&) lastLocation_ = locMap[var];
+    QStringList t;
+    QStringListPairMap::const_iterator it = stringListPairMap.constFind(var);
+    if (it != stringListPairMap.constEnd()) {
+        const QStringList& sl = it.value().second;
+        const QString d = it.value().first;
+        if (!sl.isEmpty()) {
+            t.reserve(sl.size());
+            for (int i=0; i<sl.size(); ++i) {
+                QFileInfo fileInfo;
+                QString path = d + "/" + QDir::cleanPath(sl[i]);
+                fileInfo.setFile(path);
+                if (!fileInfo.exists())
+                    lastLocation_.warning(tr("File '%1' does not exist").arg(path));
+                else
+                    t.append(path);
+            }
+        }
+    }
+    return t;
+}
+
+
+/*!
   Calls getRegExpList() with the control variable \a var and
   iterates through the resulting list of regular expressions,
   concatening them with some extras characters to form a single
@@ -443,8 +508,8 @@ QSet<QString> Config::subVars(const QString& var) const
 {
     QSet<QString> result;
     QString varDot = var + QLatin1Char('.');
-    QStringMultiMap::ConstIterator v = stringValueMap.constBegin();
-    while (v != stringValueMap.constEnd()) {
+    QStringPairMap::ConstIterator v = stringPairMap.constBegin();
+    while (v != stringPairMap.constEnd()) {
         if (v.key().startsWith(varDot)) {
             QString subVar = v.key().mid(varDot.length());
             int dot = subVar.indexOf(QLatin1Char('.'));
@@ -462,11 +527,11 @@ QSet<QString> Config::subVars(const QString& var) const
   with the matching keys (stripped of the prefix \a var and
   mapped to their values. The pairs are inserted into \a t
  */
-void Config::subVarsAndValues(const QString& var, QStringMultiMap& t) const
+void Config::subVarsAndValues(const QString& var, QStringPairMap& t) const
 {
     QString varDot = var + QLatin1Char('.');
-    QStringMultiMap::ConstIterator v = stringValueMap.constBegin();
-    while (v != stringValueMap.constEnd()) {
+    QStringPairMap::ConstIterator v = stringPairMap.constBegin();
+    while (v != stringPairMap.constEnd()) {
         if (v.key().startsWith(varDot)) {
             QString subVar = v.key().mid(varDot.length());
             int dot = subVar.indexOf(QLatin1Char('.'));
@@ -550,10 +615,10 @@ QString Config::findFile(const Location& location,
                          const QString& fileName,
                          QString& userFriendlyFilePath)
 {
-    if (debug)
-        qDebug() << "FILES:" << files
-                 << "DIRS:" << dirs
-                 << "FILENAME:" << fileName;
+    if (debug) {
+        qDebug() << "FINDFILE DIRS:" << dirs;
+        qDebug() << "FINDFILE FILENAME:" << fileName;
+    }
     if (fileName.isEmpty() || fileName.startsWith(QLatin1Char('/'))) {
         userFriendlyFilePath = fileName;
         return fileName;
@@ -637,10 +702,10 @@ QString Config::findFile(const Location& location,
 
 /*!
   Copies the \a sourceFilePath to the file name constructed by
-  concatenating \a targetDirPath and \a userFriendlySourceFilePath.
-  \a location is for identifying the file and line number where
-  a qdoc error occurred. The constructed output file name is
-  returned.
+  concatenating \a targetDirPath and the file name from the
+  \a userFriendlySourceFilePath. \a location is for identifying
+  the file and line number where a qdoc error occurred. The
+  constructed output file name is returned.
  */
 QString Config::copyFile(const Location& location,
                          const QString& sourceFilePath,
@@ -649,8 +714,8 @@ QString Config::copyFile(const Location& location,
 {
     QFile inFile(sourceFilePath);
     if (!inFile.open(QFile::ReadOnly)) {
-        location.fatal(tr("Cannot open input file '%1': %2")
-                       .arg(sourceFilePath).arg(inFile.errorString()));
+        location.warning(tr("Cannot open input file for copy: '%1': %2")
+                         .arg(sourceFilePath).arg(inFile.errorString()));
         return QString();
     }
 
@@ -658,11 +723,14 @@ QString Config::copyFile(const Location& location,
     int slash = outFileName.lastIndexOf(QLatin1Char('/'));
     if (slash != -1)
         outFileName = outFileName.mid(slash);
-
-    QFile outFile(targetDirPath + QLatin1Char('/') + outFileName);
+    if ((outFileName.size()) > 0 && (outFileName[0] != '/'))
+        outFileName = targetDirPath + QLatin1Char('/') + outFileName;
+    else
+        outFileName = targetDirPath + outFileName;
+    QFile outFile(outFileName);
     if (!outFile.open(QFile::WriteOnly)) {
-        location.fatal(tr("Cannot open output file '%1': %2")
-                       .arg(outFile.fileName()).arg(outFile.errorString()));
+        location.warning(tr("Cannot open output file for copy: '%1': %2")
+                         .arg(outFileName).arg(outFile.errorString()));
         return QString();
     }
 
@@ -745,6 +813,8 @@ bool Config::isMetaKeyChar(QChar ch)
  */
 void Config::load(Location location, const QString& fileName)
 {
+    pushWorkingDir(QFileInfo(fileName).path());
+    QDir::setCurrent(QFileInfo(fileName).path());
     QRegExp keySyntax(QLatin1String("\\w+(?:\\.\\w+)*"));
 
 #define SKIP_CHAR() \
@@ -967,29 +1037,34 @@ void Config::load(Location location, const QString& fileName)
                         else {
                             locMap[*key].setEtc(true);
                         }
-                        if (stringValueMap[*key].isEmpty()) {
-                            stringValueMap[*key] = stringValue;
+                        if (stringPairMap[*key].second.isEmpty()) {
+                            stringPairMap[*key].first = QDir::currentPath();
+                            stringPairMap[*key].second = stringValue;
                         }
                         else {
-                            stringValueMap[*key] +=
-                                    QLatin1Char(' ') + stringValue;
+                            stringPairMap[*key].second += QLatin1Char(' ') + stringValue;
                         }
-                        stringListValueMap[*key] += stringListValue;
+                        stringListPairMap[*key].first = QDir::currentPath();
+                        stringListPairMap[*key].second += stringListValue;
                     }
                     else {
                         locMap[*key] = keyLoc;
-                        stringValueMap[*key] = stringValue;
-                        stringListValueMap[*key] = stringListValue;
+                        stringPairMap[*key].first = QDir::currentPath();
+                        stringPairMap[*key].second = stringValue;
+                        stringListPairMap[*key].first = QDir::currentPath();
+                        stringListPairMap[*key].second = stringListValue;
                     }
                     ++key;
                 }
             }
         }
         else {
-            location.fatal(tr("Unexpected character '%1' at beginning of line")
-                           .arg(c));
+            location.fatal(tr("Unexpected character '%1' at beginning of line").arg(c));
         }
     }
+    popWorkingDir();
+    if (!workingDirs_.isEmpty())
+        QDir::setCurrent(QFileInfo(workingDirs_.top()).path());
 }
 
 QStringList Config::getFilesHere(const QString& uncleanDir,
@@ -1035,4 +1110,25 @@ QStringList Config::getFilesHere(const QString& uncleanDir,
     return result;
 }
 
+/*!
+  Push \a dir onto the stack of working directories.
+ */
+void Config::pushWorkingDir(const QString& dir)
+{
+    workingDirs_.push(dir);
+}
+
+/*!
+  If the stack of working directories is not empty, pop the
+  top entry and return it. Otherwise return an empty string.
+ */
+QString Config::popWorkingDir()
+{
+    if (!workingDirs_.isEmpty()) {
+        return workingDirs_.pop();
+    }
+    qDebug() << "RETURNED EMPTY WORKING DIR";
+    return QString();
+}
+
 QT_END_NAMESPACE
index eca632a..c89bb8f 100644 (file)
 #include <qmap.h>
 #include <qset.h>
 #include <qstringlist.h>
-
+#include <qstack.h>
+#include <qpair.h>
 #include "location.h"
 
 QT_BEGIN_NAMESPACE
 
-typedef QMultiMap<QString, QString> QStringMultiMap;
+/*
+  In QStringPair, the first string is the path to a directory;
+  the second string is some value.
+ */
+typedef QPair<QString, QString> QStringPair;
+
+/*
+  In QStringListPair, the first string is the path to a directory;
+  the string list is a list of string values.
+ */
+typedef QPair<QString, QStringList> QStringListPair;
+typedef QMultiMap<QString, QStringPair> QStringPairMultiMap;
+typedef QMap<QString, QStringPair> QStringPairMap;
+typedef QMap<QString, QStringListPair> QStringListPairMap;
 
 class Config
 {
@@ -68,20 +82,22 @@ public:
 
     const QString& programName() const { return prog; }
     const Location& location() const { return loc; }
-    const Location& lastLocation() const { return lastLoc; }
+    const Location& lastLocation() const { return lastLocation_; }
     bool getBool(const QString& var) const;
     int getInt(const QString& var) const;
     QString getOutputDir() const;
     QSet<QString> getOutputFormats() const;
     QString getString(const QString& var) const;
+    QString getPath(const QString& var) const;
     QSet<QString> getStringSet(const QString& var) const;
     QStringList getStringList(const QString& var) const;
     QStringList getCanonicalRelativePathList(const QString& var) const;
     QStringList getCleanPathList(const QString& var) const;
+    QStringList getPathList(const QString& var) const;
     QRegExp getRegExp(const QString& var) const;
     QList<QRegExp> getRegExpList(const QString& var) const;
     QSet<QString> subVars(const QString& var) const;
-    void subVarsAndValues(const QString& var, QStringMultiMap& t) const;
+    void subVarsAndValues(const QString& var, QStringPairMap& t) const;
     QStringList getAllFiles(const QString& filesVar,
                             const QString& dirsVar,
                             const QSet<QString> &excludedDirs = QSet<QString>(),
@@ -111,6 +127,8 @@ public:
                             const QString& targetDirPath);
     static int numParams(const QString& value);
     static bool removeDirContents(const QString& dir);
+    static void pushWorkingDir(const QString& dir);
+    static QString popWorkingDir();
 
     QT_STATIC_CONST QString dot;
 
@@ -126,14 +144,18 @@ private:
 
     QString prog;
     Location loc;
-    Location lastLoc;
+    Location lastLocation_;
     QMap<QString, Location> locMap;
-    QMap<QString, QStringList> stringListValueMap;
     QMap<QString, QString> stringValueMap;
+    QMap<QString, QStringList> stringListValueMap;
+
+    QStringPairMap      stringPairMap;
+    QStringListPairMap  stringListPairMap;
 
     static QMap<QString, QString> uncompressedFiles;
     static QMap<QString, QString> extractedDirs;
     static int numInstances;
+    static QStack<QString> workingDirs_;
 };
 
 #define CONFIG_ALIAS                    "alias"
index 1ffbcf9..3b7a4d0 100644 (file)
@@ -5884,7 +5884,7 @@ QStringList DitaXmlGenerator::getMetadataElements(const InnerNode* inner,
  */
 QString DitaXmlGenerator::metadataDefault(DitaTag t) const
 {
-    return metadataDefaults.value(ditaTags[t]);
+    return metadataDefaults.value(ditaTags[t]).second;
 }
 
 /*!
index 7e1f5a0..3f87fae 100644 (file)
@@ -513,7 +513,7 @@ private:
     static QString ditaTags[];
     QStack<QXmlStreamWriter*> xmlWriterStack;
     QStack<DitaTag> tagStack;
-    QStringMultiMap metadataDefaults;
+    QStringPairMap metadataDefaults;
     QVector<NodeMultiMap*> nodeTypeMaps;
     QVector<NodeMultiMap*> nodeSubtypeMaps;
     QVector<NodeMultiMap*> pageTypeMaps;
index b728aa3..9529823 100644 (file)
@@ -697,12 +697,14 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
                         if (!best.isEmpty() && !documentedItems.contains(best))
                             details = tr("Maybe you meant '%1'?").arg(best);
 
-                        node->doc().location().warning(tr("No such enum item '%1' in %2").arg(*a).arg(node->plainFullName()), details);
+                        node->doc().location().warning(tr("No such enum item '%1' in %2")
+                                                       .arg(*a).arg(node->plainFullName()), details);
                         if (*a == "Void")
                             qDebug() << "VOID:" << node->name() << definedItems;
                     }
                     else if (!documentedItems.contains(*a)) {
-                        node->doc().location().warning(tr("Undocumented enum item '%1' in %2").arg(*a).arg(node->plainFullName()));
+                        node->doc().location().warning(tr("Undocumented enum item '%1' in %2")
+                                                       .arg(*a).arg(node->plainFullName()));
                     }
                     ++a;
                 }
@@ -1526,7 +1528,8 @@ void Generator::initialize(const Config &config)
         if (outputFormats.contains((*g)->format())) {
             currentGenerator_ = (*g);
             (*g)->initializeGenerator(config);
-            QStringList extraImages = config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
+            QStringList extraImages =
+                config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
             QStringList::ConstIterator e = extraImages.constBegin();
             while (e != extraImages.constEnd()) {
                 QString userFriendlyFilePath;
@@ -1540,15 +1543,15 @@ void Generator::initialize(const Config &config)
                     Config::copyFile(config.lastLocation(),
                                      filePath,
                                      userFriendlyFilePath,
-                                     (*g)->outputDir() +
-                                     "/images");
+                                     (*g)->outputDir() + "/images");
                 ++e;
             }
 
             // Documentation template handling
             QStringList searchDirs;
-            QString templateDir = config.getString((*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
-            qDebug() << "TEMPLATEDIR:" << templateDir << (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR;
+            QString templateDir = config.getPath((*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
+            qDebug() << "TEMPLATEDIR:" << templateDir
+                     << (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR;
             if (templateDir.isEmpty())
                 templateDir = ".";
             searchDirs.append(templateDir);
@@ -1567,35 +1570,24 @@ void Generator::initialize(const Config &config)
                     Config::copyFile(config.lastLocation(),
                                      filePath,
                                      userFriendlyFilePath,
-                                     (*g)->outputDir() +
-                                     "/scripts");
+                                     (*g)->outputDir() + "/scripts");
                 ++e;
             }
 
-            QStringList styles = config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
+            //QStringList styles = config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
+            QStringList styles = config.getPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
             qDebug() << "STYLES:" << styles;
-            qDebug() << "SEARCHDIRS:" << searchDirs;
-            qDebug() << "STYLEFILES:" << styleFiles;
-            Config::debug = true;
             e = styles.constBegin();
             while (e != styles.constEnd()) {
-                QString userFriendlyFilePath;
-                QString filePath = Config::findFile(config.lastLocation(),
-                                                    styleFiles,
-                                                    searchDirs,
-                                                    *e,
-                                                    noExts,
-                                                    userFriendlyFilePath);
+                QString filePath = *e;
                 qDebug() << "FILEPATH:" << filePath;
                 if (!filePath.isEmpty())
                     Config::copyFile(config.lastLocation(),
                                      filePath,
-                                     userFriendlyFilePath,
-                                     (*g)->outputDir() +
-                                     "/style");
+                                     filePath,
+                                     (*g)->outputDir() + "/style");
                 ++e;
             }
-            Config::debug = false;
         }
         ++g;
     }
index fda9bf1..064617e 100644 (file)
@@ -281,6 +281,7 @@ static void processQdocconfFile(const QString &fileName)
       in the file being processed, mainly for error reporting
       purposes.
      */
+    currentDir = QFileInfo(fileName).path();
     Location::initialize(config);
     config.load(fileName);