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
|
*.out
|
||||||
*.app
|
*.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