4
0
mirror of https://github.com/QuasarApp/QtDeployer.git synced 2025-05-10 11:59:34 +00:00

Merge pull request from QuasarApp/QtDeployer

Qt deployer
This commit is contained in:
Andrei Yankovich 2018-05-10 14:49:17 +03:00 committed by GitHub
commit 6e85faf59f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 400 additions and 78 deletions

22
.gitignore vendored

@ -12,6 +12,13 @@
# Qt-es
/parts/*
/prime/*
/snap/.snapcraft/*
/stage/*
/source/android/*
!/source/android/AndroidManifest.xml
/.qmake.cache
/.qmake.stash
*.pro.user
@ -20,15 +27,26 @@
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
Makefile*
*-build-*
*build-*
# QtCreator
*.autosave
#QtCtreator Qml
# QtCtreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCtreator CMake
CMakeLists.txt.user*
snap/plugins/__pycache__/
*.snap
\.buildconfig

@ -1 +1,32 @@
QtLinuxDeployer
# Welcome to the Qt Deployer!
# ![Hanoi Towers Logo](/source/res/icon.png)
***************************
***************************
## What is Qt Deployer
The Qt Deployer is gui application for extract all depends library of executable and create launch script for your application.
supported platform:
1. Linux
## Build for Linux (snap)
- sudo apt install git snapcraft
- git clone https://github.com/EndrII/Hanoi-Towers.git
- cd Hanoi-Towers
- snapcraft
## Install
You can download the latest version of the game [here](https://github.com/EndrII/Hanoi-Towers/releases).
Or download from official services
* Ubuntu
## Donate
If you want to help the project, then you can donate a small amount to our bitcoin wallet.
### Bitcoin address - 1NJNbDKmezcUcHRfzpBeq2fHeG21oEKX8Q

@ -1,35 +0,0 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <CPP/cppmanager.h>
#include <CPP/mainmanager.h>
#include <CPP/outputmanager.h>
#include <CPP/pluginmanager.h>
#include <CPP/qmlmanager.h>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
CppManager C;
QmlManager Q;
PluginManager P;
OutputManager O;
MainManager M(&C, &Q, &O, &P);
QQmlApplicationEngine engine;
auto *R = engine.rootContext();
R->setContextProperty("CppManager", &C);
R->setContextProperty("QmlManager", &Q);
R->setContextProperty("PluginManager", &P);
R->setContextProperty("MainManager", &M);
R->setContextProperty("OutputManager", &O);
engine.load(QUrl(QLatin1String("qrc:/QML/main.qml")));
if (engine.rootObjects().isEmpty()) return -1;
return app.exec();
}

15
snap/gui/QtDeployer.desktop Executable file

@ -0,0 +1,15 @@
[Desktop Entry]
Version=1.0
Name=Qt Deployer
Comment=Deploy Qt projects.
Exec=qt-deployer
Icon=/snap/qt-deployer/current/meta/gui/icon.png
Terminal=false
Type=Application
Categories=utils;Application;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=qt-deployer
X-GNOME-Bugzilla-Component=General
X-GNOME-Bugzilla-Version=1.0
StartupNotify=true
Name[ru_RU]=QtDeployer

BIN
snap/gui/icon.png Normal file

Binary file not shown.

After

(image error) Size: 52 KiB

37
snap/snapcraft.yaml Executable file

@ -0,0 +1,37 @@
name: qt-deployer
version: '1.0 test1'
summary: Deploy Qt Project
description: |
Deploy Qt Projects. this application extract all depends library of executable and create launch script for your application.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: classic # use 'strict' once you have the right plugs and slots
base: core18
icon: snap/gui/icon.png
apps:
qt-deployer:
command: qt5-launch opt/qt-deployer/bin/qt-deployer
# desktop: usr/share/applications/desc.desktop
plugs: [desktop, home, opengl, x11, wayland]
parts:
qt-deployer:
plugin: qmake
source: source/
build-packages:
- qtbase5-dev
- qtdeclarative5-dev
stage-packages:
# Here for the plugins-- they're not linked in automatically.
- libqt5gui5
- libqt5qml5
- libqt5quick5
- qml-module-qtquick2
- qml-module-qtquick-dialogs
- qml-module-qtquick-controls
- qml-module-qtgraphicaleffects
after: [qt5conf] # A wiki part

@ -1,4 +1,5 @@
#include "baseclass.h"
#include <QRegularExpression>
QString BaseClass::m_qtdir = QString();
QString BaseClass::m_outputdir = QString();
@ -18,4 +19,18 @@ QStringList BaseClass::findFilesInsideDir(const QString &name, const QString &di
return files;
}
bool BaseClass::getName(QString &name, const QString &url) const{
int index = url.lastIndexOf(QRegularExpression("[\\\/]"));
if(index < 0 || url.isEmpty()){
return false;
}
index = url.length() - index - 1;
name = url.right(index);
return true;
}
BaseClass::BaseClass(QObject *parent) : QObject(parent) {}

@ -22,6 +22,8 @@ protected:
QStringList findFilesInsideDir(const QString &name, const QString &dirpath);
bool getName(QString &name, const QString &url) const;
public:
explicit BaseClass(QObject *parent = nullptr);
};

@ -24,11 +24,15 @@ void CppManager::setNotFoundLibs(const QStringList &notFoundLibs)
emit notFoundLibsChanged(m_notFoundLibs);
}
bool CppManager::isQtLib(const QString &lib) const{
return lib.indexOf(m_qtdir) == 0;
}
void CppManager::extractAllLibs(const QStringList &execfiles)
{
for (const QString &execfile : execfiles)
for (const QString &lib : extractLibsFromExecutable(execfile))
if (!m_cppLibraries.contains(lib))
if (!m_cppLibraries.contains(lib))
{
m_cppLibraries << lib;
extractAllLibs(QStringList(lib));
@ -69,10 +73,7 @@ void CppManager::divideLibraries()
{
QString name;
QFileInfo libInfo(lib);
name = libInfo.fileName();
if (!name.isEmpty() && name.startsWith("libQt"))
if (getName(name, lib) && !name.isEmpty() && isQtLib(lib))
{
m_qtLibraries << name;
m_cppLibraries.removeOne(lib);
@ -91,9 +92,9 @@ void CppManager::start(const QStringList &executables)
m_notFoundLibs.removeDuplicates();
emit qtLibrariesChanged(m_qtLibraries);
emit cppLibrariesChanged(m_cppLibraries);
emit notFoundLibsChanged(m_notFoundLibs);
emit qtLibrariesChanged(m_qtLibraries);
emit cppLibrariesChanged(m_cppLibraries);
emit notFoundLibsChanged(m_notFoundLibs);
}
QStringList CppManager::getQtLibrariesFullPaths()

@ -19,6 +19,8 @@ class CppManager : public BaseClass
QStringList m_cppLibraries;
QStringList m_notFoundLibs;
bool isQtLib(const QString&) const;
public: // TODO remove this line
void extractAllLibs(const QStringList &execfiles);
QStringList extractLibsFromExecutable(const QString &execpath);

@ -10,7 +10,7 @@ QStringList MainManager::getAllExecutables()
}
MainManager::MainManager(CppManager *cpp, QmlManager *qml, OutputManager *out,
PluginManager *plg, QObject *parent)
PluginManager *plg, QObject *parent)
: BaseClass(parent)
{
setState(0);
@ -19,6 +19,7 @@ MainManager::MainManager(CppManager *cpp, QmlManager *qml, OutputManager *out,
m_qml = qml;
m_out = out;
m_plg = plg;
}
void MainManager::prepare(const QString &qtdir, const QString &execpath,
@ -28,7 +29,7 @@ void MainManager::prepare(const QString &qtdir, const QString &execpath,
list << qtdir << execpath << projectdir << outdir;
for (QString &S : list)
if (S[S.count() - 1] == "/") S.remove(S.count() - 1, 1);
if (S[S.count() - 1] == '/') S.remove(S.count() - 1, 1);
m_qtdir = list[0];
m_executablepath = list[1];

@ -24,7 +24,7 @@ class MainManager : public BaseClass
public:
explicit MainManager(CppManager *cpp, QmlManager *qml, OutputManager *out,
PluginManager *plg, QObject *parent = nullptr);
PluginManager *plg, QObject *parent = nullptr);
int state() const;

@ -26,22 +26,22 @@ ColumnLayout {
TextField {
id: field
Layout.fillWidth: true
placeholderText: "Enter path or browse"
placeholderText: qsTr("Enter path or browse")
onTextChanged: {
if (!MainManager.pathExists(isdir, text))
{
wlabel.text = "Path doesn't exist"
wlabel.text = qsTr("Path doesn't exist")
confirmed = false
}
else if (!MainManager.hasPrems(text))
{
wlabel.text = "I don't have permission to access this path"
wlabel.text = qsTr("I don't have permission to access this path")
confirmed = false
}
else
{
wlabel.text = "This path is OK"
wlabel.text = qsTr("This path is OK")
confirmed = true
}
}

@ -9,7 +9,7 @@ Page {
clip: true
header: TopBar {
text: "Prepare"
text: qsTr("Prepare")
ToolButton {
text: "➔"
@ -33,7 +33,7 @@ Page {
elide: Text.ElideRight
Layout.fillWidth: true
font.pointSize: mediumFont
text: "Choose Non-Qt Libraries To Copy"
text: qsTr("Choose Non-Qt Libraries To Copy")
}
Flickable {
@ -58,7 +58,7 @@ Page {
width: parent.width
Repeater {
model: CppManager.cppLibraries
model: CppManager.cppLibraries
delegate: CheckDelegate {
id: del
@ -86,17 +86,17 @@ Page {
CheckBox {
id: checkAll
Layout.fillWidth: true
text: "Check All The Above"
text: qsTr("Check All The Above")
}
CheckBox {
id: erase
Layout.fillWidth: true
text: "Erase Everything In: " + outdir
text: qsTr("Erase Everything In: ") + outdir
}
Button {
text: "Next"
text: qsTr("Next")
Material.background: buttonColor
Layout.alignment: Qt.AlignRight

@ -11,7 +11,7 @@ Page {
property int state: MainManager.state
header: TopBar {
text: "Qt Linux Deployer"
text: qsTr("Qt Deployer")
ToolButton {
text: "➔"
@ -28,7 +28,7 @@ Page {
padding: 18
anchors.centerIn: parent
Material.background: buttonColor
text: page.state == 0 ? "Go!":(page.state == 1 ? "Wait!":"Done!")
text: page.state == 0 ? "Go!":(page.state == 1 ? qsTr("Wait!"):qsTr("Done!"))
onClicked: {
if (page.state == 0)

@ -1,11 +1,13 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
Page {
clip: true
header: TopBar {
text: "Result"
text: qsTr("Result")
ToolButton {
text: "➔"
@ -19,45 +21,45 @@ Page {
ListView {
id: listview
anchors.fill: parent
anchors.fill: parent
ScrollBar.vertical: ScrollBar {}
model: VisualItemModel {
ExtendableView {
checkable: false
title: "Qt Libraries"
title: qsTr("Qt Libraries")
model: CppManager.qtLibraries
}
ExtendableView {
checkable: false
title: "Non-Qt Libraries"
title: qsTr("Non-Qt Libraries")
model: CppManager.cppLibraries
}
ExtendableView {
checkable: false
title: "Unknown Libraries"
title: qsTr("Unknown Libraries")
model: CppManager.notFoundLibs
}
ExtendableView {
checkable: false
title: "Qml Imports"
title: qsTr("Qml Imports")
model: QmlManager.foundImports
}
ExtendableView {
checkable: false
title: "Failed Qml Imports"
title: qsTr("Failed Qml Imports")
model: QmlManager.notFoundImports
}
ExtendableView {
checkable: true
title: "Copied Paths"
title: qsTr("Copied Paths")
model: OutputManager.pathsToCopy
}
}
}
}
}

@ -9,7 +9,7 @@ Page {
clip: true
header: TopBar {
text: "Qt Linux Deployer"
text: qsTr("Qt Deployer")
}
Settings {
@ -26,23 +26,23 @@ Page {
PathChooser {
id: qtdir
title: "Qt Build Directory"
title: qsTr("Qt Build Directory")
}
PathChooser {
id: execpath
isdir: false
title: "Executable File Path"
title: qsTr("Executable File Path")
}
PathChooser {
id: projectdir
title: "Project Directory"
title: qsTr("Project Directory")
}
PathChooser {
id: outdir
title: "Final Output Directory"
title: qsTr("Final Output Directory")
}
Item {
@ -51,7 +51,7 @@ Page {
}
Button {
text: "Next"
text: qsTr("Next")
Material.background: buttonColor
Layout.alignment: Qt.AlignRight
enabled: qtdir.confirmed && execpath.confirmed

@ -5,7 +5,7 @@ import QtQuick.Controls.Material 2.0
ApplicationWindow {
id: window
visible: true
title: qsTr("Qt Linux Deployer")
title: qsTr("Qt Deployer")
width: 600
height: sp.implicitHeight + 30

@ -1,6 +1,8 @@
TEMPLATE = app
QT += qml quick
CONFIG += c++11
CONFIG += c++14
RESOURCES += qml.qrc
@ -20,6 +22,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
TARGET = QtDeployer
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
@ -42,3 +45,10 @@ HEADERS += \
CPP/outputmanager.h \
CPP/pluginmanager.h \
CPP/qmlmanager.h
TRANSLATIONS += \
languages/en.ts
VERSION = 1.0.0.0
TEMPLATE = app
RC_ICONS = snap/icon.ico

1
source/languages/en.qm Normal file

@ -0,0 +1 @@
<クd<>箆!ソ`。スン

152
source/languages/en.ts Normal file

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>PathChooser</name>
<message>
<location filename="../QML/PathChooser.qml" line="29"/>
<source>Enter path or browse</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PathChooser.qml" line="34"/>
<source>Path doesn&apos;t exist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PathChooser.qml" line="39"/>
<source>I don&apos;t have permission to access this path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PathChooser.qml" line="44"/>
<source>This path is OK</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreparePage</name>
<message>
<location filename="../QML/PreparePage.qml" line="12"/>
<source>Prepare</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PreparePage.qml" line="36"/>
<source>Choose Non-Qt Libraries To Copy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PreparePage.qml" line="89"/>
<source>Check All The Above</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PreparePage.qml" line="95"/>
<source>Erase Everything In: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/PreparePage.qml" line="99"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProcessPage</name>
<message>
<location filename="../QML/ProcessPage.qml" line="14"/>
<source>Qt Deployer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ProcessPage.qml" line="31"/>
<source>Wait!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ProcessPage.qml" line="31"/>
<source>Done!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ResultPage</name>
<message>
<location filename="../QML/ResultPage.qml" line="10"/>
<source>Result</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="30"/>
<source>Qt Libraries</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="36"/>
<source>Non-Qt Libraries</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="42"/>
<source>Unknown Libraries</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="48"/>
<source>Qml Imports</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="54"/>
<source>Failed Qml Imports</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/ResultPage.qml" line="60"/>
<source>Copied Paths</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StartPage</name>
<message>
<location filename="../QML/StartPage.qml" line="12"/>
<source>Qt Deployer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/StartPage.qml" line="29"/>
<source>Qt Build Directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/StartPage.qml" line="35"/>
<source>Executable File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/StartPage.qml" line="40"/>
<source>Project Directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/StartPage.qml" line="45"/>
<source>Final Output Directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../QML/StartPage.qml" line="54"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>main</name>
<message>
<location filename="../QML/main.qml" line="8"/>
<source>Qt Deployer</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

57
source/main.cpp Executable file

@ -0,0 +1,57 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QIcon>
#include <QTranslator>
#include "CPP/cppmanager.h"
#include "CPP/mainmanager.h"
#include "CPP/outputmanager.h"
#include "CPP/pluginmanager.h"
#include "CPP/qmlmanager.h"
bool loadTr(QGuiApplication &app){
QTranslator translator;
QString defaultLocale = QLocale::system().name();
defaultLocale.truncate(defaultLocale.lastIndexOf('_'));
if(!translator.load(QString(":/languages/%0").arg(defaultLocale))){
return false;
}
app.installTranslator(&translator);
return true;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
app.setWindowIcon(QIcon("://icon"));
loadTr(app);
CppManager C;
QmlManager Q;
PluginManager P;
OutputManager O;
MainManager M(&C, &Q, &O, &P);
QQmlApplicationEngine engine;
auto *R = engine.rootContext();
R->setContextProperty("CppManager", &C);
R->setContextProperty("QmlManager", &Q);
R->setContextProperty("PluginManager", &P);
R->setContextProperty("MainManager", &M);
R->setContextProperty("OutputManager", &O);
engine.load(QUrl(QLatin1String("qrc:/QML/main.qml")));
if (engine.rootObjects().isEmpty()) return -1;
return app.exec();
}

9
source/main.qml Normal file

@ -0,0 +1,9 @@
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
}

@ -9,5 +9,9 @@
<file>QML/ResultPage.qml</file>
<file>QML/StartPage.qml</file>
<file>QML/TopBar.qml</file>
<file alias="icon">res/icon.png</file>
</qresource>
<qresource prefix="/languages">
<file alias="en">languages/en.qm</file>
</qresource>
</RCC>

BIN
source/res/icon.ico Normal file

Binary file not shown.

After

(image error) Size: 126 KiB

BIN
source/res/icon.png Normal file

Binary file not shown.

After

(image error) Size: 52 KiB