Добавлена реализация базовых профилей (Имя, путь до java)
This commit is contained in:
@@ -16,7 +16,7 @@ qt_add_executable(minecraft-launcher
|
|||||||
settingsdialog.h settingsdialog.cpp
|
settingsdialog.h settingsdialog.cpp
|
||||||
settingsdialog.ui
|
settingsdialog.ui
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
|
profiledialog.h profiledialog.cpp profiledialog.ui
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
146
mainwindow.cpp
146
mainwindow.cpp
@@ -1,6 +1,7 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_mainwindow.h" // Подключаем сгенерированный заголовочный файл
|
#include "ui_mainwindow.h" // Подключаем сгенерированный заголовочный файл
|
||||||
#include "settingsdialog.h"
|
#include "settingsdialog.h"
|
||||||
|
#include "profiledialog.h" // Подключаем новый диалог
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@@ -12,6 +13,8 @@
|
|||||||
#include <QJsonObject> // Для работы с JSON
|
#include <QJsonObject> // Для работы с JSON
|
||||||
#include <QJsonArray> // Для работы с JSON
|
#include <QJsonArray> // Для работы с JSON
|
||||||
#include <QJsonValue> // Для работы с JSON
|
#include <QJsonValue> // Для работы с JSON
|
||||||
|
#include <QUuid> // Для генерации ID профиля
|
||||||
|
#include <QStandardPaths> // Для поиска папки с данными
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
@@ -32,6 +35,9 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
connect(process, &QProcess::readyReadStandardError, this, &MainWindow::readProcessOutput);
|
connect(process, &QProcess::readyReadStandardError, this, &MainWindow::readProcessOutput);
|
||||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onProcessFinished(int, QProcess::ExitStatus)));
|
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onProcessFinished(int, QProcess::ExitStatus)));
|
||||||
connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(onProcessError(QProcess::ProcessError)));
|
connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(onProcessError(QProcess::ProcessError)));
|
||||||
|
// Загружаем профили при старте
|
||||||
|
profilesPath = "/launcher_profiles.json";
|
||||||
|
loadProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
@@ -86,8 +92,146 @@ bool checkRules(const QJsonObject &item) {
|
|||||||
return isAllowed;
|
return isAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::loadProfiles()
|
||||||
|
{
|
||||||
|
QFile profilesFile(profilesPath);
|
||||||
|
if (profilesFile.exists() && profilesFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(profilesFile.readAll());
|
||||||
|
profilesData = doc.object();
|
||||||
|
profilesFile.close();
|
||||||
|
} else {
|
||||||
|
// Создаем базовую структуру, если файла нет
|
||||||
|
profilesData = QJsonObject({{"profiles", QJsonObject()}});
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject profiles = profilesData["profiles"].toObject();
|
||||||
|
ui->profileComboBox->clear();
|
||||||
|
|
||||||
|
if (profiles.isEmpty()) {
|
||||||
|
// Если профилей нет, принудительно открываем диалог создания
|
||||||
|
QMessageBox::information(this, "Настройка", "Не найдено ни одного профиля. Давайте создадим новый.");
|
||||||
|
createNewProfile();
|
||||||
|
return; // createNewProfile вызовет loadProfiles() повторно
|
||||||
|
}
|
||||||
|
|
||||||
|
// Заполняем ComboBox
|
||||||
|
for (const QString &key : profiles.keys()) {
|
||||||
|
QJsonObject profile = profiles[key].toObject();
|
||||||
|
ui->profileComboBox->addItem(profile["name"].toString(), key); // Имя и UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::saveProfiles()
|
||||||
|
{
|
||||||
|
QFile profilesFile(profilesPath);
|
||||||
|
if (profilesFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
QJsonDocument doc(profilesData);
|
||||||
|
profilesFile.write(doc.toJson(QJsonDocument::Indented));
|
||||||
|
profilesFile.close();
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(this, "Ошибка", "Не удалось сохранить файл профилей: " + profilesFile.errorString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_editProfileButton_clicked()
|
||||||
|
{
|
||||||
|
// 1. Проверяем, выбран ли профиль
|
||||||
|
QString currentProfileId = ui->profileComboBox->currentData().toString();
|
||||||
|
if (currentProfileId.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "Нет профиля", "Пожалуйста, выберите профиль для редактирования.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Получаем данные текущего профиля
|
||||||
|
QJsonObject profiles = profilesData["profiles"].toObject();
|
||||||
|
QJsonObject currentProfile = profiles[currentProfileId].toObject();
|
||||||
|
|
||||||
|
// 3. Создаем диалог и заполняем его данными
|
||||||
|
ProfileDialog dialog(this);
|
||||||
|
dialog.setWindowTitle("Редактирование профиля");
|
||||||
|
dialog.setProfileName(currentProfile["name"].toString());
|
||||||
|
dialog.setJavaPath(currentProfile["javaDir"].toString());
|
||||||
|
|
||||||
|
// 4. Показываем диалог и обрабатываем результат
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
if (dialog.profileName().isEmpty() || dialog.javaPath().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "Ошибка", "Имя профиля и путь к Java не могут быть пустыми.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Обновляем данные в нашем JSON объекте
|
||||||
|
currentProfile["name"] = dialog.profileName();
|
||||||
|
currentProfile["javaDir"] = dialog.javaPath();
|
||||||
|
|
||||||
|
// 6. Записываем обновленный профиль обратно
|
||||||
|
profiles[currentProfileId] = currentProfile;
|
||||||
|
profilesData["profiles"] = profiles;
|
||||||
|
|
||||||
|
// 7. Сохраняем и перезагружаем список
|
||||||
|
saveProfiles();
|
||||||
|
|
||||||
|
// Сохраняем ID, чтобы восстановить выбор после перезагрузки
|
||||||
|
QString previouslySelectedId = currentProfileId;
|
||||||
|
loadProfiles();
|
||||||
|
int indexToSelect = ui->profileComboBox->findData(previouslySelectedId);
|
||||||
|
if (indexToSelect != -1) {
|
||||||
|
ui->profileComboBox->setCurrentIndex(indexToSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::createNewProfile()
|
||||||
|
{
|
||||||
|
ProfileDialog dialog(this);
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
if (dialog.profileName().isEmpty() || dialog.javaPath().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "Ошибка", "Имя профиля и путь к Java не могут быть пустыми.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||||
|
QJsonObject newProfile;
|
||||||
|
newProfile["name"] = dialog.profileName();
|
||||||
|
newProfile["javaDir"] = dialog.javaPath();
|
||||||
|
newProfile["lastVersionId"] = "";
|
||||||
|
newProfile["created"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||||
|
newProfile["lastUsed"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||||
|
newProfile["icon"] = "Bedrock";
|
||||||
|
newProfile["type"] = "custom";
|
||||||
|
|
||||||
|
QJsonObject profiles = profilesData["profiles"].toObject();
|
||||||
|
profiles[uuid] = newProfile;
|
||||||
|
profilesData["profiles"] = profiles;
|
||||||
|
|
||||||
|
saveProfiles();
|
||||||
|
loadProfiles(); // Перезагружаем список профилей
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_addProfileButton_clicked()
|
||||||
|
{
|
||||||
|
createNewProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_profileComboBox_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
// Пока ничего не делаем, но слот полезен для будущего
|
||||||
|
Q_UNUSED(index);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_launchButton_clicked()
|
void MainWindow::on_launchButton_clicked()
|
||||||
{
|
{
|
||||||
|
QString currentProfileId = ui->profileComboBox->currentData().toString();
|
||||||
|
if (currentProfileId.isEmpty()) {
|
||||||
|
QMessageBox::critical(this, "Ошибка", "Не выбран профиль для запуска!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QJsonObject profile = profilesData["profiles"].toObject()[currentProfileId].toObject();
|
||||||
|
QString javaPath = profile["javaDir"].toString();
|
||||||
|
if (!QFileInfo::exists(javaPath)) {
|
||||||
|
QMessageBox::critical(this, "Ошибка", "Не найден исполняемый файл Java, указанный в профиле:\n" + javaPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// --- 1. Выбор версии (остается без изменений) ---
|
// --- 1. Выбор версии (остается без изменений) ---
|
||||||
QString minecraftPath = getMinecraftPath();
|
QString minecraftPath = getMinecraftPath();
|
||||||
if (minecraftPath.isEmpty()) {
|
if (minecraftPath.isEmpty()) {
|
||||||
@@ -229,7 +373,7 @@ void MainWindow::on_launchButton_clicked()
|
|||||||
|
|
||||||
// --- 6. Финальная сборка и запуск ---
|
// --- 6. Финальная сборка и запуск ---
|
||||||
QString mainClass = rootObj["mainClass"].toString();
|
QString mainClass = rootObj["mainClass"].toString();
|
||||||
QString javaPath = "java";
|
//QString javaPath = "java";
|
||||||
|
|
||||||
QStringList finalArguments;
|
QStringList finalArguments;
|
||||||
finalArguments << jvmArgs << mainClass << gameArgs;
|
finalArguments << jvmArgs << mainClass << gameArgs;
|
||||||
|
|||||||
11
mainwindow.h
11
mainwindow.h
@@ -4,6 +4,7 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QJsonObject> // Важно: добавить для хранения данных профилей
|
||||||
|
|
||||||
// Предварительное объявление класса, сгенерированного из mainwindow.ui
|
// Предварительное объявление класса, сгенерированного из mainwindow.ui
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -24,6 +25,9 @@ private slots:
|
|||||||
void on_modsFolderButton_clicked();
|
void on_modsFolderButton_clicked();
|
||||||
void on_updateModsButton_clicked();
|
void on_updateModsButton_clicked();
|
||||||
void on_settingsButton_clicked();
|
void on_settingsButton_clicked();
|
||||||
|
void on_addProfileButton_clicked(); // Слот для кнопки "Новый..."
|
||||||
|
void on_editProfileButton_clicked(); // <-- ДОБАВЬТЕ ЭТОТ СЛОТ
|
||||||
|
void on_profileComboBox_currentIndexChanged(int index); // Слот для смены профиля
|
||||||
|
|
||||||
// Слоты для QProcess (подключаются вручную)
|
// Слоты для QProcess (подключаются вручную)
|
||||||
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
@@ -33,6 +37,13 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
QString getMinecraftPath();
|
QString getMinecraftPath();
|
||||||
|
|
||||||
|
// Новые методы для работы с профилями
|
||||||
|
void loadProfiles();
|
||||||
|
void saveProfiles();
|
||||||
|
void createNewProfile();
|
||||||
|
QString profilesPath; // Путь к launcher_profiles.json
|
||||||
|
QJsonObject profilesData; // JSON данные из файла
|
||||||
|
|
||||||
Ui::MainWindow *ui; // Указатель на объект интерфейса
|
Ui::MainWindow *ui; // Указатель на объект интерфейса
|
||||||
QProcess *process;
|
QProcess *process;
|
||||||
QSettings *settings;
|
QSettings *settings;
|
||||||
|
|||||||
@@ -15,6 +15,34 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Профиль:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="profileComboBox"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="addProfileButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Новый...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="editProfileButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Редактировать...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="launchButton">
|
<widget class="QPushButton" name="launchButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -65,4 +93,4 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
48
profiledialog.cpp
Normal file
48
profiledialog.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include "profiledialog.h"
|
||||||
|
#include "ui_profiledialog.h"
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
ProfileDialog::ProfileDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ProfileDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileDialog::~ProfileDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileDialog::profileName() const
|
||||||
|
{
|
||||||
|
return ui->profileNameEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileDialog::javaPath() const
|
||||||
|
{
|
||||||
|
return ui->javaPathEdit->text();
|
||||||
|
}
|
||||||
|
// === РЕАЛИЗАЦИЯ НОВЫХ ФУНКЦИЙ ===
|
||||||
|
void ProfileDialog::setProfileName(const QString &name)
|
||||||
|
{
|
||||||
|
ui->profileNameEdit->setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileDialog::setJavaPath(const QString &path)
|
||||||
|
{
|
||||||
|
ui->javaPathEdit->setText(path);
|
||||||
|
}
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
void ProfileDialog::on_browseButton_clicked()
|
||||||
|
{
|
||||||
|
QString filter = "Исполняемый файл (java.exe)";
|
||||||
|
#if !defined(Q_OS_WIN)
|
||||||
|
filter = "Все файлы (*)";
|
||||||
|
#endif
|
||||||
|
QString path = QFileDialog::getOpenFileName(this, "Выберите java.exe", QDir::homePath(), filter);
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
ui->javaPathEdit->setText(QDir::toNativeSeparators(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
32
profiledialog.h
Normal file
32
profiledialog.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef PROFILEDIALOG_H
|
||||||
|
#define PROFILEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ProfileDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ProfileDialog(QWidget *parent = nullptr);
|
||||||
|
~ProfileDialog();
|
||||||
|
|
||||||
|
QString profileName() const;
|
||||||
|
QString javaPath() const;
|
||||||
|
// === НОВЫЕ ФУНКЦИИ ===
|
||||||
|
void setProfileName(const QString &name);
|
||||||
|
void setJavaPath(const QString &path);
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_browseButton_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ProfileDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PROFILEDIALOG_H
|
||||||
99
profiledialog.ui
Normal file
99
profiledialog.ui
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ProfileDialog</class>
|
||||||
|
<widget class="QDialog" name="ProfileDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>450</width>
|
||||||
|
<height>150</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Настройка профиля</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Имя профиля:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="profileNameEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Путь к Java:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="javaPathEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="browseButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>ProfileDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>ProfileDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
Reference in New Issue
Block a user