Merge remote-tracking branch 'upstream/develop' into data-packs
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
commit
6ab4fef0c5
686 changed files with 15261 additions and 9719 deletions
|
@ -17,7 +17,6 @@ namespace ResourceDownload {
|
|||
|
||||
DataPackResourcePage::DataPackResourcePage(DataPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance)
|
||||
{
|
||||
connect(m_ui->searchButton, &QPushButton::clicked, this, &DataPackResourcePage::triggerSearch);
|
||||
connect(m_ui->packView, &QListView::doubleClicked, this, &DataPackResourcePage::onResourceSelected);
|
||||
}
|
||||
|
||||
|
@ -32,7 +31,7 @@ void DataPackResourcePage::triggerSearch()
|
|||
updateSelectionButton();
|
||||
|
||||
static_cast<DataPackResourceModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt());
|
||||
m_fetch_progress.watch(m_model->activeSearchJob().get());
|
||||
m_fetchProgress.watch(m_model->activeSearchJob().get());
|
||||
}
|
||||
|
||||
QMap<QString, QString> DataPackResourcePage::urlHandlers() const
|
||||
|
|
|
@ -39,7 +39,9 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
|
|||
|
||||
auto sort = getCurrentSortingMethodByIndex();
|
||||
|
||||
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions, side, categories };
|
||||
return {
|
||||
ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions, side, categories, m_filter->openSource
|
||||
};
|
||||
}
|
||||
|
||||
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
|
||||
|
@ -104,18 +106,6 @@ bool checkSide(QString filter, QString value)
|
|||
return filter.isEmpty() || value.isEmpty() || filter == "both" || value == "both" || filter == value;
|
||||
}
|
||||
|
||||
bool checkMcVersions(std::list<Version> filter, QStringList value)
|
||||
{
|
||||
bool valid = false;
|
||||
for (auto mcVersion : filter) {
|
||||
if (value.contains(mcVersion.toString())) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return filter.empty() || valid;
|
||||
}
|
||||
|
||||
bool ModModel::checkFilters(ModPlatform::IndexedPack::Ptr pack)
|
||||
{
|
||||
if (!m_filter)
|
||||
|
@ -135,7 +125,7 @@ bool ModModel::checkVersionFilters(const ModPlatform::IndexedVersion& v)
|
|||
checkSide(m_filter->side, v.side) && // side
|
||||
(m_filter->releases.empty() || // releases
|
||||
std::find(m_filter->releases.cbegin(), m_filter->releases.cend(), v.version_type) != m_filter->releases.cend()) &&
|
||||
checkMcVersions(m_filter->versions, v.mcVersion)); // mcVersions
|
||||
m_filter->checkMcVersions(v.mcVersion)); // mcVersions
|
||||
}
|
||||
|
||||
} // namespace ResourceDownload
|
||||
|
|
|
@ -99,7 +99,7 @@ void ModPage::triggerSearch()
|
|||
updateSelectionButton();
|
||||
|
||||
static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), changed);
|
||||
m_fetch_progress.watch(m_model->activeSearchJob().get());
|
||||
m_fetchProgress.watch(m_model->activeSearchJob().get());
|
||||
}
|
||||
|
||||
QMap<QString, QString> ModPage::urlHandlers() const
|
||||
|
|
29
launcher/ui/pages/modplatform/ModpackProviderBasePage.h
Normal file
29
launcher/ui/pages/modplatform/ModpackProviderBasePage.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui/pages/BasePage.h"
|
||||
|
||||
class ModpackProviderBasePage : public BasePage {
|
||||
public:
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) = 0;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const = 0;
|
||||
};
|
|
@ -43,6 +43,9 @@ OptionalModDialog::OptionalModDialog(QWidget* parent, const QStringList& mods) :
|
|||
else
|
||||
item->setCheckState(Qt::Checked);
|
||||
});
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
|
||||
}
|
||||
|
||||
OptionalModDialog::~OptionalModDialog()
|
||||
|
|
|
@ -31,9 +31,9 @@ QHash<ResourceModel*, bool> ResourceModel::s_running_models;
|
|||
ResourceModel::ResourceModel(ResourceAPI* api) : QAbstractListModel(), m_api(api)
|
||||
{
|
||||
s_running_models.insert(this, true);
|
||||
#ifndef LAUNCHER_TEST
|
||||
m_current_info_job.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
#endif
|
||||
if (APPLICATION_DYN) {
|
||||
m_current_info_job.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||
}
|
||||
}
|
||||
|
||||
ResourceModel::~ResourceModel()
|
||||
|
@ -60,11 +60,15 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
|
|||
return pack->description;
|
||||
}
|
||||
case Qt::DecorationRole: {
|
||||
if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack->logoUrl);
|
||||
icon_or_none.has_value())
|
||||
return icon_or_none.value();
|
||||
if (APPLICATION_DYN) {
|
||||
if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack->logoUrl);
|
||||
icon_or_none.has_value())
|
||||
return icon_or_none.value();
|
||||
|
||||
return APPLICATION->getThemedIcon("screenshot-placeholder");
|
||||
return APPLICATION->getThemedIcon("screenshot-placeholder");
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
case Qt::SizeHintRole:
|
||||
return QSize(0, 58);
|
||||
|
@ -333,7 +337,7 @@ std::optional<QIcon> ResourceModel::getIcon(QModelIndex& index, const QUrl& url)
|
|||
auto icon_fetch_action = Net::ApiDownload::makeCached(url, cache_entry);
|
||||
|
||||
auto full_file_path = cache_entry->getFullPath();
|
||||
connect(icon_fetch_action.get(), &Task::succeeded, this, [=] {
|
||||
connect(icon_fetch_action.get(), &Task::succeeded, this, [this, url, full_file_path, index] {
|
||||
auto icon = QIcon(full_file_path);
|
||||
QPixmapCache::insert(url.toString(), icon.pixmap(icon.actualSize({ 64, 64 })));
|
||||
|
||||
|
@ -341,7 +345,7 @@ std::optional<QIcon> ResourceModel::getIcon(QModelIndex& index, const QUrl& url)
|
|||
|
||||
emit dataChanged(index, index, { Qt::DecorationRole });
|
||||
});
|
||||
connect(icon_fetch_action.get(), &Task::failed, this, [=] {
|
||||
connect(icon_fetch_action.get(), &Task::failed, this, [this, url] {
|
||||
m_currently_running_icon_actions.remove(url);
|
||||
m_failed_icon_actions.insert(url);
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@ void ResourcePackResourcePage::triggerSearch()
|
|||
updateSelectionButton();
|
||||
|
||||
static_cast<ResourcePackResourceModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt());
|
||||
m_fetch_progress.watch(m_model->activeSearchJob().get());
|
||||
m_fetchProgress.watch(m_model->activeSearchJob().get());
|
||||
}
|
||||
|
||||
QMap<QString, QString> ResourcePackResourcePage::urlHandlers() const
|
||||
|
|
|
@ -39,14 +39,16 @@
|
|||
|
||||
#include "ResourcePage.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui_ResourcePage.h"
|
||||
|
||||
#include <StringUtils.h>
|
||||
#include <QDesktopServices>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "Markdown.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include "Application.h"
|
||||
#include "ui/dialogs/ResourceDownloadDialog.h"
|
||||
#include "ui/pages/modplatform/ResourceModel.h"
|
||||
#include "ui/widgets/ProjectItem.h"
|
||||
|
@ -54,7 +56,7 @@
|
|||
namespace ResourceDownload {
|
||||
|
||||
ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_instance)
|
||||
: QWidget(parent), m_base_instance(base_instance), m_ui(new Ui::ResourcePage), m_parent_dialog(parent), m_fetch_progress(this, false)
|
||||
: QWidget(parent), m_baseInstance(base_instance), m_ui(new Ui::ResourcePage), m_parentDialog(parent), m_fetchProgress(this, false)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
|
@ -63,18 +65,18 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_in
|
|||
m_ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
m_ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
|
||||
|
||||
m_search_timer.setTimerType(Qt::TimerType::CoarseTimer);
|
||||
m_search_timer.setSingleShot(true);
|
||||
m_searchTimer.setTimerType(Qt::TimerType::CoarseTimer);
|
||||
m_searchTimer.setSingleShot(true);
|
||||
|
||||
connect(&m_search_timer, &QTimer::timeout, this, &ResourcePage::triggerSearch);
|
||||
connect(&m_searchTimer, &QTimer::timeout, this, &ResourcePage::triggerSearch);
|
||||
|
||||
// hide progress bar to prevent weird artifact
|
||||
m_fetch_progress.hide();
|
||||
m_fetch_progress.hideIfInactive(true);
|
||||
m_fetch_progress.setFixedHeight(24);
|
||||
m_fetch_progress.progressFormat("");
|
||||
m_fetchProgress.hide();
|
||||
m_fetchProgress.hideIfInactive(true);
|
||||
m_fetchProgress.setFixedHeight(24);
|
||||
m_fetchProgress.progressFormat("");
|
||||
|
||||
m_ui->verticalLayout->insertWidget(1, &m_fetch_progress);
|
||||
m_ui->verticalLayout->insertWidget(1, &m_fetchProgress);
|
||||
|
||||
m_ui->packView->setItemDelegate(new ProjectItemDelegate(this));
|
||||
m_ui->packView->installEventFilter(this);
|
||||
|
@ -120,10 +122,10 @@ auto ResourcePage::eventFilter(QObject* watched, QEvent* event) -> bool
|
|||
keyEvent->accept();
|
||||
return true;
|
||||
} else {
|
||||
if (m_search_timer.isActive())
|
||||
m_search_timer.stop();
|
||||
if (m_searchTimer.isActive())
|
||||
m_searchTimer.stop();
|
||||
|
||||
m_search_timer.start(350);
|
||||
m_searchTimer.start(350);
|
||||
}
|
||||
} else if (watched == m_ui->packView) {
|
||||
if (keyEvent->key() == Qt::Key_Return) {
|
||||
|
@ -247,14 +249,17 @@ void ResourcePage::updateUi()
|
|||
|
||||
void ResourcePage::updateSelectionButton()
|
||||
{
|
||||
if (!isOpened || m_selected_version_index < 0) {
|
||||
if (!isOpened || m_selectedVersionIndex < 0) {
|
||||
m_ui->resourceSelectionButton->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_ui->resourceSelectionButton->setEnabled(true);
|
||||
if (auto current_pack = getCurrentPack(); current_pack) {
|
||||
if (!current_pack->isVersionSelected(m_selected_version_index))
|
||||
if (current_pack->versionsLoaded && current_pack->versions.empty()) {
|
||||
m_ui->resourceSelectionButton->setEnabled(false);
|
||||
qWarning() << tr("No version available for the selected pack");
|
||||
} else if (!current_pack->isVersionSelected(m_selectedVersionIndex))
|
||||
m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString()));
|
||||
else
|
||||
m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString()));
|
||||
|
@ -279,11 +284,15 @@ void ResourcePage::updateVersionList()
|
|||
if (!m_model->checkVersionFilters(version))
|
||||
continue;
|
||||
|
||||
auto release_type = current_pack->versions[i].version_type.isValid()
|
||||
? QString(" [%1]").arg(current_pack->versions[i].version_type.toString())
|
||||
: "";
|
||||
auto versionText = version.version;
|
||||
if (version.version_type.isValid()) {
|
||||
versionText += QString(" [%1]").arg(version.version_type.toString());
|
||||
}
|
||||
if (version.fileId == installedVersion) {
|
||||
versionText += tr(" [installed]", "Mod version select");
|
||||
}
|
||||
|
||||
m_ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(i));
|
||||
m_ui->versionSelectionBox->addItem(versionText, QVariant(i));
|
||||
}
|
||||
}
|
||||
if (m_ui->versionSelectionBox->count() == 0) {
|
||||
|
@ -323,25 +332,26 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
|||
|
||||
void ResourcePage::onVersionSelectionChanged(int index)
|
||||
{
|
||||
m_selected_version_index = index;
|
||||
m_selectedVersionIndex = m_ui->versionSelectionBox->itemData(index).toInt();
|
||||
updateSelectionButton();
|
||||
}
|
||||
|
||||
void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version)
|
||||
{
|
||||
m_parent_dialog->addResource(pack, version);
|
||||
m_parentDialog->addResource(pack, version);
|
||||
}
|
||||
|
||||
void ResourcePage::removeResourceFromDialog(const QString& pack_name)
|
||||
{
|
||||
m_parent_dialog->removeResource(pack_name);
|
||||
m_parentDialog->removeResource(pack_name);
|
||||
}
|
||||
|
||||
void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
|
||||
ModPlatform::IndexedVersion& ver,
|
||||
const std::shared_ptr<ResourceFolderModel> base_model)
|
||||
{
|
||||
m_model->addPack(pack, ver, base_model);
|
||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
||||
m_model->addPack(pack, ver, base_model, is_indexed);
|
||||
}
|
||||
|
||||
void ResourcePage::removeResourceFromPage(const QString& name)
|
||||
|
@ -351,14 +361,15 @@ void ResourcePage::removeResourceFromPage(const QString& name)
|
|||
|
||||
void ResourcePage::onResourceSelected()
|
||||
{
|
||||
if (m_selected_version_index < 0)
|
||||
if (m_selectedVersionIndex < 0)
|
||||
return;
|
||||
|
||||
auto current_pack = getCurrentPack();
|
||||
if (!current_pack || !current_pack->versionsLoaded)
|
||||
if (!current_pack || !current_pack->versionsLoaded || current_pack->versions.size() < m_selectedVersionIndex)
|
||||
return;
|
||||
|
||||
auto& version = current_pack->versions[m_selected_version_index];
|
||||
auto& version = current_pack->versions[m_selectedVersionIndex];
|
||||
Q_ASSERT(!version.downloadUrl.isNull());
|
||||
if (version.is_currently_selected)
|
||||
removeResourceFromDialog(current_pack->name);
|
||||
else
|
||||
|
@ -397,14 +408,14 @@ void ResourcePage::openUrl(const QUrl& url)
|
|||
}
|
||||
}
|
||||
|
||||
if (!page.isNull() && !m_do_not_jump_to_mod) {
|
||||
if (!page.isNull() && !m_doNotJumpToMod) {
|
||||
const QString slug = match.captured(1);
|
||||
|
||||
// ensure the user isn't opening the same mod
|
||||
if (auto current_pack = getCurrentPack(); current_pack && slug != current_pack->slug) {
|
||||
m_parent_dialog->selectPage(page);
|
||||
m_parentDialog->selectPage(page);
|
||||
|
||||
auto newPage = m_parent_dialog->selectedPage();
|
||||
auto newPage = m_parentDialog->selectedPage();
|
||||
|
||||
QLineEdit* searchEdit = newPage->m_ui->searchEdit;
|
||||
auto model = newPage->m_model;
|
||||
|
@ -448,7 +459,7 @@ void ResourcePage::openProject(QVariant projectID)
|
|||
m_ui->resourceFilterButton->hide();
|
||||
m_ui->packView->hide();
|
||||
m_ui->resourceSelectionButton->hide();
|
||||
m_do_not_jump_to_mod = true;
|
||||
m_doNotJumpToMod = true;
|
||||
|
||||
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
|
||||
|
@ -462,20 +473,23 @@ void ResourcePage::openProject(QVariant projectID)
|
|||
auto cancelBtn = buttonBox->button(QDialogButtonBox::Cancel);
|
||||
cancelBtn->setDefault(false);
|
||||
cancelBtn->setAutoDefault(false);
|
||||
cancelBtn->setText(tr("Cancel"));
|
||||
|
||||
connect(okBtn, &QPushButton::clicked, this, [this] {
|
||||
onResourceSelected();
|
||||
m_parent_dialog->accept();
|
||||
m_parentDialog->accept();
|
||||
});
|
||||
|
||||
connect(cancelBtn, &QPushButton::clicked, m_parent_dialog, &ResourceDownloadDialog::reject);
|
||||
connect(cancelBtn, &QPushButton::clicked, m_parentDialog, &ResourceDownloadDialog::reject);
|
||||
m_ui->gridLayout_4->addWidget(buttonBox, 1, 2);
|
||||
|
||||
auto jump = [this, okBtn] {
|
||||
connect(m_ui->versionSelectionBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
[this, okBtn](int index) { okBtn->setEnabled(m_ui->versionSelectionBox->itemData(index).toInt() >= 0); });
|
||||
|
||||
auto jump = [this] {
|
||||
for (int row = 0; row < m_model->rowCount({}); row++) {
|
||||
const QModelIndex index = m_model->index(row);
|
||||
m_ui->packView->setCurrentIndex(index);
|
||||
okBtn->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
m_ui->packDescription->setText(tr("The resource was not found"));
|
||||
|
|
|
@ -62,7 +62,7 @@ class ResourcePage : public QWidget, public BasePage {
|
|||
|
||||
[[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack::Ptr);
|
||||
[[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr;
|
||||
[[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parent_dialog; }
|
||||
[[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parentDialog; }
|
||||
[[nodiscard]] auto getModel() const -> ResourceModel* { return m_model; }
|
||||
|
||||
protected:
|
||||
|
@ -99,22 +99,22 @@ class ResourcePage : public QWidget, public BasePage {
|
|||
virtual void openUrl(const QUrl&);
|
||||
|
||||
public:
|
||||
BaseInstance& m_base_instance;
|
||||
BaseInstance& m_baseInstance;
|
||||
|
||||
protected:
|
||||
Ui::ResourcePage* m_ui;
|
||||
|
||||
ResourceDownloadDialog* m_parent_dialog = nullptr;
|
||||
ResourceDownloadDialog* m_parentDialog = nullptr;
|
||||
ResourceModel* m_model = nullptr;
|
||||
|
||||
int m_selected_version_index = -1;
|
||||
int m_selectedVersionIndex = -1;
|
||||
|
||||
ProgressWidget m_fetch_progress;
|
||||
ProgressWidget m_fetchProgress;
|
||||
|
||||
// Used to do instant searching with a delay to cache quick changes
|
||||
QTimer m_search_timer;
|
||||
QTimer m_searchTimer;
|
||||
|
||||
bool m_do_not_jump_to_mod = false;
|
||||
bool m_doNotJumpToMod = false;
|
||||
};
|
||||
|
||||
} // namespace ResourceDownload
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "ShaderPackModel.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/dialogs/ResourceDownloadDialog.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
@ -31,7 +32,7 @@ void ShaderPackResourcePage::triggerSearch()
|
|||
updateSelectionButton();
|
||||
|
||||
static_cast<ShaderPackResourceModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt());
|
||||
m_fetch_progress.watch(m_model->activeSearchJob().get());
|
||||
m_fetchProgress.watch(m_model->activeSearchJob().get());
|
||||
}
|
||||
|
||||
QMap<QString, QString> ShaderPackResourcePage::urlHandlers() const
|
||||
|
@ -48,10 +49,11 @@ void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pac
|
|||
ModPlatform::IndexedVersion& version,
|
||||
const std::shared_ptr<ResourceFolderModel> base_model)
|
||||
{
|
||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
||||
QString custom_target_folder;
|
||||
if (version.loaders & ModPlatform::Cauldron)
|
||||
custom_target_folder = QStringLiteral("resourcepacks");
|
||||
m_model->addPack(pack, version, base_model, false, custom_target_folder);
|
||||
m_model->addPack(pack, version, base_model, is_indexed, custom_target_folder);
|
||||
}
|
||||
|
||||
} // namespace ResourceDownload
|
||||
|
|
|
@ -164,3 +164,13 @@ void AtlPage::onVersionSelectionChanged(QString version)
|
|||
selectedVersion = version;
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void AtlPage::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
QString AtlPage::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
|
||||
namespace Ui {
|
||||
class AtlPage;
|
||||
|
@ -51,7 +50,7 @@ class AtlPage;
|
|||
|
||||
class NewInstanceDialog;
|
||||
|
||||
class AtlPage : public QWidget, public BasePage {
|
||||
class AtlPage : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -66,6 +65,11 @@ class AtlPage : public QWidget, public BasePage {
|
|||
|
||||
void openedImpl() override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "FlameModel.h"
|
||||
#include <Json.h>
|
||||
#include "Application.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/ResourceAPI.h"
|
||||
#include "modplatform/flame/FlameAPI.h"
|
||||
#include "ui/widgets/ProjectItem.h"
|
||||
|
@ -183,34 +184,28 @@ void ListModel::performPaginatedSearch()
|
|||
return;
|
||||
}
|
||||
}
|
||||
auto netJob = makeShared<NetJob>("Flame::Search", APPLICATION->network());
|
||||
auto searchUrl = QString(
|
||||
"https://api.curseforge.com/v1/mods/search?"
|
||||
"gameId=432&"
|
||||
"classId=4471&"
|
||||
"index=%1&"
|
||||
"pageSize=25&"
|
||||
"searchFilter=%2&"
|
||||
"sortField=%3&"
|
||||
"sortOrder=desc")
|
||||
.arg(nextSearchOffset)
|
||||
.arg(currentSearchTerm)
|
||||
.arg(currentSort + 1);
|
||||
ResourceAPI::SortingMethod sort{};
|
||||
sort.index = currentSort + 1;
|
||||
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response));
|
||||
auto netJob = makeShared<NetJob>("Flame::Search", APPLICATION->network());
|
||||
auto searchUrl = FlameAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort,
|
||||
m_filter->loaders, m_filter->versions, "", m_filter->categoryIds, m_filter->openSource });
|
||||
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::searchRequestFailed);
|
||||
}
|
||||
|
||||
void ListModel::searchWithTerm(const QString& term, int sort)
|
||||
void ListModel::searchWithTerm(const QString& term, int sort, std::shared_ptr<ModFilterWidget::Filter> filter, bool filterChanged)
|
||||
{
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) {
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort && !filterChanged) {
|
||||
return;
|
||||
}
|
||||
currentSearchTerm = term;
|
||||
currentSort = sort;
|
||||
m_filter = filter;
|
||||
if (hasActiveSearchJob()) {
|
||||
jobPtr->abort();
|
||||
searchState = ResetRequested;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <net/NetJob.h>
|
||||
#include <functional>
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
|
||||
#include <modplatform/flame/FlamePackIndex.h>
|
||||
|
||||
|
@ -38,7 +39,7 @@ class ListModel : public QAbstractListModel {
|
|||
void fetchMore(const QModelIndex& parent) override;
|
||||
|
||||
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
|
||||
void searchWithTerm(const QString& term, int sort);
|
||||
void searchWithTerm(const QString& term, int sort, std::shared_ptr<ModFilterWidget::Filter> filter, bool filterChanged);
|
||||
|
||||
[[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); }
|
||||
[[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; }
|
||||
|
@ -65,6 +66,7 @@ class ListModel : public QAbstractListModel {
|
|||
|
||||
QString currentSearchTerm;
|
||||
int currentSort = 0;
|
||||
std::shared_ptr<ModFilterWidget::Filter> m_filter;
|
||||
int nextSearchOffset = 0;
|
||||
enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
|
||||
Task::Ptr jobPtr;
|
||||
|
|
|
@ -34,10 +34,14 @@
|
|||
*/
|
||||
|
||||
#include "FlamePage.h"
|
||||
#include "Version.h"
|
||||
#include "modplatform/flame/FlamePackIndex.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
#include "ui_FlamePage.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <memory>
|
||||
|
||||
#include "Application.h"
|
||||
#include "FlameModel.h"
|
||||
|
@ -88,6 +92,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent)
|
|||
|
||||
ui->packView->setItemDelegate(new ProjectItemDelegate(this));
|
||||
ui->packDescription->setMetaEntry("FlamePacks");
|
||||
createFilterWidget();
|
||||
}
|
||||
|
||||
FlamePage::~FlamePage()
|
||||
|
@ -131,10 +136,25 @@ void FlamePage::openedImpl()
|
|||
|
||||
void FlamePage::triggerSearch()
|
||||
{
|
||||
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
|
||||
ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
||||
ui->packView->clearSelection();
|
||||
ui->packDescription->clear();
|
||||
ui->versionSelectionBox->clear();
|
||||
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(),
|
||||
m_filterWidget->changed());
|
||||
m_fetch_progress.watch(listModel->activeSearchJob().get());
|
||||
}
|
||||
|
||||
bool checkVersionFilters(const Flame::IndexedVersion& v, std::shared_ptr<ModFilterWidget::Filter> filter)
|
||||
{
|
||||
if (!filter)
|
||||
return true;
|
||||
return ((!filter->loaders || !v.loaders || filter->loaders & v.loaders) && // loaders
|
||||
(filter->releases.empty() || // releases
|
||||
std::find(filter->releases.cbegin(), filter->releases.cend(), v.version_type) != filter->releases.cend()) &&
|
||||
filter->checkMcVersions({ v.mcVersion })); // mcVersions}
|
||||
}
|
||||
|
||||
void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev)
|
||||
{
|
||||
ui->versionSelectionBox->clear();
|
||||
|
@ -148,7 +168,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
|||
|
||||
current = listModel->data(curr, Qt::UserRole).value<Flame::IndexedPack>();
|
||||
|
||||
if (current.versionsLoaded == false) {
|
||||
if (!current.versionsLoaded || m_filterWidget->changed()) {
|
||||
qDebug() << "Loading flame modpack versions";
|
||||
auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
|
@ -176,6 +196,16 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
|||
qWarning() << "Error while reading flame modpack version: " << e.cause();
|
||||
}
|
||||
|
||||
auto pred = [this](const Flame::IndexedVersion& v) { return !checkVersionFilters(v, m_filterWidget->getFilter()); };
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
current.versions.removeIf(pred);
|
||||
#else
|
||||
for (auto it = current.versions.begin(); it != current.versions.end();)
|
||||
if (pred(*it))
|
||||
it = current.versions.erase(it);
|
||||
else
|
||||
++it;
|
||||
#endif
|
||||
for (auto version : current.versions) {
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
auto mcVersion = !version.mcVersion.isEmpty() && !version.version.contains(version.mcVersion)
|
||||
|
@ -243,7 +273,7 @@ void FlamePage::suggestCurrent()
|
|||
void FlamePage::onVersionSelectionChanged(int index)
|
||||
{
|
||||
bool is_blocked = false;
|
||||
ui->versionSelectionBox->currentData().toInt(&is_blocked);
|
||||
ui->versionSelectionBox->itemData(index).toInt(&is_blocked);
|
||||
|
||||
if (index == -1 || is_blocked) {
|
||||
m_selected_version_index = -1;
|
||||
|
@ -299,3 +329,34 @@ void FlamePage::updateUi()
|
|||
ui->packDescription->setHtml(StringUtils::htmlListPatch(text + current.description));
|
||||
ui->packDescription->flush();
|
||||
}
|
||||
QString FlamePage::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
|
||||
void FlamePage::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
void FlamePage::createFilterWidget()
|
||||
{
|
||||
auto widget = ModFilterWidget::create(nullptr, false, this);
|
||||
m_filterWidget.swap(widget);
|
||||
auto old = ui->splitter->replaceWidget(0, m_filterWidget.get());
|
||||
// because we replaced the widget we also need to delete it
|
||||
if (old) {
|
||||
delete old;
|
||||
}
|
||||
|
||||
connect(ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); });
|
||||
|
||||
connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &FlamePage::triggerSearch);
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
m_categoriesTask = FlameAPI::getCategories(response, ModPlatform::ResourceType::MODPACK);
|
||||
QObject::connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() {
|
||||
auto categories = FlameAPI::loadModCategories(response);
|
||||
m_filterWidget->setCategories(categories);
|
||||
});
|
||||
m_categoriesTask->start();
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
#include <Application.h>
|
||||
#include <modplatform/flame/FlamePackIndex.h>
|
||||
#include <QTimer>
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
#include "ui/widgets/ProgressWidget.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -53,7 +54,7 @@ namespace Flame {
|
|||
class ListModel;
|
||||
}
|
||||
|
||||
class FlamePage : public QWidget, public BasePage {
|
||||
class FlamePage : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -72,6 +73,11 @@ class FlamePage : public QWidget, public BasePage {
|
|||
|
||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
|
||||
|
@ -79,6 +85,7 @@ class FlamePage : public QWidget, public BasePage {
|
|||
void triggerSearch();
|
||||
void onSelectionChanged(QModelIndex first, QModelIndex second);
|
||||
void onVersionSelectionChanged(int index);
|
||||
void createFilterWidget();
|
||||
|
||||
private:
|
||||
Ui::FlamePage* ui = nullptr;
|
||||
|
@ -92,4 +99,7 @@ class FlamePage : public QWidget, public BasePage {
|
|||
|
||||
// Used to do instant searching with a delay to cache quick changes
|
||||
QTimer m_search_timer;
|
||||
|
||||
unique_qobject_ptr<ModFilterWidget> m_filterWidget;
|
||||
Task::Ptr m_categoriesTask;
|
||||
};
|
||||
|
|
|
@ -30,42 +30,59 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
<widget class="QPushButton" name="filterButton">
|
||||
<property name="text">
|
||||
<string>Filter options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true"/>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
|
|
|
@ -32,7 +32,7 @@ void FlameModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject&
|
|||
|
||||
void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
|
||||
FlameMod::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
|
||||
|
@ -65,7 +65,7 @@ void FlameResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJso
|
|||
|
||||
void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
|
||||
FlameMod::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
bool FlameResourcePackModel::optedOut(const ModPlatform::IndexedVersion& ver) const
|
||||
|
@ -93,7 +93,7 @@ void FlameTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJson
|
|||
|
||||
void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
|
||||
FlameMod::loadIndexedPackVersions(m, arr);
|
||||
|
||||
QVector<ModPlatform::IndexedVersion> filtered_versions(m.versions.size());
|
||||
|
||||
|
@ -157,7 +157,7 @@ void FlameShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonO
|
|||
|
||||
void FlameShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
|
||||
FlameMod::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
bool FlameShaderPackModel::optedOut(const ModPlatform::IndexedVersion& ver) const
|
||||
|
|
|
@ -209,17 +209,17 @@ auto FlameShaderPackPage::shouldDisplay() const -> bool
|
|||
|
||||
unique_qobject_ptr<ModFilterWidget> FlameModPage::createFilterWidget()
|
||||
{
|
||||
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_base_instance), false, this);
|
||||
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_baseInstance), false, this);
|
||||
}
|
||||
|
||||
void FlameModPage::prepareProviderCategories()
|
||||
{
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
auto task = FlameAPI::getModCategories(response);
|
||||
QObject::connect(task.get(), &Task::succeeded, [this, response]() {
|
||||
m_categoriesTask = FlameAPI::getModCategories(response);
|
||||
QObject::connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() {
|
||||
auto categories = FlameAPI::loadModCategories(response);
|
||||
m_filter_widget->setCategories(categories);
|
||||
});
|
||||
task->start();
|
||||
m_categoriesTask->start();
|
||||
};
|
||||
} // namespace ResourceDownload
|
||||
|
|
|
@ -100,6 +100,9 @@ class FlameModPage : public ModPage {
|
|||
|
||||
protected:
|
||||
virtual void prepareProviderCategories() override;
|
||||
|
||||
private:
|
||||
Task::Ptr m_categoriesTask;
|
||||
};
|
||||
|
||||
class FlameResourcePackPage : public ResourcePackResourcePage {
|
||||
|
|
|
@ -135,4 +135,13 @@ void ImportFTBPage::triggerSearch()
|
|||
currentModel->setSearchTerm(ui->searchEdit->text());
|
||||
}
|
||||
|
||||
void ImportFTBPage::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
QString ImportFTBPage::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
} // namespace FTBImportAPP
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <Application.h>
|
||||
#include "modplatform/import_ftb/PackHelpers.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
#include "ui/pages/modplatform/import_ftb/ListModel.h"
|
||||
|
||||
class NewInstanceDialog;
|
||||
|
@ -35,7 +35,7 @@ namespace Ui {
|
|||
class ImportFTBPage;
|
||||
}
|
||||
|
||||
class ImportFTBPage : public QWidget, public BasePage {
|
||||
class ImportFTBPage : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -49,6 +49,11 @@ class ImportFTBPage : public QWidget, public BasePage {
|
|||
void openedImpl() override;
|
||||
void retranslate() override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
void onPackSelectionChanged(Modpack* pack = nullptr);
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Note: If your FTB instances are not in the default location, select it using the button next to search.</string>
|
||||
</property>
|
||||
|
|
|
@ -369,4 +369,13 @@ void Page::triggerSearch()
|
|||
currentModel->setSearchTerm(ui->searchEdit->text());
|
||||
}
|
||||
|
||||
void Page::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
QString Page::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
} // namespace LegacyFTB
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "QObjectPtr.h"
|
||||
#include "modplatform/legacy_ftb/PackFetchTask.h"
|
||||
#include "modplatform/legacy_ftb/PackHelpers.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
|
||||
class NewInstanceDialog;
|
||||
|
||||
|
@ -57,7 +57,7 @@ class ListModel;
|
|||
class FilterModel;
|
||||
class PrivatePackManager;
|
||||
|
||||
class Page : public QWidget, public BasePage {
|
||||
class Page : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -71,6 +71,11 @@ class Page : public QWidget, public BasePage {
|
|||
void openedImpl() override;
|
||||
void retranslate() override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
void onPackSelectionChanged(Modpack* pack = nullptr);
|
||||
|
|
|
@ -152,33 +152,26 @@ void ModpackListModel::performPaginatedSearch()
|
|||
return;
|
||||
}
|
||||
} // TODO: Move to standalone API
|
||||
auto netJob = makeShared<NetJob>("Modrinth::SearchModpack", APPLICATION->network());
|
||||
auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL +
|
||||
"/search?"
|
||||
"offset=%1&"
|
||||
"limit=%2&"
|
||||
"query=%3&"
|
||||
"index=%4&"
|
||||
"facets=[[\"project_type:modpack\"]]")
|
||||
.arg(nextSearchOffset)
|
||||
.arg(m_modpacks_per_page)
|
||||
.arg(currentSearchTerm)
|
||||
.arg(currentSort);
|
||||
ResourceAPI::SortingMethod sort{};
|
||||
sort.name = currentSort;
|
||||
auto searchUrl = ModrinthAPI().getSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort,
|
||||
m_filter->loaders, m_filter->versions, "", m_filter->categoryIds, m_filter->openSource });
|
||||
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchAllUrl), m_all_response));
|
||||
auto netJob = makeShared<NetJob>("Modrinth::SearchModpack", APPLICATION->network());
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), m_allResponse));
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] {
|
||||
QJsonParseError parse_error_all{};
|
||||
QJsonParseError parseError{};
|
||||
|
||||
QJsonDocument doc_all = QJsonDocument::fromJson(*m_all_response, &parse_error_all);
|
||||
if (parse_error_all.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset
|
||||
<< " reason: " << parse_error_all.errorString();
|
||||
qWarning() << *m_all_response;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(*m_allResponse, &parseError);
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parseError.offset
|
||||
<< " reason: " << parseError.errorString();
|
||||
qWarning() << *m_allResponse;
|
||||
return;
|
||||
}
|
||||
|
||||
searchRequestFinished(doc_all);
|
||||
searchRequestFinished(doc);
|
||||
});
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ModpackListModel::searchRequestFailed);
|
||||
|
||||
|
@ -220,19 +213,23 @@ static auto sortFromIndex(int index) -> QString
|
|||
}
|
||||
}
|
||||
|
||||
void ModpackListModel::searchWithTerm(const QString& term, const int sort)
|
||||
void ModpackListModel::searchWithTerm(const QString& term,
|
||||
const int sort,
|
||||
std::shared_ptr<ModFilterWidget::Filter> filter,
|
||||
bool filterChanged)
|
||||
{
|
||||
if (sort > 5 || sort < 0)
|
||||
return;
|
||||
|
||||
auto sort_str = sortFromIndex(sort);
|
||||
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort_str) {
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort_str && !filterChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSearchTerm = term;
|
||||
currentSort = sort_str;
|
||||
m_filter = filter;
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class ModpackListModel : public QAbstractListModel {
|
|||
/* Ask the API for more information */
|
||||
void fetchMore(const QModelIndex& parent) override;
|
||||
void refresh();
|
||||
void searchWithTerm(const QString& term, int sort);
|
||||
void searchWithTerm(const QString& term, int sort, std::shared_ptr<ModFilterWidget::Filter> filter, bool filterChanged);
|
||||
|
||||
[[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); }
|
||||
[[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; }
|
||||
|
@ -112,12 +112,13 @@ class ModpackListModel : public QAbstractListModel {
|
|||
|
||||
QString currentSearchTerm;
|
||||
QString currentSort;
|
||||
std::shared_ptr<ModFilterWidget::Filter> m_filter;
|
||||
int nextSearchOffset = 0;
|
||||
enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
|
||||
|
||||
Task::Ptr jobPtr;
|
||||
|
||||
std::shared_ptr<QByteArray> m_all_response = std::make_shared<QByteArray>();
|
||||
std::shared_ptr<QByteArray> m_allResponse = std::make_shared<QByteArray>();
|
||||
QByteArray m_specific_response;
|
||||
|
||||
int m_modpacks_per_page = 20;
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
*/
|
||||
|
||||
#include "ModrinthPage.h"
|
||||
#include "Version.h"
|
||||
#include "modplatform/modrinth/ModrinthAPI.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui_ModrinthPage.h"
|
||||
|
||||
|
@ -58,6 +60,7 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent)
|
|||
: QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog), m_fetch_progress(this, false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
createFilterWidget();
|
||||
|
||||
ui->searchEdit->installEventFilter(this);
|
||||
m_model = new Modrinth::ModpackListModel(this);
|
||||
|
@ -126,6 +129,16 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event)
|
|||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
bool checkVersionFilters(const Modrinth::ModpackVersion& v, std::shared_ptr<ModFilterWidget::Filter> filter)
|
||||
{
|
||||
if (!filter)
|
||||
return true;
|
||||
return ((!filter->loaders || !v.loaders || filter->loaders & v.loaders) && // loaders
|
||||
(filter->releases.empty() || // releases
|
||||
std::find(filter->releases.cbegin(), filter->releases.cend(), v.version_type) != filter->releases.cend()) &&
|
||||
filter->checkMcVersions({ v.gameVersion })); // gameVersion}
|
||||
}
|
||||
|
||||
void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev)
|
||||
{
|
||||
ui->versionSelectionBox->clear();
|
||||
|
@ -190,7 +203,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
|||
} else
|
||||
updateUI();
|
||||
|
||||
if (!current.versionsLoaded) {
|
||||
if (!current.versionsLoaded || m_filterWidget->changed()) {
|
||||
qDebug() << "Loading modrinth modpack versions";
|
||||
|
||||
auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(current.name), APPLICATION->network());
|
||||
|
@ -221,6 +234,16 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
|||
qDebug() << *response;
|
||||
qWarning() << "Error while reading modrinth modpack version: " << e.cause();
|
||||
}
|
||||
auto pred = [this](const Modrinth::ModpackVersion& v) { return !checkVersionFilters(v, m_filterWidget->getFilter()); };
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
current.versions.removeIf(pred);
|
||||
#else
|
||||
for (auto it = current.versions.begin(); it != current.versions.end();)
|
||||
if (pred(*it))
|
||||
it = current.versions.erase(it);
|
||||
else
|
||||
++it;
|
||||
#endif
|
||||
for (auto version : current.versions) {
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
auto mcVersion = !version.gameVersion.isEmpty() && !version.name.contains(version.gameVersion)
|
||||
|
@ -338,7 +361,11 @@ void ModrinthPage::suggestCurrent()
|
|||
|
||||
void ModrinthPage::triggerSearch()
|
||||
{
|
||||
m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
|
||||
ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
||||
ui->packView->clearSelection();
|
||||
ui->packDescription->clear();
|
||||
ui->versionSelectionBox->clear();
|
||||
m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(), m_filterWidget->changed());
|
||||
m_fetch_progress.watch(m_model->activeSearchJob().get());
|
||||
}
|
||||
|
||||
|
@ -348,6 +375,38 @@ void ModrinthPage::onVersionSelectionChanged(int index)
|
|||
selectedVersion = "";
|
||||
return;
|
||||
}
|
||||
selectedVersion = ui->versionSelectionBox->currentData().toString();
|
||||
selectedVersion = ui->versionSelectionBox->itemData(index).toString();
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void ModrinthPage::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
QString ModrinthPage::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
|
||||
void ModrinthPage::createFilterWidget()
|
||||
{
|
||||
auto widget = ModFilterWidget::create(nullptr, true, this);
|
||||
m_filterWidget.swap(widget);
|
||||
auto old = ui->splitter->replaceWidget(0, m_filterWidget.get());
|
||||
// because we replaced the widget we also need to delete it
|
||||
if (old) {
|
||||
delete old;
|
||||
}
|
||||
|
||||
connect(ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); });
|
||||
|
||||
connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &ModrinthPage::triggerSearch);
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
m_categoriesTask = ModrinthAPI::getModCategories(response);
|
||||
QObject::connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() {
|
||||
auto categories = ModrinthAPI::loadCategories(response, "modpack");
|
||||
m_filterWidget->setCategories(categories);
|
||||
});
|
||||
m_categoriesTask->start();
|
||||
}
|
|
@ -38,9 +38,10 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "ui/dialogs/NewInstanceDialog.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
|
||||
#include "modplatform/modrinth/ModrinthPackManifest.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
#include "ui/widgets/ProgressWidget.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
@ -54,7 +55,7 @@ namespace Modrinth {
|
|||
class ModpackListModel;
|
||||
}
|
||||
|
||||
class ModrinthPage : public QWidget, public BasePage {
|
||||
class ModrinthPage : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -78,10 +79,16 @@ class ModrinthPage : public QWidget, public BasePage {
|
|||
void openedImpl() override;
|
||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private slots:
|
||||
void onSelectionChanged(QModelIndex first, QModelIndex second);
|
||||
void onVersionSelectionChanged(int index);
|
||||
void triggerSearch();
|
||||
void createFilterWidget();
|
||||
|
||||
private:
|
||||
Ui::ModrinthPage* ui;
|
||||
|
@ -95,4 +102,7 @@ class ModrinthPage : public QWidget, public BasePage {
|
|||
|
||||
// Used to do instant searching with a delay to cache quick changes
|
||||
QTimer m_search_timer;
|
||||
|
||||
unique_qobject_ptr<ModFilterWidget> m_filterWidget;
|
||||
Task::Ptr m_categoriesTask;
|
||||
};
|
||||
|
|
|
@ -12,42 +12,59 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
<widget class="QPushButton" name="filterButton">
|
||||
<property name="text">
|
||||
<string>Filter options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true"/>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
|
|
|
@ -39,7 +39,7 @@ void ModrinthModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObjec
|
|||
|
||||
void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
|
||||
::Modrinth::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
|
||||
|
@ -66,7 +66,7 @@ void ModrinthResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, Q
|
|||
|
||||
void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
|
||||
::Modrinth::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
|
||||
|
@ -88,7 +88,7 @@ void ModrinthTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJ
|
|||
|
||||
void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
|
||||
::Modrinth::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
|
||||
|
@ -110,7 +110,7 @@ void ModrinthShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJs
|
|||
|
||||
void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
|
||||
::Modrinth::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
|
||||
|
@ -132,7 +132,7 @@ void ModrinthDataPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJson
|
|||
|
||||
void ModrinthDataPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
|
||||
{
|
||||
::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
|
||||
::Modrinth::loadIndexedPackVersions(m, arr);
|
||||
}
|
||||
|
||||
auto ModrinthDataPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
|
||||
|
|
|
@ -134,7 +134,8 @@ ModrinthDataPackPage::ModrinthDataPackPage(DataPackDownloadDialog* dialog, BaseI
|
|||
// so it's best not to connect them in the parent's constructor...
|
||||
connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch()));
|
||||
connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthDataPackPage::onSelectionChanged);
|
||||
connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthDataPackPage::onVersionSelectionChanged);
|
||||
connect(m_ui->versionSelectionBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&ModrinthDataPackPage::onVersionSelectionChanged);
|
||||
connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &ModrinthDataPackPage::onResourceSelected);
|
||||
|
||||
m_ui->packDescription->setMetaEntry(metaEntryBase());
|
||||
|
@ -166,7 +167,7 @@ auto ModrinthDataPackPage::shouldDisplay() const -> bool
|
|||
|
||||
unique_qobject_ptr<ModFilterWidget> ModrinthModPage::createFilterWidget()
|
||||
{
|
||||
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_base_instance), true, this);
|
||||
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_baseInstance), true, this);
|
||||
}
|
||||
|
||||
void ModrinthModPage::prepareProviderCategories()
|
||||
|
|
|
@ -154,6 +154,10 @@ void Technic::ListModel::performSearch()
|
|||
QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm);
|
||||
searchMode = List;
|
||||
}
|
||||
auto clientId = APPLICATION->settings()->get("TechnicClientID").toString();
|
||||
if (!clientId.isEmpty()) {
|
||||
searchUrl += "?cid=" + clientId;
|
||||
}
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
|
|
@ -342,3 +342,13 @@ void TechnicPage::onVersionSelectionChanged(QString version)
|
|||
selectedVersion = version;
|
||||
selectVersion();
|
||||
}
|
||||
|
||||
void TechnicPage::setSearchTerm(QString term)
|
||||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
QString TechnicPage::getSerachTerm() const
|
||||
{
|
||||
return ui->searchEdit->text();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <Application.h>
|
||||
#include "TechnicData.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
#include "ui/widgets/ProgressWidget.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -54,7 +54,7 @@ namespace Technic {
|
|||
class ListModel;
|
||||
}
|
||||
|
||||
class TechnicPage : public QWidget, public BasePage {
|
||||
class TechnicPage : public QWidget, public ModpackProviderBasePage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -71,6 +71,11 @@ class TechnicPage : public QWidget, public BasePage {
|
|||
|
||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
|
||||
/** Programatically set the term in the search bar. */
|
||||
virtual void setSearchTerm(QString) override;
|
||||
/** Get the current term in the search bar. */
|
||||
[[nodiscard]] virtual QString getSerachTerm() const override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
void metadataLoaded();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue