diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ddacec..f880f4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(Qt6 REQUIRED COMPONENTS Widgets) +find_package(Qt6 REQUIRED COMPONENTS Widgets Network) qt_standard_project_setup() diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 56572e2..f109814 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -1,11 +1,15 @@ qt_add_executable(PunkLauncher - mainwindow.ui - mainwindow.cpp main.cpp + ui/mainwindow.cpp + launcher/launcher.cpp + launcher/forge1.12.2/getArgs.cpp + backend/backend.cpp + settings/settings.cpp ../resources/resources.qrc + ../resources/mainwindow.ui ) -target_link_libraries(PunkLauncher PRIVATE Qt6::Widgets) +target_link_libraries(PunkLauncher PRIVATE Qt6::Widgets Qt6::Network) set_target_properties(PunkLauncher PROPERTIES WIN32_EXECUTABLE ON diff --git a/src/app/backend/backend.cpp b/src/app/backend/backend.cpp new file mode 100644 index 0000000..cb1c338 --- /dev/null +++ b/src/app/backend/backend.cpp @@ -0,0 +1,158 @@ +#include "backend.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +Backend::Backend() {} + + +QString Backend::getStateFilePath() { +#ifdef Q_OS_WIN + QString stateDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); +#else + QString stateDir = QStandardPaths::writableLocation(QStandardPaths::StateLocation); +#endif + QDir().mkpath(stateDir); + return stateDir + "/session.json"; +} + + +void Backend::saveToJson(const QString &uuid, const QString &access_token) { + QString filePath = getStateFilePath(); + QJsonObject json; + json["uuid"] = uuid; + json["access_token"] = access_token; + + QFile file(filePath); + if (file.open(QIODevice::WriteOnly)) { + file.write(QJsonDocument(json).toJson()); + file.close(); + qDebug() << "Данные сохранены в" << filePath; + } else { + qWarning() << "Не удалось открыть файл для записи:" << filePath; + } +} + + +QJsonObject Backend::loadFromJson() { + QString filePath = getStateFilePath(); + QFile file(filePath); + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.readAll(); + file.close(); + QJsonDocument doc = QJsonDocument::fromJson(data); + if (doc.isObject()) { + return doc.object(); + } + } + qWarning() << "Не удалось загрузить данные из файла:" << filePath; + return QJsonObject(); +} + + +void Backend::sendPostRequest(const QString &url, const QJsonObject &payload, std::function callback) { + QNetworkAccessManager* manager = new QNetworkAccessManager(); + QNetworkRequest request{QUrl(url)}; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QNetworkReply* reply = manager->post(request, QJsonDocument(payload).toJson()); + QObject::connect(reply, &QNetworkReply::finished, [reply, callback]() { + if (reply->error() == QNetworkReply::NoError) { + QByteArray response = reply->readAll(); + QJsonDocument jsonResponse = QJsonDocument::fromJson(response); + if (jsonResponse.isObject()) { + callback(jsonResponse.object()); + } else { + qWarning() << "Некорректный JSON-ответ."; + callback(QJsonObject()); + } + } else { + qWarning() << "Ошибка запроса:" << reply->errorString(); + callback(QJsonObject()); + } + reply->deleteLater(); + }); +} + + +void Backend::authWithPassword( + QString &username, QString &password, bool &session_save_flag, + std::function callback) +{ + QString url = "http://root-kit.ru:3001/punkcraft/session/auth"; + QJsonObject payload; + payload["username"] = username; + payload["password"] = password; + + sendPostRequest(url, payload, [this, callback, session_save_flag](QJsonObject response) { + if (response.isEmpty()) { + qWarning() << "Ошибка авторизации: пустой ответ."; + if (callback) { + callback("", "", ""); + } + return; + } + + // Сохраняем пользователя в json и отправляет callback функцию + QString username = response["username"].toString(); + QString uuid = response["uuid"].toString(); + QString access_token = response["access_token"].toString(); + + if (session_save_flag) { + saveToJson(uuid, access_token); + } + + + if (callback) { + callback(username, uuid, access_token); + } + }); +} + + +void Backend::authWithToken(std::function callback) { + QJsonObject savedData = loadFromJson(); + if (savedData.isEmpty()) { + qWarning() << "Нет сохранённых данных для авторизации."; + if (callback) { + callback("", "", ""); + } + return; + } + + QString uuid = savedData["uuid"].toString(); + QString access_token = savedData["access_token"].toString(); + + QString url = "http://root-kit.ru:3001/punkcraft/session/auth/token"; + QJsonObject payload; + payload["uuid"] = uuid; + payload["access_token"] = access_token; + + sendPostRequest(url, payload, [this, callback](QJsonObject response) { + if (response.isEmpty()) { + qWarning() << "Ошибка авторизации по токену: пустой ответ."; + if (callback) { + callback("", "", ""); + } + return; + } + + QString username = response["username"].toString(); + QString uuid = response["uuid"].toString(); + QString access_token = response["access_token"].toString(); + + qDebug() << "Авторизация по токену успешна. Пользователь:" << username; + saveToJson(uuid, access_token); + + if (callback) { + callback(username, uuid, access_token); + } + }); +} diff --git a/src/app/backend/backend.h b/src/app/backend/backend.h new file mode 100644 index 0000000..7a51912 --- /dev/null +++ b/src/app/backend/backend.h @@ -0,0 +1,25 @@ +#ifndef BACKEND_H +#define BACKEND_H + +#include +#include +#include + + +class Backend { +public: + Backend(); + void authWithPassword( + QString &username, QString &password, bool &session_save_flag, + std::function callback); + void authWithToken(std::function callback); + QString getStateFilePath(); + + +private: + void saveToJson(const QString &uuid, const QString &access_token); + void sendPostRequest(const QString &url, const QJsonObject &payload, std::function callback); + QJsonObject loadFromJson(); +}; + +#endif diff --git a/src/app/launcher/forge1.12.2/getArgs.cpp b/src/app/launcher/forge1.12.2/getArgs.cpp new file mode 100644 index 0000000..620225b --- /dev/null +++ b/src/app/launcher/forge1.12.2/getArgs.cpp @@ -0,0 +1,146 @@ +#include "getArgs.h" + +#include +#include +#include +#include +#include +#include +#include + + +getArgs::getArgs() { +} + +getArgs::~getArgs() { +} + +QStringList getArgs::getCrossPlatformArgs(QString &RAM, QString &username, QString &uuid, QString &access_token, QString &garbarge_collector) { + QStringList arguments; + arguments + << "-Djava.library.path=./versions/Forge_1.12.2/natives" + //<< "-Xms" + RAM + "M" + << "-Xmx" + RAM + << "-cp" + << "./libraries/net/minecraftforge/forge/1.12.2-14.23.5.2860/" + "forge-1.12.2-14.23.5.2860.jar:./libraries/org/ow2/asm/asm-debug-all/" + "5.2/asm-debug-all-5.2.jar:./libraries/net/minecraft/launchwrapper/" + "1.12/launchwrapper-1.12.jar:./libraries/org/jline/jline/3.5.1/" + "jline-3.5.1.jar:./libraries/com/typesafe/akka/akka-actor_2.11/2.3.3/" + "akka-actor_2.11-2.3.3.jar:./libraries/com/typesafe/config/1.2.1/" + "config-1.2.1.jar:./libraries/org/scala-lang/" + "scala-actors-migration_2.11/1.1.0/" + "scala-actors-migration_2.11-1.1.0.jar:./libraries/org/scala-lang/" + "scala-compiler/2.11.1/scala-compiler-2.11.1.jar:./libraries/org/" + "scala-lang/plugins/scala-continuations-library_2.11/1.0.2_mc/" + "scala-continuations-library_2.11-1.0.2_mc.jar:./libraries/org/" + "scala-lang/plugins/scala-continuations-plugin_2.11.1/1.0.2_mc/" + "scala-continuations-plugin_2.11.1-1.0.2_mc.jar:./libraries/org/" + "scala-lang/scala-library/2.11.1/scala-library-2.11.1.jar:./libraries/" + "org/scala-lang/scala-parser-combinators_2.11/1.0.1/" + "scala-parser-combinators_2.11-1.0.1.jar:./libraries/org/scala-lang/" + "scala-reflect/2.11.1/scala-reflect-2.11.1.jar:./libraries/org/" + "scala-lang/scala-swing_2.11/1.0.1/scala-swing_2.11-1.0.1.jar:./" + "libraries/org/scala-lang/scala-xml_2.11/1.0.2/" + "scala-xml_2.11-1.0.2.jar:./libraries/lzma/lzma/0.0.1/" + "lzma-0.0.1.jar:./libraries/java3d/vecmath/1.5.2/vecmath-1.5.2.jar:./" + "libraries/net/sf/trove4j/trove4j/3.0.3/trove4j-3.0.3.jar:./libraries/" + "org/apache/maven/maven-artifact/3.5.3/maven-artifact-3.5.3.jar:./" + "libraries/net/sf/jopt-simple/jopt-simple/5.0.3/" + "jopt-simple-5.0.3.jar:./libraries/org/apache/logging/log4j/log4j-api/" + "2.15.0/log4j-api-2.15.0.jar:./libraries/org/apache/logging/log4j/" + "log4j-core/2.15.0/log4j-core-2.15.0.jar:./libraries/org/tlauncher/" + "patchy/1.3.9/patchy-1.3.9.jar:./libraries/oshi-project/oshi-core/1.1/" + "oshi-core-1.1.jar:./libraries/net/java/dev/jna/jna/4.4.0/" + "jna-4.4.0.jar:./libraries/net/java/dev/jna/platform/3.4.0/" + "platform-3.4.0.jar:./libraries/com/ibm/icu/icu4j-core-mojang/51.2/" + "icu4j-core-mojang-51.2.jar:./libraries/com/paulscode/codecjorbis/" + "20101023/codecjorbis-20101023.jar:./libraries/com/paulscode/codecwav/" + "20101023/codecwav-20101023.jar:./libraries/com/paulscode/" + "libraryjavasound/20101123/libraryjavasound-20101123.jar:./libraries/" + "com/paulscode/librarylwjglopenal/20100824/" + "librarylwjglopenal-20100824.jar:./libraries/com/paulscode/" + "soundsystem/20120107/soundsystem-20120107.jar:./libraries/io/netty/" + "netty-all/4.1.9.Final/netty-all-4.1.9.Final.jar:./libraries/com/" + "google/guava/guava/21.0/guava-21.0.jar:./libraries/org/apache/" + "commons/commons-lang3/3.5/commons-lang3-3.5.jar:./libraries/" + "commons-io/commons-io/2.5/commons-io-2.5.jar:./libraries/" + "commons-codec/commons-codec/1.10/commons-codec-1.10.jar:./libraries/" + "net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:./libraries/net/java/" + "jutils/jutils/1.0.0/jutils-1.0.0.jar:./libraries/com/google/code/" + "gson/gson/2.8.0/gson-2.8.0.jar:./libraries/com/mojang/authlib/" + "1.5.25/authlib-1.5.25.jar:./libraries/com/mojang/realms/1.10.22/" + "realms-1.10.22.jar:./libraries/org/apache/commons/commons-compress/" + "1.8.1/commons-compress-1.8.1.jar:./libraries/org/apache/" + "httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:./libraries/" + "commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:./" + "libraries/org/apache/httpcomponents/httpcore/4.3.2/" + "httpcore-4.3.2.jar:./libraries/it/unimi/dsi/fastutil/7.1.0/" + "fastutil-7.1.0.jar:./libraries/org/apache/logging/log4j/log4j-api/" + "2.8.1/log4j-api-2.8.1.jar:./libraries/org/apache/logging/log4j/" + "log4j-core/2.8.1/log4j-core-2.8.1.jar:./libraries/org/lwjgl/lwjgl/" + "lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar:./" + "libraries/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/" + "lwjgl_util-2.9.4-nightly-20150209.jar:./libraries/com/mojang/" + "text2speech/1.10.3/text2speech-1.10.3.jar:./versions/Forge_1.12.2/" + "Forge_1.12.2.jar" + + << "-Dfml.ignoreInvalidMinecraftCertificates=true" + << "-Dfml.ignorePatchDiscrepancies=true" + << "-Djava.net.preferIPv4Stack=true" + << "-Dminecraft.applet.TargetDirectory=./" + << "-DlibraryDirectory=./libraries" + << "-Dlog4j.configurationFile=./assets/log_configs/client-1.12.xml" + + << "net.minecraft.launchwrapper.Launch" + << "--username" << username + << "--version" << "Forge_1.12.2" + << "--assetsDir" << "./assets" + << "--assetIndex" << "1.12" + << "--uuid" << uuid + << "--accessToken" << access_token + << "--userType" << "mojang" + + << "--tweakClass" << "net.minecraftforge.fml.common.launcher.FMLTweaker" + + << "--versionType" << "Forge" + << "--height" << "480" + << "--width" << "854" + + // Garbarge Collector общие настройки + << "-XX:+UnlockDiagnosticVMOptions" + << "-XX:+DisableExplicitGC" + << "-XX:ReservedCodeCacheSize=400M" + << "-XX:+AlwaysPreTouch" + << "-XX:+UseNUMA" + //<< "-XX:+UseFastUnorderedTimeStamps" // Не работает + //<< "-server" + << "-XX:+PerfDisableSharedMem" + << "-XX:AllocatePrefetchStyle=3"; + + + + // Garbarge Collector + // CMS (Concurrent Mark-Sweep) + arguments + << "-XX:+UseConcMarkSweepGC" + << "-XX:CMSInitiatingOccupancyFraction=75" + << "-XX:+UseCMSInitiatingOccupancyOnly" + << "-XX:CMSWaitDuration=1000" + << "-XX:+CMSConcurrentMTEnabled"; + + // G1GC (Garbage First Garbage Collector) + /* + << "-XX:+UseG1GC" + << "-XX:G1NewSizePercent=20" + << "-XX:G1ReservePercent=20" + << "-XX:MaxGCPauseMillis=50" + << "-XX:G1HeapRegionSize=32M" + */ + // C4 - Не поддерживается java8 + //<< "-XX:+UseC4GC" + //<< "-XX:MaxHeapSize=2G" + //<< "-XX:InitialHeapSize=1G" + + return arguments; +} diff --git a/src/app/launcher/forge1.12.2/getArgs.h b/src/app/launcher/forge1.12.2/getArgs.h new file mode 100644 index 0000000..44b0713 --- /dev/null +++ b/src/app/launcher/forge1.12.2/getArgs.h @@ -0,0 +1,22 @@ +#ifndef GETARGS_H +#define GETARGS_H + +#include +#include +#include +#include +#include + + +class getArgs : public QObject { + Q_OBJECT + +public: + explicit getArgs(); + ~getArgs(); + + QStringList getCrossPlatformArgs(QString &RAM, QString &username, QString &uuid, QString &access_token, QString &garbarge_collector); + +}; + +#endif diff --git a/src/app/launcher/launcher.cpp b/src/app/launcher/launcher.cpp new file mode 100644 index 0000000..c846921 --- /dev/null +++ b/src/app/launcher/launcher.cpp @@ -0,0 +1,69 @@ +#include "launcher.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "forge1.12.2/getArgs.h" + + +Launcher::Launcher(QObject *mainwindow) : QObject(mainwindow), process(new QProcess(this)), mainwindow(mainwindow), get_args(new getArgs()) { + // Подключение сигналов для отладки + /* + connect(process, &QProcess::readyReadStandardOutput, [this]() { + qDebug() << "Standard Output: " << process->readAllStandardOutput(); + }); + + connect(process, &QProcess::readyReadStandardError, [this]() { + qDebug() << "Standard Error: " << process->readAllStandardError(); + }); + + connect(process, QOverload::of(&QProcess::finished), + [this](int exitCode, QProcess::ExitStatus status) { + qDebug() << "Process finished with exit code:" << exitCode + << "and status:" << status; + }); + */ +} + +Launcher::~Launcher() { + delete process; +} + +void Launcher::startProcess( + QString &workingDir, + QString &executablePath, + QString &RAM, + QString &username, + QString &uuid, + QString &access_token, + QString garbarge_collector) { + QStringList arguments = get_args->getCrossPlatformArgs(RAM, username, uuid, access_token, garbarge_collector); + + process->setWorkingDirectory(workingDir); + process->start(executablePath, arguments); + + if (!process->waitForStarted()) { + qDebug() << "Failed to start process"; + qDebug() << process->errorString(); + return; + } + + QWidget *mainwindowWidget = qobject_cast(mainwindow); + + // Скрытие лаунчера при запуске + connect(process, + QOverload::of(&QProcess::finished), + [mainwindowWidget](int, QProcess::ExitStatus) { mainwindowWidget->show(); }); + + if (mainwindowWidget) { + mainwindowWidget->hide(); + } else { + qDebug() << "Parent object is not a QWidget."; + } + qDebug() << "Process started successfully"; +} diff --git a/src/app/launcher/launcher.h b/src/app/launcher/launcher.h new file mode 100644 index 0000000..0474743 --- /dev/null +++ b/src/app/launcher/launcher.h @@ -0,0 +1,34 @@ +#ifndef LAUNCHER_H +#define LAUNCHER_H + +#include +#include +#include +#include +#include + +#include "forge1.12.2/getArgs.h" + +class Launcher : public QObject { + Q_OBJECT + +public: + explicit Launcher(QObject *mainwindow = nullptr); + ~Launcher(); + + void startProcess( + QString &workingDir, + QString &executablePath, + QString &RAM, + QString &username, + QString &uuid, + QString &access_token, + QString garbarge_collector); + +private: + QProcess *process; + QObject *mainwindow; + getArgs *get_args; +}; + +#endif diff --git a/src/app/main.cpp b/src/app/main.cpp index cace609..4c8c6af 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,4 +1,4 @@ -#include "mainwindow.h" +#include "ui/mainwindow.h" #include diff --git a/src/app/mainwindow.cpp b/src/app/mainwindow.cpp deleted file mode 100644 index 369d4aa..0000000 --- a/src/app/mainwindow.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include - -#include "mainwindow.h" -#include "ui_mainwindow.h" - -#include -#include -#include -#include -#include -#include - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), ui(new Ui::MainWindow), process(new QProcess(this)) { - ui->setupUi(this); - - setWindowFlags(Qt::FramelessWindowHint); - setAttribute(Qt::WA_TranslucentBackground); - - connect(process, &QProcess::readyReadStandardOutput, this, [this]() { - qDebug() << "Standard Output: " << process->readAllStandardOutput(); - }); - - connect(process, &QProcess::readyReadStandardError, this, [this]() { - qDebug() << "Standard Error: " << process->readAllStandardError(); - }); -} - -MainWindow::~MainWindow() { delete ui; } - -void MainWindow::mousePressEvent(QMouseEvent *event) { - if (ui->border_top->geometry().contains(event->pos())) { - isDragging = true; - ui->border_top->setCursor(Qt::SizeAllCursor); - dragStartPosition = - event->globalPosition().toPoint() - frameGeometry().topLeft(); - event->accept(); - } -} - -void MainWindow::mouseMoveEvent(QMouseEvent *event) { - if (isDragging) { - move(event->globalPosition().toPoint() - dragStartPosition); - event->accept(); - } -} - -void MainWindow::mouseReleaseEvent(QMouseEvent *event) { - isDragging = false; - ui->border_top->setCursor(Qt::ArrowCursor); - event->accept(); -} - -void MainWindow::on_startBtn_clicked() { - QString RAM = "6154"; - - QDir exeDir(QCoreApplication::applicationDirPath()); - QString workDir = exeDir.absolutePath() + "/../../../mine/hitech"; - - QStringList arguments; - arguments - << "-Djava.library.path=./versions/Forge_1.12.2/natives" - //<< "-Xms" + RAM + "M" - << "-Xmx" + RAM + "M" - << "-cp" - << "./libraries/net/minecraftforge/forge/1.12.2-14.23.5.2860/" - "forge-1.12.2-14.23.5.2860.jar:./libraries/org/ow2/asm/asm-debug-all/" - "5.2/asm-debug-all-5.2.jar:./libraries/net/minecraft/launchwrapper/" - "1.12/launchwrapper-1.12.jar:./libraries/org/jline/jline/3.5.1/" - "jline-3.5.1.jar:./libraries/com/typesafe/akka/akka-actor_2.11/2.3.3/" - "akka-actor_2.11-2.3.3.jar:./libraries/com/typesafe/config/1.2.1/" - "config-1.2.1.jar:./libraries/org/scala-lang/" - "scala-actors-migration_2.11/1.1.0/" - "scala-actors-migration_2.11-1.1.0.jar:./libraries/org/scala-lang/" - "scala-compiler/2.11.1/scala-compiler-2.11.1.jar:./libraries/org/" - "scala-lang/plugins/scala-continuations-library_2.11/1.0.2_mc/" - "scala-continuations-library_2.11-1.0.2_mc.jar:./libraries/org/" - "scala-lang/plugins/scala-continuations-plugin_2.11.1/1.0.2_mc/" - "scala-continuations-plugin_2.11.1-1.0.2_mc.jar:./libraries/org/" - "scala-lang/scala-library/2.11.1/scala-library-2.11.1.jar:./libraries/" - "org/scala-lang/scala-parser-combinators_2.11/1.0.1/" - "scala-parser-combinators_2.11-1.0.1.jar:./libraries/org/scala-lang/" - "scala-reflect/2.11.1/scala-reflect-2.11.1.jar:./libraries/org/" - "scala-lang/scala-swing_2.11/1.0.1/scala-swing_2.11-1.0.1.jar:./" - "libraries/org/scala-lang/scala-xml_2.11/1.0.2/" - "scala-xml_2.11-1.0.2.jar:./libraries/lzma/lzma/0.0.1/" - "lzma-0.0.1.jar:./libraries/java3d/vecmath/1.5.2/vecmath-1.5.2.jar:./" - "libraries/net/sf/trove4j/trove4j/3.0.3/trove4j-3.0.3.jar:./libraries/" - "org/apache/maven/maven-artifact/3.5.3/maven-artifact-3.5.3.jar:./" - "libraries/net/sf/jopt-simple/jopt-simple/5.0.3/" - "jopt-simple-5.0.3.jar:./libraries/org/apache/logging/log4j/log4j-api/" - "2.15.0/log4j-api-2.15.0.jar:./libraries/org/apache/logging/log4j/" - "log4j-core/2.15.0/log4j-core-2.15.0.jar:./libraries/org/tlauncher/" - "patchy/1.3.9/patchy-1.3.9.jar:./libraries/oshi-project/oshi-core/1.1/" - "oshi-core-1.1.jar:./libraries/net/java/dev/jna/jna/4.4.0/" - "jna-4.4.0.jar:./libraries/net/java/dev/jna/platform/3.4.0/" - "platform-3.4.0.jar:./libraries/com/ibm/icu/icu4j-core-mojang/51.2/" - "icu4j-core-mojang-51.2.jar:./libraries/com/paulscode/codecjorbis/" - "20101023/codecjorbis-20101023.jar:./libraries/com/paulscode/codecwav/" - "20101023/codecwav-20101023.jar:./libraries/com/paulscode/" - "libraryjavasound/20101123/libraryjavasound-20101123.jar:./libraries/" - "com/paulscode/librarylwjglopenal/20100824/" - "librarylwjglopenal-20100824.jar:./libraries/com/paulscode/" - "soundsystem/20120107/soundsystem-20120107.jar:./libraries/io/netty/" - "netty-all/4.1.9.Final/netty-all-4.1.9.Final.jar:./libraries/com/" - "google/guava/guava/21.0/guava-21.0.jar:./libraries/org/apache/" - "commons/commons-lang3/3.5/commons-lang3-3.5.jar:./libraries/" - "commons-io/commons-io/2.5/commons-io-2.5.jar:./libraries/" - "commons-codec/commons-codec/1.10/commons-codec-1.10.jar:./libraries/" - "net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:./libraries/net/java/" - "jutils/jutils/1.0.0/jutils-1.0.0.jar:./libraries/com/google/code/" - "gson/gson/2.8.0/gson-2.8.0.jar:./libraries/com/mojang/authlib/" - "1.5.25/authlib-1.5.25.jar:./libraries/com/mojang/realms/1.10.22/" - "realms-1.10.22.jar:./libraries/org/apache/commons/commons-compress/" - "1.8.1/commons-compress-1.8.1.jar:./libraries/org/apache/" - "httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:./libraries/" - "commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:./" - "libraries/org/apache/httpcomponents/httpcore/4.3.2/" - "httpcore-4.3.2.jar:./libraries/it/unimi/dsi/fastutil/7.1.0/" - "fastutil-7.1.0.jar:./libraries/org/apache/logging/log4j/log4j-api/" - "2.8.1/log4j-api-2.8.1.jar:./libraries/org/apache/logging/log4j/" - "log4j-core/2.8.1/log4j-core-2.8.1.jar:./libraries/org/lwjgl/lwjgl/" - "lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar:./" - "libraries/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/" - "lwjgl_util-2.9.4-nightly-20150209.jar:./libraries/com/mojang/" - "text2speech/1.10.3/text2speech-1.10.3.jar:./versions/Forge_1.12.2/" - "Forge_1.12.2.jar" - // Общие - << "-XX:+UnlockDiagnosticVMOptions" - << "-XX:+DisableExplicitGC" - << "-XX:ReservedCodeCacheSize=400M" - << "-XX:+AlwaysPreTouch" - << "-XX:+UseNUMA" - //<< "-XX:+UseFastUnorderedTimeStamps" // Не работает - << "-XX:+PerfDisableSharedMem" - << "-XX:AllocatePrefetchStyle=3" - << "-server" - // CMS (Concurrent Mark-Sweep) - // - << "-XX:+UseConcMarkSweepGC" - << "-XX:CMSInitiatingOccupancyFraction=75" - << "-XX:+UseCMSInitiatingOccupancyOnly" - << "-XX:CMSWaitDuration=1000" - << "-XX:+CMSConcurrentMTEnabled" - // G1GC (Garbage First Garbage Collector) - //<< "-XX:+UseG1GC" - //<< "-XX:G1NewSizePercent=20" - //<< "-XX:G1ReservePercent=20" - //<< "-XX:MaxGCPauseMillis=50" - //<< "-XX:G1HeapRegionSize=32M" - // C4 - //<< "-XX:+UseC4GC" - //<< "-XX:MaxHeapSize=2G" - //<< "-XX:InitialHeapSize=1G" - << "-Dfml.ignoreInvalidMinecraftCertificates=true" - << "-Dfml.ignorePatchDiscrepancies=true" - << "-Djava.net.preferIPv4Stack=true" - << "-Dminecraft.applet.TargetDirectory=./" - << "-DlibraryDirectory=./libraries" - << "-Dlog4j.configurationFile=./assets/log_configs/client-1.12.xml" - - << "net.minecraft.launchwrapper.Launch" - << "--username" << "PIVODEVAT" - << "--version" << "Forge_1.12.2" - << "--gameDir" << "./" - << "--assetsDir" << "./assets" - << "--assetIndex" << "1.12" - << "--uuid" << "2c175d38f2e04dcab1dcd8f8d254c130" - << "--accessToken" << "fvTLJuNer7WUFh0AE1Xh5CZ3q2B92kTn" - << "--userType" << "mojang" - - << "--tweakClass" << "net.minecraftforge.fml.common.launcher.FMLTweaker" - - << "--versionType" << "Forge" - << "--height" << "480" - << "--width" << "854"; - - - QProcess *process = new QProcess(this); - process->setWorkingDirectory(workDir); - //process->start("/usr/lib/jvm/openjdk8/bin/java", arguments); - process->start("/home/xuy/dev/punkcraft/mine/hitech/java/zulu8.82.0.21-ca-jdk8.0.432-linux_x64/bin/java", arguments); - - // Подключение сигнала finished к слоту lambda для показа окна - connect(process, - QOverload::of(&QProcess::finished), - [this](int, QProcess::ExitStatus) { this->show(); }); - - // Скрытие окна перед запуском процесса - this->hide(); - - if (!process->waitForStarted()) { - qDebug() << "Failed to start process"; - qDebug() << process->errorString(); - return; - } -} diff --git a/src/app/mainwindow.h b/src/app/mainwindow.h deleted file mode 100644 index 78fbdf6..0000000 --- a/src/app/mainwindow.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include // Для обработки событий мыши -#include - -QT_BEGIN_NAMESPACE -namespace Ui { -class MainWindow; -} -QT_END_NAMESPACE - -class MainWindow : public QMainWindow { - Q_OBJECT - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - -protected: - void mousePressEvent(QMouseEvent *event) override; - void mouseMoveEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - -private slots: - void on_startBtn_clicked(); - -private: - Ui::MainWindow *ui; - QProcess *process; - - // Для перемещения окна - bool isDragging = false; - QPoint dragStartPosition; -}; -#endif diff --git a/src/app/settings/settings.cpp b/src/app/settings/settings.cpp new file mode 100644 index 0000000..99e8390 --- /dev/null +++ b/src/app/settings/settings.cpp @@ -0,0 +1,58 @@ +#include "settings.h" + +#include +#include +#include +#include +#include +#include +#include + + +Settings::Settings() {} + + +QString Settings::getStateFilePath(QString &profile) { +#ifdef Q_OS_WIN + QString stateDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); +#else + QString stateDir = QStandardPaths::writableLocation(QStandardPaths::StateLocation); +#endif + QDir().mkpath(stateDir); + return stateDir + "/settings_" + profile + ".json"; +} + + +void Settings::saveToJson(QString profile, QString RAM, QString java_path, QString garbarge_collector_method, QJsonArray additions_list) { + QString filePath = getStateFilePath(profile); + QJsonObject json; + json["RAM"] = RAM; + json["java_path"] = java_path; + json["garbarge_collector"] = garbarge_collector_method; + json["additions_list"] = additions_list; + + QFile file(filePath); + if (file.open(QIODevice::WriteOnly)) { + file.write(QJsonDocument(json).toJson()); + file.close(); + qDebug() << "Данные сохранены в" << filePath; + } else { + qWarning() << "Не удалось открыть файл для записи:" << filePath; + } +} + + +QJsonObject Settings::loadFromJson(QString &profile) { + QString filePath = getStateFilePath(profile); + QFile file(filePath); + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.readAll(); + file.close(); + QJsonDocument doc = QJsonDocument::fromJson(data); + if (doc.isObject()) { + return doc.object(); + } + } + qWarning() << "Не удалось загрузить данные из файла:" << filePath; + return QJsonObject(); +} diff --git a/src/app/settings/settings.h b/src/app/settings/settings.h new file mode 100644 index 0000000..7614cf2 --- /dev/null +++ b/src/app/settings/settings.h @@ -0,0 +1,19 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include + + +class Settings { +public: + explicit Settings(); + ~Settings(); + QJsonObject loadFromJson(QString &profile); + void saveToJson(QString profile, QString RAM, QString java_path, QString garbarge_collector_method, QJsonArray additions_list); + +private: + QString getStateFilePath(QString &profile); +}; + +#endif diff --git a/src/app/ui/mainwindow.cpp b/src/app/ui/mainwindow.cpp new file mode 100644 index 0000000..8e14821 --- /dev/null +++ b/src/app/ui/mainwindow.cpp @@ -0,0 +1,215 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "../launcher/launcher.h" +#include "../backend/backend.h" +#include "../settings/settings.h" +#include "../../resources/ui_mainwindow.h" + + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + process(new QProcess(this)), + launcher(new Launcher(this)), + backend(new Backend()), + settings(new Settings()) +{ + ui->setupUi(this); + + // Инициализация + setWindowFlags(Qt::FramelessWindowHint); + setAttribute(Qt::WA_TranslucentBackground); + ui->StackedWidget->setCurrentWidget(ui->load); // Окно по умолчанию + on_selected_profile_currentTextChanged(ui->selected_profile->currentText()); // Обновление ui->selected_profile + + + backend->authWithToken([this](QString username, QString uuid, QString access_token) { + if (username.isEmpty() || uuid.isEmpty() || access_token.isEmpty()) { + ui->StackedWidget->setCurrentWidget(ui->auth); + } else { + ui->StackedWidget->setCurrentWidget(ui->main); + ui->main_nickname_label->setText(username); + this->username = username; + this->uuid = uuid; + this->access_token = access_token; + } + }); + + /* + connect(process, &QProcess::readyReadStandardOutput, this, [this]() { + qDebug() << "Standard Output: " << process->readAllStandardOutput(); + }); + + connect(process, &QProcess::readyReadStandardError, this, [this]() { + qDebug() << "Standard Error: " << process->readAllStandardError(); + }); + */ +} + + +MainWindow::~MainWindow() { delete ui; } + + +void MainWindow::mousePressEvent(QMouseEvent *event) { + if (ui->border_top->geometry().contains(event->pos())) { + isDragging = true; + ui->border_top->setCursor(Qt::SizeAllCursor); + dragStartPosition = + event->globalPosition().toPoint() - frameGeometry().topLeft(); + event->accept(); + } +} + + +void MainWindow::mouseMoveEvent(QMouseEvent *event) { + if (isDragging) { + move(event->globalPosition().toPoint() - dragStartPosition); + event->accept(); + } +} + + +void MainWindow::mouseReleaseEvent(QMouseEvent *event) { + isDragging = false; + ui->border_top->setCursor(Qt::ArrowCursor); + event->accept(); +} + + +void MainWindow::on_auth_login_btn_clicked() { + QString username = ui->auth_login_line->text(); + QString password = ui->auth_pass_line->text(); + + bool flag = ui->auth_save_session_check_btn->isChecked(); + + backend->authWithPassword( + username, + password, + flag, + [this](QString username, QString uuid, QString access_token) + { + if (!username.isEmpty() && !uuid.isEmpty() && !access_token.isEmpty()) { + ui->auth_status_label->setText(""); + ui->StackedWidget->setCurrentWidget(ui->main); + ui->main_nickname_label->setText(username); + + this->username = username; + this->uuid = uuid; + this->access_token = access_token; + } else { + ui->auth_status_label->setText("Ошибка авторизации"); + } + }); +} + + +/* + * QComoBox не позволяет менять ориентацию текста + * В этой функции происходит его центрирование через padding-left + */ +void MainWindow::on_selected_profile_currentTextChanged(QString text) { + // Рассчёт padding-left + QFontMetrics metrics(ui->selected_profile->font()); + int textWidth = metrics.horizontalAdvance(text); + int comboBoxWidth = ui->selected_profile->width(); + int paddingLeft = (comboBoxWidth - textWidth) / 2; + + // Обновление stylesheet заменой + QString currentStyleSheet = ui->selected_profile->styleSheet(); + QString newStyleSheet = currentStyleSheet; + if (currentStyleSheet.contains("padding-left:")) { + newStyleSheet.replace(QRegularExpression("padding-left:\\s*\\d+px;?"), QString("padding-left: %1px;").arg(paddingLeft)); + } else { + newStyleSheet += QString(" QComboBox { padding-left: %1px; }").arg(paddingLeft); + } + ui->selected_profile->setStyleSheet(newStyleSheet); +} + + +void MainWindow::on_settings_btn_clicked() { + ui->StackedWidget->setCurrentWidget(ui->settings); + + // Обновление значений + QString selected_profile = ui->selected_profile->currentText(); + json_settings = settings->loadFromJson(selected_profile); + + ui->settings_ram->setText(json_settings["RAM"].toString()); + ui->settings_java_path->setText(json_settings["java_path"].toString()); + ui->settings_garbarge_collector->setCurrentText(json_settings["garbarge_collector"].toString()); + +} + + +void MainWindow::on_settings_back_btn_clicked() { + ui->StackedWidget->setCurrentWidget(ui->main); +} + + +void MainWindow::on_logout_btn_clicked() { + ui->StackedWidget->setCurrentWidget(ui->auth); + QString session_cache = backend->getStateFilePath(); + QFile::remove(session_cache); +} + + +void MainWindow::on_settings_apply_btn_clicked() { + QJsonArray addition_settings; + settings->saveToJson( + ui->selected_profile->currentText(), + ui->settings_ram->text(), + ui->settings_java_path->text(), + ui->settings_garbarge_collector->currentText(), + addition_settings + ); + ui->StackedWidget->setCurrentWidget(ui->main); +} + + +void MainWindow::on_start_btn_clicked() { + // Обновление переменных запуска клиента + QString selected_profile = ui->selected_profile->currentText(); + QDir exe_dir(QCoreApplication::applicationDirPath()); + client_dir = exe_dir.absolutePath() + "/../../../mine/" + selected_profile; + + + json_settings = settings->loadFromJson(selected_profile); + java_path = json_settings["java_path"].toString(); + RAM = json_settings["RAM"].toString(); + garbarge_collector = json_settings["garbarge_collector"].toString(); + + // Значения по умолчанию + if (selected_profile == "CyberExtrieme") { + java_path = java_path.isEmpty() ? + exe_dir.absolutePath() + "/../../../mine/CyberExtrieme/java/zing24.12.0.0-6-jre8.0.432/bin/java" : java_path; + RAM = RAM.isEmpty() ? + "4096M" : RAM; + garbarge_collector = garbarge_collector.isEmpty() ? + "default_collector" : garbarge_collector; + } + + + + // Запуск клиента + launcher->startProcess( + this->client_dir, + this->java_path, + this->RAM, + this->username, + this->uuid, + this->access_token, + this->garbarge_collector + ); + +} diff --git a/src/app/ui/mainwindow.h b/src/app/ui/mainwindow.h new file mode 100644 index 0000000..6a52e1d --- /dev/null +++ b/src/app/ui/mainwindow.h @@ -0,0 +1,62 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include + +#include "../launcher/launcher.h" +#include "../backend/backend.h" +#include "../settings/settings.h" + + + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow { + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + +private slots: + void on_start_btn_clicked(); + void on_auth_login_btn_clicked(); + void on_settings_btn_clicked(); + void on_settings_back_btn_clicked(); + void on_logout_btn_clicked(); + void on_settings_apply_btn_clicked(); + void on_selected_profile_currentTextChanged(QString text); + + +private: + Ui::MainWindow *ui; + QProcess *process; + Launcher *launcher; + Backend *backend; + Settings *settings; + + bool isDragging = false; + QPoint dragStartPosition; + QString username; + QString uuid; + QString access_token; + + // Переменные для запуска клиента + QString client_dir; + QString RAM; + QString java_path; + QString garbarge_collector; + QJsonObject json_settings; +}; +#endif diff --git a/src/resources/main/banner.jpg b/src/resources/main/banner.jpg index c59dda9..16e1eb2 100644 Binary files a/src/resources/main/banner.jpg and b/src/resources/main/banner.jpg differ diff --git a/src/resources/main/selected_profile.png b/src/resources/main/selected_profile.png new file mode 100644 index 0000000..eeb8f11 Binary files /dev/null and b/src/resources/main/selected_profile.png differ diff --git a/src/resources/main/svg/selected_profile.svg b/src/resources/main/svg/selected_profile.svg new file mode 100644 index 0000000..2fc3346 --- /dev/null +++ b/src/resources/main/svg/selected_profile.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/src/app/mainwindow.ui b/src/resources/mainwindow.ui similarity index 52% rename from src/app/mainwindow.ui rename to src/resources/mainwindow.ui index 8bf141a..0adff74 100644 --- a/src/app/mainwindow.ui +++ b/src/resources/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1032 - 637 + 1009 + 631 @@ -33,7 +33,8 @@ QFrame#border_top, QFrame#border_bottom, QFrame#border_left, QFrame#border_right { - background-color: rgb(217, 78, 108); + /*background-color: rgb(217, 78, 108);*/ + background-color: rgba(255, 255, 255, 0.14); border: none; } @@ -171,8 +172,9 @@ QLineEdit::placeholder { } - 1 + 2 + QWidget#auth { @@ -198,6 +200,26 @@ QLineEdit::placeholder { 0 + + + + + 11 + 50 + false + + + + margin-top: 10px; + + + + + + Qt::AlignCenter + + + @@ -353,7 +375,7 @@ QLineEdit::placeholder { 0 - + 0 @@ -387,7 +409,7 @@ QLineEdit::placeholder { - + 0 @@ -421,7 +443,7 @@ QLineEdit::placeholder { - + 0 @@ -489,7 +511,7 @@ QLineEdit::placeholder { - + 10 @@ -529,7 +551,7 @@ QLineEdit::placeholder { - + 16777215 @@ -601,30 +623,166 @@ QLineEdit::placeholder { 0 - - - - 0 - 0 - - - - - 250 - 300 - - + - QWidget#main_banner { + QWidget#CyberExtrieme { border-image: url(:/main/banner.jpg) 0 0 0 0 stretch stretch; } - - QFrame::StyledPanel - - - QFrame::Raised - + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 351 + 45 + + + + + 351 + 45 + + + + + 12 + 75 + true + + + + QComboBox { + color: rgba(255, 255, 255,0.9); + background-color: rgb(31, 35, 40); + border: 2px solid rgb(66, 68, 70); + border-top: 0px solid rgba(255, 255, 255, 0.5); + border-top-left-radius: 2px; + border-top-right-radius: 2px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + + /* + QComboBox не имеет автовыравнивания + в коде автовыравнивание реализовано через изменение этого параметра + к слоту currentIndexChanged подключена функция реализующая это: + MainWindow::on_selected_profile_currentIndexChanged + + Есть реализация этого с кастомным QComboBox, но она не сохраняет font + и styleSheet виджета, поэтому пользуемся :) + Здесь padding-left как затычка чтобы в глаза не бросалось + */ + padding-left: 100px; +} + +QFrame { + border-bottom-right-radius: 5px; +} + +QComboBox::drop-down { + width: 15px; + + background-color: rgba(255,255,255,0.02); + image: url(:/main/selected_profile.png); + + border-left: 2px solid rgba(255, 255, 255, 0.01); + border-bottom: 2px solid rgba(255, 255, 255, 0.014); + border-right: 2px solid rgba(0, 0, 0, 0.01); + border-top: 2px solid rgba(255, 255, 255, 0.01); + + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 5px; +} + + +QComboBox:hover { + border: 2px solid rgb(86, 88, 90); + border-top: 0px solid rgba(255, 255, 255, 0.68); +} + + + QComboBox::InsertAtBottom + + + + + + + CyberExtrieme + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 473 + + + + + + + @@ -647,6 +805,13 @@ QLineEdit::placeholder { 72 + + QFrame#frame_settings_btn { + border-top: 2px solid rgb(66, 68, 70); + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + QFrame::StyledPanel @@ -658,7 +823,7 @@ QLineEdit::placeholder { 0 - 20 + 24 0 @@ -670,44 +835,29 @@ QLineEdit::placeholder { 0 - - - - 48 - 48 - - - - - 48 - 48 - - - - background-color: rgb(255, 255, 255); - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - + - 12 + 14 75 true - margin-left: 15px; + QLabel { + color: rgba(255,255,255,0.96); +} + +QLabel:hover { + color: rgba(255,255,255,0.8); +} + +QLabel:pressed { + color: rgba(255,255,255,0.96); +} - PIVODEVAT + UNAUTHORIZED @@ -724,6 +874,85 @@ QLineEdit::placeholder { + + + + 0 + + + 0 + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 50 + + + + + + + + + 35 + 35 + + + + + 35 + 35 + + + + + 13 + 75 + true + + + + QPushButton { + border:none; + color: rgba(255,255,255,0.85); +} + +QPushButton:hover { + color: rgba(255,255,255,0.55); +} + +QPushButton:pressed { + color: rgba(255,255,255,0.3); +} + + + |← + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -746,7 +975,7 @@ QLineEdit::placeholder { - + 0 @@ -825,7 +1054,7 @@ QPushButton:pressed { - + 0 @@ -845,6 +1074,19 @@ QPushButton:pressed { true + + QPushButton { + color: rgba(255,255,255,0.96); +} + +QPushButton:hover { + color: rgba(255,255,255,0.8); +} + +QPushButton:pressed { + color: rgba(255,255,255,0.96); +} + Играть @@ -856,40 +1098,535 @@ QPushButton:pressed { - - - - 30 - 30 - 951 - 61 - + + + 4 - - 2000 + + 0 - - 8000 + + 7 - - 2000 + + 0 - - 2000 + + 0 - - true - - - Qt::Horizontal - - - false - - - false - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 310 + 35 + + + + + 310 + 35 + + + + + 12 + 75 + true + + + + color: rgb(242, 185, 70); +background-color: rgb(48, 50, 54); +padding-left: 5px; +padding-right: 5px; +border: 1px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 3px; +border-top-right-radius: 3px; +border-bottom-left-radius: 0px; +border-bottom-right-radius: 0px; + + + Garbarge collector method + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 310 + 27 + + + + + 310 + 16777215 + + + + + 10 + + + + color: rgb(255, 255, 255); +background-color: rgb(24, 27, 31); +border: none; +border: 1px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 0px; +border-top-right-radius: 0px; +border-bottom-left-radius: 3px; +border-bottom-right-radius: 3px; + + + QComboBox::InsertAtBottom + + + + CMS (Concurrent Mark-Sweep) + + + + + G1GC (Garbage First Garbage Collector) + + + + + Azul's Continuously Concurrent Compacting Collector (C4) + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 0 + 4 + + + + + + + + 0 + + + 11 + + + 11 + + + + + + 0 + 0 + + + + + 0 + 42 + + + + + 130 + 42 + + + + + 12 + 75 + true + + + + color: rgb(242, 185, 70); +background-color: rgb(48, 50, 54); +padding-left: 5px; +padding-right: 5px; +border: 1px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 3px; +border-bottom-left-radius: 3px; +border-top-right-radius: 0px; +border-bottom-right-radius: 0px; + + + Java path + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 42 + + + + + 16777215 + 42 + + + + + 9 + + + + background-color: rgb(24, 27, 31); + +/* padding */ +padding-left: 14px; + +/* Border */ +border: 1px solid rgba(255, 255, 255, 0.5); +border-left: 0px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 0px; +border-bottom-left-radius: 0px; +border-top-right-radius: 3px; +border-bottom-right-radius: 3px; + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + default + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 42 + + + + + 230 + 42 + + + + + 12 + 75 + true + + + + color: rgb(242, 185, 70); +background-color: rgb(48, 50, 54); +padding-left: 5px; +padding-right: 5px; +border: 1px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 3px; +border-bottom-left-radius: 3px; +border-top-right-radius: 0px; +border-bottom-right-radius: 0px; + + + Оперативная память + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 42 + + + + + 80 + 42 + + + + + 10 + + + + background-color: rgb(24, 27, 31); +border: 1px solid rgba(255, 255, 255, 0.5); +border-left: 0px solid rgba(255, 255, 255, 0.5); +border-top-left-radius: 0px; +border-bottom-left-radius: 0px; +border-top-right-radius: 3px; +border-bottom-right-radius: 3px; + + + Qt::AlignCenter + + + 4096M + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 8 + + + + + + + + QFrame { + background-color: rgb(48, 50, 54); + border-top: 2px solid rgb(66, 68, 70); + padding-bottom: 8px; + padding-top: 10px; + + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + + + + 7 + + + 0 + + + 13 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 85 + 45 + + + + + 85 + 45 + + + + + 14 + 50 + false + + + + color: rgba(217,78,108,1); + + + + + + + + + + + 85 + 45 + + + + + 85 + 45 + + + + + 19 + 50 + false + + + + <html><head/><body><p><br/></p></body></html> + + + color: rgb(96,153,38); +padding-bottom: 2px; +/* +color: rgb(242, 185, 70); +*/ + + + ✔️ + + + + + + + @@ -961,7 +1698,7 @@ QPushButton:pressed { - + diff --git a/src/resources/resources.qrc b/src/resources/resources.qrc index 979a742..8fb3988 100644 --- a/src/resources/resources.qrc +++ b/src/resources/resources.qrc @@ -1,6 +1,7 @@ auth/logo.png + main/selected_profile.png main/settings_pressed_32x32.png main/settings_hover_32x32.png main/settings_32x32.png