Support for CurseForge recommended memory (#3711)

This commit is contained in:
TheKodeToad 2025-05-31 17:22:06 +00:00 committed by GitHub
commit 43dcafda60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 274 additions and 135 deletions

View File

@ -211,6 +211,7 @@ void InstanceImportTask::processZipPack()
progressStep->status = status; progressStep->status = status;
stepProgress(*progressStep); stepProgress(*progressStep);
}); });
connect(zipTask.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
m_task.reset(zipTask); m_task.reset(zipTask);
zipTask->start(); 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::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable); 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); m_task.reset(inst_creation_task);
setAbortable(true); setAbortable(true);
m_task->start(); 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::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable); 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); m_task.reset(inst_creation_task);
setAbortable(true); setAbortable(true);
m_task->start(); m_task->start();

View File

@ -248,6 +248,7 @@ void MinecraftInstance::loadSpecificSettings()
m_settings->registerSetting("ExportSummary", ""); m_settings->registerSetting("ExportSummary", "");
m_settings->registerSetting("ExportAuthor", ""); m_settings->registerSetting("ExportAuthor", "");
m_settings->registerSetting("ExportOptionalFiles", true); m_settings->registerSetting("ExportOptionalFiles", true);
m_settings->registerSetting("ExportRecommendedRAM");
qDebug() << "Instance-type specific settings were loaded!"; qDebug() << "Instance-type specific settings were loaded!";

View File

