diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 0c31052bfd00974d4608f4e8d54f99d8b59ba57a..daa047c50e61914dc16ab5c35b093d67f7930570 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -59,6 +59,16 @@ QStringList Bind::includedScripts() const
     return _includedScripts;
 }
 
+QStringList Bind::fileImports() const
+{
+    return _fileImports;
+}
+
+QStringList Bind::libraryImports() const
+{
+    return _libraryImports;
+}
+
 Interpreter::ObjectValue *Bind::currentObjectValue() const
 {
     return _currentObjectValue;
@@ -205,8 +215,14 @@ bool Bind::visit(AST::Program *)
     return true;
 }
 
-bool Bind::visit(UiImport *)
+bool Bind::visit(UiImport *ast)
 {
+    if (ast->importUri) {
+        _libraryImports += toString(ast->importUri, QLatin1Char('/'));
+    } else if (ast->fileName) {
+        _fileImports += ast->fileName->asString();
+    }
+
     return false;
 }
 
diff --git a/src/libs/qmljs/qmljsbind.h b/src/libs/qmljs/qmljsbind.h
index e9f5fef931f9857c287dee83d1f4ac88ff81910f..82ed248ce53729aa14cea86012ebb3bea41e6082 100644
--- a/src/libs/qmljs/qmljsbind.h
+++ b/src/libs/qmljs/qmljsbind.h
@@ -51,6 +51,8 @@ public:
     virtual ~Bind();
 
     QStringList includedScripts() const;
+    QStringList fileImports() const;
+    QStringList libraryImports() const;
 
     Interpreter::ObjectValue *currentObjectValue() const;
     Interpreter::ObjectValue *idEnvironment() const;
@@ -100,6 +102,9 @@ private:
 
     QHash<AST::Node *, Interpreter::ObjectValue *> _qmlObjects;
     QStringList _includedScripts;
+
+    QStringList _fileImports;
+    QStringList _libraryImports;
 };
 
 } // end of namespace Qml
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.cpp b/src/plugins/qmljseditor/qmljsmodelmanager.cpp
index d21bda3660fbfccc9a6e8c02a8a7b95ca4fecb5b..3bd87c0659f624bc4831a0a05d1740064a0e5314 100644
--- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljseditor/qmljsmodelmanager.cpp
@@ -36,11 +36,11 @@
 #include <coreplugin/progressmanager/progressmanager.h>
 #include <coreplugin/mimedatabase.h>
 #include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsbind.h>
 #include <qmljs/parser/qmldirparser_p.h>
 #include <texteditor/itexteditor.h>
 
 #include <QDir>
-#include <QDirIterator>
 #include <QFile>
 #include <QFileInfo>
 #include <QLibraryInfo>
@@ -74,7 +74,6 @@ ModelManager::ModelManager(QObject *parent):
 
     m_defaultImportPaths << environmentImportPaths();
     m_defaultImportPaths << QLibraryInfo::location(QLibraryInfo::ImportsPath);
-    refreshSourceDirectories(m_defaultImportPaths);
 }
 
 void ModelManager::loadQmlTypeDescriptions()
@@ -100,19 +99,7 @@ Snapshot ModelManager::snapshot() const
 
 void ModelManager::updateSourceFiles(const QStringList &files)
 {
-    // for files that are not yet in the snapshot, scan the whole directory
-    QStringList filesToParse;
-    QSet<QString> sourceDirectories;
-
-    foreach (const QString &file, files) {
-        if (! _snapshot.document(file))
-            sourceDirectories.insert(QFileInfo(file).path());
-        else
-            filesToParse.append(file);
-    }
-
-    refreshSourceFiles(filesToParse);
-    refreshSourceDirectories(sourceDirectories.toList());
+    refreshSourceFiles(files);
 }
 
 QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles)
@@ -148,42 +135,6 @@ QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles)
     return result;
 }
 
