diff options
Diffstat (limited to 'application')
42 files changed, 717 insertions, 165 deletions
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index c5be22d0..ab2b9960 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -129,6 +129,8 @@ SET(MULTIMC_SOURCES pages/modplatform/atlauncher/AtlFilterModel.h pages/modplatform/atlauncher/AtlListModel.cpp pages/modplatform/atlauncher/AtlListModel.h + pages/modplatform/atlauncher/AtlOptionalModDialog.cpp + pages/modplatform/atlauncher/AtlOptionalModDialog.h pages/modplatform/atlauncher/AtlPage.cpp pages/modplatform/atlauncher/AtlPage.h @@ -278,6 +280,9 @@ SET(MULTIMC_UIS pages/modplatform/technic/TechnicPage.ui pages/modplatform/ImportPage.ui + # Platform Dialogs + pages/modplatform/atlauncher/AtlOptionalModDialog.ui + # Dialogs dialogs/CopyInstanceDialog.ui dialogs/NewComponentDialog.ui diff --git a/application/LaunchController.cpp b/application/LaunchController.cpp index 3c4491a3..ee764082 100644 --- a/application/LaunchController.cpp +++ b/application/LaunchController.cpp @@ -15,6 +15,9 @@ #include <minecraft/auth/YggdrasilTask.h> #include <launch/steps/TextPrint.h> #include <QStringList> +#include <QHostInfo> +#include <QList> +#include <QHostAddress> LaunchController::LaunchController(QObject *parent) : Task(parent) { @@ -215,7 +218,46 @@ void LaunchController::launchInstance() connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed); connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested); + // Prepend Online and Auth Status + QString online_mode; + if(m_session->wants_online) { + online_mode = "online"; + // Prepend Server Status + QStringList servers = {"authserver.mojang.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com"}; + QString resolved_servers = ""; + QHostInfo host_info; + + for(QString server : servers) { + host_info = QHostInfo::fromName(server); + resolved_servers = resolved_servers + server + " resolves to:\n ["; + if(!host_info.addresses().isEmpty()) { + for(QHostAddress address : host_info.addresses()) { + resolved_servers = resolved_servers + address.toString(); + if(!host_info.addresses().endsWith(address)) { + resolved_servers = resolved_servers + ", "; + } + } + } else { + resolved_servers = resolved_servers + "N/A"; + } + resolved_servers = resolved_servers + "]\n\n"; + } + m_launcher->prependStep(new TextPrint(m_launcher.get(), resolved_servers, MessageLevel::MultiMC)); + } else { + online_mode = "offline"; + } + + QString auth_server_status; + if(m_session->auth_server_online) { + auth_server_status = "online"; + } else { + auth_server_status = "offline"; + } + + m_launcher->prependStep(new TextPrint(m_launcher.get(), "Launched instance in " + online_mode + " mode\nAuthentication server is " + auth_server_status + "\n", MessageLevel::MultiMC)); + + // Prepend Version m_launcher->prependStep(new TextPrint(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC)); m_launcher->start(); } diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp index 1286007d..13a7c7ae 100644 --- a/application/MainWindow.cpp +++ b/application/MainWindow.cpp @@ -306,29 +306,35 @@ public: helpMenu = new QMenu(MainWindow); helpMenu->setToolTipsVisible(true); - actionReportBug = TranslatedAction(MainWindow); - actionReportBug->setObjectName(QStringLiteral("actionReportBug")); - actionReportBug->setIcon(MMC->getThemedIcon("bug")); - actionReportBug.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Report a Bug")); - actionReportBug.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the bug tracker to report a bug with MultiMC.")); - all_actions.append(&actionReportBug); - helpMenu->addAction(actionReportBug); - - actionDISCORD = TranslatedAction(MainWindow); - actionDISCORD->setObjectName(QStringLiteral("actionDISCORD")); - actionDISCORD->setIcon(MMC->getThemedIcon("discord")); - actionDISCORD.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Discord")); - actionDISCORD.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC discord voice chat.")); - all_actions.append(&actionDISCORD); - helpMenu->addAction(actionDISCORD); - - actionREDDIT = TranslatedAction(MainWindow); - actionREDDIT->setObjectName(QStringLiteral("actionREDDIT")); - actionREDDIT->setIcon(MMC->getThemedIcon("reddit-alien")); - actionREDDIT.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Reddit")); - actionREDDIT.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC subreddit.")); - all_actions.append(&actionREDDIT); - helpMenu->addAction(actionREDDIT); + if (!BuildConfig.BUG_TRACKER_URL.isEmpty()) { + actionReportBug = TranslatedAction(MainWindow); + actionReportBug->setObjectName(QStringLiteral("actionReportBug")); + actionReportBug->setIcon(MMC->getThemedIcon("bug")); + actionReportBug.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Report a Bug")); + actionReportBug.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the bug tracker to report a bug with MultiMC.")); + all_actions.append(&actionReportBug); + helpMenu->addAction(actionReportBug); + } + + if (!BuildConfig.DISCORD_URL.isEmpty()) { + actionDISCORD = TranslatedAction(MainWindow); + actionDISCORD->setObjectName(QStringLiteral("actionDISCORD")); + actionDISCORD->setIcon(MMC->getThemedIcon("discord")); + actionDISCORD.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Discord")); + actionDISCORD.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC discord voice chat.")); + all_actions.append(&actionDISCORD); + helpMenu->addAction(actionDISCORD); + } + + if (!BuildConfig.SUBREDDIT_URL.isEmpty()) { + actionREDDIT = TranslatedAction(MainWindow); + actionREDDIT->setObjectName(QStringLiteral("actionREDDIT")); + actionREDDIT->setIcon(MMC->getThemedIcon("reddit-alien")); + actionREDDIT.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Reddit")); + actionREDDIT.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open MultiMC subreddit.")); + all_actions.append(&actionREDDIT); + helpMenu->addAction(actionREDDIT); + } actionAbout = TranslatedAction(MainWindow); actionAbout->setObjectName(QStringLiteral("actionAbout")); @@ -732,7 +738,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow repopulateAccountsMenu(); accountMenuButton = new QToolButton(this); - accountMenuButton->setText(tr("Profiles")); accountMenuButton->setMenu(accountMenu); accountMenuButton->setPopupMode(QToolButton::InstantPopup); accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -831,6 +836,21 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow // removing this looks stupid view->setFocus(); + + retranslateUi(); +} + +void MainWindow::retranslateUi() +{ + accountMenuButton->setText(tr("Profiles")); + + if (m_selectedInstance) { + m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); + } else { + m_statusLeft->setText(tr("No instance selected")); + } + + ui->retranslateUi(this); } MainWindow::~MainWindow() @@ -1455,12 +1475,12 @@ void MainWindow::droppedURLs(QList<QUrl> urls) void MainWindow::on_actionREDDIT_triggered() { - DesktopServices::openUrl(QUrl("https://www.reddit.com/r/MultiMC/")); + DesktopServices::openUrl(QUrl(BuildConfig.SUBREDDIT_URL)); } void MainWindow::on_actionDISCORD_triggered() { - DesktopServices::openUrl(QUrl("https://discord.gg/multimc")); + DesktopServices::openUrl(QUrl(BuildConfig.DISCORD_URL)); } void MainWindow::on_actionChangeInstIcon_triggered() @@ -1638,7 +1658,7 @@ void MainWindow::on_actionManageAccounts_triggered() void MainWindow::on_actionReportBug_triggered() { - DesktopServices::openUrl(QUrl("https://github.com/MultiMC/MultiMC5/issues")); + DesktopServices::openUrl(QUrl(BuildConfig.BUG_TRACKER_URL)); } void MainWindow::on_actionPatreon_triggered() @@ -1745,7 +1765,7 @@ void MainWindow::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { - ui->retranslateUi(this); + retranslateUi(); } QMainWindow::changeEvent(event); } diff --git a/application/MainWindow.h b/application/MainWindow.h index 3d4114de..08c6b969 100644 --- a/application/MainWindow.h +++ b/application/MainWindow.h @@ -187,6 +187,8 @@ private slots: void globalSettingsClosed(); private: + void retranslateUi(); + void addInstance(QString url = QString()); void activateInstance(InstancePtr instance); void setCatBackground(bool enabled); diff --git a/application/dialogs/LoginDialog.ui b/application/dialogs/LoginDialog.ui index d92fbae3..dbdb3b93 100644 --- a/application/dialogs/LoginDialog.ui +++ b/application/dialogs/LoginDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> - <height>162</height> + <width>421</width> + <height>238</height> </rect> </property> <property name="sizePolicy"> @@ -21,6 +21,16 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> + <widget class="QLabel" name="microsoftAccountsNoticeLabel"> + <property name="text"> + <string>NOTICE: MultiMC does not currently support Microsoft accounts. This means that accounts created from December 2020 onwards cannot be used.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> <widget class="QLabel" name="label"> <property name="text"> <string notr="true">Message label placeholder.</string> diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp index 112e46ff..86963149 100644 --- a/application/dialogs/NewInstanceDialog.cpp +++ b/application/dialogs/NewInstanceDialog.cpp @@ -173,6 +173,14 @@ void NewInstanceDialog::setSuggestedIconFromFile(const QString &path, const QStr ui->iconButton->setIcon(QIcon(path)); } +void NewInstanceDialog::setSuggestedIcon(const QString &key) +{ + auto icon = MMC->icons()->getIcon(key); + importIcon = false; + + ui->iconButton->setIcon(icon); +} + InstanceTask * NewInstanceDialog::extractTask() { InstanceTask * extracted = creationTask.get(); diff --git a/application/dialogs/NewInstanceDialog.h b/application/dialogs/NewInstanceDialog.h index f8d96dbf..53abf8cf 100644 --- a/application/dialogs/NewInstanceDialog.h +++ b/application/dialogs/NewInstanceDialog.h @@ -43,6 +43,7 @@ public: void setSuggestedPack(const QString & name = QString(), InstanceTask * task = nullptr); void setSuggestedIconFromFile(const QString &path, const QString &name); + void setSuggestedIcon(const QString &key); InstanceTask * extractTask(); diff --git a/application/pages/global/JavaPage.cpp b/application/pages/global/JavaPage.cpp index 95271c91..cde0e035 100644 --- a/application/pages/global/JavaPage.cpp +++ b/application/pages/global/JavaPage.cpp @@ -37,8 +37,8 @@ JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) ui->setupUi(this); ui->tabWidget->tabBar()->hide(); - auto sysMB = Sys::getSystemRam() / Sys::megabyte; - ui->maxMemSpinBox->setMaximum(sysMB); + auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; + ui->maxMemSpinBox->setMaximum(sysMiB); loadSettings(); } diff --git a/application/pages/global/JavaPage.ui b/application/pages/global/JavaPage.ui index 201b310c..b67e9994 100644 --- a/application/pages/global/JavaPage.ui +++ b/application/pages/global/JavaPage.ui @@ -51,7 +51,7 @@ <string>The maximum amount of memory Minecraft is allowed to use.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>128</number> @@ -87,7 +87,7 @@ <string>The amount of memory Minecraft is started with.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>128</number> @@ -116,7 +116,7 @@ <string>The amount of memory available to store loaded Java classes.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>64</number> diff --git a/application/pages/instance/InstanceSettingsPage.cpp b/application/pages/instance/InstanceSettingsPage.cpp index 00fc19af..7bd424c0 100644 --- a/application/pages/instance/InstanceSettingsPage.cpp +++ b/application/pages/instance/InstanceSettingsPage.cpp @@ -19,7 +19,7 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) { m_settings = inst->settings(); ui->setupUi(this); - auto sysMB = Sys::getSystemRam() / Sys::megabyte; + auto sysMB = Sys::getSystemRam() / Sys::mebibyte; ui->maxMemSpinBox->setMaximum(sysMB); connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(MMC, &MultiMC::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); diff --git a/application/pages/instance/InstanceSettingsPage.ui b/application/pages/instance/InstanceSettingsPage.ui index 29024b65..e569ce56 100644 --- a/application/pages/instance/InstanceSettingsPage.ui +++ b/application/pages/instance/InstanceSettingsPage.ui @@ -116,7 +116,7 @@ <string>The maximum amount of memory Minecraft is allowed to use.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>128</number> @@ -138,7 +138,7 @@ <string>The amount of memory Minecraft is started with.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>128</number> @@ -160,7 +160,7 @@ <string>The amount of memory available to store loaded Java classes.</string> </property> <property name="suffix"> - <string notr="true"> MB</string> + <string notr="true"> MiB</string> </property> <property name="minimum"> <number>64</number> diff --git a/application/pages/instance/LogPage.cpp b/application/pages/instance/LogPage.cpp index 94ada424..3d2085c6 100644 --- a/application/pages/instance/LogPage.cpp +++ b/application/pages/instance/LogPage.cpp @@ -236,15 +236,15 @@ void LogPage::on_btnPaste_clicked() return; //FIXME: turn this into a proper task and move the upload logic out of GuiUtil! - m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); + m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this); if(!url.isEmpty()) { - m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log uploaded to: %1").arg(url)); + m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log uploaded to: %1").arg(url)); } else { - m_model->append(MessageLevel::Error, tr("MultiMC: Log upload failed!")); + m_model->append(MessageLevel::Error, "MultiMC: Log upload failed!"); } } diff --git a/application/pages/instance/ModFolderPage.cpp b/application/pages/instance/ModFolderPage.cpp index c3d6483a..98f20e77 100644 --- a/application/pages/instance/ModFolderPage.cpp +++ b/application/pages/instance/ModFolderPage.cpp @@ -163,7 +163,7 @@ ModFolderPage::ModFolderPage( auto smodel = ui->modTreeView->selectionModel(); connect(smodel, &QItemSelectionModel::currentChanged, this, &ModFolderPage::modCurrent); - connect(ui->filterEdit, &QLineEdit::textChanged, this, &ModFolderPage::on_filterTextChanged ); + connect(ui->filterEdit, &QLineEdit::textChanged, this, &ModFolderPage::on_filterTextChanged); connect(m_inst, &BaseInstance::runningStatusChanged, this, &ModFolderPage::on_RunningState_changed); } diff --git a/application/pages/instance/ResourcePackPage.h b/application/pages/instance/ResourcePackPage.h index e11c78a3..1486bf52 100644 --- a/application/pages/instance/ResourcePackPage.h +++ b/application/pages/instance/ResourcePackPage.h @@ -1,4 +1,5 @@ #pragma once + #include "ModFolderPage.h" #include "ui_ModFolderPage.h" @@ -12,8 +13,8 @@ public: { ui->actionView_configs->setVisible(false); } - virtual ~ResourcePackPage() {} + virtual bool shouldDisplay() const override { return !m_inst->traits().contains("no-texturepacks") && diff --git a/application/pages/instance/TexturePackPage.h b/application/pages/instance/TexturePackPage.h index a792ba07..3f04997d 100644 --- a/application/pages/instance/TexturePackPage.h +++ b/application/pages/instance/TexturePackPage.h @@ -1,4 +1,5 @@ #pragma once + #include "ModFolderPage.h" #include "ui_ModFolderPage.h" @@ -13,6 +14,7 @@ public: ui->actionView_configs->setVisible(false); } virtual ~TexturePackPage() {} + virtual bool shouldDisplay() const override { return m_inst->traits().contains("texturepacks"); diff --git a/application/pages/instance/VersionPage.cpp b/application/pages/instance/VersionPage.cpp index 7f7ba860..eff12c9c 100644 --- a/application/pages/instance/VersionPage.cpp +++ b/application/pages/instance/VersionPage.cpp @@ -120,7 +120,15 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) auto proxy = new IconProxy(ui->packageView); proxy->setSourceModel(m_profile.get()); - ui->packageView->setModel(proxy); + + m_filterModel = new QSortFilterProxyModel(); + m_filterModel->setDynamicSortFilter(true); + m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); + m_filterModel->setSourceModel(proxy); + m_filterModel->setFilterKeyColumn(-1); + + ui->packageView->setModel(m_filterModel); ui->packageView->installEventFilter(this); ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection); ui->packageView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -134,7 +142,8 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) updateVersionControls(); preselect(0); connect(m_inst, &BaseInstance::runningStatusChanged, this, &VersionPage::updateRunningStatus); - connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::ShowContextMenu); + connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::showContextMenu); + connect(ui->filterEdit, &QLineEdit::textChanged, this, &VersionPage::onFilterTextChanged); } VersionPage::~VersionPage() @@ -142,7 +151,7 @@ VersionPage::~VersionPage() delete ui; } -void VersionPage::ShowContextMenu(const QPoint& pos) +void VersionPage::showContextMenu(const QPoint& pos) { auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); menu->exec(ui->packageView->mapToGlobal(pos)); @@ -620,5 +629,10 @@ void VersionPage::on_actionRevert_triggered() m_container->refreshContainer(); } +void VersionPage::onFilterTextChanged(const QString &newContents) +{ + m_filterModel->setFilterFixedString(newContents); +} + #include "VersionPage.moc" diff --git a/application/pages/instance/VersionPage.h b/application/pages/instance/VersionPage.h index dbd9c1ee..b5b4a6f5 100644 --- a/application/pages/instance/VersionPage.h +++ b/application/pages/instance/VersionPage.h @@ -86,6 +86,7 @@ protected: private: Ui::VersionPage *ui; + QSortFilterProxyModel *m_filterModel; std::shared_ptr<PackProfile> m_profile; MinecraftInstance *m_inst; int currentIdx = 0; @@ -98,5 +99,6 @@ private slots: void updateRunningStatus(bool running); void onGameUpdateError(QString error); void packageCurrent(const QModelIndex ¤t, const QModelIndex &previous); - void ShowContextMenu(const QPoint &pos); + void showContextMenu(const QPoint &pos); + void onFilterTextChanged(const QString & newContents); }; diff --git a/application/pages/instance/VersionPage.ui b/application/pages/instance/VersionPage.ui index 718ad067..84d06e2e 100644 --- a/application/pages/instance/VersionPage.ui +++ b/application/pages/instance/VersionPage.ui @@ -46,6 +46,24 @@ </widget> </item> <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="1"> + <widget class="QLineEdit" name="filterEdit"> + <property name="clearButtonEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="filterLabel"> + <property name="text"> + <string>Filter:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> <widget class="MCModInfoFrame" name="frame"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> diff --git a/application/pages/modplatform/ImportPage.cpp b/application/pages/modplatform/ImportPage.cpp index 3910dfda..c2369bdc 100644 --- a/application/pages/modplatform/ImportPage.cpp +++ b/application/pages/modplatform/ImportPage.cpp @@ -71,6 +71,7 @@ void ImportPage::updateState() { QFileInfo fi(url.fileName()); dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url)); + dialog->setSuggestedIcon("default"); } } else @@ -83,6 +84,7 @@ void ImportPage::updateState() // hook, line and sinker. QFileInfo fi(url.fileName()); dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url)); + dialog->setSuggestedIcon("default"); } } else diff --git a/application/pages/modplatform/VanillaPage.cpp b/application/pages/modplatform/VanillaPage.cpp index 17535f1e..02638315 100644 --- a/application/pages/modplatform/VanillaPage.cpp +++ b/application/pages/modplatform/VanillaPage.cpp @@ -82,10 +82,19 @@ BaseVersionPtr VanillaPage::selectedVersion() const void VanillaPage::suggestCurrent() { - if(m_selectedVersion && isOpened) + if (!isOpened) { - dialog->setSuggestedPack(m_selectedVersion->descriptor(), new InstanceCreationTask(m_selectedVersion)); + return; } + + if(!m_selectedVersion) + { + dialog->setSuggestedPack(); + return; + } + + dialog->setSuggestedPack(m_selectedVersion->descriptor(), new InstanceCreationTask(m_selectedVersion)); + dialog->setSuggestedIcon("default"); } void VanillaPage::setSelectedVersion(BaseVersionPtr version) diff --git a/application/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp new file mode 100644 index 00000000..14bbd18b --- /dev/null +++ b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -0,0 +1,209 @@ +#include "AtlOptionalModDialog.h" +#include "ui_AtlOptionalModDialog.h" + +AtlOptionalModListModel::AtlOptionalModListModel(QWidget *parent, QVector<ATLauncher::VersionMod> mods) + : QAbstractListModel(parent), m_mods(mods) { + + // fill mod index + for (int i = 0; i < m_mods.size(); i++) { + auto mod = m_mods.at(i); + m_index[mod.name] = i; + } + // set initial state + for (int i = 0; i < m_mods.size(); i++) { + auto mod = m_mods.at(i); + m_selection[mod.name] = false; + setMod(mod, i, mod.selected, false); + } +} + +QVector<QString> AtlOptionalModListModel::getResult() { + QVector<QString> result; + + for (const auto& mod : m_mods) { + if (m_selection[mod.name]) { + result.push_back(mod.name); + } + } + + return result; +} + +int AtlOptionalModListModel::rowCount(const QModelIndex &parent) const { + return m_mods.size(); +} + +int AtlOptionalModListModel::columnCount(const QModelIndex &parent) const { + // Enabled, Name, Description + return 3; +} + +QVariant AtlOptionalModListModel::data(const QModelIndex &index, int role) const { + auto row = index.row(); + auto mod = m_mods.at(row); + + if (role == Qt::DisplayRole) { + if (index.column() == NameColumn) { + return mod.name; + } + if (index.column() == DescriptionColumn) { + return mod.description; + } + } + else if (role == Qt::ToolTipRole) { + if (index.column() == DescriptionColumn) { + return mod.description; + } + } + else if (role == Qt::CheckStateRole) { + if (index.column() == EnabledColumn) { + return m_selection[mod.name] ? Qt::Checked : Qt::Unchecked; + } + } + + return QVariant(); +} + +bool AtlOptionalModListModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (role == Qt::CheckStateRole) { + auto row = index.row(); + auto mod = m_mods.at(row); + + toggleMod(mod, row); + return true; + } + + return false; +} + +QVariant AtlOptionalModListModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + switch (section) { + case EnabledColumn: + return QString(); + case NameColumn: + return QString("Name"); + case DescriptionColumn: + return QString("Description"); + } + } + + return QVariant(); +} + +Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { + auto flags = QAbstractListModel::flags(index); + if (index.isValid() && index.column() == EnabledColumn) { + flags |= Qt::ItemIsUserCheckable; + } + return flags; +} + +void AtlOptionalModListModel::selectRecommended() { + for (const auto& mod : m_mods) { + m_selection[mod.name] = mod.recommended; + } + + emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), + AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); +} + +void AtlOptionalModListModel::clearAll() { + for (const auto& mod : m_mods) { + m_selection[mod.name] = false; + } + + emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), + AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); +} + +void AtlOptionalModListModel::toggleMod(ATLauncher::VersionMod mod, int index) { + setMod(mod, index, !m_selection[mod.name]); +} + +void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit) { + if (m_selection[mod.name] == enable) return; + + m_selection[mod.name] = enable; + + // disable other mods in the group, if applicable + if (enable && !mod.group.isEmpty()) { + for (int i = 0; i < m_mods.size(); i++) { + if (index == i) continue; + auto other = m_mods.at(i); + + if (mod.group == other.group) { + setMod(other, i, false, shouldEmit); + } + } + } + + for (const auto& dependencyName : mod.depends) { + auto dependencyIndex = m_index[dependencyName]; + auto dependencyMod = m_mods.at(dependencyIndex); + + // enable/disable dependencies + if (enable) { + setMod(dependencyMod, dependencyIndex, true, shouldEmit); + } + + // if the dependency is 'effectively hidden', then track which mods + // depend on it - so we can efficiently disable it when no more dependents + // depend on it. + auto dependants = m_dependants[dependencyName]; + + if (enable) { + dependants.append(mod.name); + } + else { + dependants.removeAll(mod.name); + + // if there are no longer any dependents, let's disable the mod + if (dependencyMod.effectively_hidden && dependants.isEmpty()) { + setMod(dependencyMod, dependencyIndex, false, shouldEmit); + } + } + } + + // disable mods that depend on this one, if disabling + if (!enable) { + auto dependants = m_dependants[mod.name]; + for (const auto& dependencyName : dependants) { + auto dependencyIndex = m_index[dependencyName]; + auto dependencyMod = m_mods.at(dependencyIndex); + + setMod(dependencyMod, dependencyIndex, false, shouldEmit); + } + } + + if (shouldEmit) { + emit dataChanged(AtlOptionalModListModel::index(index, EnabledColumn), + AtlOptionalModListModel::index(index, EnabledColumn)); + } +} + + +AtlOptionalModDialog::AtlOptionalModDialog(QWidget *parent, QVector<ATLauncher::VersionMod> mods) + : QDialog(parent), ui(new Ui::AtlOptionalModDialog) { + ui->setupUi(this); + + listModel = new AtlOptionalModListModel(this, mods); + ui->treeView->setModel(listModel); + + ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui->treeView->header()->setSectionResizeMode( + AtlOptionalModListModel::NameColumn, QHeaderView::ResizeToContents); + ui->treeView->header()->setSectionResizeMode( + AtlOptionalModListModel::DescriptionColumn, QHeaderView::Stretch); + + connect(ui->selectRecommendedButton, &QPushButton::pressed, + listModel, &AtlOptionalModListModel::selectRecommended); + connect(ui->clearAllButton, &QPushButton::pressed, + listModel, &AtlOptionalModListModel::clearAll); + connect(ui->installButton, &QPushButton::pressed, + this, &QDialog::close); +} + +AtlOptionalModDialog::~AtlOptionalModDialog() { + delete ui; +} diff --git a/application/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.h new file mode 100644 index 00000000..a1df43f6 --- /dev/null +++ b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -0,0 +1,66 @@ +#pragma once + +#include <QDialog> +#include <QAbstractListModel> + +#include "modplatform/atlauncher/ATLPackIndex.h" + +namespace Ui { +class AtlOptionalModDialog; +} + +class AtlOptionalModListModel : public QAbstractListModel { + Q_OBJECT + +public: + enum Columns + { + EnabledColumn = 0, + NameColumn, + DescriptionColumn, + }; + + AtlOptionalModListModel(QWidget *parent, QVector<ATLauncher::VersionMod> mods); + + QVector<QString> getResult(); + + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + + QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + +public slots: + void selectRecommended(); + void clearAll(); + +private: + void toggleMod(ATLauncher::VersionMod mod, int index); + void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true); + +private: + QVector<ATLauncher::VersionMod> m_mods; + QMap<QString, bool> m_selection; + QMap<QString, int> m_index; + QMap<QString, QVector<QString>> m_dependants; +}; + +class AtlOptionalModDialog : public QDialog { + Q_OBJECT + +public: + AtlOptionalModDialog(QWidget *parent, QVector<ATLauncher::VersionMod> mods); + ~AtlOptionalModDialog() override; + + QVector<QString> getResult() { + return listModel->getResult(); + } + +private: + Ui::AtlOptionalModDialog *ui; + + AtlOptionalModListModel *listModel; +}; diff --git a/application/pages/modplatform/atlauncher/AtlOptionalModDialog.ui b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.ui new file mode 100644 index 00000000..5d3193a4 --- /dev/null +++ b/application/pages/modplatform/atlauncher/AtlOptionalModDialog.ui @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AtlOptionalModDialog</class> + <widget class="QDialog" name="AtlOptionalModDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>550</width> + <height>310</height> + </rect> + </property> + <property name="windowTitle"> + <string>Select Mods To Install</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="3"> + <widget class="QPushButton" name="installButton"> + <property name="text"> + <string>Install</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="selectRecommendedButton"> + <property name="text"> + <string>Select Recommended</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="shareCodeButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Use Share Code</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="clearAllButton"> + <property name="text"> + <string>Clear All</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="4"> + <widget class="ModListView" name="treeView"/> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ModListView</class> + <extends>QTreeView</extends> + <header>widgets/ModListView.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/application/pages/modplatform/atlauncher/AtlPage.cpp b/application/pages/modplatform/atlauncher/AtlPage.cpp index 748f467c..9fdf111f 100644 --- a/application/pages/modplatform/atlauncher/AtlPage.cpp +++ b/application/pages/modplatform/atlauncher/AtlPage.cpp @@ -2,6 +2,7 @@ #include "ui_AtlPage.h" #include "dialogs/NewInstanceDialog.h" +#include "AtlOptionalModDialog.h" #include <modplatform/atlauncher/ATLPackInstallTask.h> #include <BuildConfig.h> #include <dialogs/VersionSelectDialog.h> @@ -20,6 +21,9 @@ AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget *parent) ui->packView->header()->hide(); ui->packView->setIndentation(0); + ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + for(int i = 0; i < filterModel->getAvailableSortings().size(); i++) { ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i)); @@ -45,15 +49,29 @@ bool AtlPage::shouldDisplay() const void AtlPage::openedImpl() { - listModel->request(); + if(!initialized) + { + listModel->request(); + initialized = true; + } + + suggestCurrent(); } void AtlPage::suggestCurrent() { - if(isOpened) { - dialog->setSuggestedPack(selected.name, new ATLauncher::PackInstallTask(this, selected.safeName, selectedVersion)); + if(!isOpened) + { + return; } + if (selectedVersion.isEmpty()) + { + dialog->setSuggestedPack(); + return; + } + + dialog->setSuggestedPack(selected.name, new ATLauncher::PackInstallTask(this, selected.safeName, selectedVersion)); auto editedLogoName = selected.safeName; auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(selected.safeName.toLower()); listModel->getLogo(selected.safeName, url, [this, editedLogoName](QString logo) @@ -114,6 +132,12 @@ void AtlPage::onVersionSelectionChanged(QString data) suggestCurrent(); } +QVector<QString> AtlPage::chooseOptionalMods(QVector<ATLauncher::VersionMod> mods) { + AtlOptionalModDialog optionalModDialog(this, mods); + optionalModDialog.exec(); + return optionalModDialog.getResult(); +} + QString AtlPage::chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) { VersionSelectDialog vselect(vlist.get(), "Choose Version", MMC->activeWindow(), false); if (minecraftVersion != Q_NULLPTR) { diff --git a/application/pages/modplatform/atlauncher/AtlPage.h b/application/pages/modplatform/atlauncher/AtlPage.h index 6a89b609..932ec6a6 100644 --- a/application/pages/modplatform/atlauncher/AtlPage.h +++ b/application/pages/modplatform/atlauncher/AtlPage.h @@ -63,6 +63,7 @@ private: void suggestCurrent(); QString chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) override; + QVector<QString> chooseOptionalMods(QVector<ATLauncher::VersionMod> mods) override; private slots: void triggerSearch(); @@ -81,4 +82,6 @@ private: ATLauncher::IndexedPack selected; QString selectedVersion; + + bool initialized = false; }; diff --git a/application/pages/modplatform/atlauncher/AtlPage.ui b/application/pages/modplatform/atlauncher/AtlPage.ui index bb0d5310..f16c24b8 100644 --- a/application/pages/modplatform/atlauncher/AtlPage.ui +++ b/application/pages/modplatform/atlauncher/AtlPage.ui @@ -21,6 +21,9 @@ <height>48</height> </size> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> </widget> </item> <item row="1" column="1"> diff --git a/application/pages/modplatform/flame/FlamePage.cpp b/application/pages/modplatform/flame/FlamePage.cpp index 1fadc501..ade58431 100644 --- a/application/pages/modplatform/flame/FlamePage.cpp +++ b/application/pages/modplatform/flame/FlamePage.cpp @@ -17,6 +17,9 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget *parent) listModel = new Flame::ListModel(this); ui->packView->setModel(listModel); + ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + // index is used to set the sorting with the curseforge api ui->sortByBox->addItem(tr("Sort by featured")); ui->sortByBox->addItem(tr("Sort by popularity")); @@ -155,6 +158,12 @@ void FlamePage::suggestCurrent() return; } + if (selectedVersion.isEmpty()) + { + dialog->setSuggestedPack(); + return; + } + dialog->setSuggestedPack(current.name, new InstanceImportTask(selectedVersion)); QString editedLogoName; editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0); diff --git a/application/pages/modplatform/ftb/FtbPage.cpp b/application/pages/modplatform/ftb/FtbPage.cpp index dd2ff666..b7f35c5d 100644 --- a/application/pages/modplatform/ftb/FtbPage.cpp +++ b/application/pages/modplatform/ftb/FtbPage.cpp @@ -23,6 +23,9 @@ FtbPage::FtbPage(NewInstanceDialog* dialog, QWidget *parent) ui->searchEdit->installEventFilter(this); + ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + for(int i = 0; i < filterModel->getAvailableSortings().size(); i++) { ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i)); @@ -60,26 +63,33 @@ bool FtbPage::shouldDisplay() const void FtbPage::openedImpl() { - dialog->setSuggestedPack(); triggerSearch(); + suggestCurrent(); } void FtbPage::suggestCurrent() { - if(isOpened) + if(!isOpened) + { + return; + } + + if (selectedVersion.isEmpty()) { - dialog->setSuggestedPack(selected.name, new ModpacksCH::PackInstallTask(selected, selectedVersion)); - - for(auto art : selected.art) { - if(art.type == "square") { - QString editedLogoName; - editedLogoName = selected.name; - - listModel->getLogo(selected.name, art.url, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName); - }); - } + dialog->setSuggestedPack(); + return; + } + + dialog->setSuggestedPack(selected.name, new ModpacksCH::PackInstallTask(selected, selectedVersion)); + for(auto art : selected.art) { + if(art.type == "square") { + QString editedLogoName; + editedLogoName = selected.name; + + listModel->getLogo(selected.name, art.url, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName); + }); } } } diff --git a/application/pages/modplatform/ftb/FtbPage.ui b/application/pages/modplatform/ftb/FtbPage.ui index 475d78bb..135afc6d 100644 --- a/application/pages/modplatform/ftb/FtbPage.ui +++ b/application/pages/modplatform/ftb/FtbPage.ui @@ -32,7 +32,11 @@ </layout> </item> <item row="0" column="0"> - <widget class="QLineEdit" name="searchEdit"/> + <widget class="QLineEdit" name="searchEdit"> + <property name="placeholderText"> + <string>Search and filter ...</string> + </property> + </widget> </item> <item row="0" column="1"> <widget class="QPushButton" name="searchButton"> @@ -51,6 +55,9 @@ <height>48</height> </size> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> </widget> </item> <item row="0" column="1"> diff --git a/application/pages/modplatform/legacy_ftb/Page.cpp b/application/pages/modplatform/legacy_ftb/Page.cpp index 8e40ba9e..a438f76c 100644 --- a/application/pages/modplatform/legacy_ftb/Page.cpp +++ b/application/pages/modplatform/legacy_ftb/Page.cpp @@ -122,49 +122,50 @@ void Page::openedImpl() void Page::suggestCurrent() { - if(isOpened) + if(!isOpened) { - if(!selected.broken) - { - dialog->setSuggestedPack(selected.name, new PackInstallTask(selected, selectedVersion)); - QString editedLogoName; - if(selected.logo.toLower().startsWith("ftb")) - { - editedLogoName = selected.logo; - } - else - { - editedLogoName = "ftb_" + selected.logo; - } + return; + } - editedLogoName = editedLogoName.left(editedLogoName.lastIndexOf(".png")); + if(selected.broken || selectedVersion.isEmpty()) + { + dialog->setSuggestedPack(); + return; + } - if(selected.type == PackType::Public) - { - publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); - } - else if (selected.type == PackType::ThirdParty) - { - thirdPartyModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); - } - else if (selected.type == PackType::Private) - { - privateListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); - } - } - else + dialog->setSuggestedPack(selected.name, new PackInstallTask(selected, selectedVersion)); + 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 == PackType::Public) + { + publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) { - dialog->setSuggestedPack(); - } + dialog->setSuggestedIconFromFile(logo, editedLogoName); + }); + } + else if (selected.type == PackType::ThirdParty) + { + thirdPartyModel->getLogo(selected.logo, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo, editedLogoName); + }); + } + else if (selected.type == PackType::Private) + { + privateListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) + { + dialog->setSuggestedIconFromFile(logo, editedLogoName); + }); } } diff --git a/application/pages/modplatform/legacy_ftb/Page.ui b/application/pages/modplatform/legacy_ftb/Page.ui index 36fb2359..15e5d432 100644 --- a/application/pages/modplatform/legacy_ftb/Page.ui +++ b/application/pages/modplatform/legacy_ftb/Page.ui @@ -29,6 +29,9 @@ <height>16777215</height> </size> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> </widget> </item> <item row="0" column="1"> @@ -52,6 +55,9 @@ <height>16777215</height> </size> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> </widget> </item> </layout> @@ -69,6 +75,9 @@ <height>16777215</height> </size> </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> </widget> </item> <item row="1" column="0"> diff --git a/application/pages/modplatform/technic/TechnicModel.cpp b/application/pages/modplatform/technic/TechnicModel.cpp index bf256ab6..def30783 100644 --- a/application/pages/modplatform/technic/TechnicModel.cpp +++ b/application/pages/modplatform/technic/TechnicModel.cpp @@ -72,7 +72,7 @@ int Technic::ListModel::rowCount(const QModelIndex&) const void Technic::ListModel::searchWithTerm(const QString& term) { - if(currentSearchTerm == term) { + if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) { return; } currentSearchTerm = term; @@ -93,9 +93,16 @@ void Technic::ListModel::searchWithTerm(const QString& term) void Technic::ListModel::performSearch() { NetJob *netJob = new NetJob("Technic::Search"); - auto searchUrl = QString( - "https://api.technicpack.net/search?build=multimc&q=%1" - ).arg(currentSearchTerm); + QString searchUrl = ""; + if (currentSearchTerm.isEmpty()) { + searchUrl = "https://api.technicpack.net/trending?build=multimc"; + } + else + { + searchUrl = QString( + "https://api.technicpack.net/search?build=multimc&q=%1" + ).arg(currentSearchTerm); + } netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); jobPtr = netJob; jobPtr->start(); diff --git a/application/pages/modplatform/technic/TechnicPage.cpp b/application/pages/modplatform/technic/TechnicPage.cpp index d246edf2..e836f767 100644 --- a/application/pages/modplatform/technic/TechnicPage.cpp +++ b/application/pages/modplatform/technic/TechnicPage.cpp @@ -60,7 +60,8 @@ bool TechnicPage::shouldDisplay() const void TechnicPage::openedImpl() { - dialog->setSuggestedPack(); + suggestCurrent(); + triggerSearch(); } void TechnicPage::triggerSearch() { @@ -95,8 +96,7 @@ void TechnicPage::suggestCurrent() return; } - QString editedLogoName; - editedLogoName = "technic_" + current.logoName.section(".", 0, 0); + QString editedLogoName = "technic_" + current.logoName.section(".", 0, 0); model->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); @@ -105,67 +105,66 @@ void TechnicPage::suggestCurrent() if (current.metadataLoaded) { metadataLoaded(); + return; } - else + + NetJob *netJob = new NetJob(QString("Technic::PackMeta(%1)").arg(current.name)); + std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>(); + QString slug = current.slug; + netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.technicpack.net/modpack/%1?build=multimc").arg(slug), response.get())); + QObject::connect(netJob, &NetJob::succeeded, this, [this, response, slug] { - NetJob *netJob = new NetJob(QString("Technic::PackMeta(%1)").arg(current.name)); - std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>(); - QString slug = current.slug; - netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.technicpack.net/modpack/%1?build=multimc").arg(slug), response.get())); - QObject::connect(netJob, &NetJob::succeeded, this, [this, response, slug] + if (current.slug != slug) { - if (current.slug != slug) - { - return; - } - QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - QJsonObject obj = doc.object(); - if(parse_error.error != QJsonParseError::NoError) - { - qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *response; - return; - } - if (!obj.contains("url")) + return; + } + QJsonParseError parse_error; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonObject obj = doc.object(); + if(parse_error.error != QJsonParseError::NoError) + { + qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + if (!obj.contains("url")) + { + qWarning() << "Json doesn't contain an url key"; + return; + } + QJsonValueRef url = obj["url"]; + if (url.isString()) + { + current.url = url.toString(); + } + else + { + if (!obj.contains("solder")) { - qWarning() << "Json doesn't contain an url key"; + qWarning() << "Json doesn't contain a valid url or solder key"; return; } - QJsonValueRef url = obj["url"]; - if (url.isString()) + QJsonValueRef solderUrl = obj["solder"]; + if (solderUrl.isString()) { - current.url = url.toString(); + current.url = solderUrl.toString(); + current.isSolder = true; } else { - if (!obj.contains("solder")) - { - qWarning() << "Json doesn't contain a valid url or solder key"; - return; - } - QJsonValueRef solderUrl = obj["solder"]; - if (solderUrl.isString()) - { - current.url = solderUrl.toString(); - current.isSolder = true; - } - else - { - qWarning() << "Json doesn't contain a valid url or solder key"; - return; - } + qWarning() << "Json doesn't contain a valid url or solder key"; + return; } + } - current.minecraftVersion = Json::ensureString(obj, "minecraft", QString(), "__placeholder__"); - current.websiteUrl = Json::ensureString(obj, "platformUrl", QString(), "__placeholder__"); - current.author = Json::ensureString(obj, "user", QString(), "__placeholder__"); - current.description = Json::ensureString(obj, "description", QString(), "__placeholder__"); - current.metadataLoaded = true; - metadataLoaded(); - }); - netJob->start(); - } + current.minecraftVersion = Json::ensureString(obj, "minecraft", QString(), "__placeholder__"); + current.websiteUrl = Json::ensureString(obj, "platformUrl", QString(), "__placeholder__"); + current.author = Json::ensureString(obj, "user", QString(), "__placeholder__"); + current.description = Json::ensureString(obj, "description", QString(), "__placeholder__"); + current.metadataLoaded = true; + metadataLoaded(); + }); + netJob->start(); } // expects current.metadataLoaded to be true diff --git a/application/pages/modplatform/technic/TechnicPage.ui b/application/pages/modplatform/technic/TechnicPage.ui index 36ce2ecf..2ca45dd2 100644 --- a/application/pages/modplatform/technic/TechnicPage.ui +++ b/application/pages/modplatform/technic/TechnicPage.ui @@ -27,7 +27,11 @@ <number>0</number> </property> <item> - <widget class="QLineEdit" name="searchEdit"/> + <widget class="QLineEdit" name="searchEdit"> + <property name="placeholderText"> + <string>Search and filter ...</string> + </property> + </widget> </item> <item> <widget class="QPushButton" name="searchButton"> diff --git a/application/resources/MultiMC.ico b/application/resources/MultiMC.ico Binary files differindex 1846964e..a86a1f0d 100644 --- a/application/resources/MultiMC.ico +++ b/application/resources/MultiMC.ico diff --git a/application/resources/multimc/16x16/patreon.png b/application/resources/multimc/16x16/patreon.png Binary files differindex cde2b326..9150c478 100644 --- a/application/resources/multimc/16x16/patreon.png +++ b/application/resources/multimc/16x16/patreon.png diff --git a/application/resources/multimc/22x22/patreon.png b/application/resources/multimc/22x22/patreon.png Binary files differindex b6235ad2..f2c2076c 100644 --- a/application/resources/multimc/22x22/patreon.png +++ b/application/resources/multimc/22x22/patreon.png diff --git a/application/resources/multimc/24x24/patreon.png b/application/resources/multimc/24x24/patreon.png Binary files differindex c1da080f..add80668 100644 --- a/application/resources/multimc/24x24/patreon.png +++ b/application/resources/multimc/24x24/patreon.png diff --git a/application/resources/multimc/32x32/patreon.png b/application/resources/multimc/32x32/patreon.png Binary files differindex f5ae8a5e..70085aa1 100644 --- a/application/resources/multimc/32x32/patreon.png +++ b/application/resources/multimc/32x32/patreon.png diff --git a/application/resources/multimc/48x48/patreon.png b/application/resources/multimc/48x48/patreon.png Binary files differindex 2708a85a..7aec4d7d 100644 --- a/application/resources/multimc/48x48/patreon.png +++ b/application/resources/multimc/48x48/patreon.png diff --git a/application/resources/multimc/64x64/patreon.png b/application/resources/multimc/64x64/patreon.png Binary files differindex 7b4814ec..ef5d690e 100644 --- a/application/resources/multimc/64x64/patreon.png +++ b/application/resources/multimc/64x64/patreon.png diff --git a/application/widgets/JavaSettingsWidget.cpp b/application/widgets/JavaSettingsWidget.cpp index a11dd1aa..7f53dc23 100644 --- a/application/widgets/JavaSettingsWidget.cpp +++ b/application/widgets/JavaSettingsWidget.cpp @@ -19,7 +19,7 @@ JavaSettingsWidget::JavaSettingsWidget(QWidget* parent) : QWidget(parent) { - m_availableMemory = Sys::getSystemRam() / Sys::megabyte; + m_availableMemory = Sys::getSystemRam() / Sys::mebibyte; goodIcon = MMC->getThemedIcon("status-good"); yellowIcon = MMC->getThemedIcon("status-yellow"); |