@ -54,6 +54,7 @@
#include "settings/INISettingsObject.h" #include "settings/INISettingsObject.h"
#include "sys.h"
#include "tasks/ConcurrentTask.h" #include "tasks/ConcurrentTask.h"
#include "ui/dialogs/BlockedModsDialog.h" #include "ui/dialogs/BlockedModsDialog.h"
#include "ui/dialogs/CustomMessageBox.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"); QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods");
QFileInfo jarmodsInfo(jarmodsPath); QFileInfo jarmodsInfo(jarmodsPath);
if (jarmodsInfo.isDir()) { if (jarmodsInfo.isDir()) {

View File

@ -41,22 +41,8 @@
const QString FlamePackExportTask::TEMPLATE = "<li><a href=\"{url}\">{name}{authors}</a></li>\n"; const QString FlamePackExportTask::TEMPLATE = "<li><a href=\"{url}\">{name}{authors}</a></li>\n";
const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" });
FlamePackExportTask::FlamePackExportTask(const QString& name, FlamePackExportTask::FlamePackExportTask(FlamePackExportOptions&& options)
const QString& version, : m_options(std::move(options)), m_gameRoot(m_options.instance->gameRoot())
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<MinecraftInstance*>(instance.get()))
, gameRoot(instance->gameRoot())
, output(output)
, filter(filter)
{} {}
void FlamePackExportTask::executeTask() void FlamePackExportTask::executeTask()
@ -81,7 +67,7 @@ void FlamePackExportTask::collectFiles()
QCoreApplication::processEvents(); QCoreApplication::processEvents();
files.clear(); 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")); emitFailed(tr("Could not search for files"));
return; return;
} }
@ -89,11 +75,8 @@ void FlamePackExportTask::collectFiles()
pendingHashes.clear(); pendingHashes.clear();
resolvedFiles.clear(); resolvedFiles.clear();
if (mcInstance != nullptr) { m_options.instance->loaderModList()->update();
mcInstance->loaderModList()->update(); connect(m_options.instance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes);
connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes);
} else
collectHashes();
} }
void FlamePackExportTask::collectHashes() void FlamePackExportTask::collectHashes()
@ -101,11 +84,11 @@ void FlamePackExportTask::collectHashes()
setAbortable(true); setAbortable(true);
setStatus(tr("Finding file hashes...")); setStatus(tr("Finding file hashes..."));
setProgress(1, 5); 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())); ConcurrentTask::Ptr hashingTask(new ConcurrentTask("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
task.reset(hashingTask); task.reset(hashingTask);
for (const QFileInfo& file : files) { for (const QFileInfo& file : files) {
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); const QString relative = m_gameRoot.relativeFilePath(file.absoluteFilePath());
// require sensible file types // require sensible file types
if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) {
return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled");
@ -335,13 +318,13 @@ void FlamePackExportTask::buildZip()
setStatus(tr("Adding files...")); setStatus(tr("Adding files..."));
setProgress(4, 5); setProgress(4, 5);
auto zipTask = makeShared<MMCZip::ExportToZipTask>(output, gameRoot, files, "overrides/", true, false); auto zipTask = makeShared<MMCZip::ExportToZipTask>(m_options.output, m_gameRoot, files, "overrides/", true, false);
zipTask->addExtraFile("manifest.json", generateIndex()); zipTask->addExtraFile("manifest.json", generateIndex());
zipTask->addExtraFile("modlist.html", generateHTML()); zipTask->addExtraFile("modlist.html", generateHTML());
QStringList exclude; QStringList exclude;
std::transform(resolvedFiles.keyBegin(), resolvedFiles.keyEnd(), std::back_insert_iterator(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); zipTask->setExcludeFiles(exclude);
auto progressStep = std::make_shared<TaskStepProgress>(); auto progressStep = std::make_shared<TaskStepProgress>();
@ -376,13 +359,14 @@ QByteArray FlamePackExportTask::generateIndex()
QJsonObject obj; QJsonObject obj;
obj["manifestType"] = "minecraftModpack"; obj["manifestType"] = "minecraftModpack";
obj["manifestVersion"] = 1; obj["manifestVersion"] = 1;
obj["name"] = name; obj["name"] = m_options.name;
obj["version"] = version; obj["version"] = m_options.version;
obj["author"] = author; obj["author"] = m_options.author;
obj["overrides"] = "overrides"; obj["overrides"] = "overrides";
if (mcInstance) {
QJsonObject version; QJsonObject version;
auto profile = mcInstance->getPackProfile();
auto profile = m_options.instance->getPackProfile();
// collect all supported components // collect all supported components
const ComponentPtr minecraft = profile->getComponent("net.minecraft"); const ComponentPtr minecraft = profile->getComponent("net.minecraft");
const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader");
@ -413,15 +397,18 @@ QByteArray FlamePackExportTask::generateIndex()
loader["primary"] = true; loader["primary"] = true;
version["modLoaders"] = QJsonArray({ loader }); version["modLoaders"] = QJsonArray({ loader });
} }
if (m_options.recommendedRAM > 0)
version["recommendedRam"] = m_options.recommendedRAM;
obj["minecraft"] = version; obj["minecraft"] = version;
}
QJsonArray files; QJsonArray files;
for (auto mod : resolvedFiles) { for (auto mod : resolvedFiles) {
QJsonObject file; QJsonObject file;
file["projectID"] = mod.addonId; file["projectID"] = mod.addonId;
file["fileID"] = mod.version; file["fileID"] = mod.version;
file["required"] = mod.enabled || !optionalFiles; file["required"] = mod.enabled || !m_options.optionalFiles;
files << file; files << file;
} }
obj["files"] = files; obj["files"] = files;

View File

@ -19,22 +19,26 @@
#pragma once #pragma once
#include "BaseInstance.h"
#include "MMCZip.h" #include "MMCZip.h"
#include "minecraft/MinecraftInstance.h" #include "minecraft/MinecraftInstance.h"
#include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameAPI.h"
#include "tasks/Task.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 { class FlamePackExportTask : public Task {
Q_OBJECT Q_OBJECT
public: public:
FlamePackExportTask(const QString& name, FlamePackExportTask(FlamePackExportOptions&& options);
const QString& version,
const QString& author,
bool optionalFiles,
InstancePtr instance,
const QString& output,
MMCZip::FilterFileFunction filter);
protected: protected:
void executeTask() override; void executeTask() override;
@ -45,13 +49,6 @@ class FlamePackExportTask : public Task {
static const QStringList FILE_EXTENSIONS; static const QStringList FILE_EXTENSIONS;
// inputs // 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 { struct ResolvedFile {
int addonId; int addonId;
@ -70,6 +67,9 @@ class FlamePackExportTask : public Task {
bool isMod; bool isMod;
}; };
FlamePackExportOptions m_options;
QDir m_gameRoot;
FlameAPI api; FlameAPI api;
QFileInfoList files; QFileInfoList files;

View File

@ -27,6 +27,7 @@ static void loadMinecraftV1(Flame::Minecraft& m, QJsonObject& minecraft)
loadModloaderV1(loader, obj); loadModloaderV1(loader, obj);
m.modLoaders.append(loader); m.modLoaders.append(loader);
} }
m.recommendedRAM = Json::ensureInteger(minecraft, "recommendedRam", 0);
} }
static void loadManifestV1(Flame::Manifest& pack, QJsonObject& manifest) static void loadManifestV1(Flame::Manifest& pack, QJsonObject& manifest)

View File

