Add first files of the launcher
This commit is contained in:
parent
92f5494a72
commit
afc7be6f12
83
.gitignore
vendored
83
.gitignore
vendored
@ -88,3 +88,86 @@ compile_commands.json
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# From Qt
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
*.qbs.user*
|
||||
CMakeLists.txt.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
# Directories with generated files
|
||||
.moc/
|
||||
.obj/
|
||||
.pch/
|
||||
.rcc/
|
||||
.uic/
|
||||
/build*/
|
||||
|
||||
82
CMakeLists.txt
Normal file
82
CMakeLists.txt
Normal file
@ -0,0 +1,82 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(ConanCraft-Launcher VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
welcome.cpp
|
||||
welcome.h
|
||||
welcome.ui
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(ConanCraft-Launcher
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET ConanCraft-Launcher APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||
else()
|
||||
if(ANDROID)
|
||||
add_library(ConanCraft-Launcher SHARED
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||
else()
|
||||
add_executable(ConanCraft-Launcher
|
||||
${PROJECT_SOURCES}
|
||||
loading.h loading.cpp loading.ui
|
||||
source.qrc
|
||||
loading-worker.h loading-worker.cpp
|
||||
locales.h
|
||||
locales.cpp
|
||||
install-java.h
|
||||
install-java.cpp
|
||||
network-downloader.h
|
||||
network-downloader.cpp
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(ConanCraft-Launcher PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.ConanCraft-Launcher)
|
||||
endif()
|
||||
set_target_properties(ConanCraft-Launcher PROPERTIES
|
||||
${BUNDLE_ID_OPTION}
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS ConanCraft-Launcher
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(ConanCraft-Launcher)
|
||||
endif()
|
||||
172
install-java.cpp
Normal file
172
install-java.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
#include "install-java.h"
|
||||
#include "network-downloader.h"
|
||||
|
||||
QString checkDirHash(QString path) {
|
||||
QCryptographicHash hash(QCryptographicHash::Sha256);
|
||||
QDir dir(path);
|
||||
|
||||
if (!dir.exists()) {
|
||||
qDebug() << "Directory not exists:" << path;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QFileInfoList fileList = dir.entryInfoList(
|
||||
QDir::Files | QDir::NoSymLinks | QDir::AllDirs | QDir::NoDotAndDotDot,
|
||||
QDir::Name | QDir::DirsFirst
|
||||
);
|
||||
|
||||
for (const QFileInfo &info : fileList) {
|
||||
if (info.isDir()) {
|
||||
QString subHash = checkDirHash(info.absoluteFilePath());
|
||||
hash.addData(subHash.toUtf8());
|
||||
} else if (info.isFile()) {
|
||||
QFile file(info.absoluteFilePath());
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
while (!file.atEnd()) {
|
||||
QByteArray chunk = file.read(8192);
|
||||
hash.addData(chunk);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString(hash.result().toHex());
|
||||
}
|
||||
|
||||
bool checkJava () {
|
||||
QString JAVA_HASH = "null";
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#if defined(Q_PROCESSOR_X86_64)
|
||||
//JAVA_HASH = "null";
|
||||
#elif defined(Q_PROCESSOR_ARM_64)
|
||||
//JAVA_HASH = "null";
|
||||
#endif
|
||||
#elif defined(Q_OS_LINUX)
|
||||
#if defined(Q_PROCESSOR_X86_64)
|
||||
//JAVA_HASH = "6268e94a0d6f37390fd33325725eb2991f9b26eb739baf2506064bfe3ea33075";
|
||||
#elif defined(Q_PROCESSOR_ARM_64)
|
||||
#else
|
||||
//JAVA_HASH = "null";
|
||||
#endif
|
||||
#endif
|
||||
QString hash = checkDirHash("./java");
|
||||
if (JAVA_HASH == "null" || hash != JAVA_HASH)
|
||||
qDebug() << "Java hash:" << hash;
|
||||
|
||||
return hash == JAVA_HASH;
|
||||
}
|
||||
|
||||
void installJava(std::function<void(QString)> logCallback = nullptr) {
|
||||
// Detect OS and architecture
|
||||
QString javaUrl;
|
||||
QString archiveType = "zip";
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#if defined(Q_PROCESSOR_X86_64)
|
||||
javaUrl = "https://example.com/java-windows-x64.zip";
|
||||
#elif defined(Q_PROCESSOR_X86)
|
||||
javaUrl = "https://example.com/java-windows-x86.zip";
|
||||
#else
|
||||
if (logCallback) logCallback("Unsupported Windows architecture");
|
||||
return;
|
||||
#endif
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
#if defined(Q_PROCESSOR_X86_64)
|
||||
javaUrl = "";
|
||||
archiveType = "tar.gz";
|
||||
#elif defined(Q_PROCESSOR_ARM_64)
|
||||
javaUrl = "";
|
||||
archiveType = "tar.gz";
|
||||
#else
|
||||
if (logCallback) logCallback("Unsupported Linux architecture");
|
||||
return;
|
||||
#endif
|
||||
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#if defined(Q_PROCESSOR_X86_64)
|
||||
javaUrl = "https://example.com/java-macos-x64.tar.gz";
|
||||
#elif defined(Q_PROCESSOR_ARM_64)
|
||||
javaUrl = "https://example.com/java-macos-arm64.tar.gz";
|
||||
#else
|
||||
if (logCallback) logCallback("Unsupported macOS architecture");
|
||||
return;
|
||||
#endif
|
||||
|
||||
#else
|
||||
if (logCallback) logCallback("Unsupported OS");
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (logCallback) logCallback("Creating directories...");
|
||||
QDir tempDir("./temp");
|
||||
if (!tempDir.exists()) tempDir.mkpath(".");
|
||||
QDir javaDir("./java");
|
||||
if (!javaDir.exists()) javaDir.mkpath(".");
|
||||
|
||||
QString archivePath = tempDir.filePath(QFileInfo(QUrl(javaUrl).path()).fileName());
|
||||
|
||||
// Download archive
|
||||
downloadFromUrl(javaUrl, archivePath, logCallback);
|
||||
|
||||
// Extract archive
|
||||
if (logCallback) logCallback("Extracting Java archive...");
|
||||
#if defined(Q_OS_WIN)
|
||||
// Unzip and move contents up one level
|
||||
QProcess proc;
|
||||
QString tempExtractDir = "./temp/java_extract";
|
||||
QDir().mkpath(tempExtractDir);
|
||||
proc.start("powershell", {"-Command", QString("Expand-Archive -Force -Path '%1' -DestinationPath '%2'").arg(archivePath).arg(tempExtractDir)});
|
||||
proc.waitForFinished(-1);
|
||||
|
||||
// Move contents from subfolder to ./java
|
||||
QDir extracted(tempExtractDir);
|
||||
QStringList entries = extracted.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
for (const QString &e : entries) {
|
||||
QString srcPath = extracted.filePath(e);
|
||||
QString dstPath = javaDir.filePath(e);
|
||||
if (!QFile::rename(srcPath, dstPath)) {
|
||||
QDir srcDir(srcPath);
|
||||
srcDir.rename(srcPath, dstPath);
|
||||
}
|
||||
}
|
||||
QDir(tempExtractDir).removeRecursively();
|
||||
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||
// Extract to temp folder first
|
||||
QString tempExtractDir = "./temp/java_extract";
|
||||
QDir().mkpath(tempExtractDir);
|
||||
QProcess proc;
|
||||
|
||||
if (archiveType == "tar.gz") {
|
||||
proc.start("tar", {"-xzf", archivePath, "-C", tempExtractDir});
|
||||
} else if (archiveType == "zip") {
|
||||
proc.start("unzip", {archivePath, "-d", tempExtractDir});
|
||||
} else {
|
||||
if (logCallback) logCallback("Unknown archive format");
|
||||
return;
|
||||
}
|
||||
proc.waitForFinished(-1);
|
||||
|
||||
// Move contents of the inner folder to ./java
|
||||
QDir extracted(tempExtractDir);
|
||||
QStringList folders = extracted.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
QString rootFolder = folders.isEmpty() ? "" : folders.first();
|
||||
QDir rootDir(tempExtractDir + "/" + rootFolder);
|
||||
QStringList items = rootDir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
for (const QString &item : items) {
|
||||
QString src = rootDir.filePath(item);
|
||||
QString dst = javaDir.filePath(item);
|
||||
QFile::rename(src, dst);
|
||||
}
|
||||
QDir(tempExtractDir).removeRecursively();
|
||||
#endif
|
||||
|
||||
if (logCallback) logCallback("Extraction complete.");
|
||||
|
||||
// Check hash
|
||||
QString hash = checkDirHash("./java");
|
||||
if (logCallback) logCallback("Java installation hash: " + hash);
|
||||
}
|
||||
20
install-java.h
Normal file
20
install-java.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef INSTALL_JAVA_H
|
||||
#define INSTALL_JAVA_H
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
#include <QStandardPaths>
|
||||
#include <QProcess>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QEventLoop>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
void installJava(std::function<void(QString)> logCallback);
|
||||
bool checkJava ();
|
||||
QString checkDirHash(QString path);
|
||||
|
||||
#endif // INSTALL_JAVA_H
|
||||
58
loading-worker.cpp
Normal file
58
loading-worker.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "loading-worker.h"
|
||||
#include "locales.h"
|
||||
#include "install-java.h"
|
||||
#include <QLocale>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
|
||||
LoadingWorker::LoadingWorker(Loading *loading, QObject *parent) {
|
||||
this->loading = loading;
|
||||
}
|
||||
|
||||
LoadingWorker::~LoadingWorker () {
|
||||
//delete this->loading;
|
||||
}
|
||||
|
||||
void LoadingWorker::process() {
|
||||
std::string locale = (QLocale::system()).name().toStdString();
|
||||
if (locales.find(locale) == locales.end()) {
|
||||
locale = "en_US";
|
||||
}
|
||||
LocaleMap* localeMap = locales[locale];
|
||||
|
||||
// Checking updates
|
||||
this->loading->changeStep(localeMap->at("loading.checkUpdates"));
|
||||
// TODO: Add it later
|
||||
|
||||
// Checking: Is java installed
|
||||
this->loading->changeStep(localeMap->at("loading.isJavaInst"));
|
||||
if (!checkJava()) {
|
||||
// Let's we install the java
|
||||
installJava([this, localeMap](QString msg){
|
||||
qDebug() << msg;
|
||||
this->loading->changeStep(localeMap->at("loading.installJava") + ": " + msg.toStdString());
|
||||
});
|
||||
}
|
||||
// Start I2P
|
||||
this->loading->changeStep(localeMap->at("loading.i2p"));
|
||||
// TODO: Add it later
|
||||
|
||||
// Getting endpoint API
|
||||
this->loading->changeStep(localeMap->at("loading.gettingEndpoint"));
|
||||
std::string endpointAPI = "TODO: Add it later";
|
||||
|
||||
// Handle data
|
||||
this->loading->changeStep(localeMap->at("loading.logging"));
|
||||
// TODO: Add it later
|
||||
|
||||
// Setup current locale for welcome form
|
||||
this->loading->changeStep(localeMap->at("loading.setupLocale"));
|
||||
this->loading->setupWelcomeLocale(locale);
|
||||
|
||||
this->loading->changeStep(localeMap->at("loading.end"));
|
||||
emit finished();
|
||||
this->loading->finishWorker();
|
||||
}
|
||||
21
loading-worker.h
Normal file
21
loading-worker.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef LOADING_WORKER_H
|
||||
#define LOADING_WORKER_H
|
||||
|
||||
#include "loading.h"
|
||||
#include <qobject.h>
|
||||
class LoadingWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LoadingWorker (Loading *loading, QObject *parent = nullptr);
|
||||
~LoadingWorker();
|
||||
private:
|
||||
Loading *loading;
|
||||
public slots:
|
||||
void process();
|
||||
signals:
|
||||
void finished();
|
||||
void progress(int value);
|
||||
};
|
||||
|
||||
#endif // LOADING_WORKER_H
|
||||
54
loading.cpp
Normal file
54
loading.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "loading.h"
|
||||
#include "loading-worker.h"
|
||||
#include "locales.h"
|
||||
#include "ui_loading.h"
|
||||
#include <QThread>
|
||||
|
||||
Loading::Loading(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::Loading)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setWindowFlags(Qt::FramelessWindowHint);
|
||||
this->startLoading();
|
||||
}
|
||||
|
||||
Loading::~Loading()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Loading::changeStep(std::string text) {
|
||||
this->ui->condition->setText(QString::fromStdString(text));
|
||||
}
|
||||
|
||||
void Loading::setupWelcomeLocale(std::string locale) {
|
||||
this->welcome.setupWelcomeLocale(locale);
|
||||
}
|
||||
|
||||
void Loading::finishWorker() {
|
||||
this->hide();
|
||||
this->welcome.show();
|
||||
}
|
||||
|
||||
void Loading::startLoading()
|
||||
{
|
||||
QThread* thread = new QThread;
|
||||
LoadingWorker* worker = new LoadingWorker(this);
|
||||
|
||||
worker->moveToThread(thread);
|
||||
|
||||
connect(thread, &QThread::started,
|
||||
worker, &LoadingWorker::process);
|
||||
|
||||
connect(worker, &LoadingWorker::finished,
|
||||
thread, &QThread::quit);
|
||||
|
||||
connect(worker, &LoadingWorker::finished,
|
||||
worker, &QObject::deleteLater);
|
||||
|
||||
connect(thread, &QThread::finished,
|
||||
thread, &QObject::deleteLater);
|
||||
|
||||
thread->start();
|
||||
}
|
||||
28
loading.h
Normal file
28
loading.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef LOADING_H
|
||||
#define LOADING_H
|
||||
|
||||
#include "welcome.h"
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class Loading;
|
||||
}
|
||||
|
||||
class Loading : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Loading(QWidget *parent = nullptr);
|
||||
~Loading();
|
||||
void changeStep(std::string text);
|
||||
void setupWelcomeLocale(std::string locale);
|
||||
void finishWorker();
|
||||
|
||||
private:
|
||||
Ui::Loading *ui;
|
||||
void startLoading();
|
||||
Welcome welcome;
|
||||
};
|
||||
|
||||
#endif // LOADING_H
|
||||
63
loading.ui
Normal file
63
loading.ui
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Loading</class>
|
||||
<widget class="QWidget" name="Loading">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>450</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>450</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>450</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ConanCraft</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="source.qrc">
|
||||
<normaloff>:/icons/sources/icons/96.png</normaloff>:/icons/sources/icons/96.png</iconset>
|
||||
</property>
|
||||
<widget class="QLabel" name="condition">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>410</y>
|
||||
<width>281</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Getting system language information...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>301</width>
|
||||
<height>411</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700;">Conan Craft</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="source.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
56
locales.cpp
Normal file
56
locales.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "locales.h"
|
||||
|
||||
std::map<const std::string, LocaleMap*> locales;
|
||||
|
||||
// Russian
|
||||
LocaleMap ru_RU = {
|
||||
// Locale Info
|
||||
{"locale.name", "Русский"},
|
||||
{"locale.fullname", "Русский (Russian)"},
|
||||
// Loading
|
||||
{"loading.checkUpdates", "Проверяем обновления"},
|
||||
{"loading.i2p", "Запускаем i2p"},
|
||||
{"loading.isJavaInst", "Проверка установки Java"},
|
||||
{"loading.installJava", "Установка Java"},
|
||||
{"loading.gettingEndpoint", "Получаем Endpoint API"},
|
||||
{"loading.logging", "Обрабатываем данные лаунчера"},
|
||||
{"loading.setupLocale", "Устанавливаем язык лаунчера"},
|
||||
{"loading.end", "Закончили. Приятной игры"},
|
||||
// Welcome
|
||||
{"welcome.main", "Главная"},
|
||||
{"welcome.settings", "Настройки"},
|
||||
{"welcome.authorise", "Авторизация"},
|
||||
{"welcome.showPassword", "Показать пароль"},
|
||||
{"welcome.logIn", "Войти"},
|
||||
{"welcome.register", "Зарегистрироваться"},
|
||||
};
|
||||
|
||||
// English
|
||||
LocaleMap en_US = {
|
||||
// Locale Info
|
||||
{"locale.name", "English"},
|
||||
{"locale.fullname", "English (English)"},
|
||||
// Loading
|
||||
{"loading.checkUpdates", "Checking updates"},
|
||||
{"loading.i2p", "Starting i2p"},
|
||||
{"loading.isJavaInst", "Checking Is Java installed"},
|
||||
{"loading.installJava", "Java installation"},
|
||||
{"loading.gettingEndpoint", "Getting Endpoint API"},
|
||||
{"loading.logging", "Handle the launcher data"},
|
||||
{"loading.setupLocale", "Setup the launcher's language"},
|
||||
{"loading.end", "Finished. Let's start"},
|
||||
// Welcome
|
||||
{"welcome.main", "Home"},
|
||||
{"welcome.settings", "Settings"},
|
||||
{"welcome.authorise", "Authorization"},
|
||||
{"welcome.showPassword", "Show the password"},
|
||||
{"welcome.logIn", "LogIn"},
|
||||
{"welcome.register", "Registration"},
|
||||
};
|
||||
|
||||
void initLocales () {
|
||||
locales["ru_RU"] = &ru_RU;
|
||||
locales["ru_UA"] = &ru_RU;
|
||||
locales["en_US"] = &en_US;
|
||||
//locales["en_UK"] = &en_US;
|
||||
}
|
||||
11
locales.h
Normal file
11
locales.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef LOCALES_H
|
||||
#define LOCALES_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
using LocaleMap = std::map<const std::string, const std::string>;
|
||||
extern std::map<const std::string, LocaleMap*> locales;
|
||||
extern void initLocales ();
|
||||
|
||||
#endif // LOCALES_H
|
||||
15
main.cpp
Normal file
15
main.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "loading.h"
|
||||
#include "locales.h"
|
||||
//#include "welcome.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
initLocales();
|
||||
QApplication a(argc, argv);
|
||||
Loading w;
|
||||
//w.setWindowFlags(Qt::FramelessWindowHint);
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
56
network-downloader.cpp
Normal file
56
network-downloader.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "network-downloader.h"
|
||||
void downloadFromUrl(const QString &url, const QString &installPath, std::function<void(QString)> logCallback = nullptr) {
|
||||
if (QFile::exists(installPath)) {
|
||||
if (logCallback) logCallback("File already exists: " + installPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (logCallback) logCallback("Downloading from url...");
|
||||
QNetworkAccessManager manager;
|
||||
QNetworkRequest request((QUrl(url)));
|
||||
QEventLoop loop;
|
||||
QNetworkReply *reply = manager.get(request);
|
||||
|
||||
QObject::connect(reply, &QNetworkReply::downloadProgress, [&](qint64 received, qint64 total){
|
||||
if (logCallback) logCallback(QString("Download progress: %1/%2 bytes").arg(received).arg(total));
|
||||
});
|
||||
|
||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
|
||||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
|
||||
if (!statusCode.isValid()) {
|
||||
if (logCallback) logCallback("Download failed: Invalid Status code");
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
if (logCallback) logCallback("Download failed: " + reply->errorString());
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusCode.toInt() == 302 || statusCode.toInt() == 301) {
|
||||
QVariant redir = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (!redir.isValid()) {
|
||||
if (logCallback) logCallback("Download failed: Invalid redirect");
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
QUrl newUrl = redir.toUrl();
|
||||
downloadFromUrl(newUrl.toString(), installPath, logCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(installPath);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
if (logCallback) logCallback("Download complete: " + installPath);
|
||||
} else {
|
||||
if (logCallback) logCallback("Cannot write file: " + installPath);
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
18
network-downloader.h
Normal file
18
network-downloader.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef NETWORK_DOWNLOADER_H
|
||||
#define NETWORK_DOWNLOADER_H
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
#include <QStandardPaths>
|
||||
#include <QProcess>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QEventLoop>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
void downloadFromUrl(const QString &url, const QString &installPath, std::function<void(QString)> logCallback);
|
||||
|
||||
#endif // NETWORK_DOWNLOADER_H
|
||||
7
source.qrc
Normal file
7
source.qrc
Normal file
@ -0,0 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>sources/icons/96.png</file>
|
||||
<file>sources/icons/32.png</file>
|
||||
<file>sources/icons/16.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
BIN
sources/icons/16.png
Normal file
BIN
sources/icons/16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 368 B |
BIN
sources/icons/32.png
Normal file
BIN
sources/icons/32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 677 B |
BIN
sources/icons/96.png
Normal file
BIN
sources/icons/96.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
33
welcome.cpp
Normal file
33
welcome.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "welcome.h"
|
||||
#include "./ui_welcome.h"
|
||||
#include "locales.h"
|
||||
|
||||
Welcome::Welcome(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::Welcome)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
Welcome::~Welcome()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Welcome::setupWelcomeLocale(std::string locale) {
|
||||
if (locales.find(locale) == locales.end()) {
|
||||
locale = "en_US";
|
||||
}
|
||||
LocaleMap* localeMap = locales[locale];
|
||||
|
||||
this->ui->authForm->setTitle(QString::fromStdString(localeMap->at("welcome.authorise")));
|
||||
|
||||
this->ui->tabWidget->setTabText(0, QString::fromStdString(localeMap->at("welcome.main")));
|
||||
this->ui->tabWidget->setTabText(1, QString::fromStdString(localeMap->at("welcome.settings")));
|
||||
|
||||
this->ui->showPassword->setText(QString::fromStdString(localeMap->at("welcome.showPassword")));
|
||||
this->ui->loginBtn->setText(QString::fromStdString(localeMap->at("welcome.logIn")));
|
||||
this->ui->registerBtn->setText(QString::fromStdString(localeMap->at("welcome.register")));
|
||||
|
||||
this->ui->tabWidget->setCurrentIndex(0);
|
||||
}
|
||||
24
welcome.h
Normal file
24
welcome.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef WELCOME_H
|
||||
#define WELCOME_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class Welcome;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class Welcome : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Welcome(QWidget *parent = nullptr);
|
||||
~Welcome();
|
||||
void setupWelcomeLocale(std::string locale);
|
||||
|
||||
private:
|
||||
Ui::Welcome *ui;
|
||||
};
|
||||
#endif // WELCOME_H
|
||||
114
welcome.ui
Normal file
114
welcome.ui
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Welcome</class>
|
||||
<widget class="QMainWindow" name="Welcome">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Welcome</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="source.qrc">
|
||||
<normaloff>:/icons/sources/icons/96.png</normaloff>:/icons/sources/icons/96.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>801</width>
|
||||
<height>551</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QWidget" name="main">
|
||||
<attribute name="title">
|
||||
<string>welcome.main</string>
|
||||
</attribute>
|
||||
<widget class="QGroupBox" name="authForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<y>130</y>
|
||||
<width>331</width>
|
||||
<height>291</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>welcome.authorise</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>311</width>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="login"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showPassword">
|
||||
<property name="text">
|
||||
<string>welcome.showPassword</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="loginBtn">
|
||||
<property name="text">
|
||||
<string>welcome.logIn</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="registerBtn">
|
||||
<property name="text">
|
||||
<string>welcome.register</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="settings">
|
||||
<attribute name="title">
|
||||
<string>welcome.settings</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="source.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
Loading…
Reference in New Issue
Block a user