From b5646d35da9edccee83730aa17242825250cd844 Mon Sep 17 00:00:00 2001
From: Kai Koehne <kai.koehne@nokia.com>
Date: Wed, 17 Feb 2010 11:20:35 +0100
Subject: [PATCH] Don't show error message if file added to qmlproject is
 picked up

Check for the case that a new file to be added to a .qmlproject
is also automatically covered e.g. by a wildcard filter. In this
case we don't have to do anything.
---
 .../fileformat/filefilteritems.cpp            | 47 +++++++++++++++++--
 .../fileformat/filefilteritems.h              |  2 +
 .../fileformat/qmlprojectitem.cpp             | 20 ++++++++
 .../fileformat/qmlprojectitem.h               |  1 +
 src/plugins/qmlprojectmanager/qmlproject.cpp  | 10 ++++
 src/plugins/qmlprojectmanager/qmlproject.h    |  2 +
 .../qmlprojectmanager/qmlprojectnodes.cpp     |  4 +-
 .../fileformat/tst_fileformat.cpp             | 36 ++++++++++++++
 8 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
index e12afdc700c..a1f4ff9e285 100644
--- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
@@ -89,6 +89,47 @@ QStringList FileFilterBaseItem::files() const
     return m_files.toList();
 }
 
+/**
+  Check whether filter matches a file path - regardless whether the file already exists or not.
+
+  @param filePath: absolute file path
+  */
+bool FileFilterBaseItem::matchesFile(const QString &filePath) const
+{
+    foreach (const QString &explicitFile, m_explicitFiles) {
+        if (absolutePath(explicitFile) == filePath)
+            return true;
+    }
+
+    bool regexMatches = false;
+    const QString &fileName = QFileInfo(filePath).fileName();
+    foreach (const QRegExp &exp, m_regExpList) {
+        if (exp.exactMatch(fileName)) {
+            regexMatches = true;
+            break;
+        }
+    }
+
+    if (!regexMatches)
+        return false;
+
+    const QStringList watchedDirectories = m_fsWatcher.directories();
+    const QDir fileDir = QFileInfo(filePath).absoluteDir();
+    foreach (const QString &watchedDirectory, watchedDirectories) {
+        if (QDir(watchedDirectory) == fileDir)
+            return true;
+    }
+
+    return false;
+}
+
+QString FileFilterBaseItem::absolutePath(const QString &path) const
+{
+    if (QFileInfo(path).isAbsolute())
+        return path;
+    return QDir(absoluteDir()).absoluteFilePath(path);
+}
+
 QString FileFilterBaseItem::absoluteDir() const
 {
     QString absoluteDir;
@@ -110,11 +151,7 @@ void FileFilterBaseItem::updateFileList()
     QSet<QString> dirsToBeWatched;
     QSet<QString> newFiles;
     foreach (const QString &explicitPath, m_explicitFiles) {
-        if (QFileInfo(explicitPath).isAbsolute()) {
-            newFiles << explicitPath;
-        } else {
-            newFiles << QDir(projectDir).absoluteFilePath(explicitPath);
-        }
+        newFiles << absolutePath(explicitPath);
     }
     if (!m_regExpList.isEmpty() && m_explicitFiles.isEmpty())
         newFiles += filesInSubTree(QDir(m_defaultDir), QDir(projectDir), &dirsToBeWatched);
diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
index 8c302408929..575fd89e12d 100644
--- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
+++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h
@@ -38,6 +38,7 @@ public:
     void setPathsProperty(const QString &path);
 
     virtual QStringList files() const;
+    bool matchesFile(const QString &filePath) const;
 
 signals:
     void directoryChanged();
@@ -50,6 +51,7 @@ private slots:
     void updateFileList();
 
 private:
+    QString absolutePath(const QString &path) const;
     QString absoluteDir() const;
 
     QSet<QString> filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs = 0);
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
index 6f0e1dcee80..3da27455a44 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
@@ -115,6 +115,26 @@ QStringList QmlProjectItem::files() const
     return files;
 }
 