@ -67,6 +67,7 @@ struct Minecraft {
QString version; QString version;
QString libraries; QString libraries;
QList<Flame::Modloader> modLoaders; QList<Flame::Modloader> modLoaders;
int recommendedRAM;
}; };
struct Manifest { struct Manifest {

View File

@ -196,6 +196,8 @@ void Task::logWarning(const QString& line)
{ {
qWarning() << line; qWarning() << line;
m_Warnings.append(line); m_Warnings.append(line);
emit warningLogged(line);
} }
QStringList Task::warnings() const QStringList Task::warnings() const

View File

@ -145,6 +145,7 @@ class Task : public QObject, public QRunnable {
void failed(QString reason); void failed(QString reason);
void status(QString status); void status(QString status);
void details(QString details); void details(QString details);
void warningLogged(const QString& warning);
void stepProgress(TaskStepProgress const& task_progress); void stepProgress(TaskStepProgress const& task_progress);
//! Emitted when the canAbort() status has changed. */ //! Emitted when the canAbort() status has changed. */

View File

@ -71,6 +71,7 @@
#include <QToolButton> #include <QToolButton>
#include <QWidget> #include <QWidget>
#include <QWidgetAction> #include <QWidgetAction>
#include <memory>
#include <BaseInstance.h> #include <BaseInstance.h>
#include <BuildConfig.h> #include <BuildConfig.h>
@ -1439,15 +1440,18 @@ void MainWindow::on_actionExportInstanceZip_triggered()
void MainWindow::on_actionExportInstanceMrPack_triggered() void MainWindow::on_actionExportInstanceMrPack_triggered()
{ {
if (m_selectedInstance) { if (m_selectedInstance) {
ExportPackDialog dlg(m_selectedInstance, this); auto instance = std::dynamic_pointer_cast<MinecraftInstance>(m_selectedInstance);
if (instance != nullptr) {
ExportPackDialog dlg(instance, this);
dlg.exec(); dlg.exec();
} }
}
} }
void MainWindow::on_actionExportInstanceFlamePack_triggered() void MainWindow::on_actionExportInstanceFlamePack_triggered()
{ {
if (m_selectedInstance) { if (m_selectedInstance) {
auto instance = dynamic_cast<MinecraftInstance*>(m_selectedInstance.get()); auto instance = std::dynamic_pointer_cast<MinecraftInstance>(m_selectedInstance);
if (instance) { if (instance) {
if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft"); if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft");
cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") { cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") {
@ -1456,7 +1460,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered()
msgBox.exec(); msgBox.exec();
return; return;
} }
ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); ExportPackDialog dlg(instance, this, ModPlatform::ResourceProvider::FLAME);
dlg.exec(); dlg.exec();
} }
} }

View File

@ -17,7 +17,7 @@
*/ */
#include "ExportPackDialog.h" #include "ExportPackDialog.h"
#include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h"
#include "modplatform/ModIndex.h" #include "modplatform/ModIndex.h"
#include "modplatform/flame/FlamePackExportTask.h" #include "modplatform/flame/FlamePackExportTask.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
@ -33,7 +33,7 @@
#include "MMCZip.h" #include "MMCZip.h"
#include "modplatform/modrinth/ModrinthPackExportTask.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) : 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); 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->version->setText(instance->settings()->get("ExportVersion").toString());
m_ui->optionalFiles->setChecked(instance->settings()->get("ExportOptionalFiles").toBool()); 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) { if (m_provider == ModPlatform::ResourceProvider::MODRINTH) {
setWindowTitle(tr("Export Modrinth Pack")); setWindowTitle(tr("Export Modrinth Pack"));
m_ui->authorLabel->hide(); m_ui->authorLabel->hide();
m_ui->author->hide(); m_ui->author->hide();
m_ui->recommendedMemoryWidget->hide();
m_ui->summary->setPlainText(instance->settings()->get("ExportSummary").toString()); m_ui->summary->setPlainText(instance->settings()->get("ExportSummary").toString());
} else { } else {
setWindowTitle(tr("Export CurseForge Pack")); setWindowTitle(tr("Export CurseForge Pack"));
@ -57,6 +61,19 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla
m_ui->summaryLabel->hide(); m_ui->summaryLabel->hide();
m_ui->summary->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()); m_ui->author->setText(instance->settings()->get("ExportAuthor").toString());
} }
@ -120,9 +137,15 @@ void ExportPackDialog::done(int result)
if (m_provider == ModPlatform::ResourceProvider::MODRINTH) if (m_provider == ModPlatform::ResourceProvider::MODRINTH)
settings->set("ExportSummary", m_ui->summary->toPlainText()); settings->set("ExportSummary", m_ui->summary->toPlainText());
else else {
settings->set("ExportAuthor", m_ui->author->text()); 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) { if (result == Accepted) {
const QString name = m_ui->name->text().isEmpty() ? m_instance->name() : m_ui->name->text(); const QString name = m_ui->name->text().isEmpty() ? m_instance->name() : m_ui->name->text();
const QString filename = FS::RemoveInvalidFilenameChars(name); 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(), 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)); m_instance, output, std::bind(&FileIgnoreProxy::filterFile, m_proxy, std::placeholders::_1));
} else { } else {
task = new FlamePackExportTask(name, m_ui->version->text(), m_ui->author->text(), m_ui->optionalFiles->isChecked(), m_instance, FlamePackExportOptions options{};
output, std::bind(&FileIgnoreProxy::filterFile, m_proxy, std::placeholders::_1));
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, connect(task, &Task::failed,

View File

@ -22,6 +22,7 @@
#include "BaseInstance.h" #include "BaseInstance.h"
#include "FastFileIconProvider.h" #include "FastFileIconProvider.h"
#include "FileIgnoreProxy.h" #include "FileIgnoreProxy.h"
#include "minecraft/MinecraftInstance.h"
#include "modplatform/ModIndex.h" #include "modplatform/ModIndex.h"
namespace Ui { namespace Ui {
@ -32,7 +33,7 @@ class ExportPackDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ExportPackDialog(InstancePtr instance, explicit ExportPackDialog(MinecraftInstancePtr instance,
QWidget* parent = nullptr, QWidget* parent = nullptr,
ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH);
~ExportPackDialog(); ~ExportPackDialog();
@ -44,7 +45,7 @@ class ExportPackDialog : public QDialog {
QString ignoreFileName(); QString ignoreFileName();
private: private:
const InstancePtr m_instance; const MinecraftInstancePtr m_instance;
Ui::ExportPackDialog* m_ui; Ui::ExportPackDialog* m_ui;
FileIgnoreProxy* m_proxy; FileIgnoreProxy* m_proxy;
FastFileIconProvider m_icons; FastFileIconProvider m_icons;

View File

@ -19,37 +19,57 @@
<property name="title"> <property name="title">
<string>&amp;Description</string> <string>&amp;Description</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QFormLayout" name="formLayout">
<property name="labelAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="nameLabel"> <widget class="QLabel" name="nameLabel">
<property name="text"> <property name="text">
<string>&amp;Name</string> <string>&amp;Name:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>name</cstring> <cstring>name</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="0" column="1">
<widget class="QLineEdit" name="name"/> <widget class="QLineEdit" name="name"/>
</item> </item>
<item> <item row="1" column="0">
<widget class="QLabel" name="versionLabel"> <widget class="QLabel" name="versionLabel">
<property name="text"> <property name="text">
<string>&amp;Version</string> <string>&amp;Version:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>version</cstring> <cstring>version</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="1">
<widget class="QLineEdit" name="version"> <widget class="QLineEdit" name="version">
<property name="text"> <property name="text">
<string>1.0.0</string> <string>1.0.0</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="authorLabel">
<property name="text">
<string>&amp;Author:</string>
</property>
<property name="buddy">
<cstring>author</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="author"/>
</item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="summaryLabel"> <widget class="QLabel" name="summaryLabel">
<property name="text"> <property name="text">
@ -62,24 +82,29 @@
</item> </item>
<item> <item>
<widget class="QPlainTextEdit" name="summary"> <widget class="QPlainTextEdit" name="summary">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="tabChangesFocus"> <property name="tabChangesFocus">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="authorLabel">
<property name="text">
<string>&amp;Author</string>
</property>
<property name="buddy">
<cstring>author</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="author"/>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -88,7 +113,70 @@
<property name="title"> <property name="title">
<string>&amp;Options</string> <string>&amp;Options</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QWidget" name="recommendedMemoryWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="recommendedMemoryCheckBox">
<property name="text">
<string>&amp;Recommended Memory:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="recommendedMemory">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> MiB</string>
</property>
<property name="minimum">
<number>8</number>
</property>
<property name="maximum">
<number>32768</number>
</property>
<property name="singleStep">
<number>128</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="filesLabel"> <widget class="QLabel" name="filesLabel">
<property name="text"> <property name="text">
@ -138,10 +226,6 @@
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>name</tabstop>
<tabstop>version</tabstop>
<tabstop>summary</tabstop>
<tabstop>author</tabstop>
<tabstop>files</tabstop> <tabstop>files</tabstop>
<tabstop>optionalFiles</tabstop> <tabstop>optionalFiles</tabstop>
</tabstops> </tabstops>