mirror of
https://github.com/QuasarApp/CQtDeployer.git
synced 2025-04-28 02:34:34 +00:00
Merge branch 'qmlScaner' into v1.2
This commit is contained in:
commit
39c7a173b7
@ -14,7 +14,7 @@
|
||||
#include <QList>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
QCoreApplication::setOrganizationName("QuasarApp");
|
||||
QCoreApplication::setOrganizationDomain("https://github.com/QuasarApp");
|
||||
|
@ -47,7 +47,8 @@ SOURCES += \
|
||||
igetlibinfo.cpp \
|
||||
dependenciesscanner.cpp \
|
||||
../qtTools/src/shared/winutils/elfreader.cpp \
|
||||
elf.cpp
|
||||
elf.cpp \
|
||||
qml.cpp
|
||||
|
||||
HEADERS += \
|
||||
deploy.h \
|
||||
@ -57,4 +58,5 @@ HEADERS += \
|
||||
igetlibinfo.h \
|
||||
dependenciesscanner.h \
|
||||
../qtTools/src/shared/winutils/elfreader.h \
|
||||
elf.h
|
||||
elf.h \
|
||||
qml.h
|
||||
|
@ -56,18 +56,18 @@ QMultiMap<libPriority, LibInfo> DependenciesScanner::getLibsFromEnvirement(
|
||||
|
||||
bool DependenciesScanner::fillLibInfo(LibInfo &info, const QString &file) {
|
||||
|
||||
info.clear();
|
||||
auto scaner = getScaner(file);
|
||||
info.clear();
|
||||
auto scaner = getScaner(file);
|
||||
|
||||
switch (scaner) {
|
||||
case PrivateScaner::PE: {
|
||||
return _peScaner.getLibInfo(file, info);
|
||||
}
|
||||
case PrivateScaner::ELF:
|
||||
return _elfScaner.getLibInfo(file, info);
|
||||
switch (scaner) {
|
||||
case PrivateScaner::PE: {
|
||||
return _peScaner.getLibInfo(file, info);
|
||||
}
|
||||
case PrivateScaner::ELF:
|
||||
return _elfScaner.getLibInfo(file, info);
|
||||
|
||||
default: return false;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DependenciesScanner::setEnvironment(const QStringList &env) {
|
||||
@ -81,9 +81,10 @@ void DependenciesScanner::setEnvironment(const QStringList &env) {
|
||||
|
||||
auto list = dir.entryInfoList(QStringList() << "*.dll" << ".DLL"
|
||||
<< "*.SO*" << "*.so*",
|
||||
QDir::Files| QDir::NoDotAndDotDot);
|
||||
QDir::Files| QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto i : list) {
|
||||
|
||||
_EnvLibs.insertMulti(i.fileName(), i.absoluteFilePath());
|
||||
}
|
||||
|
||||
@ -103,14 +104,22 @@ QStringList DependenciesScanner::scan(const QString &path) {
|
||||
for (auto i : info.dependncies) {
|
||||
|
||||
auto libs = getLibsFromEnvirement(i);
|
||||
while (libs.size()) {
|
||||
auto lib = libs.take(libs.lastKey());
|
||||
if (lib.platform == info.platform) {
|
||||
result.push_back(lib.fullPath());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!libs.size()) {
|
||||
QuasarAppUtils::Params::verboseLog("lib for dependese " + i + " not findet!!",
|
||||
QuasarAppUtils::Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto lib = libs.begin();
|
||||
|
||||
while (lib != libs.end() &&
|
||||
lib.value().platform != info.platform) lib++;
|
||||
|
||||
if (lib != libs.end())
|
||||
result.push_back(lib->fullPath());
|
||||
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -24,12 +24,12 @@ bool Deploy::getDeployQml() const { return deployQml; }
|
||||
|
||||
void Deploy::setDeployQml(bool value) { deployQml = value; }
|
||||
|
||||
QString Deploy::getQmlScaner() const { return qmlScaner; }
|
||||
QString Deploy::getQmlScaner() const { return externQmlScaner; }
|
||||
|
||||
void Deploy::setQmlScaner(const QString &value) {
|
||||
qmlScaner = QDir::fromNativeSeparators(value);
|
||||
QuasarAppUtils::Params::verboseLog("qmlScaner = " + qmlScaner);
|
||||
deployQml = QFileInfo(qmlScaner).isFile();
|
||||
externQmlScaner = QDir::fromNativeSeparators(value);
|
||||
QuasarAppUtils::Params::verboseLog("qmlScaner = " + externQmlScaner);
|
||||
deployQml = QFileInfo(externQmlScaner).isFile();
|
||||
}
|
||||
|
||||
QString Deploy::getQmake() const { return qmake; }
|
||||
@ -42,6 +42,7 @@ void Deploy::setQmake(const QString &value) {
|
||||
|
||||
if (!dir.cdUp() || !dir.cd("qml")) {
|
||||
QuasarAppUtils::Params::verboseLog("get qml fail!");
|
||||
return;
|
||||
}
|
||||
|
||||
qmlDir = dir.absolutePath();
|
||||
@ -50,6 +51,7 @@ void Deploy::setQmake(const QString &value) {
|
||||
dir = (info.absoluteDir());
|
||||
if (!dir.cdUp() || !dir.cd("translations")) {
|
||||
QuasarAppUtils::Params::verboseLog("get translations fail!");
|
||||
return;
|
||||
}
|
||||
|
||||
translationDir = dir.absolutePath();
|
||||
@ -220,6 +222,8 @@ void Deploy::createQConf() {
|
||||
void Deploy::deploy() {
|
||||
qInfo() << "target deploy started!!";
|
||||
|
||||
initEnvirement();
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("ignore")) {
|
||||
auto list = QuasarAppUtils::Params::getStrArg("ignore").split(',');
|
||||
ignoreList.append(list);
|
||||
@ -235,18 +239,15 @@ void Deploy::deploy() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!onlyCLibs)
|
||||
copyPlugins(neededPlugins);
|
||||
copyPlugins(neededPlugins);
|
||||
|
||||
if (!onlyCLibs && deployQml && !extractQml()) {
|
||||
if (deployQml && !extractQml()) {
|
||||
qCritical() << "qml not extacted!";
|
||||
}
|
||||
|
||||
if (!onlyCLibs) {
|
||||
copyFiles(QtLibs);
|
||||
}
|
||||
copyFiles(QtLibs);
|
||||
|
||||
if (onlyCLibs || QuasarAppUtils::Params::isEndable("deploy-not-qt")) {
|
||||
if (QuasarAppUtils::Params::isEndable("deploy-not-qt")) {
|
||||
copyFiles(noQTLibs);
|
||||
}
|
||||
|
||||
@ -254,7 +255,7 @@ void Deploy::deploy() {
|
||||
QuasarAppUtils::Params::verboseLog("strip failed!");
|
||||
}
|
||||
|
||||
if (!onlyCLibs && !QuasarAppUtils::Params::isEndable("noTranslations")) {
|
||||
if (!QuasarAppUtils::Params::isEndable("noTranslations")) {
|
||||
if (!copyTranslations(DeployUtils::extractTranslation(QtLibs))) {
|
||||
qWarning() << " copy TR ERROR";
|
||||
}
|
||||
@ -279,8 +280,6 @@ void Deploy::setQtDir(const QString &value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void Deploy::setOnlyCLibs(bool value) { onlyCLibs = value; }
|
||||
|
||||
void Deploy::setExtraPath(const QStringList &value) {
|
||||
QDir dir;
|
||||
|
||||
@ -323,7 +322,7 @@ bool Deploy::fileActionPrivate(const QString &file, const QString &target,
|
||||
bool copy = !masks;
|
||||
if (masks) {
|
||||
for (auto mask : *masks) {
|
||||
if (info.absolutePath().contains(mask)) {
|
||||
if (info.absoluteFilePath().contains(mask)) {
|
||||
copy = true;
|
||||
break;
|
||||
}
|
||||
@ -654,7 +653,7 @@ void Deploy::extractLib(const QString &file, bool isExtractPlugins) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((onlyCLibs || QuasarAppUtils::Params::isEndable("deploy-not-qt")) &&
|
||||
if ((QuasarAppUtils::Params::isEndable("deploy-not-qt")) &&
|
||||
!noQTLibs.contains(line)) {
|
||||
noQTLibs << line;
|
||||
extractLib(line, isExtractPlugins);
|
||||
@ -765,7 +764,7 @@ QStringList Deploy::extractImportsFromDir(const QString &filepath) {
|
||||
env.insert("QT_QPA_PLATFORM_PLUGIN_PATH", DeployUtils::qtDir + "/plugins/platforms");
|
||||
|
||||
p.setProcessEnvironment(env);
|
||||
p.setProgram(qmlScaner);
|
||||
p.setProgram(externQmlScaner);
|
||||
p.setArguments(QStringList()
|
||||
<< "-rootPath" << filepath << "-importPath" << qmlDir);
|
||||
p.start();
|
||||
@ -847,16 +846,31 @@ bool Deploy::extractQmlFromSource(const QString& sourceDir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList plugins = extractImportsFromDir(info.absoluteFilePath());
|
||||
QStringList plugins;
|
||||
QStringList listItems;
|
||||
QStringList filter;
|
||||
|
||||
for (auto &&i: plugins) {
|
||||
QuasarAppUtils::Params::verboseLog(i);
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("qmlExtern")) {
|
||||
|
||||
qInfo() << "use extern qml scaner!";
|
||||
|
||||
plugins = extractImportsFromDir(info.absoluteFilePath());
|
||||
filter << ".so.debug" << "d.dll";
|
||||
|
||||
} else {
|
||||
qInfo() << "use own qml scaner!";
|
||||
|
||||
QML ownQmlScaner(qmlDir);
|
||||
|
||||
if (!ownQmlScaner.scan(plugins, info.absoluteFilePath())) {
|
||||
QuasarAppUtils::Params::verboseLog("qml scaner run failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!copyFolder(qmlDir, targetDir + "/qml",
|
||||
QStringList() << ".so.debug" << "d.dll",
|
||||
&listItems, &plugins)) {
|
||||
filter , &listItems, &plugins)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -949,11 +963,36 @@ void Deploy::initEnvirement() {
|
||||
addEnv(env.value("LD_LIBRARY_PATH"));
|
||||
addEnv(env.value("PATH"));
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("deploy-not-qt")) {
|
||||
QStringList dirs;
|
||||
dirs.append(getDirsRecursive("/lib"));
|
||||
dirs.append(getDirsRecursive("/usr/lib"));
|
||||
|
||||
for (auto &&i : dirs) {
|
||||
addEnv(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (deployEnvironment.size() < 2) {
|
||||
qWarning() << "system environment is empty";
|
||||
}
|
||||
}
|
||||
|
||||
QStringList Deploy::getDirsRecursive(const QString &path) {
|
||||
QDir dir(path);
|
||||
|
||||
QStringList res;
|
||||
|
||||
auto list = dir.entryInfoList(QDir::Dirs| QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto &&subDir: list) {
|
||||
res.push_back(subDir.absoluteFilePath());
|
||||
res.append(getDirsRecursive(subDir.absoluteFilePath()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Deploy::Deploy() {
|
||||
#ifdef Q_OS_LINUX
|
||||
|
@ -13,16 +13,17 @@
|
||||
#include <QStringList>
|
||||
#include <dependenciesscanner.h>
|
||||
#include "deploy_global.h"
|
||||
#include "qml.h"
|
||||
|
||||
class DEPLOYSHARED_EXPORT Deploy {
|
||||
private:
|
||||
bool deployQml = false;
|
||||
bool onlyCLibs = false;
|
||||
int depchLimit = 0;
|
||||
QStringList deployedFiles;
|
||||
|
||||
QSettings settings;
|
||||
QString qmlScaner = "";
|
||||
QString externQmlScaner = "";
|
||||
|
||||
QString qmake = "";
|
||||
/**
|
||||
* @brief targets
|
||||
@ -101,6 +102,7 @@ class DEPLOYSHARED_EXPORT Deploy {
|
||||
public:
|
||||
Deploy();
|
||||
void initEnvirement();
|
||||
QStringList getDirsRecursive(const QString& path);
|
||||
|
||||
bool getDeployQml() const;
|
||||
void setDeployQml(bool value);
|
||||
@ -121,7 +123,6 @@ public:
|
||||
void setQtDir(const QString &value);
|
||||
|
||||
void clear();
|
||||
void setOnlyCLibs(bool value);
|
||||
void setExtraPath(const QStringList &value);
|
||||
void setExtraPlugins(const QStringList &value);
|
||||
void setDepchLimit(int value);
|
||||
|
@ -162,6 +162,8 @@ void DeployUtils::help() {
|
||||
qInfo() << " -targetDir [params] : set target Dir for binaryes (default is path of first target)";
|
||||
qInfo() << " noStrip : skip strip step";
|
||||
qInfo() << " noTranslations : skip translations files";
|
||||
qInfo() << " qmlExtern : use qml external scanner (qmlimportscaner)";
|
||||
qInfo() << " | not work without qmake and in snap package";
|
||||
|
||||
qInfo() << " verbose : show debug log";
|
||||
|
||||
@ -196,8 +198,6 @@ bool DeployUtils::parseQt(Deploy *deploy) {
|
||||
deploy->clear();
|
||||
}
|
||||
|
||||
deploy->initEnvirement();
|
||||
|
||||
int limit = 0;
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("recursiveDepth")) {
|
||||
@ -224,7 +224,7 @@ bool DeployUtils::parseQt(Deploy *deploy) {
|
||||
|
||||
if (!info.isFile() || (info.baseName() != "qmake")) {
|
||||
qInfo() << "deploy only C libs because qmake is not found";
|
||||
deploy->setOnlyCLibs(true);
|
||||
QuasarAppUtils::Params::setEnable("deploy-not-qt", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
156
Deploy/qml.cpp
Normal file
156
Deploy/qml.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "qml.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <quasarapp.h>
|
||||
|
||||
QStringList QML::extractImportsFromFile(const QString &filepath) {
|
||||
QStringList imports;
|
||||
QFile F(filepath);
|
||||
if (!F.open(QIODevice::ReadOnly)) return QStringList();
|
||||
|
||||
QString content = F.readAll();
|
||||
content.remove(QRegExp("\\{(.*)\\}"));
|
||||
content.remove(QRegExp("/\\*(.*)\\*/"));
|
||||
|
||||
for (const QString &line : content.split("\n"))
|
||||
for (QString &word : line.split(";", QString::SkipEmptyParts))
|
||||
{
|
||||
word = word.simplified();
|
||||
if (word.startsWith("//")) continue;
|
||||
if (!word.startsWith("import")) continue;
|
||||
|
||||
QStringList list = word.split(" ", QString::SkipEmptyParts);
|
||||
if (list.count() != 3)
|
||||
{
|
||||
if (list.count() == 5)
|
||||
{
|
||||
if (list[3] != "as") continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
imports << (list[2][0] + "#" + list[1].replace(".", "/"));
|
||||
}
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
bool QML::extractImportsFromDir(const QString &path, bool recursive) {
|
||||
QDir dir(path);
|
||||
auto infoList = dir.entryInfoList(QStringList() << "*.qml" << "*.QML"
|
||||
,QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
|
||||
for (auto &&info: infoList) {
|
||||
|
||||
if (info.isFile()) {
|
||||
auto imports = extractImportsFromFile(info.absoluteFilePath());
|
||||
for (auto import : imports) {
|
||||
if (!_imports.contains(import)) {
|
||||
_imports.insert(import);
|
||||
extractImportsFromDir(getPathFromImport(import), recursive);
|
||||
}
|
||||
}
|
||||
} else if (recursive) {
|
||||
extractImportsFromDir(info.absoluteFilePath(), recursive);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QML::getPathFromImport(const QString &import) {
|
||||
auto importData = import.split("#");
|
||||
|
||||
int index;
|
||||
|
||||
if (importData.size() == 2)
|
||||
index = 1;
|
||||
else if (!importData.isEmpty()) {
|
||||
index = 0;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
auto words = importData.value(index).split(QRegExp("[/\\\\]"));
|
||||
|
||||
bool isSecond = importData.first() == "2";
|
||||
|
||||
QString path;
|
||||
for (auto i = words.rbegin(); i != words.rend(); ++i) {
|
||||
QString word = *i;
|
||||
if (isSecond && secondVersions.contains(word)) {
|
||||
isSecond = false;
|
||||
word.push_back(".2");
|
||||
}
|
||||
|
||||
path.push_front(word + "/");
|
||||
}
|
||||
|
||||
return QFileInfo(_qmlRoot + "/" + path).absoluteFilePath();
|
||||
}
|
||||
|
||||
bool QML::deployPath(const QString &path, QStringList &res) {
|
||||
QDir dir(path);
|
||||
auto infoList = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
|
||||
for (auto info : infoList) {
|
||||
if (info.fileName().contains(".so.debug") ||
|
||||
info.fileName().contains("d.dll")) {
|
||||
QuasarAppUtils::Params::verboseLog("sciped debug lib " +
|
||||
info.absoluteFilePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
res.push_back(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QML::scanQmlTree(const QString &qmlTree) {
|
||||
QDir dir(qmlTree);
|
||||
|
||||
if (!dir.isReadable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto list = dir.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto &&info : list) {
|
||||
if (info.fileName().contains(".2")) {
|
||||
secondVersions.insert(info.fileName().left(info.fileName().size() - 2));
|
||||
}
|
||||
scanQmlTree(info.absoluteFilePath());
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QML::addImport() {
|
||||
|
||||
}
|
||||
|
||||
QML::QML(const QString &qmlRoot) {
|
||||
_qmlRoot = qmlRoot;
|
||||
|
||||
}
|
||||
|
||||
bool QML::scan(QStringList &res, const QString& _qmlProjectDir) {
|
||||
|
||||
if (!scanQmlTree(_qmlRoot)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!extractImportsFromDir(_qmlProjectDir, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &&import : _imports) {
|
||||
res.push_back(getPathFromImport(import));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
28
Deploy/qml.h
Normal file
28
Deploy/qml.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef QML_H
|
||||
#define QML_H
|
||||
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
class QML
|
||||
{
|
||||
private:
|
||||
QStringList extractImportsFromFile(const QString &filepath);
|
||||
bool extractImportsFromDir(const QString &path, bool recursive = false);
|
||||
QString getPathFromImport(const QString& import);
|
||||
bool deployPath( const QString& path, QStringList& res);
|
||||
bool scanQmlTree(const QString& qmlTree);
|
||||
void addImport();
|
||||
QString _qmlRoot = "";
|
||||
QSet<QString> _imports;
|
||||
QSet<QString> secondVersions;
|
||||
|
||||
public:
|
||||
QML(const QString& qmlRoot);
|
||||
|
||||
bool scan(QStringList &res, const QString &_qmlProjectDir);
|
||||
|
||||
friend class deploytest;
|
||||
};
|
||||
|
||||
#endif // QML_H
|
@ -1 +1 @@
|
||||
Subproject commit 02d3e668851fc24149edd4db8f26946d66a88c8e
|
||||
Subproject commit f16b511e6c9a415ee457dc931d8b2566c263294a
|
24
README.md
24
README.md
@ -38,7 +38,9 @@ Key differences of this program:
|
||||
| -targetDir [params] | set target Dir for binaryes (default is path of first target) |
|
||||
| noStrip | skip strip step |
|
||||
| noTranslations | skip translations files |
|
||||
| verbose | show debug log |
|
||||
| qmlExtern | use qml external scanner (qmlimportscaner) |
|
||||
| | not work without qmake and in snap package |
|
||||
| -verbose [0-3] | show debug log |
|
||||
|
||||
|
||||
|
||||
@ -59,12 +61,6 @@ You can download the latest version of the application [here](https://github.com
|
||||
### Snap
|
||||
[](https://snapcraft.io/cqtdeployer)
|
||||
|
||||
#### Attention!!!
|
||||
This application may not work stably in an isolated container. To solve these problems, use the console installation in the Classic box.
|
||||
```bash
|
||||
snap install cqtdeployer --classic
|
||||
```
|
||||
|
||||
## Donate
|
||||
If you want to help the project, then you can donate a small amount to our bitcoin wallet.
|
||||
|
||||
@ -106,9 +102,11 @@ Console QtDeployer является консольной реализацией
|
||||
| -extraPlugin [list,params] | Установить дополнительный путь для extraPlugin приложения |
|
||||
| -recursiveDepth [params] | Установит глубену поиска библиотек (по умолчанию 0) |
|
||||
| -targetDir [params] | Установит целевой коталог (по умолчанию это путь к первому развертываемому файлу)|
|
||||
| noStrip | пропустить шаг strip |
|
||||
| noTranslations | пропустить файлы переводов |
|
||||
| verbose | Показ дебаг лога |
|
||||
| noStrip | Пропустить шаг strip |
|
||||
| noTranslations | Пропустить файлы переводов |
|
||||
| qmlExtern | Использовать внешний сканер qml (qmlimportscaner) |
|
||||
| | не работает без qmake и в snap |
|
||||
| -verbose [0-3] | Показ дебаг лога |
|
||||
|
||||
|
||||
#### Пример: cqtdeployer -bin myApp -qmlDir ~/MyAppProject/qml -qmake ~/Qt/5.11.1/gcc_64/bin/qmake clear
|
||||
@ -124,12 +122,6 @@ Console QtDeployer является консольной реализацией
|
||||
### Snap
|
||||
[](https://snapcraft.io/cqtdeployer)
|
||||
|
||||
#### Внимание!!!
|
||||
это приложение может работать не стабильно в изолированном контейнере, Для решения этих проблемм используйте становку через консоль в рижеми Classic
|
||||
```bash
|
||||
snap install cqtdeployer --classic
|
||||
```
|
||||
|
||||
|
||||
## Установить
|
||||
Вы можете загрузить последнюю версию приложения [здесь](https://github.com/QuasarApp/Console-QtDeployer/releases).
|
||||
|
@ -20,16 +20,21 @@ include('$$PWD/../Deploy/Deploy.pri')
|
||||
include('$$PWD/../pe/pe-parser-library/pe-parser-library.pri')
|
||||
|
||||
|
||||
QT_DIR = $$dirname(QMAKE_QMAKE)/../
|
||||
DEFINES+=QT_BASE_DIR='\\"$$QT_DIR\\"'
|
||||
|
||||
CONFIG += qt console warn_on depend_includepath testcase
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += tst_deploytest.cpp \
|
||||
libcreator.cpp
|
||||
libcreator.cpp \
|
||||
qmlcreator.cpp
|
||||
|
||||
RESOURCES += \
|
||||
res.qrc
|
||||
|
||||
HEADERS += \
|
||||
libcreator.h
|
||||
libcreator.h \
|
||||
qmlcreator.h
|
||||
|
58
UnitTests/qmlcreator.cpp
Normal file
58
UnitTests/qmlcreator.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "qmlcreator.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
QMap<QString, QStringList> QmlCreator::getQmlImports() const {
|
||||
return qmlImports;
|
||||
}
|
||||
|
||||
QStringList QmlCreator::getCopyedQml() const {
|
||||
return copyedQml;
|
||||
}
|
||||
|
||||
void QmlCreator::createQml(const QString &qmlFile, const QStringList &imports) {
|
||||
QFile qml(qmlFile);
|
||||
|
||||
if (qml.open(QIODevice::ReadOnly)) {
|
||||
|
||||
QFile target(path + "/" + QFileInfo(qmlFile).fileName());
|
||||
|
||||
if (target.open(QIODevice::ReadWrite)) {
|
||||
|
||||
auto data = qml.readAll();
|
||||
target.write(data.data(), data.size());
|
||||
|
||||
target.close();
|
||||
|
||||
copyedQml.push_back(target.fileName());
|
||||
qmlImports.insert(target.fileName(), imports);
|
||||
}
|
||||
|
||||
qml.close();
|
||||
}
|
||||
}
|
||||
|
||||
void QmlCreator::initQml() {
|
||||
createQml(":/qmlFile.qml", {
|
||||
"2#QtQuick",
|
||||
"2#QtQuick/Controls/Material",
|
||||
"2#QtQuick/Controls",
|
||||
"1#QtQuick/Controls",
|
||||
"1#QtQuick/Layouts"
|
||||
});
|
||||
}
|
||||
|
||||
QmlCreator::QmlCreator(const QString &path) {
|
||||
this->path = path;
|
||||
initQml();
|
||||
}
|
||||
|
||||
|
||||
QmlCreator::~QmlCreator() {
|
||||
|
||||
for(auto &&lib : copyedQml) {
|
||||
QFile::remove(lib);
|
||||
}
|
||||
|
||||
}
|
26
UnitTests/qmlcreator.h
Normal file
26
UnitTests/qmlcreator.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef QMLCREATOR_H
|
||||
#define QMLCREATOR_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
|
||||
class QmlCreator
|
||||
{
|
||||
private:
|
||||
QString path;
|
||||
QStringList copyedQml;
|
||||
|
||||
QMap<QString, QStringList> qmlImports;
|
||||
void createQml(const QString& resLib, const QStringList& imports);
|
||||
|
||||
void initQml();
|
||||
public:
|
||||
QmlCreator(const QString &path);
|
||||
~QmlCreator();
|
||||
QMap<QString, QStringList> getQmlImports() const;
|
||||
QStringList getCopyedQml() const;
|
||||
};
|
||||
|
||||
#endif // QMLCREATOR_H
|
@ -11,5 +11,6 @@
|
||||
<file alias="win64mingw.dll">testRes/win64/mingw/Deploy.dll</file>
|
||||
<file alias="win64msvc.exe">testRes/win64/msvc/exe.exe</file>
|
||||
<file alias="win64msvc.dll">testRes/win64/msvc/lib.dll</file>
|
||||
<file alias="qmlFile.qml">testRes/qml/Scene.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
272
UnitTests/testRes/qml/Scene.qml
Normal file
272
UnitTests/testRes/qml/Scene.qml
Normal file
@ -0,0 +1,272 @@
|
||||
import QtQuick 2.11
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls 1.3 as ctrl
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Item {
|
||||
id: scene;
|
||||
z: -2
|
||||
|
||||
Rectangle {
|
||||
id: background;
|
||||
color: "#ffffff"
|
||||
anchors.fill: parent;
|
||||
|
||||
Behavior on color {
|
||||
|
||||
ColorAnimation {
|
||||
duration: 5000
|
||||
}
|
||||
}
|
||||
|
||||
z: -3
|
||||
|
||||
}
|
||||
|
||||
property var model: (contr)? contr: null;
|
||||
property var arrayObjects: []
|
||||
property bool showMenu: false
|
||||
property bool isPause: false
|
||||
|
||||
function add (cppObjId) {
|
||||
if (!model) {
|
||||
console.log("create object fail")
|
||||
return;
|
||||
}
|
||||
var objModel = model.getGameObject(cppObjId);
|
||||
|
||||
if (!objModel) {
|
||||
console.log("object model not found");
|
||||
return;
|
||||
}
|
||||
|
||||
var viewTemplate = objModel.viewTemplate;
|
||||
|
||||
var temp = Qt.createComponent( viewTemplate + ".qml")
|
||||
if (temp.status === Component.Ready) {
|
||||
var obj = temp.createObject(parent) // parent - это обьект на который будет помещен соззданный элемент
|
||||
obj.model = model.getGameObject(cppObjId);
|
||||
obj.z = -2;
|
||||
arrayObjects.push(obj)
|
||||
} else {
|
||||
console.log("wrong viewTemplate in model");
|
||||
}
|
||||
}
|
||||
|
||||
function remove(id) {
|
||||
if (typeof id !== "number" || id < 0) {
|
||||
console.log("id not found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < arrayObjects.length; ++i) {
|
||||
if (id === arrayObjects[i].guiId) {
|
||||
arrayObjects.splice(i,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAuto (auto) {
|
||||
if (auto && model) {
|
||||
model.newGame();
|
||||
|
||||
}
|
||||
showMenu = (auto && model)
|
||||
autoTimer.running = auto && model;
|
||||
}
|
||||
|
||||
function updateBackgroundColor(lvl) {
|
||||
switch(lvl % 7) {
|
||||
case 0: background.color = "#d6eaf8"; break;
|
||||
case 1: background.color = "#d0ece7"; break;
|
||||
case 2: background.color = "#d4efdf"; break;
|
||||
case 3: background.color = "#fcf3cf"; break;
|
||||
case 4: background.color = "#f6ddcc"; break;
|
||||
case 5: background.color = "#f2d7d5"; break;
|
||||
case 6: background.color = "#ebdef0"; break;
|
||||
case 7: background.color = "#fbfcfc"; break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id :autoTimer;
|
||||
repeat: true;
|
||||
running: false;
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
interval = Math.random() * 600
|
||||
scene.model.buttonPress();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: model;
|
||||
onGameObjectsChanged: {
|
||||
if (!dif) {
|
||||
console.log("dif not found");
|
||||
return;
|
||||
}
|
||||
|
||||
var tempDifRem = [];
|
||||
tempDifRem = dif.getRemoveIds();
|
||||
var tempDifAdd = [];
|
||||
tempDifAdd = dif.getAddedIds();
|
||||
|
||||
for (var i = 0; i < tempDifAdd.length; ++i) {
|
||||
add(tempDifAdd[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < tempDifRem.length; ++i) {
|
||||
remove(tempDifRem[i]);
|
||||
}
|
||||
}
|
||||
|
||||
onFinished: {
|
||||
|
||||
var isVictory = victory;
|
||||
var gameLvl = lvl + 1;
|
||||
var dist = distance;
|
||||
updateBackgroundColor(gameLvl);
|
||||
|
||||
if (isVictory ) {
|
||||
|
||||
if (!autoTimer.running)
|
||||
notification.show(qsTr(" Next Lvl!!!"),
|
||||
qsTr(" You anblock next lvl (" + gameLvl + ")" ),
|
||||
"qrc:/texture/up");
|
||||
|
||||
model.nextLvl();
|
||||
} else if (autoTimer.running) {
|
||||
model.newGame();
|
||||
} else {
|
||||
showMenu = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateBackgroundColor(0);
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
||||
onClicked: {
|
||||
if (!model) {
|
||||
console.log("model not found");
|
||||
return;
|
||||
}
|
||||
|
||||
model.buttonPress();
|
||||
}
|
||||
}
|
||||
|
||||
NotificationForm {
|
||||
z: -1
|
||||
id: notification;
|
||||
margin: mainWindow.point;
|
||||
|
||||
x: parent.width - width - margin;
|
||||
y: margin;
|
||||
|
||||
width: 40 * mainWindow.point;
|
||||
height: width * 0.5
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: returnToMenu;
|
||||
|
||||
text: "<<"
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: point
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: point
|
||||
z: 1
|
||||
|
||||
onClicked: {
|
||||
showMenu = true;
|
||||
}
|
||||
|
||||
visible: !showMenu
|
||||
}
|
||||
|
||||
Button {
|
||||
id: pause
|
||||
|
||||
text: (isPause)? "▶" :"||"
|
||||
|
||||
anchors.left: returnToMenu.right
|
||||
anchors.leftMargin: point
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: point
|
||||
z: returnToMenu.z
|
||||
|
||||
onClicked: {
|
||||
isPause = !isPause;
|
||||
if (model) model.setPause(isPause);
|
||||
}
|
||||
|
||||
visible: !showMenu
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: long_
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
|
||||
textFormat: Text.AutoText
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: qsTr("lvl long: ") + ((model)? model.long_: "0")
|
||||
}
|
||||
|
||||
width: 35 * point;
|
||||
height: pause.height;
|
||||
|
||||
anchors.left: pause.right
|
||||
anchors.leftMargin: point
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: point
|
||||
z: returnToMenu.z
|
||||
|
||||
visible: !showMenu
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
Label {
|
||||
anchors.fill: parent;
|
||||
|
||||
textFormat: Text.AutoText
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: qsTr("general long: ") + ((model)? model.generalLong: "0")
|
||||
}
|
||||
|
||||
width: 35 * point;
|
||||
height: long_.height;
|
||||
|
||||
anchors.left: long_.right
|
||||
anchors.leftMargin: point
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: point
|
||||
z: returnToMenu.z
|
||||
|
||||
visible: !showMenu
|
||||
|
||||
}
|
||||
}
|
@ -10,18 +10,25 @@
|
||||
#include <deployutils.h>
|
||||
#include <deploy.h>
|
||||
#include <dependenciesscanner.h>
|
||||
#include <qml.h>
|
||||
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
#include <thread>
|
||||
#include "libcreator.h"
|
||||
#include "qmlcreator.h"
|
||||
// add necessary includes here
|
||||
|
||||
class deploytest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
bool runProcess(const QString& DistroPath,
|
||||
const QString& filename,
|
||||
const QString &qt = "");
|
||||
QStringList getFilesFromDir(const QString& dir);
|
||||
public:
|
||||
deploytest();
|
||||
/**
|
||||
@ -32,6 +39,10 @@ public:
|
||||
int generateLib(const QString& paath);
|
||||
void deleteLib(const QString& paath);
|
||||
|
||||
bool mainTestOnlyC();
|
||||
bool mainTestQMake();
|
||||
bool mainTestQML();
|
||||
|
||||
~deploytest();
|
||||
|
||||
private slots:
|
||||
@ -43,9 +54,84 @@ private slots:
|
||||
void testStrip();
|
||||
void testDeploy();
|
||||
void testExtractLib();
|
||||
void testQmlExtrct();
|
||||
|
||||
void mainTests();
|
||||
void testMSVC();
|
||||
};
|
||||
|
||||
bool deploytest::runProcess(const QString &DistroPath,
|
||||
const QString &filename,
|
||||
const QString& qt) {
|
||||
|
||||
QProcess p;
|
||||
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
|
||||
if (qt.size()) {
|
||||
auto val = env.value("LD_LIBRARY_PATH","").remove(qt);
|
||||
env.insert("LD_LIBRARY_PATH", val);
|
||||
|
||||
val = env.value("PATH","").remove(qt);
|
||||
env.insert("PATH", val);
|
||||
|
||||
env.insert("QTDIR", "");
|
||||
} else {
|
||||
env.clear();
|
||||
env.insert("QTDIR", "");
|
||||
|
||||
}
|
||||
p.setProcessEnvironment(env);
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
p.setProgram(DistroPath + "/" + filename + ".sh");
|
||||
#else
|
||||
p.setProgram(DistroPath + "/" + filename + ".exe");
|
||||
#endif
|
||||
|
||||
p.start();
|
||||
|
||||
if (!p.waitForFinished(1000)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString str = p.readAll();
|
||||
if (p.exitCode()) {
|
||||
qCritical() << p.errorString();
|
||||
}
|
||||
|
||||
if (p.exitCode()) {
|
||||
qWarning() << "exitCode == " << p.exitCode();
|
||||
}
|
||||
|
||||
if (str.contains("failed to load component", Qt::CaseInsensitive)
|
||||
|| str.contains("is not installed", Qt::CaseInsensitive) ||
|
||||
str.contains("error", Qt::CaseInsensitive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p.exitCode() == 0;
|
||||
}
|
||||
|
||||
QStringList deploytest::getFilesFromDir(const QString &path) {
|
||||
QDir dir(path);
|
||||
|
||||
QStringList res;
|
||||
|
||||
auto list = dir.entryInfoList(QDir::Dirs| QDir::Files| QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto &&subDir: list) {
|
||||
|
||||
if (subDir.isFile()) {
|
||||
res.push_back(subDir.fileName());
|
||||
} else {
|
||||
res.append(getFilesFromDir(subDir.absoluteFilePath()));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
deploytest::deploytest(){}
|
||||
|
||||
int deploytest::generateLib(const QString &paath)
|
||||
@ -337,6 +423,188 @@ void deploytest::testMSVC() {
|
||||
|
||||
}
|
||||
|
||||
void deploytest::testQmlExtract() {
|
||||
QmlCreator creator("./");
|
||||
auto imports = creator.getQmlImports();
|
||||
|
||||
auto qmlFiles = creator.getCopyedQml();
|
||||
|
||||
|
||||
QML scaner("./");
|
||||
|
||||
|
||||
for (auto &&file : qmlFiles) {
|
||||
|
||||
|
||||
auto fileImports = scaner.extractImportsFromFile(file);
|
||||
|
||||
for (auto &file : imports.value(file)) {
|
||||
QVERIFY(fileImports.contains(file, Qt::CaseInsensitive));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void deploytest::mainTests() {
|
||||
#ifdef WITH_ALL_TESTS
|
||||
QVERIFY(mainTestOnlyC());
|
||||
QVERIFY(mainTestQMake());
|
||||
QVERIFY(mainTestQML());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool deploytest::mainTestOnlyC() {
|
||||
#ifdef WITH_ALL_TESTS
|
||||
int argc = 5;
|
||||
const char * argv[] = {"./",
|
||||
"-bin", "./../../../tests/build/TestOnlyC",
|
||||
"-targetDir", "./Distro"};
|
||||
|
||||
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Deploy deploy;
|
||||
|
||||
if (!DeployUtils::parseQt(&deploy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deploy.deploy();
|
||||
|
||||
if (!QFileInfo("./Distro").isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir info("./Distro");
|
||||
|
||||
bool run = runProcess("./Distro", "TestOnlyC");
|
||||
if (!info.removeRecursively()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return run;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool deploytest::mainTestQMake() {
|
||||
#ifdef WITH_ALL_TESTS
|
||||
|
||||
QFileInfo QtDir = QFileInfo(QT_BASE_DIR);
|
||||
|
||||
if (!QtDir.isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int argc = 7;
|
||||
const char * argv[] = {"./",
|
||||
"-bin", "./../../../tests/build/QtWidgetsProject",
|
||||
"-qmake", (QtDir.absoluteFilePath() + "/bin/qmake").toLatin1(),
|
||||
"-targetDir", "./Distro"};
|
||||
|
||||
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Deploy deploy;
|
||||
|
||||
if (!DeployUtils::parseQt(&deploy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deploy.deploy();
|
||||
|
||||
QDir info("./Distro");
|
||||
|
||||
if (!QFileInfo("./Distro").isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool run = runProcess("./Distro", "QtWidgetsProject", QtDir.absoluteFilePath());
|
||||
|
||||
if (!info.removeRecursively()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return run;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool deploytest::mainTestQML() {
|
||||
|
||||
#ifdef WITH_ALL_TESTS
|
||||
|
||||
QFileInfo QtDir = QFileInfo(QT_BASE_DIR);
|
||||
|
||||
if (!QtDir.isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int argc = 9;
|
||||
const char * argv[] = {"./",
|
||||
"-bin", "./../../../tests/build/TestQMLWidgets",
|
||||
"-qmlDir", "./../../../tests/TestQMLWidgets",
|
||||
"-qmake", (QtDir.absoluteFilePath() + "/bin/qmake").toLatin1(),
|
||||
"-targetDir", "./Distro"};
|
||||
|
||||
if (!QuasarAppUtils::Params::parseParams(argc, argv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Deploy deploy;
|
||||
|
||||
if (!DeployUtils::parseQt(&deploy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deploy.deploy();
|
||||
|
||||
QDir info("./Distro");
|
||||
|
||||
bool run = runProcess("./Distro", "TestQMLWidgets", QtDir.absoluteFilePath());
|
||||
|
||||
if (!info.removeRecursively()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!run ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!QFileInfo(QtDir).isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
argc = 10;
|
||||
const char * argv2[] = {"./",
|
||||
"-bin", "./../../../tests/build/TestQMLWidgets",
|
||||
"-qmlDir", "./../../../tests/TestQMLWidgets",
|
||||
"-qmake", (QtDir.absoluteFilePath() + "/bin/qmake").toLatin1(),
|
||||
"-targetDir", "./Distro", "qmlExtern"};
|
||||
|
||||
if (!QuasarAppUtils::Params::parseParams(argc, argv2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Deploy deploy2;
|
||||
|
||||
if (!DeployUtils::parseQt(&deploy2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deploy2.deploy();
|
||||
run = runProcess("./Distro", "TestQMLWidgets", QtDir.absoluteFilePath());
|
||||
|
||||
if (!info.removeRecursively()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return run;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void deploytest::testTranslations() {
|
||||
QStringList trList = {
|
||||
("./test/QtDir/translations/qtbase_ru.qm"),
|
||||
|
@ -7,3 +7,6 @@ SOURCES += \
|
||||
main.cpp
|
||||
|
||||
DESTDIR="$$PWD/../build"
|
||||
|
||||
RESOURCES += \
|
||||
conf.qrc
|
||||
|
5
tests/TestOnlyC/conf.qrc
Normal file
5
tests/TestOnlyC/conf.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
0
tests/TestOnlyC/qt.conf
Normal file
0
tests/TestOnlyC/qt.conf
Normal file
5
tests/TestQMLWidgets/conf.qrc
Normal file
5
tests/TestQMLWidgets/conf.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -1,5 +1,6 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QTimer>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -12,5 +13,7 @@ int main(int argc, char *argv[])
|
||||
if (engine.rootObjects().isEmpty())
|
||||
return -1;
|
||||
|
||||
QTimer::singleShot(200, [&app](){ app.exit(0);});
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -6,4 +6,8 @@
|
||||
<file>Page2Form.ui.qml</file>
|
||||
<file>qtquickcontrols2.conf</file>
|
||||
</qresource>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
</qresource>
|
||||
|
||||
</RCC>
|
||||
|
0
tests/TestQMLWidgets/qt.conf
Normal file
0
tests/TestQMLWidgets/qt.conf
Normal file
@ -36,4 +36,7 @@ FORMS += \
|
||||
|
||||
DESTDIR="$$PWD/../build"
|
||||
|
||||
RESOURCES += \
|
||||
conf.qrc
|
||||
|
||||
|
||||
|
5
tests/TestQtWidgets/conf.qrc
Normal file
5
tests/TestQtWidgets/conf.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -1,5 +1,6 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -7,5 +8,9 @@ int main(int argc, char *argv[])
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
|
||||
QTimer::singleShot(200, [&a](){ a.exit(0);});
|
||||
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
2
tests/TestQtWidgets/qt.conf
Normal file
2
tests/TestQtWidgets/qt.conf
Normal file
@ -0,0 +1,2 @@
|
||||
[Paths]
|
||||
Prefix = /some/path
|
Loading…
x
Reference in New Issue
Block a user