+/**
+  Check whether the project would include a file path
+  - regardless whether the file already exists or not.
+
+  @param filePath: absolute file path to check
+  */
+bool QmlProjectItem::matchesFile(const QString &filePath) const
+{
+    const Q_D(QmlProjectItem);
+    for (int i = 0; i < d->content.size(); ++i) {
+        QmlProjectContentItem *contentElement = d->content.at(i);
+        FileFilterBaseItem *fileFilter = qobject_cast<FileFilterBaseItem*>(contentElement);
+        if (fileFilter) {
+            if (fileFilter->matchesFile(filePath))
+                return true;
+        }
+    }
+    return false;
+}
+
 } // namespace QmlProjectManager
 
 QML_DEFINE_NOCREATE_TYPE(QmlProjectManager::QmlProjectContentItem)
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
index 31ad175d05a..99e2c5c31ab 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
@@ -40,6 +40,7 @@ public:
     void setLibraryPaths(const QStringList &paths);
 
     QStringList files() const;
+    bool matchesFile(const QString &filePath) const;
 
 signals:
     void qmlFilesChanged();
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index c0cb71294cc..87ff6de3575 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -242,6 +242,16 @@ QStringList QmlProject::libraryPaths() const
     return libraryPaths;
 }
 
+bool QmlProject::addFiles(const QStringList &filePaths)
+{
+    QStringList toAdd;
+    foreach (const QString &filePath, filePaths) {
+        if (!m_projectItem.data()->matchesFile(filePath))
+            toAdd << filePaths;
+    }
+    return toAdd.isEmpty();
+}
+
 void QmlProject::refreshProjectFile()
 {
     refresh(QmlProject::ProjectFile | Files);
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index fc194cb41f2..994d75acb4e 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -99,6 +99,8 @@ public:
     QStringList files() const;
     QStringList libraryPaths() const;
 
+    bool addFiles(const QStringList &filePaths);
+
 private slots:
     void refreshProjectFile();
     void refreshFiles();
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
index 63b4f813ade..dd52333dd7d 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
@@ -183,9 +183,9 @@ bool QmlProjectNode::removeSubProjects(const QStringList &proFilePaths)
 }
 
 bool QmlProjectNode::addFiles(const ProjectExplorer::FileType /*fileType*/,
-                              const QStringList & /*filePaths*/, QStringList * /*notAdded*/)
+                              const QStringList &filePaths, QStringList * /*notAdded*/)
 {
-    return false;
+    return m_project->addFiles(filePaths);
 }
 
 bool QmlProjectNode::removeFiles(const ProjectExplorer::FileType /*fileType*/,
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
index a12de28f1b3..d32b731078a 100644
--- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
@@ -15,6 +15,7 @@ public:
 
 private slots:
     void testFileFilter();
+    void testMatchesFile();
     void testLibraryPaths();
 };
 
@@ -205,6 +206,41 @@ void TestProject::testFileFilter()
     }
 }
 
+void TestProject::testMatchesFile()
+{
+    //
+    // search for qml files in local directory
+    //
+    QString projectFile = QLatin1String(
+            "import QmlProject 1.0\n"
+            "Project {\n"
+            "  QmlFiles {"
+            "    recursive: true"
+            "  }"
+            "  JavaScriptFiles {"
+            "    paths: [\"script.js\"]"
+            "  }"
+            "}\n");
+
+    QmlEngine engine;
+    QmlComponent component(&engine);
+    component.setData(projectFile.toUtf8(), QUrl());
+    if (!component.isReady())
+        qDebug() << component.errorsString();
+    QVERIFY(component.isReady());
+
+    QmlProjectItem *project = qobject_cast<QmlProjectItem*>(component.create());
+    QVERIFY(project);
+
+    project->setSourceDirectory(testDataDir);
+
+    QVERIFY(project->matchesFile(testDataDir + "/file1.qml"));
+    QVERIFY(project->matchesFile(testDataDir + "/notyetexistingfile.qml"));
+    QVERIFY(project->matchesFile(testDataDir + "/subdir/notyetexistingfile.qml"));
+    QVERIFY(project->matchesFile(testDataDir + "/script.js"));
+    QVERIFY(!project->matchesFile(testDataDir + "/script.css"));
+}
+
 void TestProject::testLibraryPaths()
 {
     //
-- 
GitLab