From 97a74d5c1f00a11d331a41b16690f7202fe102a3 Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 10 Aug 2022 14:48:34 -0300 Subject: [PATCH] refactor: adapt rest of the codebase to the new resource model In order to access the ModFolderModel from the ModFolderPage, i created a new m_model for the correct type, shadowing the m_model of type ResourceFolderModel. This creates two shared_ptr references to the same object, but since they will have the same lifetime, it doesn't generate a memory leak. Signed-off-by: flow --- launcher/CMakeLists.txt | 7 +- launcher/InstancePageProvider.h | 6 +- launcher/minecraft/MinecraftInstance.cpp | 13 +- launcher/minecraft/MinecraftInstance.h | 16 +- launcher/minecraft/mod/Mod.h | 3 +- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/Resource.h | 2 + launcher/minecraft/mod/ResourceFolderModel.h | 3 + launcher/minecraft/mod/ResourcePack.h | 13 ++ .../minecraft/mod/ResourcePackFolderModel.cpp | 3 +- .../minecraft/mod/ResourcePackFolderModel.h | 4 + .../minecraft/mod/ShaderPackFolderModel.h | 10 ++ .../minecraft/mod/TexturePackFolderModel.cpp | 22 +-- .../minecraft/mod/TexturePackFolderModel.h | 6 +- .../pages/instance/ExternalResourcesPage.cpp | 142 +++--------------- .../ui/pages/instance/ExternalResourcesPage.h | 17 ++- .../pages/instance/ExternalResourcesPage.ui | 6 +- launcher/ui/pages/instance/ModFolderPage.cpp | 42 +++++- launcher/ui/pages/instance/ModFolderPage.h | 11 ++ launcher/ui/pages/instance/ResourcePackPage.h | 6 +- launcher/ui/pages/instance/ShaderPackPage.h | 6 +- launcher/ui/pages/instance/TexturePackPage.h | 6 +- launcher/ui/pages/instance/VersionPage.cpp | 6 +- launcher/ui/pages/instance/VersionPage.ui | 6 +- .../{MCModInfoFrame.cpp => InfoFrame.cpp} | 96 ++++++------ .../widgets/{MCModInfoFrame.h => InfoFrame.h} | 36 ++--- .../{MCModInfoFrame.ui => InfoFrame.ui} | 8 +- 27 files changed, 235 insertions(+), 263 deletions(-) create mode 100644 launcher/minecraft/mod/ResourcePack.h create mode 100644 launcher/minecraft/mod/ShaderPackFolderModel.h rename launcher/ui/widgets/{MCModInfoFrame.cpp => InfoFrame.cpp} (55%) rename launcher/ui/widgets/{MCModInfoFrame.h => InfoFrame.h} (59%) rename launcher/ui/widgets/{MCModInfoFrame.ui => InfoFrame.ui} (92%) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index d1e0befd..badd0eaa 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -326,6 +326,7 @@ set(MINECRAFT_SOURCES minecraft/mod/ResourcePackFolderModel.cpp minecraft/mod/TexturePackFolderModel.h minecraft/mod/TexturePackFolderModel.cpp + minecraft/mod/ShaderPackFolderModel.h minecraft/mod/tasks/BasicFolderLoadTask.h minecraft/mod/tasks/ModFolderLoadTask.h minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -884,8 +885,8 @@ SET(LAUNCHER_SOURCES ui/widgets/LineSeparator.h ui/widgets/LogView.cpp ui/widgets/LogView.h - ui/widgets/MCModInfoFrame.cpp - ui/widgets/MCModInfoFrame.h + ui/widgets/InfoFrame.cpp + ui/widgets/InfoFrame.h ui/widgets/ModFilterWidget.cpp ui/widgets/ModFilterWidget.h ui/widgets/ModListView.cpp @@ -947,7 +948,7 @@ qt_wrap_ui(LAUNCHER_UI ui/pages/modplatform/technic/TechnicPage.ui ui/widgets/InstanceCardWidget.ui ui/widgets/CustomCommands.ui - ui/widgets/MCModInfoFrame.ui + ui/widgets/InfoFrame.ui ui/widgets/ModFilterWidget.ui ui/dialogs/CopyInstanceDialog.ui ui/dialogs/ProfileSetupDialog.ui diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index 78fb7016..bf29377d 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -37,9 +37,9 @@ public: modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); values.append(modsPage); values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList())); - values.append(new ResourcePackPage(onesix.get())); - values.append(new TexturePackPage(onesix.get())); - values.append(new ShaderPackPage(onesix.get())); + values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList())); + values.append(new TexturePackPage(onesix.get(), onesix->texturePackList())); + values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList())); values.append(new NotesPage(onesix.get())); values.append(new WorldListPage(onesix.get(), onesix->worldList())); values.append(new ServersPage(onesix)); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index b42aeda3..94b4776e 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -76,6 +76,7 @@ #include "mod/ModFolderModel.h" #include "mod/ResourcePackFolderModel.h" +#include "mod/ShaderPackFolderModel.h" #include "mod/TexturePackFolderModel.h" #include "WorldList.h" @@ -1092,18 +1093,18 @@ std::shared_ptr MinecraftInstance::coreModList() const return m_core_mod_list; } -std::shared_ptr MinecraftInstance::resourcePackList() const +std::shared_ptr MinecraftInstance::resourcePackList() const { if (!m_resource_pack_list) { m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir())); - m_resource_pack_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ModFolderModel::disableInteraction); + m_resource_pack_list->enableInteraction(!isRunning()); + connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ResourcePackFolderModel::disableInteraction); } return m_resource_pack_list; } -std::shared_ptr MinecraftInstance::texturePackList() const +std::shared_ptr MinecraftInstance::texturePackList() const { if (!m_texture_pack_list) { @@ -1114,11 +1115,11 @@ std::shared_ptr MinecraftInstance::texturePackList() const return m_texture_pack_list; } -std::shared_ptr MinecraftInstance::shaderPackList() const +std::shared_ptr MinecraftInstance::shaderPackList() const { if (!m_shader_pack_list) { - m_shader_pack_list.reset(new ResourcePackFolderModel(shaderPacksDir())); + m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir())); m_shader_pack_list->disableInteraction(isRunning()); connect(this, &BaseInstance::runningStatusChanged, m_shader_pack_list.get(), &ModFolderModel::disableInteraction); } diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 7a75f452..d62ac655 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -7,6 +7,10 @@ #include "minecraft/launch/MinecraftServerTarget.h" class ModFolderModel; +class ResourceFolderModel; +class ResourcePackFolderModel; +class ShaderPackFolderModel; +class TexturePackFolderModel; class WorldList; class GameOptions; class LaunchStep; @@ -72,9 +76,9 @@ public: ////// Mod Lists ////// std::shared_ptr loaderModList() const; std::shared_ptr coreModList() const; - std::shared_ptr resourcePackList() const; - std::shared_ptr texturePackList() const; - std::shared_ptr shaderPackList() const; + std::shared_ptr resourcePackList() const; + std::shared_ptr texturePackList() const; + std::shared_ptr shaderPackList() const; std::shared_ptr worldList() const; std::shared_ptr gameOptionsModel() const; @@ -125,9 +129,9 @@ protected: // data std::shared_ptr m_components; mutable std::shared_ptr m_loader_mod_list; mutable std::shared_ptr m_core_mod_list; - mutable std::shared_ptr m_resource_pack_list; - mutable std::shared_ptr m_shader_pack_list; - mutable std::shared_ptr m_texture_pack_list; + mutable std::shared_ptr m_resource_pack_list; + mutable std::shared_ptr m_shader_pack_list; + mutable std::shared_ptr m_texture_pack_list; mutable std::shared_ptr m_world_list; mutable std::shared_ptr m_game_options; }; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 25ac88c9..0835e3b1 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -50,7 +50,8 @@ public: Mod() = default; Mod(const QFileInfo &file); - explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); + Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); + Mod(QString file_path) : Mod(QFileInfo(file_path)) {} auto enabled() const -> bool { return m_enabled; } diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 9b8c58bc..c316e710 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -49,7 +49,7 @@ #include "minecraft/mod/tasks/LocalModParseTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" -ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(dir), m_is_indexed(is_indexed) +ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed) { FS::ensureFolderPathExists(m_dir.absolutePath()); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE }; diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index 68663ab0..bec7490f 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -34,6 +34,8 @@ class Resource : public QObject { Resource(QObject* parent = nullptr); Resource(QFileInfo file_info); + Resource(QString file_path) : Resource(QFileInfo(file_path)) {} + ~Resource() override = default; void setFile(QFileInfo file_info); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 2ccf14f0..986d9885 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -261,6 +261,9 @@ void ResourceFolderModel::applyUpdates(QSet& current_set, QSet std::sort(removed_rows.begin(), removed_rows.end()); + for (int i = 0; i < removed_rows.size(); i++) + removed_rows[i] -= i; + for (auto& removed_index : removed_rows) { beginRemoveRows(QModelIndex(), removed_index, removed_index); diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h new file mode 100644 index 00000000..c2cc8690 --- /dev/null +++ b/launcher/minecraft/mod/ResourcePack.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Resource.h" + +class ResourcePack : public Resource { + Q_OBJECT + public: + using Ptr = shared_qobject_ptr; + + ResourcePack(QObject* parent = nullptr) : Resource(parent) {} + ResourcePack(QFileInfo file_info) : Resource(file_info) {} + +}; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 64a04469..e92be894 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -35,5 +35,4 @@ #include "ResourcePackFolderModel.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QString &dir) : ResourceFolderModel(dir) { -} +ResourcePackFolderModel::ResourcePackFolderModel(const QString &dir) : ResourceFolderModel(QDir(dir)) {} diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index d2a5bf18..1fe82867 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -2,9 +2,13 @@ #include "ResourceFolderModel.h" +#include "ResourcePack.h" + class ResourcePackFolderModel : public ResourceFolderModel { Q_OBJECT public: explicit ResourcePackFolderModel(const QString &dir); + + RESOURCE_HELPERS(ResourcePack) }; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h new file mode 100644 index 00000000..a3aa958f --- /dev/null +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -0,0 +1,10 @@ +#pragma once + +#include "ResourceFolderModel.h" + +class ShaderPackFolderModel : public ResourceFolderModel { + Q_OBJECT + + public: + explicit ShaderPackFolderModel(const QString& dir) : ResourceFolderModel(QDir(dir)) {} +}; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index e3a22219..2c7c945b 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -35,24 +35,4 @@ #include "TexturePackFolderModel.h" -TexturePackFolderModel::TexturePackFolderModel(const QString &dir) : ModFolderModel(dir) { -} - -QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role == Qt::ToolTipRole) { - switch (section) { - case ActiveColumn: - return tr("Is the texture pack enabled?"); - case NameColumn: - return tr("The name of the texture pack."); - case VersionColumn: - return tr("The version of the texture pack."); - case DateColumn: - return tr("The date and time this texture pack was last changed (or added)."); - default: - return QVariant(); - } - } - - return ModFolderModel::headerData(section, orientation, role); -} +TexturePackFolderModel::TexturePackFolderModel(const QString &dir) : ResourceFolderModel(QDir(dir)) {} diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index a59d5119..69e98661 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -1,13 +1,11 @@ #pragma once -#include "ModFolderModel.h" +#include "ResourceFolderModel.h" -class TexturePackFolderModel : public ModFolderModel +class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT public: explicit TexturePackFolderModel(const QString &dir); - - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; }; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index da7c4af0..0a3687e5 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -3,100 +3,13 @@ #include "DesktopServices.h" #include "Version.h" -#include "minecraft/mod/ModFolderModel.h" +#include "minecraft/mod/ResourceFolderModel.h" #include "ui/GuiUtil.h" #include #include -namespace { -// FIXME: wasteful -void RemoveThePrefix(QString& string) -{ - QRegularExpression regex(QStringLiteral("^(?:the|teh) +"), QRegularExpression::CaseInsensitiveOption); - string.remove(regex); - string = string.trimmed(); -} -} // namespace - -class SortProxy : public QSortFilterProxyModel { - public: - explicit SortProxy(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {} - - protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override - { - ModFolderModel* model = qobject_cast(sourceModel()); - if (!model) - return false; - - const auto& mod = model->at(source_row); - - if (filterRegularExpression().match(mod->name()).hasMatch()) - return true; - if (filterRegularExpression().match(mod->description()).hasMatch()) - return true; - - for (auto& author : mod->authors()) { - if (filterRegularExpression().match(author).hasMatch()) { - return true; - } - } - - return false; - } - - bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override - { - ModFolderModel* model = qobject_cast(sourceModel()); - if (!model || !source_left.isValid() || !source_right.isValid() || source_left.column() != source_right.column()) { - return QSortFilterProxyModel::lessThan(source_left, source_right); - } - - // we are now guaranteed to have two valid indexes in the same column... we love the provided invariants unconditionally and - // proceed. - - auto column = (ModFolderModel::Columns) source_left.column(); - bool invert = false; - switch (column) { - // GH-2550 - sort by enabled/disabled - case ModFolderModel::ActiveColumn: { - auto dataL = source_left.data(Qt::CheckStateRole).toBool(); - auto dataR = source_right.data(Qt::CheckStateRole).toBool(); - if (dataL != dataR) - return dataL > dataR; - - // fallthrough - invert = sortOrder() == Qt::DescendingOrder; - } - // GH-2722 - sort mod names in a way that discards "The" prefixes - case ModFolderModel::NameColumn: { - auto dataL = model->data(model->index(source_left.row(), ModFolderModel::NameColumn)).toString(); - RemoveThePrefix(dataL); - auto dataR = model->data(model->index(source_right.row(), ModFolderModel::NameColumn)).toString(); - RemoveThePrefix(dataR); - - auto less = dataL.compare(dataR, sortCaseSensitivity()); - if (less != 0) - return invert ? (less > 0) : (less < 0); - - // fallthrough - invert = sortOrder() == Qt::DescendingOrder; - } - // GH-2762 - sort versions by parsing them as versions - case ModFolderModel::VersionColumn: { - auto dataL = Version(model->data(model->index(source_left.row(), ModFolderModel::VersionColumn)).toString()); - auto dataR = Version(model->data(model->index(source_right.row(), ModFolderModel::VersionColumn)).toString()); - return invert ? (dataL > dataR) : (dataL < dataR); - } - default: { - return QSortFilterProxyModel::lessThan(source_left, source_right); - } - } - } -}; - -ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent) +ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent) : QMainWindow(parent), m_instance(instance), ui(new Ui::ExternalResourcesPage), m_model(model) { ui->setupUi(this); @@ -105,7 +18,7 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared ui->actionsToolbar->insertSpacer(ui->actionViewConfigs); - m_filterModel = new SortProxy(this); + m_filterModel = model->createFilterProxyModel(this); m_filterModel->setDynamicSortFilter(true); m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); @@ -127,7 +40,6 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared connect(ui->actionViewFolder, &QAction::triggered, this, &ExternalResourcesPage::viewFolder); connect(ui->treeView, &ModListView::customContextMenuRequested, this, &ExternalResourcesPage::ShowContextMenu); - connect(ui->treeView, &ModListView::activated, this, &ExternalResourcesPage::itemActivated); auto selection_model = ui->treeView->selectionModel(); connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current); @@ -137,19 +49,9 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared ExternalResourcesPage::~ExternalResourcesPage() { - m_model->stopWatching(); delete ui; } -void ExternalResourcesPage::itemActivated(const QModelIndex&) -{ - if (!m_controlsEnabled) - return; - - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); - m_model->setModStatus(selection.indexes(), ModFolderModel::Toggle); -} - QMenu* ExternalResourcesPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); @@ -241,7 +143,7 @@ void ExternalResourcesPage::addItem() if (!list.isEmpty()) { for (auto filename : list) { - m_model->installMod(filename); + m_model->installResource(filename); } } } @@ -252,25 +154,7 @@ void ExternalResourcesPage::removeItem() return; auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); - m_model->deleteMods(selection.indexes()); -} - -void ExternalResourcesPage::enableItem() -{ - if (!m_controlsEnabled) - return; - - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); - m_model->setModStatus(selection.indexes(), ModFolderModel::Enable); -} - -void ExternalResourcesPage::disableItem() -{ - if (!m_controlsEnabled) - return; - - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); - m_model->setModStatus(selection.indexes(), ModFolderModel::Disable); + m_model->deleteResources(selection.indexes()); } void ExternalResourcesPage::viewConfigs() @@ -283,15 +167,23 @@ void ExternalResourcesPage::viewFolder() DesktopServices::openDirectory(m_model->dir().absolutePath(), true); } -void ExternalResourcesPage::current(const QModelIndex& current, const QModelIndex& previous) +bool ExternalResourcesPage::current(const QModelIndex& current, const QModelIndex& previous) { if (!current.isValid()) { ui->frame->clear(); - return; + return false; } + return onSelectionChanged(current, previous); +} + +bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +{ auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); - Mod& m = *m_model->operator[](row); - ui->frame->updateWithMod(m); + Resource const& resource = m_model->at(row); + ui->frame->updateWithResource(resource); + + return true; } + diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index ff294678..280f1542 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -7,7 +7,7 @@ #include "minecraft/MinecraftInstance.h" #include "ui/pages/BasePage.h" -class ModFolderModel; +class ResourceFolderModel; namespace Ui { class ExternalResourcesPage; @@ -19,8 +19,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { Q_OBJECT public: - // FIXME: Switch to different model (or change the name of this one) - explicit ExternalResourcesPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); + explicit ExternalResourcesPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); virtual ~ExternalResourcesPage(); virtual QString displayName() const override = 0; @@ -41,18 +40,20 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { QMenu* createPopupMenu() override; public slots: - void current(const QModelIndex& current, const QModelIndex& previous); + bool current(const QModelIndex& current, const QModelIndex& previous); + + virtual bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous); protected slots: - void itemActivated(const QModelIndex& index); + virtual void itemActivated(const QModelIndex& index) {}; void filterTextChanged(const QString& newContents); virtual void runningStateChanged(bool running); virtual void addItem(); virtual void removeItem(); - virtual void enableItem(); - virtual void disableItem(); + virtual void enableItem() {}; + virtual void disableItem() {}; virtual void viewFolder(); virtual void viewConfigs(); @@ -63,7 +64,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { BaseInstance* m_instance = nullptr; Ui::ExternalResourcesPage* ui = nullptr; - std::shared_ptr m_model; + std::shared_ptr m_model; QSortFilterProxyModel* m_filterModel = nullptr; QString m_fileSelectionFilter; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index a13666b2..76f8ec18 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -43,7 +43,7 @@ - + 0 @@ -166,9 +166,9 @@
ui/widgets/ModListView.h
- MCModInfoFrame + InfoFrame QFrame -
ui/widgets/MCModInfoFrame.h
+
ui/widgets/InfoFrame.h
1
diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 45678db1..63897fb0 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -65,7 +65,7 @@ #include "ui/dialogs/ProgressDialog.h" ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr mods, QWidget* parent) - : ExternalResourcesPage(inst, mods, parent) + : ExternalResourcesPage(inst, mods, parent), m_model(mods) { // This is structured like that so that these changes // do not affect the Resource pack and Shader pack tabs @@ -110,6 +110,8 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning()); } + + connect(ui->treeView, &ModListView::activated, this, &ModFolderPage::itemActivated); } void ModFolderPage::runningStateChanged(bool running) @@ -124,6 +126,44 @@ bool ModFolderPage::shouldDisplay() const return true; } +void ModFolderPage::itemActivated(const QModelIndex&) +{ + if (!m_controlsEnabled) + return; + + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); + m_model->setModStatus(selection.indexes(), ModFolderModel::Toggle); +} + +void ModFolderPage::enableItem() +{ + if (!m_controlsEnabled) + return; + + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); + m_model->setModStatus(selection.indexes(), ModFolderModel::Enable); +} + +void ModFolderPage::disableItem() +{ + if (!m_controlsEnabled) + return; + + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); + m_model->setModStatus(selection.indexes(), ModFolderModel::Disable); +} + +bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +{ + auto sourceCurrent = m_filterModel->mapToSource(current); + int row = sourceCurrent.row(); + Mod const* m = m_model->at(row); + if (m) + ui->frame->updateWithMod(*m); + + return true; +} + void ModFolderPage::installMods() { if (!m_controlsEnabled) diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 7e305951..5da353f0 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -55,9 +55,20 @@ class ModFolderPage : public ExternalResourcesPage { virtual bool shouldDisplay() const override; void runningStateChanged(bool running) override; + public slots: + bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; + + void itemActivated(const QModelIndex& index) override; + + void enableItem() override; + void disableItem() override; + private slots: void installMods(); void updateMods(); + + protected: + std::shared_ptr m_model; }; class CoreModFolderPage : public ModFolderPage { diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index a6c9fdd3..2eefc3d3 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -38,12 +38,14 @@ #include "ExternalResourcesPage.h" #include "ui_ExternalResourcesPage.h" +#include "minecraft/mod/ResourcePackFolderModel.h" + class ResourcePackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit ResourcePackPage(MinecraftInstance *instance, QWidget *parent = 0) - : ExternalResourcesPage(instance, instance->resourcePackList(), parent) + explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) + : ExternalResourcesPage(instance, model, parent) { ui->actionViewConfigs->setVisible(false); } diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index 2cc056c8..7f7ff8c1 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -38,12 +38,14 @@ #include "ExternalResourcesPage.h" #include "ui_ExternalResourcesPage.h" +#include "minecraft/mod/ShaderPackFolderModel.h" + class ShaderPackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit ShaderPackPage(MinecraftInstance *instance, QWidget *parent = 0) - : ExternalResourcesPage(instance, instance->shaderPackList(), parent) + explicit ShaderPackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) + : ExternalResourcesPage(instance, model, parent) { ui->actionViewConfigs->setVisible(false); } diff --git a/launcher/ui/pages/instance/TexturePackPage.h b/launcher/ui/pages/instance/TexturePackPage.h index f550a5bc..fa219eda 100644 --- a/launcher/ui/pages/instance/TexturePackPage.h +++ b/launcher/ui/pages/instance/TexturePackPage.h @@ -38,12 +38,14 @@ #include "ExternalResourcesPage.h" #include "ui_ExternalResourcesPage.h" +#include "minecraft/mod/TexturePackFolderModel.h" + class TexturePackPage : public ExternalResourcesPage { Q_OBJECT public: - explicit TexturePackPage(MinecraftInstance *instance, QWidget *parent = 0) - : ExternalResourcesPage(instance, instance->texturePackList(), parent) + explicit TexturePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0) + : ExternalResourcesPage(instance, model, parent) { ui->actionViewConfigs->setVisible(false); } diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 468ff35c..a021c633 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -196,10 +196,10 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & switch(severity) { case ProblemSeverity::Warning: - ui->frame->setModText(tr("%1 possibly has issues.").arg(patch->getName())); + ui->frame->setName(tr("%1 possibly has issues.").arg(patch->getName())); break; case ProblemSeverity::Error: - ui->frame->setModText(tr("%1 has issues!").arg(patch->getName())); + ui->frame->setName(tr("%1 has issues!").arg(patch->getName())); break; default: case ProblemSeverity::None: @@ -222,7 +222,7 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & problemOut += problem.m_description; problemOut += "\n"; } - ui->frame->setModDescription(problemOut); + ui->frame->setDescription(problemOut); } void VersionPage::updateRunningStatus(bool running) diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui index 489f7218..fcba5598 100644 --- a/launcher/ui/pages/instance/VersionPage.ui +++ b/launcher/ui/pages/instance/VersionPage.ui @@ -64,7 +64,7 @@
- + 0 @@ -278,9 +278,9 @@
ui/widgets/ModListView.h
- MCModInfoFrame + InfoFrame QFrame -
ui/widgets/MCModInfoFrame.h
+
ui/widgets/InfoFrame.h
1
diff --git a/launcher/ui/widgets/MCModInfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp similarity index 55% rename from launcher/ui/widgets/MCModInfoFrame.cpp rename to launcher/ui/widgets/InfoFrame.cpp index 22475abc..821e61a7 100644 --- a/launcher/ui/widgets/MCModInfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -14,14 +14,28 @@ */ #include -#include -#include "MCModInfoFrame.h" -#include "ui_MCModInfoFrame.h" +#include "InfoFrame.h" +#include "ui_InfoFrame.h" #include "ui/dialogs/CustomMessageBox.h" -void MCModInfoFrame::updateWithMod(Mod &m) +InfoFrame::InfoFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::InfoFrame) +{ + ui->setupUi(this); + ui->descriptionLabel->setHidden(true); + ui->nameLabel->setHidden(true); + updateHiddenState(); +} + +InfoFrame::~InfoFrame() +{ + delete ui; +} + +void InfoFrame::updateWithMod(Mod const& m) { if (m.type() == ResourceType::FOLDER) { @@ -43,42 +57,32 @@ void MCModInfoFrame::updateWithMod(Mod &m) if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); - setModText(text); + setName(text); if (m.description().isEmpty()) { - setModDescription(QString()); + setDescription(QString()); } else { - setModDescription(m.description()); + setDescription(m.description()); } } -void MCModInfoFrame::clear() +void InfoFrame::updateWithResource(const Resource& resource) { - setModText(QString()); - setModDescription(QString()); + setName(resource.name()); } -MCModInfoFrame::MCModInfoFrame(QWidget *parent) : - QFrame(parent), - ui(new Ui::MCModInfoFrame) +void InfoFrame::clear() { - ui->setupUi(this); - ui->label_ModDescription->setHidden(true); - ui->label_ModText->setHidden(true); - updateHiddenState(); + setName(); + setDescription(); } -MCModInfoFrame::~MCModInfoFrame() +void InfoFrame::updateHiddenState() { - delete ui; -} - -void MCModInfoFrame::updateHiddenState() -{ - if(ui->label_ModDescription->isHidden() && ui->label_ModText->isHidden()) + if(ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden()) { setHidden(true); } @@ -88,34 +92,34 @@ void MCModInfoFrame::updateHiddenState() } } -void MCModInfoFrame::setModText(QString text) +void InfoFrame::setName(QString text) { if(text.isEmpty()) { - ui->label_ModText->setHidden(true); + ui->nameLabel->setHidden(true); } else { - ui->label_ModText->setText(text); - ui->label_ModText->setHidden(false); + ui->nameLabel->setText(text); + ui->nameLabel->setHidden(false); } updateHiddenState(); } -void MCModInfoFrame::setModDescription(QString text) +void InfoFrame::setDescription(QString text) { if(text.isEmpty()) { - ui->label_ModDescription->setHidden(true); + ui->descriptionLabel->setHidden(true); updateHiddenState(); return; } else { - ui->label_ModDescription->setHidden(false); + ui->descriptionLabel->setHidden(false); updateHiddenState(); } - ui->label_ModDescription->setToolTip(""); + ui->descriptionLabel->setToolTip(""); QString intermediatetext = text.trimmed(); bool prev(false); QChar rem('\n'); @@ -133,36 +137,36 @@ void MCModInfoFrame::setModDescription(QString text) labeltext.reserve(300); if(finaltext.length() > 290) { - ui->label_ModDescription->setOpenExternalLinks(false); - ui->label_ModDescription->setTextFormat(Qt::TextFormat::RichText); - desc = text; + ui->descriptionLabel->setOpenExternalLinks(false); + ui->descriptionLabel->setTextFormat(Qt::TextFormat::RichText); + m_description = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); - QObject::connect(ui->label_ModDescription, &QLabel::linkActivated, this, &MCModInfoFrame::modDescEllipsisHandler); + QObject::connect(ui->descriptionLabel, &QLabel::linkActivated, this, &InfoFrame::descriptionEllipsisHandler); } else { - ui->label_ModDescription->setTextFormat(Qt::TextFormat::PlainText); + ui->descriptionLabel->setTextFormat(Qt::TextFormat::PlainText); labeltext.append(finaltext); } - ui->label_ModDescription->setText(labeltext); + ui->descriptionLabel->setText(labeltext); } -void MCModInfoFrame::modDescEllipsisHandler(const QString &link) +void InfoFrame::descriptionEllipsisHandler(QString link) { - if(!currentBox) + if(!m_current_box) { - currentBox = CustomMessageBox::selectable(this, QString(), desc); - connect(currentBox, &QMessageBox::finished, this, &MCModInfoFrame::boxClosed); - currentBox->show(); + m_current_box = CustomMessageBox::selectable(this, "", m_description); + connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); + m_current_box->show(); } else { - currentBox->setText(desc); + m_current_box->setText(m_description); } } -void MCModInfoFrame::boxClosed(int result) +void InfoFrame::boxClosed(int result) { - currentBox = nullptr; + m_current_box = nullptr; } diff --git a/launcher/ui/widgets/MCModInfoFrame.h b/launcher/ui/widgets/InfoFrame.h similarity index 59% rename from launcher/ui/widgets/MCModInfoFrame.h rename to launcher/ui/widgets/InfoFrame.h index 0b7ef537..d69dc232 100644 --- a/launcher/ui/widgets/MCModInfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -16,37 +16,39 @@ #pragma once #include + #include "minecraft/mod/Mod.h" +#include "minecraft/mod/ResourcePack.h" namespace Ui { -class MCModInfoFrame; +class InfoFrame; } -class MCModInfoFrame : public QFrame -{ +class InfoFrame : public QFrame { Q_OBJECT -public: - explicit MCModInfoFrame(QWidget *parent = 0); - ~MCModInfoFrame(); + public: + InfoFrame(QWidget* parent = nullptr); + ~InfoFrame() override; - void setModText(QString text); - void setModDescription(QString text); + void setName(QString text = {}); + void setDescription(QString text = {}); - void updateWithMod(Mod &m); void clear(); -public slots: - void modDescEllipsisHandler(const QString& link ); + void updateWithMod(Mod const& m); + void updateWithResource(Resource const& resource); + + public slots: + void descriptionEllipsisHandler(QString link); void boxClosed(int result); -private: + private: void updateHiddenState(); -private: - Ui::MCModInfoFrame *ui; - QString desc; - class QMessageBox * currentBox = nullptr; + private: + Ui::InfoFrame* ui; + QString m_description; + class QMessageBox* m_current_box = nullptr; }; - diff --git a/launcher/ui/widgets/MCModInfoFrame.ui b/launcher/ui/widgets/InfoFrame.ui similarity index 92% rename from launcher/ui/widgets/MCModInfoFrame.ui rename to launcher/ui/widgets/InfoFrame.ui index 5ef33379..0d3772d7 100644 --- a/launcher/ui/widgets/MCModInfoFrame.ui +++ b/launcher/ui/widgets/InfoFrame.ui @@ -1,7 +1,7 @@ - MCModInfoFrame - + InfoFrame + 0 @@ -39,7 +39,7 @@ 0 - + @@ -61,7 +61,7 @@ - +