refactor: create mod pages and filter widget by factory methods

This takes most expensive operations out of the constructors.

Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
flow 2022-08-21 10:50:10 -03:00
parent 2666beafb1
commit 98fbb3613d
No known key found for this signature in database
GPG Key ID: 8D0F221F0A59F469
7 changed files with 102 additions and 47 deletions

View File

@ -121,9 +121,9 @@ QList<BasePage *> ModDownloadDialog::getPages()
{ {
QList<BasePage *> pages; QList<BasePage *> pages;
pages.append(new ModrinthModPage(this, m_instance)); pages.append(ModrinthModPage::create(this, m_instance));
if (APPLICATION->currentCapabilities() & Application::SupportsFlame) if (APPLICATION->currentCapabilities() & Application::SupportsFlame)
pages.append(new FlameModPage(this, m_instance)); pages.append(FlameModPage::create(this, m_instance));
return pages; return pages;
} }

View File

@ -44,12 +44,12 @@
#include "minecraft/PackProfile.h" #include "minecraft/PackProfile.h"
#include "ui/dialogs/ModDownloadDialog.h" #include "ui/dialogs/ModDownloadDialog.h"
ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api)
: QWidget(dialog) : QWidget(dialog)
, m_instance(instance) , m_instance(instance)
, ui(new Ui::ModPage) , ui(new Ui::ModPage)
, dialog(dialog) , dialog(dialog)
, filter_widget(static_cast<MinecraftInstance*>(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this)
, api(api) , api(api)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -59,18 +59,6 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api)
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
ui->gridLayout_3->addWidget(&filter_widget, 0, 0, 1, ui->gridLayout_3->columnCount());
filter_widget.setInstance(static_cast<MinecraftInstance*>(m_instance));
m_filter = filter_widget.getFilter();
connect(&filter_widget, &ModFilterWidget::filterChanged, this, [&]{
ui->searchButton->setStyleSheet("text-decoration: underline");
});
connect(&filter_widget, &ModFilterWidget::filterUnchanged, this, [&]{
ui->searchButton->setStyleSheet("text-decoration: none");
});
} }
ModPage::~ModPage() ModPage::~ModPage()
@ -78,6 +66,26 @@ ModPage::~ModPage()
delete ui; delete ui;
} }
void ModPage::setFilterWidget(unique_qobject_ptr<ModFilterWidget>& widget)
{
if (m_filter_widget)
disconnect(m_filter_widget.get(), nullptr, nullptr, nullptr);
m_filter_widget.swap(widget);
ui->gridLayout_3->addWidget(m_filter_widget.get(), 0, 0, 1, ui->gridLayout_3->columnCount());
m_filter_widget->setInstance(static_cast<MinecraftInstance*>(m_instance));
m_filter = m_filter_widget->getFilter();
connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, [&]{
ui->searchButton->setStyleSheet("text-decoration: underline");
});
connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, [&]{
ui->searchButton->setStyleSheet("text-decoration: none");
});
}
/******** Qt things ********/ /******** Qt things ********/
@ -105,13 +113,13 @@ auto ModPage::eventFilter(QObject* watched, QEvent* event) -> bool
void ModPage::filterMods() void ModPage::filterMods()
{ {
filter_widget.setHidden(!filter_widget.isHidden()); m_filter_widget->setHidden(!m_filter_widget->isHidden());
} }
void ModPage::triggerSearch() void ModPage::triggerSearch()
{ {
auto changed = filter_widget.changed(); auto changed = m_filter_widget->changed();
m_filter = filter_widget.getFilter(); m_filter = m_filter_widget->getFilter();
if(changed){ if(changed){
ui->packView->clearSelection(); ui->packView->clearSelection();

View File

@ -20,7 +20,17 @@ class ModPage : public QWidget, public BasePage {
Q_OBJECT Q_OBJECT
public: public:
explicit ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api); template<typename T>
static T* create(ModDownloadDialog* dialog, BaseInstance* instance)
{
auto page = new T(dialog, instance);
auto filter_widget = ModFilterWidget::create(static_cast<MinecraftInstance*>(instance)->getPackProfile()->getComponentVersion("net.minecraft"), page);
page->setFilterWidget(filter_widget);
return page;
}
~ModPage() override; ~ModPage() override;
/* Affects what the user sees */ /* Affects what the user sees */
@ -45,6 +55,8 @@ class ModPage : public QWidget, public BasePage {
auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; } auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }
auto getDialog() const -> const ModDownloadDialog* { return dialog; } auto getDialog() const -> const ModDownloadDialog* { return dialog; }
void setFilterWidget(unique_qobject_ptr<ModFilterWidget>&);
auto getCurrent() -> ModPlatform::IndexedPack& { return current; } auto getCurrent() -> ModPlatform::IndexedPack& { return current; }
void updateModVersions(int prev_count = -1); void updateModVersions(int prev_count = -1);
@ -54,6 +66,7 @@ class ModPage : public QWidget, public BasePage {
BaseInstance* m_instance; BaseInstance* m_instance;
protected: protected:
ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api);
void updateSelectionButton(); void updateSelectionButton();
protected slots: protected slots:
@ -67,7 +80,7 @@ class ModPage : public QWidget, public BasePage {
Ui::ModPage* ui = nullptr; Ui::ModPage* ui = nullptr;
ModDownloadDialog* dialog = nullptr; ModDownloadDialog* dialog = nullptr;
ModFilterWidget filter_widget; unique_qobject_ptr<ModFilterWidget> m_filter_widget;
std::shared_ptr<ModFilterWidget::Filter> m_filter; std::shared_ptr<ModFilterWidget::Filter> m_filter;
ModPlatform::ListModel* listModel = nullptr; ModPlatform::ListModel* listModel = nullptr;

View File

@ -44,7 +44,12 @@ class FlameModPage : public ModPage {
Q_OBJECT Q_OBJECT
public: public:
explicit FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance); static FlameModPage* create(ModDownloadDialog* dialog, BaseInstance* instance)
{
return ModPage::create<FlameModPage>(dialog, instance);
}
FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance);
~FlameModPage() override = default; ~FlameModPage() override = default;
inline auto displayName() const -> QString override { return "CurseForge"; } inline auto displayName() const -> QString override { return "CurseForge"; }

View File

@ -44,7 +44,12 @@ class ModrinthModPage : public ModPage {
Q_OBJECT Q_OBJECT
public: public:
explicit ModrinthModPage(ModDownloadDialog* dialog, BaseInstance* instance); static ModrinthModPage* create(ModDownloadDialog* dialog, BaseInstance* instance)
{
return ModPage::create<ModrinthModPage>(dialog, instance);
}
ModrinthModPage(ModDownloadDialog* dialog, BaseInstance* instance);
~ModrinthModPage() override = default; ~ModrinthModPage() override = default;
inline auto displayName() const -> QString override { return "Modrinth"; } inline auto displayName() const -> QString override { return "Modrinth"; }

View File

@ -3,6 +3,37 @@
#include "Application.h" #include "Application.h"
unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(Version default_version, QWidget* parent)
{
auto filter_widget = new ModFilterWidget(default_version, parent);
if (!filter_widget->versionList()->isLoaded()) {
QEventLoop load_version_list_loop;
QTimer time_limit_for_list_load;
time_limit_for_list_load.setTimerType(Qt::TimerType::CoarseTimer);
time_limit_for_list_load.setSingleShot(true);
time_limit_for_list_load.callOnTimeout(&load_version_list_loop, &QEventLoop::quit);
time_limit_for_list_load.start(4000);
auto task = filter_widget->versionList()->getLoadTask();
connect(task.get(), &Task::failed, [filter_widget]{
filter_widget->disableVersionButton(VersionButtonID::Major, tr("failed to get version index"));
});
connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit);
if (!task->isRunning())
task->start();
load_version_list_loop.exec();
if (time_limit_for_list_load.isActive())
time_limit_for_list_load.stop();
}
return unique_qobject_ptr<ModFilterWidget>(filter_widget);
}
ModFilterWidget::ModFilterWidget(Version def, QWidget* parent) ModFilterWidget::ModFilterWidget(Version def, QWidget* parent)
: QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget) : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget)
{ {
@ -19,23 +50,6 @@ ModFilterWidget::ModFilterWidget(Version def, QWidget* parent)
m_filter->versions.push_front(def); m_filter->versions.push_front(def);
m_version_list = APPLICATION->metadataIndex()->get("net.minecraft"); m_version_list = APPLICATION->metadataIndex()->get("net.minecraft");
if (!m_version_list->isLoaded()) {
QEventLoop load_version_list_loop;
auto task = m_version_list->getLoadTask();
connect(task.get(), &Task::failed, [this]{
ui->majorVersionButton->setText(tr("Major version match (failed to get version index)"));
disableVersionButton(VersionButtonID::Major);
});
connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit);
if (!task->isRunning())
task->start();
load_version_list_loop.exec();
}
setHidden(true); setHidden(true);
} }
@ -71,24 +85,30 @@ auto ModFilterWidget::getFilter() -> std::shared_ptr<Filter>
return m_filter; return m_filter;
} }
void ModFilterWidget::disableVersionButton(VersionButtonID id) void ModFilterWidget::disableVersionButton(VersionButtonID id, QString reason)
{ {
QAbstractButton* btn = nullptr;
switch(id){ switch(id){
case(VersionButtonID::Strict): case(VersionButtonID::Strict):
ui->strictVersionButton->setEnabled(false); btn = ui->strictVersionButton;
break; break;
case(VersionButtonID::Major): case(VersionButtonID::Major):
ui->majorVersionButton->setEnabled(false); btn = ui->majorVersionButton;
break; break;
case(VersionButtonID::All): case(VersionButtonID::All):
ui->allVersionsButton->setEnabled(false); btn = ui->allVersionsButton;
break; break;
case(VersionButtonID::Between): case(VersionButtonID::Between):
// ui->betweenVersionsButton->setEnabled(false);
break;
default: default:
break; break;
} }
if (btn) {
btn->setEnabled(false);
if (!reason.isEmpty())
btn->setText(btn->text() + QString(" (%1)").arg(reason));
}
} }
void ModFilterWidget::onVersionFilterChanged(int id) void ModFilterWidget::onVersionFilterChanged(int id)

View File

@ -38,18 +38,22 @@ public:
std::shared_ptr<Filter> m_filter; std::shared_ptr<Filter> m_filter;
public: public:
explicit ModFilterWidget(Version def, QWidget* parent = nullptr); static unique_qobject_ptr<ModFilterWidget> create(Version default_version, QWidget* parent = nullptr);
~ModFilterWidget(); ~ModFilterWidget();
void setInstance(MinecraftInstance* instance); void setInstance(MinecraftInstance* instance);
/// By default all buttons are enabled /// By default all buttons are enabled
void disableVersionButton(VersionButtonID); void disableVersionButton(VersionButtonID, QString reason = {});
auto getFilter() -> std::shared_ptr<Filter>; auto getFilter() -> std::shared_ptr<Filter>;
auto changed() const -> bool { return m_last_version_id != m_version_id; } auto changed() const -> bool { return m_last_version_id != m_version_id; }
Meta::VersionListPtr versionList() { return m_version_list; }
private: private:
ModFilterWidget(Version def, QWidget* parent = nullptr);
inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; }
inline auto mcVersion() const -> Version { return { mcVersionStr() }; } inline auto mcVersion() const -> Version { return { mcVersionStr() }; }