diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index b0314743d..c489f6112 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -211,6 +211,7 @@ void InstanceImportTask::processZipPack()
progressStep->status = status;
stepProgress(*progressStep);
});
+ connect(zipTask.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
m_task.reset(zipTask);
zipTask->start();
}
@@ -334,6 +335,8 @@ void InstanceImportTask::processFlame()
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
+ connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
+
m_task.reset(inst_creation_task);
setAbortable(true);
m_task->start();
@@ -431,6 +434,8 @@ void InstanceImportTask::processModrinth()
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
+ connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
+
m_task.reset(inst_creation_task);
setAbortable(true);
m_task->start();
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 991afce89..635cecfac 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -248,6 +248,7 @@ void MinecraftInstance::loadSpecificSettings()
m_settings->registerSetting("ExportSummary", "");
m_settings->registerSetting("ExportAuthor", "");
m_settings->registerSetting("ExportOptionalFiles", true);
+ m_settings->registerSetting("ExportRecommendedRAM");
qDebug() << "Instance-type specific settings were loaded!";
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index c30ba5249..5d9c74ccf 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -54,6 +54,7 @@
#include "settings/INISettingsObject.h"
+#include "sys.h"
#include "tasks/ConcurrentTask.h"
#include "ui/dialogs/BlockedModsDialog.h"
#include "ui/dialogs/CustomMessageBox.h"
@@ -418,6 +419,24 @@ bool FlameCreationTask::createInstance()
}
}
+ int recommendedRAM = m_pack.minecraft.recommendedRAM;
+
+ // only set memory if this is a fresh instance
+ if (m_instance == nullptr && recommendedRAM > 0) {
+ const uint64_t sysMiB = Sys::getSystemRam() / Sys::mebibyte;
+ const uint64_t max = sysMiB * 0.9;
+
+ if (recommendedRAM > max) {
+ logWarning(tr("The recommended memory of the modpack exceeds 90% of your system RAM—reducing it from %1 MiB to %2 MiB!")
+ .arg(recommendedRAM)
+ .arg(max));
+ recommendedRAM = max;
+ }
+
+ instance.settings()->set("OverrideMemory", true);
+ instance.settings()->set("MaxMemAlloc", recommendedRAM);
+ }
+
QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods");
QFileInfo jarmodsInfo(jarmodsPath);
if (jarmodsInfo.isDir()) {
diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp
index c9a35f3cf..900fd1a87 100644
--- a/launcher/modplatform/flame/FlamePackExportTask.cpp
+++ b/launcher/modplatform/flame/FlamePackExportTask.cpp
@@ -41,22 +41,8 @@
const QString FlamePackExportTask::TEMPLATE = "
{name}{authors}\n";
const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" });
-FlamePackExportTask::FlamePackExportTask(const QString& name,
- const QString& version,
- const QString& author,
- bool optionalFiles,
- InstancePtr instance,
- const QString& output,
- MMCZip::FilterFileFunction filter)
- : name(name)
- , version(version)
- , author(author)
- , optionalFiles(optionalFiles)
- , instance(instance)
- , mcInstance(dynamic_cast(instance.get()))
- , gameRoot(instance->gameRoot())
- , output(output)
- , filter(filter)
+FlamePackExportTask::FlamePackExportTask(FlamePackExportOptions&& options)
+ : m_options(std::move(options)), m_gameRoot(m_options.instance->gameRoot())
{}
void FlamePackExportTask::executeTask()
@@ -81,7 +67,7 @@ void FlamePackExportTask::collectFiles()
QCoreApplication::processEvents();
files.clear();
- if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) {
+ if (!MMCZip::collectFileListRecursively(m_options.instance->gameRoot(), nullptr, &files, m_options.filter)) {
emitFailed(tr("Could not search for files"));
return;
}
@@ -89,11 +75,8 @@ void FlamePackExportTask::collectFiles()
pendingHashes.clear();
resolvedFiles.clear();
- if (mcInstance != nullptr) {
- mcInstance->loaderModList()->update();
- connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes);
- } else
- collectHashes();
+ m_options.instance->loaderModList()->update();
+ connect(m_options.instance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes);
}
void FlamePackExportTask::collectHashes()
@@ -101,11 +84,11 @@ void FlamePackExportTask::collectHashes()
setAbortable(true);
setStatus(tr("Finding file hashes..."));
setProgress(1, 5);
- auto allMods = mcInstance->loaderModList()->allMods();
+ auto allMods = m_options.instance->loaderModList()->allMods();
ConcurrentTask::Ptr hashingTask(new ConcurrentTask("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
task.reset(hashingTask);
for (const QFileInfo& file : files) {
- const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());
+ const QString relative = m_gameRoot.relativeFilePath(file.absoluteFilePath());
// require sensible file types
if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) {
return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled");
@@ -335,13 +318,13 @@ void FlamePackExportTask::buildZip()
setStatus(tr("Adding files..."));
setProgress(4, 5);
- auto zipTask = makeShared(output, gameRoot, files, "overrides/", true, false);
+ auto zipTask = makeShared(m_options.output, m_gameRoot, files, "overrides/", true, false);
zipTask->addExtraFile("manifest.json", generateIndex());
zipTask->addExtraFile("modlist.html", generateHTML());
QStringList exclude;
std::transform(resolvedFiles.keyBegin(), resolvedFiles.keyEnd(), std::back_insert_iterator(exclude),
- [this](QString file) { return gameRoot.relativeFilePath(file); });
+ [this](QString file) { return m_gameRoot.relativeFilePath(file); });
zipTask->setExcludeFiles(exclude);
auto progressStep = std::make_shared();
@@ -376,52 +359,56 @@ QByteArray FlamePackExportTask::generateIndex()
QJsonObject obj;
obj["manifestType"] = "minecraftModpack";
obj["manifestVersion"] = 1;
- obj["name"] = name;
- obj["version"] = version;
- obj["author"] = author;
+ obj["name"] = m_options.name;
+ obj["version"] = m_options.version;
+ obj["author"] = m_options.author;
obj["overrides"] = "overrides";
- if (mcInstance) {
- QJsonObject version;
- auto profile = mcInstance->getPackProfile();
- // collect all supported components
- const ComponentPtr minecraft = profile->getComponent("net.minecraft");
- const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader");
- const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader");
- const ComponentPtr forge = profile->getComponent("net.minecraftforge");
- const ComponentPtr neoforge = profile->getComponent("net.neoforged");
- // convert all available components to mrpack dependencies
- if (minecraft != nullptr)
- version["version"] = minecraft->m_version;
- QString id;
- if (quilt != nullptr)
- id = "quilt-" + quilt->m_version;
- else if (fabric != nullptr)
- id = "fabric-" + fabric->m_version;
- else if (forge != nullptr)
- id = "forge-" + forge->m_version;
- else if (neoforge != nullptr) {
- id = "neoforge-";
- if (minecraft->m_version == "1.20.1")
- id += "1.20.1-";
- id += neoforge->m_version;
- }
- version["modLoaders"] = QJsonArray();
- if (!id.isEmpty()) {
- QJsonObject loader;
- loader["id"] = id;
- loader["primary"] = true;
- version["modLoaders"] = QJsonArray({ loader });
- }
- obj["minecraft"] = version;
+ QJsonObject version;
+
+ auto profile = m_options.instance->getPackProfile();
+ // collect all supported components
+ const ComponentPtr minecraft = profile->getComponent("net.minecraft");
+ const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader");
+ const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader");
+ const ComponentPtr forge = profile->getComponent("net.minecraftforge");
+ const ComponentPtr neoforge = profile->getComponent("net.neoforged");
+
+ // convert all available components to mrpack dependencies
+ if (minecraft != nullptr)
+ version["version"] = minecraft->m_version;
+ QString id;
+ if (quilt != nullptr)
+ id = "quilt-" + quilt->m_version;
+ else if (fabric != nullptr)
+ id = "fabric-" + fabric->m_version;
+ else if (forge != nullptr)
+ id = "forge-" + forge->m_version;
+ else if (neoforge != nullptr) {
+ id = "neoforge-";
+ if (minecraft->m_version == "1.20.1")
+ id += "1.20.1-";
+ id += neoforge->m_version;
}
+ version["modLoaders"] = QJsonArray();
+ if (!id.isEmpty()) {
+ QJsonObject loader;
+ loader["id"] = id;
+ loader["primary"] = true;
+ version["modLoaders"] = QJsonArray({ loader });
+ }
+
+ if (m_options.recommendedRAM > 0)
+ version["recommendedRam"] = m_options.recommendedRAM;
+
+ obj["minecraft"] = version;
QJsonArray files;
for (auto mod : resolvedFiles) {
QJsonObject file;
file["projectID"] = mod.addonId;
file["fileID"] = mod.version;
- file["required"] = mod.enabled || !optionalFiles;
+ file["required"] = mod.enabled || !m_options.optionalFiles;
files << file;
}
obj["files"] = files;
diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h
index 38acdf518..e3d4c74a7 100644
--- a/launcher/modplatform/flame/FlamePackExportTask.h
+++ b/launcher/modplatform/flame/FlamePackExportTask.h
@@ -19,22 +19,26 @@
#pragma once
-#include "BaseInstance.h"
#include "MMCZip.h"
#include "minecraft/MinecraftInstance.h"
#include "modplatform/flame/FlameAPI.h"
#include "tasks/Task.h"
+struct FlamePackExportOptions {
+ QString name;
+ QString version;
+ QString author;
+ bool optionalFiles;
+ MinecraftInstancePtr instance;
+ QString output;
+ MMCZip::FilterFileFunction filter;
+ int recommendedRAM;
+};
+
class FlamePackExportTask : public Task {
Q_OBJECT
public:
- FlamePackExportTask(const QString& name,
- const QString& version,
- const QString& author,
- bool optionalFiles,
- InstancePtr instance,
- const QString& output,
- MMCZip::FilterFileFunction filter);
+ FlamePackExportTask(FlamePackExportOptions&& options);
protected:
void executeTask() override;
@@ -45,13 +49,6 @@ class FlamePackExportTask : public Task {
static const QStringList FILE_EXTENSIONS;
// inputs
- const QString name, version, author;
- const bool optionalFiles;
- const InstancePtr instance;
- MinecraftInstance* mcInstance;
- const QDir gameRoot;
- const QString output;
- const MMCZip::FilterFileFunction filter;
struct ResolvedFile {
int addonId;
@@ -70,6 +67,9 @@ class FlamePackExportTask : public Task {
bool isMod;
};
+ FlamePackExportOptions m_options;
+ QDir m_gameRoot;
+
FlameAPI api;
QFileInfoList files;
diff --git a/launcher/modplatform/flame/PackManifest.cpp b/launcher/modplatform/flame/PackManifest.cpp
index 278105f4a..641fb5d9a 100644
--- a/launcher/modplatform/flame/PackManifest.cpp
+++ b/launcher/modplatform/flame/PackManifest.cpp
@@ -27,6 +27,7 @@ static void loadMinecraftV1(Flame::Minecraft& m, QJsonObject& minecraft)
loadModloaderV1(loader, obj);
m.modLoaders.append(loader);
}
+ m.recommendedRAM = Json::ensureInteger(minecraft, "recommendedRam", 0);
}
static void loadManifestV1(Flame::Manifest& pack, QJsonObject& manifest)
diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h
index ebb3ed5cc..6b911ffb4 100644
--- a/launcher/modplatform/flame/PackManifest.h
+++ b/launcher/modplatform/flame/PackManifest.h
@@ -67,6 +67,7 @@ struct Minecraft {
QString version;
QString libraries;
QList modLoaders;
+ int recommendedRAM;
};
struct Manifest {
diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp
index 1871c5df8..92b345c8d 100644
--- a/launcher/tasks/Task.cpp
+++ b/launcher/tasks/Task.cpp
@@ -196,6 +196,8 @@ void Task::logWarning(const QString& line)
{
qWarning() << line;
m_Warnings.append(line);
+
+ emit warningLogged(line);
}
QStringList Task::warnings() const
diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h
index fcd075150..43e71c8ab 100644
--- a/launcher/tasks/Task.h
+++ b/launcher/tasks/Task.h
@@ -145,6 +145,7 @@ class Task : public QObject, public QRunnable {
void failed(QString reason);
void status(QString status);
void details(QString details);
+ void warningLogged(const QString& warning);
void stepProgress(TaskStepProgress const& task_progress);
//! Emitted when the canAbort() status has changed. */
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 062175ece..63fcc3c9b 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -71,6 +71,7 @@
#include
#include
#include
+#include
#include
#include
@@ -1439,15 +1440,18 @@ void MainWindow::on_actionExportInstanceZip_triggered()
void MainWindow::on_actionExportInstanceMrPack_triggered()
{
if (m_selectedInstance) {
- ExportPackDialog dlg(m_selectedInstance, this);
- dlg.exec();
+ auto instance = std::dynamic_pointer_cast(m_selectedInstance);
+ if (instance != nullptr) {
+ ExportPackDialog dlg(instance, this);
+ dlg.exec();
+ }
}
}
void MainWindow::on_actionExportInstanceFlamePack_triggered()
{
if (m_selectedInstance) {
- auto instance = dynamic_cast(m_selectedInstance.get());
+ auto instance = std::dynamic_pointer_cast(m_selectedInstance);
if (instance) {
if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft");
cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") {
@@ -1456,7 +1460,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered()
msgBox.exec();
return;
}
- ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME);
+ ExportPackDialog dlg(instance, this, ModPlatform::ResourceProvider::FLAME);
dlg.exec();
}
}
diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp
index 303df94a1..15420616e 100644
--- a/launcher/ui/dialogs/ExportPackDialog.cpp
+++ b/launcher/ui/dialogs/ExportPackDialog.cpp
@@ -17,7 +17,7 @@
*/
#include "ExportPackDialog.h"
-#include "minecraft/mod/ModFolderModel.h"
+#include "minecraft/mod/ResourceFolderModel.h"
#include "modplatform/ModIndex.h"
#include "modplatform/flame/FlamePackExportTask.h"
#include "ui/dialogs/CustomMessageBox.h"
@@ -33,7 +33,7 @@
#include "MMCZip.h"
#include "modplatform/modrinth/ModrinthPackExportTask.h"
-ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider)
+ExportPackDialog::ExportPackDialog(MinecraftInstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider)
: QDialog(parent), m_instance(instance), m_ui(new Ui::ExportPackDialog), m_provider(provider)
{
Q_ASSERT(m_provider == ModPlatform::ResourceProvider::MODRINTH || m_provider == ModPlatform::ResourceProvider::FLAME);
@@ -44,12 +44,16 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla
m_ui->version->setText(instance->settings()->get("ExportVersion").toString());
m_ui->optionalFiles->setChecked(instance->settings()->get("ExportOptionalFiles").toBool());
+ connect(m_ui->recommendedMemoryCheckBox, &QCheckBox::toggled, m_ui->recommendedMemory, &QWidget::setEnabled);
+
if (m_provider == ModPlatform::ResourceProvider::MODRINTH) {
setWindowTitle(tr("Export Modrinth Pack"));
m_ui->authorLabel->hide();
m_ui->author->hide();
+ m_ui->recommendedMemoryWidget->hide();
+
m_ui->summary->setPlainText(instance->settings()->get("ExportSummary").toString());
} else {
setWindowTitle(tr("Export CurseForge Pack"));
@@ -57,6 +61,19 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla
m_ui->summaryLabel->hide();
m_ui->summary->hide();
+ const int recommendedRAM = instance->settings()->get("ExportRecommendedRAM").toInt();
+
+ if (recommendedRAM > 0) {
+ m_ui->recommendedMemoryCheckBox->setChecked(true);
+ m_ui->recommendedMemory->setValue(recommendedRAM);
+ } else {
+ m_ui->recommendedMemoryCheckBox->setChecked(false);
+
+ // recommend based on setting - limited to 12 GiB (CurseForge warns above this amount)
+ const int defaultRecommendation = qMin(m_instance->settings()->get("MaxMemAlloc").toInt(), 1024 * 12);
+ m_ui->recommendedMemory->setValue(defaultRecommendation);
+ }
+
m_ui->author->setText(instance->settings()->get("ExportAuthor").toString());
}
@@ -120,9 +137,15 @@ void ExportPackDialog::done(int result)
if (m_provider == ModPlatform::ResourceProvider::MODRINTH)
settings->set("ExportSummary", m_ui->summary->toPlainText());
- else
+ else {
settings->set("ExportAuthor", m_ui->author->text());
+ if (m_ui->recommendedMemoryCheckBox->isChecked())
+ settings->set("ExportRecommendedRAM", m_ui->recommendedMemory->value());
+ else
+ settings->reset("ExportRecommendedRAM");
+ }
+
if (result == Accepted) {
const QString name = m_ui->name->text().isEmpty() ? m_instance->name() : m_ui->name->text();
const QString filename = FS::RemoveInvalidFilenameChars(name);
@@ -149,8 +172,18 @@ void ExportPackDialog::done(int result)
task = new ModrinthPackExportTask(name, m_ui->version->text(), m_ui->summary->toPlainText(), m_ui->optionalFiles->isChecked(),
m_instance, output, std::bind(&FileIgnoreProxy::filterFile, m_proxy, std::placeholders::_1));
} else {
- task = new FlamePackExportTask(name, m_ui->version->text(), m_ui->author->text(), m_ui->optionalFiles->isChecked(), m_instance,
- output, std::bind(&FileIgnoreProxy::filterFile, m_proxy, std::placeholders::_1));
+ FlamePackExportOptions options{};
+
+ options.name = name;
+ options.version = m_ui->version->text();
+ options.author = m_ui->author->text();
+ options.optionalFiles = m_ui->optionalFiles->isChecked();
+ options.instance = m_instance;
+ options.output = output;
+ options.filter = std::bind(&FileIgnoreProxy::filterFile, m_proxy, std::placeholders::_1);
+ options.recommendedRAM = m_ui->recommendedMemoryCheckBox->isChecked() ? m_ui->recommendedMemory->value() : 0;
+
+ task = new FlamePackExportTask(std::move(options));
}
connect(task, &Task::failed,
diff --git a/launcher/ui/dialogs/ExportPackDialog.h b/launcher/ui/dialogs/ExportPackDialog.h
index 092288d49..e93055d8d 100644
--- a/launcher/ui/dialogs/ExportPackDialog.h
+++ b/launcher/ui/dialogs/ExportPackDialog.h
@@ -22,6 +22,7 @@
#include "BaseInstance.h"
#include "FastFileIconProvider.h"
#include "FileIgnoreProxy.h"
+#include "minecraft/MinecraftInstance.h"
#include "modplatform/ModIndex.h"
namespace Ui {
@@ -32,7 +33,7 @@ class ExportPackDialog : public QDialog {
Q_OBJECT
public:
- explicit ExportPackDialog(InstancePtr instance,
+ explicit ExportPackDialog(MinecraftInstancePtr instance,
QWidget* parent = nullptr,
ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH);
~ExportPackDialog();
@@ -44,7 +45,7 @@ class ExportPackDialog : public QDialog {
QString ignoreFileName();
private:
- const InstancePtr m_instance;
+ const MinecraftInstancePtr m_instance;
Ui::ExportPackDialog* m_ui;
FileIgnoreProxy* m_proxy;
FastFileIconProvider m_icons;
diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui
index a4a174212..bda8b8dd0 100644
--- a/launcher/ui/dialogs/ExportPackDialog.ui
+++ b/launcher/ui/dialogs/ExportPackDialog.ui
@@ -19,36 +19,56 @@
&Description
-
+
-
-
-
- &Name
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
- name
-
-
-
- -
-
-
- -
-
-
- &Version
-
-
- version
-
-
-
- -
-
-
- 1.0.0
-
-
+
-
+
+
+ &Name:
+
+
+ name
+
+
+
+ -
+
+
+ -
+
+
+ &Version:
+
+
+ version
+
+
+
+ -
+
+
+ 1.0.0
+
+
+
+ -
+
+
+ &Author:
+
+
+ author
+
+
+
+ -
+
+
+
-
@@ -62,24 +82,29 @@
-
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+
+ 16777215
+ 100
+
+
true
- -
-
-
- &Author
-
-
- author
-
-
-
- -
-
-
@@ -88,7 +113,70 @@
&Options
-
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ &Recommended Memory:
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ MiB
+
+
+ 8
+
+
+ 32768
+
+
+ 128
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
-
@@ -138,10 +226,6 @@
- name
- version
- summary
- author
files
optionalFiles