From 67990d3f84ac55bb5cdd10c079bb90f0f9769039 Mon Sep 17 00:00:00 2001
From: EndrII <EndrIIMail@gmail.com>
Date: Thu, 23 Aug 2018 21:28:47 +0300
Subject: [PATCH 1/2] first commit

---
 CQtDeployer/deploy.cpp | 94 ++++++++++++++++++++++++++++++++++++------
 CQtDeployer/deploy.h   |  4 ++
 CQtDeployer/main.cpp   | 14 +++++--
 3 files changed, 96 insertions(+), 16 deletions(-)

diff --git a/CQtDeployer/deploy.cpp b/CQtDeployer/deploy.cpp
index 15a1fe9..79732ba 100644
--- a/CQtDeployer/deploy.cpp
+++ b/CQtDeployer/deploy.cpp
@@ -12,6 +12,10 @@
 #include <QFile>
 #include <quasarapp.h>
 #include <QProcess>
+#include <QDirIterator>
+#include <QJsonObject>
+#include <QJsonDocument>
+#include <QJsonArray>
 
 
 bool Deploy::getDeployQml() const {
@@ -37,6 +41,15 @@ QString Deploy::getQmake() const {
 
 void Deploy::setQmake(const QString &value) {
     qmake = value;
+
+    QFileInfo info(qmake);
+    QDir dir = info.absoluteDir();
+
+    if (!dir.cdUp() || !dir.cd("qml")) {
+        qWarning() << "get qml fail!";
+    }
+
+    qmlDir = dir.absolutePath();
 }
 
 QString Deploy::getTarget() const {
@@ -376,16 +389,64 @@ bool Deploy::copyFolder( QDir &from,  QDir &to, const QString& filter,
     return true;
 }
 
-bool Deploy::extractQml() {
-    auto qmlDir = QuasarAppUtils::getStrArg("qmlDir");
+QStringList Deploy::findFilesInsideDir(const QString &name,
+                                          const QString &dirpath) {
+    QStringList files;
 
-    if (!QFileInfo::exists(qmlDir)){
-        qWarning() << "qml dir wrong!";
-        return false;
+    QDir dir(dirpath);
+    dir.setNameFilters(QStringList(name));
+
+    QDirIterator it(dir, QDirIterator::Subdirectories);
+    while (it.hasNext()) files << it.next();
+
+    return files;
+}
+
+QStringList Deploy::extractImportsFromFiles(const QStringList &filepath){
+    QProcess p;
+    p.setProgram(qmlScaner);
+    p.setArguments(QStringList () << "-qmlFiles" << filepath
+                   << "-importPath" << qmlDir);
+    p.start();
+
+    qInfo() << "run extract qml";
+
+    if (!p.waitForFinished()) {
+        qWarning() << filepath << " not scaning!";
+        return QStringList();
     }
 
-    QDir dir(qmlDir);
+    auto data = QJsonDocument::fromJson(p.readAll());
 
+    if (!data.isArray()) {
+        qWarning() << "wrong data from qml scaner! of " << filepath;
+    }
+
+    auto array =  data.array();
+
+    QStringList result;
+
+    for (auto object : array) {
+        result << object.toObject().value("path").toString();
+    }
+
+    return result;
+}
+
+QStringList Deploy::extractImportsFromDir(const QString &dirpath) {
+    auto files = findFilesInsideDir("*.qml", dirpath);
+
+    QStringList result;
+    for (auto file: files) {
+        result.append(extractImportsFromFile(file));
+    }
+
+    return result;
+}
+
+bool Deploy::extractQml() {
+
+    qInfo() << "run extract qml";
     QDir dirTo(targetDir);
 
     if (!dirTo.cd("qml")) {
@@ -398,17 +459,24 @@ bool Deploy::extractQml() {
         }
     }
 
+    auto plugins = extractImportsFromDir(qmlDir);
 
-    QStringList listItems;
 
-    if (!copyFolder(dir, dirTo, ".so.debug", &listItems)) {
-        return false;
+    for (auto plugin : plugins) {
+
+        QDir dir(plugin);
+        QStringList listItems;
+
+        if (!copyFolder(dir, dirTo, ".so.debug", &listItems)) {
+            return false;
+        }
+
+        for (auto item : listItems) {
+            extract(item, false);
+        }
+
     }
 
-//    for (auto item : listItems) {
-//        extract(item, false);
-//    }
-
     return true;
 
 }
diff --git a/CQtDeployer/deploy.h b/CQtDeployer/deploy.h
index 3f42d6d..3e89e61 100644
--- a/CQtDeployer/deploy.h
+++ b/CQtDeployer/deploy.h
@@ -20,6 +20,7 @@ private:
     QString qtDir = "";
     QString target = "";
     QString targetDir = "";
+    QString qmlDir = "";
 
     QStringList QtLibs;
     QStringList noQTLibs;
@@ -43,6 +44,9 @@ private:
 
     void strip(const QString &dir);
 
+    QStringList extractImportsFromDir(const QString &dirpath);
+    QStringList findFilesInsideDir(const QString &name, const QString &dirpath);
+    QStringList extractImportsFromFiles(const QStringList &filepath);
 public:
     Deploy();
     bool getDeployQml() const;
diff --git a/CQtDeployer/main.cpp b/CQtDeployer/main.cpp
index 0b2e15a..d3807c4 100644
--- a/CQtDeployer/main.cpp
+++ b/CQtDeployer/main.cpp
@@ -21,7 +21,7 @@ void help() {
     qInfo() << "   help / h                 : show help.";
     qInfo() << "   always-overwrite         : Copy files even if the target file exists.";
     qInfo() << "   -bin    [params]         : deployment binry.";
-    qInfo() << "   -qmlDir [params]         : qml datadir. for example -qmlDir ~/Qt/5.11.1/gcc_64/qml";
+    qInfo() << "   -qmlDir [params]         : qml datadir of project. for example -qmlDir ~/my/project/qml";
     qInfo() << "   noStrip                  : no strip deployed lib";
     qInfo() << "   deploy-not-qt            : deploy all libs";
     qInfo() << "   -qmake  [params]         : qmake path. for example";
@@ -32,6 +32,9 @@ void help() {
     qInfo() << "   clear                    : delete all old deploy data";
     qInfo() << "   -runScript [params]      : set new name of out file (AppRun.sh by default)";
     qInfo() << "                            | for example -runScript myApp.sh";
+    qInfo() << "   allQmlDependes           : This flag will force to extract all qml libraries.";
+    qInfo() << "                            | (not recommended, as it takes up a lot of memory)";
+
 
 
     qInfo() << "";
@@ -47,6 +50,7 @@ bool parseQt(Deploy& deploy) {
     }
     basePath = info.absolutePath();
     deploy.setQmake(qmake);
+    auto scaner = basePath + QDir::separator() + "qmlimportscanner";
 
     auto bin = QuasarAppUtils::getStrArg("bin");
 
@@ -69,7 +73,12 @@ bool parseQt(Deploy& deploy) {
 
     QDir dir(basePath);
 
-    if (QFileInfo::exists(qmlDir)) {
+    if (QFileInfo::exists(qmlDir) && QFileInfo::exists(scaner)) {
+
+        deploy.setDeployQml(true);
+        deploy.setQmlScaner(scaner);
+
+    } else if (QuasarAppUtils::isEndable("allQmlDependes")) {
         deploy.setDeployQml(true);
     } else {
         qCritical () << "wrong qml dir!";
@@ -83,7 +92,6 @@ bool parseQt(Deploy& deploy) {
 
     return true;
 }
-
 int main(int argc, char *argv[])
 {
 

From 00762badab0940622abba99da58a8477522951ff Mon Sep 17 00:00:00 2001
From: EndrII <endriimail@gmail.com>
Date: Fri, 24 Aug 2018 16:18:37 +0300
Subject: [PATCH 2/2] fix qml deploy

---
 CQtDeployer/deploy.cpp | 126 ++++++++++++++++++++++++++++++++++-------
 CQtDeployer/deploy.h   |   4 ++
 CQtDeployer/main.cpp   |   7 ++-
 3 files changed, 116 insertions(+), 21 deletions(-)

diff --git a/CQtDeployer/deploy.cpp b/CQtDeployer/deploy.cpp
index 79732ba..541dd50 100644
--- a/CQtDeployer/deploy.cpp
+++ b/CQtDeployer/deploy.cpp
@@ -56,9 +56,7 @@ QString Deploy::getTarget() const {
     return target;
 }
 
-bool Deploy::setTarget(const QString &value) {
-    target = value;
-    targetDir = QFileInfo(target).absolutePath();
+bool Deploy::initDirs() {
 
     if (!QFileInfo::exists(targetDir + QDir::separator() + "lib") &&
             !QDir(targetDir).mkdir("lib")) {
@@ -74,6 +72,18 @@ bool Deploy::setTarget(const QString &value) {
     return true;
 }
 
+bool Deploy::setTarget(const QString &value) {
+    target = value;
+
+    if (target.isEmpty()) {
+        return false;
+    }
+
+    targetDir = QFileInfo(target).absolutePath();
+
+    return true;
+}
+
 bool Deploy::createRunScript() {
 
     QString content =
@@ -402,6 +412,16 @@ QStringList Deploy::findFilesInsideDir(const QString &name,
     return files;
 }
 
+QString Deploy::filterQmlPath(const QString& path) {
+    if (path.contains(qmlDir)) {
+        auto endIndex = path.indexOf(QDir::separator(), qmlDir.size() + 1);
+        QString module = path.mid(qmlDir.size() + 1, endIndex - qmlDir.size() - 1);
+        return qmlDir + QDir::separator() + module;
+    }
+
+    return "";
+}
+
 QStringList Deploy::extractImportsFromFiles(const QStringList &filepath){
     QProcess p;
     p.setProgram(qmlScaner);
@@ -427,7 +447,16 @@ QStringList Deploy::extractImportsFromFiles(const QStringList &filepath){
     QStringList result;
 
     for (auto object : array) {
-        result << object.toObject().value("path").toString();
+
+        auto module = filterQmlPath(object.toObject().value("path").toString());
+
+        if (module.isEmpty()) {
+            continue;
+        }
+
+        if (!result.contains(module)) {
+            result << module;
+        }
     }
 
     return result;
@@ -437,15 +466,47 @@ QStringList Deploy::extractImportsFromDir(const QString &dirpath) {
     auto files = findFilesInsideDir("*.qml", dirpath);
 
     QStringList result;
-    for (auto file: files) {
-        result.append(extractImportsFromFile(file));
-    }
+    result.append(extractImportsFromFiles(files));
 
     return result;
 }
 
-bool Deploy::extractQml() {
+bool Deploy::extractQmlAll() {
 
+    if (!QFileInfo::exists(qmlDir)){
+        qWarning() << "qml dir wrong!";
+        return false;
+    }
+
+    QDir dir(qmlDir);
+
+    QDir dirTo(targetDir);
+
+    if (!dirTo.cd("qml")) {
+        if (!dirTo.mkdir("qml")) {
+            return false;
+        }
+
+        if (!dirTo.cd("qml")) {
+            return false;
+        }
+    }
+
+
+    QStringList listItems;
+
+    if (!copyFolder(dir, dirTo, ".so.debug", &listItems)) {
+        return false;
+    }
+
+    for (auto item : listItems) {
+        extract(item, false);
+    }
+
+return true;
+}
+
+bool Deploy::extractQmlFromSource(const QString sourceDir) {
     qInfo() << "run extract qml";
     QDir dirTo(targetDir);
 
@@ -459,29 +520,54 @@ bool Deploy::extractQml() {
         }
     }
 
-    auto plugins = extractImportsFromDir(qmlDir);
+   QStringList plugins = extractImportsFromDir(sourceDir);
 
+   for (auto plugin : plugins) {
 
-    for (auto plugin : plugins) {
+       QDir dir(plugin);
+       QStringList listItems;
 
-        QDir dir(plugin);
-        QStringList listItems;
+       if (!dirTo.cd(dir.dirName())) {
+           if (!dirTo.mkdir(dir.dirName())) {
+               return false;
+           }
 
-        if (!copyFolder(dir, dirTo, ".so.debug", &listItems)) {
-            return false;
-        }
+           if (!dirTo.cd(dir.dirName())) {
+               return false;
+           }
+       }
 
-        for (auto item : listItems) {
-            extract(item, false);
-        }
+       if (!copyFolder(dir, dirTo, ".so.debug", &listItems)) {
+           return false;
+       }
 
+       dirTo.cdUp();
+
+       for (auto item : listItems) {
+           extract(item, false);
+       }
+
+   }
+
+   return true;
+}
+
+bool Deploy::extractQml() {
+
+    if (QuasarAppUtils::isEndable("qmlDir")) {
+        return  extractQmlFromSource(QuasarAppUtils::getStrArg("qmlDir"));
+
+    } else if (QuasarAppUtils::isEndable("allQmlDependes")){
+        return  extractQmlAll();
+
+    } else {
+        return false;
     }
 
-    return true;
-
 }
 
 void Deploy::clear() {
+
     QDir dir(targetDir);
 
     if (dir.cd("lib")) {
diff --git a/CQtDeployer/deploy.h b/CQtDeployer/deploy.h
index 3e89e61..ae45dd9 100644
--- a/CQtDeployer/deploy.h
+++ b/CQtDeployer/deploy.h
@@ -47,6 +47,9 @@ private:
     QStringList extractImportsFromDir(const QString &dirpath);
     QStringList findFilesInsideDir(const QString &name, const QString &dirpath);
     QStringList extractImportsFromFiles(const QStringList &filepath);
+    bool extractQmlAll();
+    bool extractQmlFromSource(const QString sourceDir);
+    QString filterQmlPath(const QString &path);
 public:
     Deploy();
     bool getDeployQml() const;
@@ -65,6 +68,7 @@ public:
 
     void clear();
 
+    bool initDirs();
 };
 
 #endif // DEPLOY_H
diff --git a/CQtDeployer/main.cpp b/CQtDeployer/main.cpp
index d3807c4..5acb32e 100644
--- a/CQtDeployer/main.cpp
+++ b/CQtDeployer/main.cpp
@@ -59,12 +59,17 @@ bool parseQt(Deploy& deploy) {
         return false;
     }
 
+    if (!deploy.setTarget(bin)) {
+        qCritical() << "error init targeet dir";
+        return false;
+    }
+
     if (QuasarAppUtils::isEndable("clear")) {
         qInfo() << "clear old data";
         deploy.clear();
     }
 
-    if (!deploy.setTarget(bin)) {
+    if (!deploy.initDirs()) {
         qCritical() << "error init targeet dir";
         return false;
     }