-void ModelManager::updateSourceDirectories(const QStringList &directories)
-{
-    refreshSourceDirectories(directories);
-}
-
-QFuture<void> ModelManager::refreshSourceDirectories(const QStringList &sourceDirectories)
-{
-    if (sourceDirectories.isEmpty()) {
-        return QFuture<void>();
-    }
-
-    const QMap<QString, WorkingCopy> workingCopy = buildWorkingCopyList();
-
-    QFuture<void> result = QtConcurrent::run(&ModelManager::parseDirectories,
-                                              workingCopy, sourceDirectories,
-                                              this);
-
-    if (m_synchronizer.futures().size() > 10) {
-        QList<QFuture<void> > futures = m_synchronizer.futures();
-
-        m_synchronizer.clearFutures();
-
-        foreach (QFuture<void> future, futures) {
-            if (! (future.isFinished() || future.isCanceled()))
-                m_synchronizer.addFuture(future);
-        }
-    }
-
-    m_synchronizer.addFuture(result);
-
-    m_core->progressManager()->addTask(result, tr("Indexing"),
-                                       QmlJSEditor::Constants::TASK_INDEX);
-
-    return result;
-}
-
 QMap<QString, ModelManager::WorkingCopy> ModelManager::buildWorkingCopyList()
 {
     QMap<QString, WorkingCopy> workingCopy;
@@ -223,6 +174,106 @@ void ModelManager::onLibraryInfoUpdated(const QString &path, const LibraryInfo &
     _snapshot.insertLibraryInfo(path, info);
 }
 
+static QStringList qmlFilesInDirectory(const QString &path)
+{
+    // ### It would suffice to build pattern once. This function needs to be thread-safe.
+    Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
+    Core::MimeType jsSourceTy = db->findByType(QmlJSEditor::Constants::JS_MIMETYPE);
+    Core::MimeType qmlSourceTy = db->findByType(QmlJSEditor::Constants::QML_MIMETYPE);
+
+    QStringList pattern;
+    foreach (const QRegExp &glob, jsSourceTy.globPatterns())
+        pattern << glob.pattern();
+    foreach (const QRegExp &glob, qmlSourceTy.globPatterns())
+        pattern << glob.pattern();
+
+    QStringList files;
+
+    const QDir dir(path);
+    foreach (const QFileInfo &fi, dir.entryInfoList(pattern, QDir::Files))
+        files += fi.absoluteFilePath();
+
+    return files;
+}
+
+static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &snapshot,
+                            QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+    // scan files that could be implicitly imported
+    // it's important we also do this for JS files, otherwise the isEmpty check will fail
+    if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
+        if (! scannedPaths->contains(doc->path())) {
+            *importedFiles += qmlFilesInDirectory(doc->path());
+            scannedPaths->insert(doc->path());
+        }
+    }
+}
+
+static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapshot,
+                        QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+    // scan files and directories that are explicitly imported
+    foreach (const QString &fileImport, doc->bind()->fileImports()) {
+        const QFileInfo importFileInfo(doc->path() + QLatin1Char('/') + fileImport);
+        const QString &importFilePath = importFileInfo.absoluteFilePath();
+        if (importFileInfo.isFile()) {
+            if (! snapshot.document(importFilePath))
+                *importedFiles += importFilePath;
+        } else if (importFileInfo.isDir()) {
+            if (snapshot.documentsInDirectory(importFilePath).isEmpty()) {
+                if (! scannedPaths->contains(importFilePath)) {
+                    *importedFiles += qmlFilesInDirectory(importFilePath);
+                    scannedPaths->insert(importFilePath);
+                }
+            }
+        }
+    }
+}
+
+static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
+                           ModelManager *modelManager,
+                           QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+    // scan library imports
+    foreach (const QString &libraryImport, doc->bind()->libraryImports()) {
+        foreach (const QString &importPath, modelManager->importPaths()) {
+            QDir dir(importPath);
+            dir.cd(libraryImport);
+            const QString targetPath = dir.absolutePath();
+
+            // if we know there is a library, done
+            if (snapshot.libraryInfo(targetPath).isValid())
+                break;
+
+            // if there is a qmldir file, we found a new library!
+            if (dir.exists("qmldir")) {
+                QFile qmldirFile(dir.filePath("qmldir"));
+                qmldirFile.open(QFile::ReadOnly);
+                QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
+
+                QmlDirParser qmldirParser;
+                qmldirParser.setSource(qmldirData);
+                qmldirParser.parse();
+
+                modelManager->emitLibraryInfoUpdated(QFileInfo(qmldirFile).absolutePath(),
+                                                     LibraryInfo(qmldirParser));
+
+                // scan the qml files in the library
+                foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
+                    if (! component.fileName.isEmpty()) {
+                        QFileInfo componentFileInfo(dir.filePath(component.fileName));
+                        const QString path = componentFileInfo.absolutePath();
+                        if (! scannedPaths->contains(path)) {
+                            *importedFiles += qmlFilesInDirectory(path);
+                            scannedPaths->insert(path);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
 void ModelManager::parse(QFutureInterface<void> &future,
                             QMap<QString, WorkingCopy> workingCopy,
                             QStringList files,
@@ -232,10 +283,16 @@ void ModelManager::parse(QFutureInterface<void> &future,
     Core::MimeType jsSourceTy = db->findByType(QLatin1String("application/javascript"));
     Core::MimeType qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
 
-    future.setProgressRange(0, files.size());
+    int progressRange = files.size();
+    future.setProgressRange(0, progressRange);
+
+    Snapshot snapshot = modelManager->_snapshot;
+
+    // paths we have scanned for files and added to the files list
+    QSet<QString> scannedPaths;
 
     for (int i = 0; i < files.size(); ++i) {
-        future.setProgressValue(i);
+        future.setProgressValue(qreal(i) / files.size() * progressRange);
 
         const QString fileName = files.at(i);
 
@@ -270,62 +327,24 @@ void ModelManager::parse(QFutureInterface<void> &future,
         Document::Ptr doc = Document::create(fileName);
         doc->setDocumentRevision(documentRevision);
         doc->setSource(contents);
-
-        if (isQmlFile)
-            doc->parseQml();
-        else
-            doc->parseJavaScript();
-
-        modelManager->emitDocumentUpdated(doc);
-    }
-
-    future.setProgressValue(files.size());
-}
-
-void ModelManager::parseDirectories(QFutureInterface<void> &future,
-                                    QMap<QString, WorkingCopy> workingCopy,
-                                    QStringList directories,
-                                    ModelManager *modelManager)
-{
-    Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
-    Core::MimeType jsSourceTy = db->findByType(QLatin1String("application/javascript"));
-    Core::MimeType qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
-
-    QStringList pattern;
-    foreach (const QRegExp &glob, jsSourceTy.globPatterns())
-        pattern << glob.pattern();
-    foreach (const QRegExp &glob, qmlSourceTy.globPatterns())
-        pattern << glob.pattern();
-    pattern << QLatin1String("qmldir");
-
-    QStringList importedFiles;
-    QStringList qmldirFiles;
-    foreach (const QString &path, directories) {
-        QDirIterator fileIterator(path, pattern, QDir::Files,
-                                  QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
-        while (fileIterator.hasNext()) {
-            fileIterator.next();
-            if (fileIterator.fileName() == QLatin1String("qmldir"))
-                qmldirFiles << fileIterator.filePath();
-            else
-                importedFiles << fileIterator.filePath();
+        doc->parse();
+
+        // get list of referenced files not yet in snapshot or in directories already scanned
+        QStringList importedFiles;
+        findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
+        findNewFileImports(doc, snapshot, &importedFiles, &scannedPaths);
+        findNewLibraryImports(doc, snapshot, modelManager, &importedFiles, &scannedPaths);
+
+        // add new files to parse list
+        foreach (const QString &file, importedFiles) {
+            if (! files.contains(file))
+                files.append(file);
         }
-    }
 
-    foreach (const QString &qmldirFilePath, qmldirFiles) {
-        QFile qmldirFile(qmldirFilePath);
-        qmldirFile.open(QFile::ReadOnly);
-        QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
-
-        QmlDirParser qmldirParser;
-        qmldirParser.setSource(qmldirData);
-        qmldirParser.parse();
-
-        modelManager->emitLibraryInfoUpdated(QFileInfo(qmldirFilePath).path(),
-                                             LibraryInfo(qmldirParser));
+        modelManager->emitDocumentUpdated(doc);
     }
 
-    parse(future, workingCopy, importedFiles, modelManager);
+    future.setProgressValue(progressRange);
 }
 
 // Check whether fileMimeType is the same or extends knownMimeType
@@ -352,7 +371,14 @@ void ModelManager::setProjectImportPaths(const QStringList &importPaths)
 {
     m_projectImportPaths = importPaths;
 
-    refreshSourceDirectories(importPaths);
+    // check if any file in the snapshot imports something new in the new paths
+    Snapshot snapshot = _snapshot;
+    QStringList importedFiles;
+    QSet<QString> scannedPaths;
+    foreach (const Document::Ptr &doc, snapshot)
+        findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths);
+
+    updateSourceFiles(importedFiles);
 }
 
 QStringList ModelManager::importPaths() const
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.h b/src/plugins/qmljseditor/qmljsmodelmanager.h
index 8ca17240196f19a9e86a89062fc9ca938f738bd7..d83d6547c2c3b2f299b5febf531483c27d623171 100644
--- a/src/plugins/qmljseditor/qmljsmodelmanager.h
+++ b/src/plugins/qmljseditor/qmljsmodelmanager.h
@@ -55,7 +55,6 @@ public:
 
     virtual QmlJS::Snapshot snapshot() const;
     virtual void updateSourceFiles(const QStringList &files);
-    virtual void updateSourceDirectories(const QStringList &directories);
 
     void emitDocumentUpdated(QmlJS::Document::Ptr doc);
     void emitLibraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
@@ -82,7 +81,6 @@ protected:
     };
 
     QFuture<void> refreshSourceFiles(const QStringList &sourceFiles);
-    QFuture<void> refreshSourceDirectories(const QStringList &sourceDirectories);
     QMap<QString, WorkingCopy> buildWorkingCopyList();
 
     static void parse(QFutureInterface<void> &future,
@@ -90,11 +88,6 @@ protected:
                       QStringList files,
                       ModelManager *modelManager);
 
-    static void parseDirectories(QFutureInterface<void> &future,
-                                 QMap<QString, WorkingCopy> workingCopy,
-                                 QStringList directories,
-                                 ModelManager *modelManager);
-
     void loadQmlTypeDescriptions();
 
 private:
diff --git a/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h b/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h
index e1a3ab18910afb0195a951e874d81a066d481652..280828c0e753b869b965b67df4ae126b42cc2838 100644
--- a/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h
+++ b/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h
@@ -54,7 +54,6 @@ public:
 
     virtual QmlJS::Snapshot snapshot() const = 0;
     virtual void updateSourceFiles(const QStringList &files) = 0;
-    virtual void updateSourceDirectories(const QStringList &directories) = 0;
 
     virtual void setProjectImportPaths(const QStringList &importPaths) = 0;
     virtual QStringList importPaths() const = 0;
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index f0f562330abcea9edeed3ccafa9b012f1913a39b..1b495017ce8f9ddc4759c74996a7e1d923f62992 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -106,7 +106,7 @@ void QmlProject::parseProject(RefreshOptions options)
         }
         if (m_projectItem) {
             m_projectItem.data()->setSourceDirectory(projectDir().path());
-            m_modelManager->updateSourceDirectories(m_projectItem.data()->files());
+            m_modelManager->updateSourceFiles(m_projectItem.data()->files());
         }
         m_rootNode->refresh();
     }