diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index f0b2d9799..5d20b7a9b 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -425,6 +425,9 @@ set(FTB_SOURCES modplatform/ftb/FtbPackInstallTask.h modplatform/ftb/FtbPackInstallTask.cpp + modplatform/ftb/FtbPrivatePackManager.h + modplatform/ftb/FtbPrivatePackManager.cpp + modplatform/ftb/PackHelpers.h ) diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp index 67248f2c0..19f6c31a5 100644 --- a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp +++ b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp @@ -1,16 +1,12 @@ #include "FtbPackFetchTask.h" #include - -FtbPackFetchTask::FtbPackFetchTask() -{ -} - -FtbPackFetchTask::~FtbPackFetchTask() -{ -} +#include "FtbPrivatePackManager.h" void FtbPackFetchTask::fetch() { + publicPacks.clear(); + thirdPartyPacks.clear(); + NetJob *netJob = new NetJob("FtbModpackFetch"); QUrl publicPacksUrl = QUrl("https://ftb.cursecdn.com/FTB2/static/modpacks.xml"); @@ -28,23 +24,67 @@ void FtbPackFetchTask::fetch() netJob->start(); } +void FtbPackFetchTask::fetchPrivate(const QStringList & toFetch) +{ + QString privatePackBaseUrl = QString("https://ftb.cursecdn.com/FTB2/static/%1.xml"); + + for (auto &packCode: toFetch) + { + QByteArray *data = new QByteArray(); + NetJob *job = new NetJob("Fetching private pack"); + job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data)); + + QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] + { + FtbModpackList packs; + parseAndAddPacks(*data, FtbPackType::Private, packs); + foreach(FtbModpack currentPack, packs) + { + currentPack.packCode = packCode; + emit privateFileDownloadFinished(currentPack); + } + + job->deleteLater(); + + data->clear(); + delete data; + }); + + QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) + { + emit privateFileDownloadFailed(reason, packCode); + job->deleteLater(); + + data->clear(); + delete data; + }); + + job->start(); + } +} + void FtbPackFetchTask::fileDownloadFinished() { jobPtr.reset(); QStringList failedLists; - if(!parseAndAddPacks(publicModpacksXmlFileData, FtbPackType::Public, publicPacks)) { + if(!parseAndAddPacks(publicModpacksXmlFileData, FtbPackType::Public, publicPacks)) + { failedLists.append(tr("Public Packs")); } - if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, FtbPackType::ThirdParty, thirdPartyPacks)) { + if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, FtbPackType::ThirdParty, thirdPartyPacks)) + { failedLists.append(tr("Third Party Packs")); } - if(failedLists.size() > 0) { - emit failed(QString("Failed to download some pack lists:%1").arg(failedLists.join("\n- "))); - } else { + if(failedLists.size() > 0) + { + emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- "))); + } + else + { emit finished(publicPacks, thirdPartyPacks); } } @@ -57,15 +97,17 @@ bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType, int errorLine = -1; int errorCol = -1; - if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)){ - auto fullErrMsg = QString("Failed to fetch modpack data: %s %d:%d!").arg(errorMsg, errorLine, errorCol); + if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) + { + auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:3d!").arg(errorMsg, errorLine, errorCol); qWarning() << fullErrMsg; data.clear(); return false; } QDomNodeList nodes = doc.elementsByTagName("modpack"); - for(int i = 0; i < nodes.length(); i++) { + for(int i = 0; i < nodes.length(); i++) + { QDomElement element = nodes.at(i).toElement(); FtbModpack modpack; @@ -80,19 +122,25 @@ bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType, modpack.bugged = false; //remove empty if the xml is bugged - for(QString curr : modpack.oldVersions) { - if(curr.isNull() || curr.isEmpty()) { + for(QString curr : modpack.oldVersions) + { + if(curr.isNull() || curr.isEmpty()) + { modpack.oldVersions.removeAll(curr); modpack.bugged = true; qWarning() << "Removed some empty versions from" << modpack.name; } } - if(modpack.oldVersions.size() < 1) { - if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) { + if(modpack.oldVersions.size() < 1) + { + if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) + { modpack.oldVersions.append(modpack.currentVersion); qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")"; - } else { + } + else + { modpack.broken = true; qWarning() << "Broken pack:" << modpack.name << " => No valid version!"; } @@ -111,7 +159,8 @@ bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType, return true; } -void FtbPackFetchTask::fileDownloadFailed(QString reason){ - qWarning() << "Fetching FtbPacks failed: " << reason; +void FtbPackFetchTask::fileDownloadFailed(QString reason) +{ + qWarning() << "Fetching FtbPacks failed:" << reason; emit failed(reason); } diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.h b/api/logic/modplatform/ftb/FtbPackFetchTask.h index c919a6e16..f955fe836 100644 --- a/api/logic/modplatform/ftb/FtbPackFetchTask.h +++ b/api/logic/modplatform/ftb/FtbPackFetchTask.h @@ -11,10 +11,11 @@ class MULTIMC_LOGIC_EXPORT FtbPackFetchTask : public QObject { Q_OBJECT public: - FtbPackFetchTask(); - virtual ~FtbPackFetchTask(); + FtbPackFetchTask() = default; + virtual ~FtbPackFetchTask() = default; void fetch(); + void fetchPrivate(const QStringList &toFetch); private: NetJobPtr jobPtr; @@ -34,4 +35,6 @@ signals: void finished(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks); void failed(QString reason); + void privateFileDownloadFinished(FtbModpack modpack); + void privateFileDownloadFailed(QString reason, QString packCode); }; diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp index 2340666d5..9b7689d93 100644 --- a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp +++ b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp @@ -29,7 +29,15 @@ void FtbPackInstallTask::downloadPack() NetJob *job = new NetJob("Download FTB Pack"); entry->setStale(true); - QString url = QString("http://ftb.cursecdn.com/FTB2/modpacks/%1").arg(packoffset); + QString url; + if(m_pack.type == FtbPackType::Private) + { + url = QString("http://ftb.cursecdn.com/FTB2/privatepacks/%1").arg(packoffset); + } + else + { + url = QString("http://ftb.cursecdn.com/FTB2/modpacks/%1").arg(packoffset); + } job->addNetAction(Net::Download::makeCached(url, entry)); archivePath = entry->getFullPath(); diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.h b/api/logic/modplatform/ftb/FtbPackInstallTask.h index 642626884..3319025e4 100644 --- a/api/logic/modplatform/ftb/FtbPackInstallTask.h +++ b/api/logic/modplatform/ftb/FtbPackInstallTask.h @@ -8,8 +8,8 @@ #include "meta/VersionList.h" #include "modplatform/ftb/PackHelpers.h" -class MULTIMC_LOGIC_EXPORT FtbPackInstallTask : public InstanceTask { - +class MULTIMC_LOGIC_EXPORT FtbPackInstallTask : public InstanceTask +{ Q_OBJECT public: diff --git a/api/logic/modplatform/ftb/FtbPrivatePackManager.cpp b/api/logic/modplatform/ftb/FtbPrivatePackManager.cpp new file mode 100644 index 000000000..15449592f --- /dev/null +++ b/api/logic/modplatform/ftb/FtbPrivatePackManager.cpp @@ -0,0 +1,36 @@ +#include "FtbPrivatePackManager.h" + +#include + +#include "FileSystem.h" + +void FtbPrivatePackManager::load() +{ + try + { + currentPacks = QString::fromUtf8(FS::read(m_filename)).split('\n', QString::SkipEmptyParts).toSet(); + dirty = false; + } + catch(...) + { + currentPacks = {}; + qWarning() << "Failed to read third party FTB pack codes from" << m_filename; + } +} + +void FtbPrivatePackManager::save() const +{ + if(!dirty) + { + return; + } + try + { + FS::write(m_filename, currentPacks.toList().join('\n').toUtf8()); + dirty = false; + } + catch(...) + { + qWarning() << "Failed to write third party FTB pack codes to" << m_filename; + } +} diff --git a/api/logic/modplatform/ftb/FtbPrivatePackManager.h b/api/logic/modplatform/ftb/FtbPrivatePackManager.h new file mode 100644 index 000000000..388224d65 --- /dev/null +++ b/api/logic/modplatform/ftb/FtbPrivatePackManager.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include "multimc_logic_export.h" + +class MULTIMC_LOGIC_EXPORT FtbPrivatePackManager +{ +public: + ~FtbPrivatePackManager() + { + save(); + } + void load(); + void save() const; + bool empty() const + { + return currentPacks.empty(); + } + const QSet &getCurrentPackCodes() const + { + return currentPacks; + } + void add(const QString &code) + { + currentPacks.insert(code); + dirty = true; + } + void remove(const QString &code) + { + currentPacks.remove(code); + dirty = true; + } + +private: + QSet currentPacks; + QString m_filename = "private_packs.txt"; + mutable bool dirty = false; +}; diff --git a/api/logic/modplatform/ftb/PackHelpers.h b/api/logic/modplatform/ftb/PackHelpers.h index 0b36f10b0..4306caee8 100644 --- a/api/logic/modplatform/ftb/PackHelpers.h +++ b/api/logic/modplatform/ftb/PackHelpers.h @@ -6,13 +6,15 @@ #include //Header for structs etc... -enum FtbPackType { +enum class FtbPackType +{ Public, ThirdParty, Private }; -struct FtbModpack { +struct FtbModpack +{ QString name; QString description; QString author; @@ -30,6 +32,7 @@ struct FtbModpack { bool broken = false; FtbPackType type; + QString packCode; }; //We need it for the proxy model diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp index 85704ad6f..bdcd1bce4 100644 --- a/application/dialogs/NewInstanceDialog.cpp +++ b/application/dialogs/NewInstanceDialog.cpp @@ -144,6 +144,12 @@ void NewInstanceDialog::setSuggestedPack(const QString& name, InstanceTask* task creationTask.reset(task); ui->instNameTextBox->setPlaceholderText(name); + if(!task) + { + ui->iconButton->setIcon(MMC->icons()->getIcon("default")); + importIcon = false; + } + auto allowOK = task && !instName().isEmpty(); m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK); } diff --git a/application/pages/modplatform/FTBPage.cpp b/application/pages/modplatform/FTBPage.cpp index 1884bbfbf..dca86efd4 100644 --- a/application/pages/modplatform/FTBPage.cpp +++ b/application/pages/modplatform/FTBPage.cpp @@ -1,20 +1,23 @@ #include "FTBPage.h" #include "ui_FTBPage.h" +#include + #include "MultiMC.h" #include "dialogs/CustomMessageBox.h" #include "dialogs/NewInstanceDialog.h" #include "modplatform/ftb/FtbPackFetchTask.h" #include "modplatform/ftb/FtbPackInstallTask.h" +#include "modplatform/ftb/FtbPrivatePackManager.h" #include "FtbListModel.h" FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent) : QWidget(parent), dialog(dialog), ui(new Ui::FTBPage) { - ftbFetchTask = new FtbPackFetchTask(); + ftbFetchTask.reset(new FtbPackFetchTask()); + ftbPrivatePacks.reset(new FtbPrivatePackManager()); ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); { publicFilterModel = new FtbFilterModel(this); @@ -49,29 +52,47 @@ FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent) thirdPartyFilterModel->setSorting(publicFilterModel->getCurrentSorting()); } - ui->packVersionSelection->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - ui->packVersionSelection->view()->parentWidget()->setMaximumHeight(300); + { + privateFilterModel = new FtbFilterModel(this); + privateListModel = new FtbListModel(this); + privateFilterModel->setSourceModel(privateListModel); + + ui->privatePackList->setModel(privateFilterModel); + ui->privatePackList->setSortingEnabled(true); + ui->privatePackList->header()->hide(); + ui->privatePackList->setIndentation(0); + ui->privatePackList->setIconSize(QSize(42, 42)); + + privateFilterModel->setSorting(publicFilterModel->getCurrentSorting()); + } + + ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &FTBPage::onSortingSelectionChanged); - connect(ui->packVersionSelection, &QComboBox::currentTextChanged, this, &FTBPage::onVersionSelectionItemChanged); + connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FTBPage::onVersionSelectionItemChanged); connect(ui->publicPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onPublicPackSelectionChanged); connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onThirdPartyPackSelectionChanged); + connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onPrivatePackSelectionChanged); - connect(ui->ftbTabWidget, &QTabWidget::currentChanged, this, &FTBPage::onTabChanged); + connect(ui->addPackBtn, &QPushButton::pressed, this, &FTBPage::onAddPackClicked); + connect(ui->removePackBtn, &QPushButton::pressed, this, &FTBPage::onRemovePackClicked); - ui->modpackInfo->setOpenExternalLinks(true); + connect(ui->tabWidget, &QTabWidget::currentChanged, this, &FTBPage::onTabChanged); + + // ui->modpackInfo->setOpenExternalLinks(true); ui->publicPackList->selectionModel()->reset(); ui->thirdPartyPackList->selectionModel()->reset(); + ui->privatePackList->selectionModel()->reset(); + + onTabChanged(ui->tabWidget->currentIndex()); } FTBPage::~FTBPage() { delete ui; - if(ftbFetchTask) { - ftbFetchTask->deleteLater(); - } } bool FTBPage::shouldDisplay() const @@ -83,9 +104,15 @@ void FTBPage::openedImpl() { if(!initialized) { - connect(ftbFetchTask, &FtbPackFetchTask::finished, this, &FTBPage::ftbPackDataDownloadSuccessfully); - connect(ftbFetchTask, &FtbPackFetchTask::failed, this, &FTBPage::ftbPackDataDownloadFailed); + connect(ftbFetchTask.get(), &FtbPackFetchTask::finished, this, &FTBPage::ftbPackDataDownloadSuccessfully); + connect(ftbFetchTask.get(), &FtbPackFetchTask::failed, this, &FTBPage::ftbPackDataDownloadFailed); + + connect(ftbFetchTask.get(), &FtbPackFetchTask::privateFileDownloadFinished, this, &FTBPage::ftbPrivatePackDataDownloadSuccessfully); + connect(ftbFetchTask.get(), &FtbPackFetchTask::privateFileDownloadFailed, this, &FTBPage::ftbPrivatePackDataDownloadFailed); + ftbFetchTask->fetch(); + ftbPrivatePacks->load(); + ftbFetchTask->fetchPrivate(ftbPrivatePacks->getCurrentPackCodes().toList()); initialized = true; } suggestCurrent(); @@ -98,13 +125,37 @@ void FTBPage::suggestCurrent() if(!selected.broken) { dialog->setSuggestedPack(selected.name, new FtbPackInstallTask(selected, selectedVersion)); - if(selected.type == FtbPackType::Public) { - publicListModel->getLogo(selected.logo, [this](QString logo){ - dialog->setSuggestedIconFromFile(logo, "ftb_" + selected.name); + QString editedLogoName; + if(selected.logo.toLower().startsWith("ftb")) + { + editedLogoName = selected.logo; + } + else + { + editedLogoName = "ftb_" + selected.logo; + } + + editedLogoName = editedLogoName.left(editedLogoName.lastIndexOf(".png")); + + if(selected.type == FtbPackType::Public) + { + publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo, editedLogoName); }); - } else if (selected.type == FtbPackType::ThirdParty) { - thirdPartyModel->getLogo(selected.logo, [this](QString logo){ - dialog->setSuggestedIconFromFile(logo, "ftb_" + selected.name); + } + else if (selected.type == FtbPackType::ThirdParty) + { + thirdPartyModel->getLogo(selected.logo, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo, editedLogoName); + }); + } + else if (selected.type == FtbPackType::Private) + { + privateListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } } @@ -126,6 +177,24 @@ void FTBPage::ftbPackDataDownloadFailed(QString reason) //TODO: Display the error } +void FTBPage::ftbPrivatePackDataDownloadSuccessfully(FtbModpack pack) +{ + privateListModel->addPack(pack); +} + +void FTBPage::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode) +{ + auto reply = QMessageBox::question( + this, + tr("FTB private packs"), + tr("Failed to download pack information for code %1.\nShould it be removed now?").arg(packCode) + ); + if(reply == QMessageBox::Yes) + { + ftbPrivatePacks->remove(packCode); + } +} + void FTBPage::onPublicPackSelectionChanged(QModelIndex now, QModelIndex prev) { if(!now.isValid()) @@ -148,13 +217,25 @@ void FTBPage::onThirdPartyPackSelectionChanged(QModelIndex now, QModelIndex prev onPackSelectionChanged(&selectedPack); } +void FTBPage::onPrivatePackSelectionChanged(QModelIndex now, QModelIndex prev) +{ + if(!now.isValid()) + { + onPackSelectionChanged(); + return; + } + FtbModpack selectedPack = privateFilterModel->data(now, Qt::UserRole).value(); + onPackSelectionChanged(&selectedPack); +} + void FTBPage::onPackSelectionChanged(FtbModpack* pack) { - ui->packVersionSelection->clear(); + ui->versionSelectionBox->clear(); if(pack) { - ui->modpackInfo->setHtml("Pack by " + pack->author + "" + "
Minecraft " + pack->mcVersion + "
" - "
" + pack->description + "
  • " + pack->mods.replace(";", "
  • ") + "
"); + currentModpackInfo->setHtml("Pack by " + pack->author + "" + + "
Minecraft " + pack->mcVersion + "
" + "
" + pack->description + "
  • " + pack->mods.replace(";", "
  • ") + + "
"); bool currentAdded = false; for(int i = 0; i < pack->oldVersions.size(); i++) @@ -163,15 +244,25 @@ void FTBPage::onPackSelectionChanged(FtbModpack* pack) { currentAdded = true; } - ui->packVersionSelection->addItem(pack->oldVersions.at(i)); + ui->versionSelectionBox->addItem(pack->oldVersions.at(i)); } if(!currentAdded) { - ui->packVersionSelection->addItem(pack->currentVersion); + ui->versionSelectionBox->addItem(pack->currentVersion); } selected = *pack; } + else + { + currentModpackInfo->setHtml(""); + ui->versionSelectionBox->clear(); + if(isOpened) + { + dialog->setSuggestedPack(); + } + return; + } suggestCurrent(); } @@ -192,22 +283,31 @@ void FTBPage::onSortingSelectionChanged(QString data) FtbFilterModel::Sorting toSet = publicFilterModel->getAvailableSortings().value(data); publicFilterModel->setSorting(toSet); thirdPartyFilterModel->setSorting(toSet); + privateFilterModel->setSorting(toSet); } void FTBPage::onTabChanged(int tab) { - FtbFilterModel* currentModel = nullptr; - QTreeView* currentList = nullptr; - if (tab == 0) - { - currentModel = publicFilterModel; - currentList = ui->publicPackList; - } - else + if(tab == 1) { currentModel = thirdPartyFilterModel; currentList = ui->thirdPartyPackList; + currentModpackInfo = ui->thirdPartyPackDescription; } + else if(tab == 2) + { + currentModel = privateFilterModel; + currentList = ui->privatePackList; + currentModpackInfo = ui->privatePackDescription; + } + else + { + currentModel = publicFilterModel; + currentList = ui->publicPackList; + currentModpackInfo = ui->publicPackDescription; + } + + currentList->selectionModel()->reset(); QModelIndex idx = currentList->currentIndex(); if(idx.isValid()) { @@ -219,3 +319,46 @@ void FTBPage::onTabChanged(int tab) onPackSelectionChanged(); } } + +void FTBPage::onAddPackClicked() +{ + bool ok; + QString text = QInputDialog::getText( + this, + tr("Add FTB pack"), + tr("Enter pack code:"), + QLineEdit::Normal, + QString(), + &ok + ); + if(ok && !text.isEmpty()) + { + ftbPrivatePacks->add(text); + ftbFetchTask->fetchPrivate({text}); + } +} + +void FTBPage::onRemovePackClicked() +{ + auto index = ui->privatePackList->currentIndex(); + if(!index.isValid()) + { + return; + } + auto row = index.row(); + FtbModpack pack = privateListModel->at(row); + auto answer = QMessageBox::question( + this, + tr("Remove pack"), + tr("Are you sure you want to remove pack %1?").arg(pack.name), + QMessageBox::Yes | QMessageBox::No + ); + if(answer != QMessageBox::Yes) + { + return; + } + + ftbPrivatePacks->remove(pack.packCode); + privateListModel->remove(row); + onPackSelectionChanged(); +} diff --git a/application/pages/modplatform/FTBPage.h b/application/pages/modplatform/FTBPage.h index 46c14c302..6467deccf 100644 --- a/application/pages/modplatform/FTBPage.h +++ b/application/pages/modplatform/FTBPage.h @@ -16,12 +16,15 @@ #pragma once #include +#include +#include #include "pages/BasePage.h" #include #include "tasks/Task.h" #include "modplatform/ftb/PackHelpers.h" #include "modplatform/ftb/FtbPackFetchTask.h" +#include "QObjectPtr.h" namespace Ui { @@ -31,6 +34,9 @@ class FTBPage; class FtbListModel; class FtbFilterModel; class NewInstanceDialog; +class FtbPrivatePackListModel; +class FtbPrivatePackFilterModel; +class FtbPrivatePackManager; class FTBPage : public QWidget, public BasePage { @@ -66,15 +72,26 @@ private slots: void ftbPackDataDownloadSuccessfully(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks); void ftbPackDataDownloadFailed(QString reason); + void ftbPrivatePackDataDownloadSuccessfully(FtbModpack pack); + void ftbPrivatePackDataDownloadFailed(QString reason, QString packCode); + void onSortingSelectionChanged(QString data); void onVersionSelectionItemChanged(QString data); void onPublicPackSelectionChanged(QModelIndex first, QModelIndex second); void onThirdPartyPackSelectionChanged(QModelIndex first, QModelIndex second); + void onPrivatePackSelectionChanged(QModelIndex first, QModelIndex second); void onTabChanged(int tab); + void onAddPackClicked(); + void onRemovePackClicked(); + private: + FtbFilterModel* currentModel = nullptr; + QTreeView* currentList = nullptr; + QTextBrowser* currentModpackInfo = nullptr; + bool initialized = false; FtbModpack selected; QString selectedVersion; @@ -85,7 +102,12 @@ private: FtbListModel *thirdPartyModel = nullptr; FtbFilterModel *thirdPartyFilterModel = nullptr; - FtbPackFetchTask *ftbFetchTask = nullptr; + FtbListModel *privateListModel = nullptr; + FtbFilterModel *privateFilterModel = nullptr; + + unique_qobject_ptr ftbFetchTask; + std::unique_ptr ftbPrivatePacks; + NewInstanceDialog* dialog = nullptr; Ui::FTBPage *ui = nullptr; diff --git a/application/pages/modplatform/FTBPage.ui b/application/pages/modplatform/FTBPage.ui index cb085af2c..e5ed78cbb 100644 --- a/application/pages/modplatform/FTBPage.ui +++ b/application/pages/modplatform/FTBPage.ui @@ -11,18 +11,6 @@ - - 0 - - - 0 - - - 0 - - - 0 - @@ -30,86 +18,107 @@ - + Public - - - - - Qt::ScrollBarAsNeeded + + + + + + 250 + 16777215 + - - - - Version selected: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - - + + + + + 3rd Party + + + + - - - - - - - - 0 - 0 - + + + + + 250 + 16777215 + - - QTabWidget::Rounded - - - 0 - - - - Public Packs - - - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAlwaysOff - - - - - - - - 3rd Party Packs - - - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAlwaysOff - - - - - + + + Private + + + + + + + 250 + 16777215 + + + + + + + + Add pack + + + + + + + Remove selected pack + + + + + + + + + + + + + + Version selected: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 265 + 0 + + + + + + diff --git a/application/pages/modplatform/FtbListModel.cpp b/application/pages/modplatform/FtbListModel.cpp index 0d0d4d5ef..f4311afb6 100644 --- a/application/pages/modplatform/FtbListModel.cpp +++ b/application/pages/modplatform/FtbListModel.cpp @@ -72,15 +72,17 @@ FtbListModel::~FtbListModel() QString FtbListModel::translatePackType(FtbPackType type) const { - if(type == FtbPackType::Public) { - return tr("Public Modpack"); - } else if(type == FtbPackType::ThirdParty) { - return tr("Third Party Modpack"); - } else if(type == FtbPackType::Private) { - return tr("Private Modpack"); - } else { - return tr("Unknown Type"); + switch(type) + { + case FtbPackType::Public: + return tr("Public Modpack"); + case FtbPackType::ThirdParty: + return tr("Third Party Modpack"); + case FtbPackType::Private: + return tr("Private Modpack"); } + qWarning() << "Unknown FTB modpack type:" << int(type); + return QString(); } int FtbListModel::rowCount(const QModelIndex &parent) const @@ -96,15 +98,20 @@ int FtbListModel::columnCount(const QModelIndex &parent) const QVariant FtbListModel::data(const QModelIndex &index, int role) const { int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) { + if(pos >= modpacks.size() || pos < 0 || !index.isValid()) + { return QString("INVALID INDEX %1").arg(pos); } FtbModpack pack = modpacks.at(pos); - if(role == Qt::DisplayRole) { + if(role == Qt::DisplayRole) + { return pack.name + "\n" + translatePackType(pack.type); - } else if (role == Qt::ToolTipRole) { - if(pack.description.length() > 100) { + } + else if (role == Qt::ToolTipRole) + { + if(pack.description.length() > 100) + { //some magic to prevent to long tooltips and replace html linebreaks QString edit = pack.description.left(97); edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); @@ -112,23 +119,33 @@ QVariant FtbListModel::data(const QModelIndex &index, int role) const } return pack.description; - } else if(role == Qt::DecorationRole) { - if(m_logoMap.contains(pack.logo)) { + } + else if(role == Qt::DecorationRole) + { + if(m_logoMap.contains(pack.logo)) + { return (m_logoMap.value(pack.logo)); } QIcon icon = MMC->getThemedIcon("screenshot-placeholder"); ((FtbListModel *)this)->requestLogo(pack.logo); return icon; - } else if(role == Qt::TextColorRole) { - if(pack.broken) { + } + else if(role == Qt::TextColorRole) + { + if(pack.broken) + { //FIXME: Hardcoded color return QColor(255, 0, 50); - } else if(pack.bugged) { + } + else if(pack.bugged) + { //FIXME: Hardcoded color //bugged pack, currently only indicates bugged xml return QColor(244, 229, 66); } - } else if(role == Qt::UserRole) { + } + else if(role == Qt::UserRole) + { QVariant v; v.setValue(pack); return v; @@ -144,11 +161,37 @@ void FtbListModel::fill(FtbModpackList modpacks) endResetModel(); } +void FtbListModel::addPack(FtbModpack modpack) +{ + beginResetModel(); + this->modpacks.append(modpack); + endResetModel(); +} + +void FtbListModel::clear() +{ + beginResetModel(); + modpacks.clear(); + endResetModel(); +} + FtbModpack FtbListModel::at(int row) { return modpacks.at(row); } +void FtbListModel::remove(int row) +{ + if(row < 0 || row >= modpacks.size()) + { + qWarning() << "Attempt to remove FTB modpacks with invalid row" << row; + return; + } + beginRemoveRows(QModelIndex(), row, row); + modpacks.removeAt(row); + endRemoveRows(); +} + void FtbListModel::logoLoaded(QString logo, QIcon out) { m_loadingLogos.removeAll(logo); @@ -164,7 +207,8 @@ void FtbListModel::logoFailed(QString logo) void FtbListModel::requestLogo(QString file) { - if(m_loadingLogos.contains(file) || m_failedLogos.contains(file)) { + if(m_loadingLogos.contains(file) || m_failedLogos.contains(file)) + { return; } @@ -173,14 +217,17 @@ void FtbListModel::requestLogo(QString file) job->addNetAction(Net::Download::makeCached(QUrl(QString("https://ftb.cursecdn.com/FTB2/static/%1").arg(file)), entry)); auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::finished, this, [this, file, fullPath]{ + QObject::connect(job, &NetJob::finished, this, [this, file, fullPath] + { emit logoLoaded(file, QIcon(fullPath)); - if(waitingCallbacks.contains(file)) { + if(waitingCallbacks.contains(file)) + { waitingCallbacks.value(file)(fullPath); } }); - QObject::connect(job, &NetJob::failed, this, [this, file]{ + QObject::connect(job, &NetJob::failed, this, [this, file] + { emit logoFailed(file); }); @@ -191,9 +238,17 @@ void FtbListModel::requestLogo(QString file) void FtbListModel::getLogo(const QString &logo, LogoCallback callback) { - if(m_logoMap.contains(logo)) { + if(m_logoMap.contains(logo)) + { callback(ENV.metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); - } else { + } + else + { requestLogo(logo); } } + +Qt::ItemFlags FtbListModel::flags(const QModelIndex &index) const +{ + return QAbstractListModel::flags(index); +} diff --git a/application/pages/modplatform/FtbListModel.h b/application/pages/modplatform/FtbListModel.h index c85c04fa6..98301fd7b 100644 --- a/application/pages/modplatform/FtbListModel.h +++ b/application/pages/modplatform/FtbListModel.h @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -60,8 +61,12 @@ public: int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; void fill(FtbModpackList modpacks); + void addPack(FtbModpack modpack); + void clear(); + void remove(int row); FtbModpack at(int row); void getLogo(const QString &logo, LogoCallback callback);