aboutsummaryrefslogtreecommitdiff
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/CMakeLists.txt5
-rw-r--r--application/LaunchController.cpp42
-rw-r--r--application/MainWindow.cpp76
-rw-r--r--application/MainWindow.h2
-rw-r--r--application/dialogs/LoginDialog.ui14
-rw-r--r--application/dialogs/NewInstanceDialog.cpp8
-rw-r--r--application/dialogs/NewInstanceDialog.h1
-rw-r--r--application/pages/global/JavaPage.cpp4
-rw-r--r--application/pages/global/JavaPage.ui6
-rw-r--r--application/pages/instance/InstanceSettingsPage.cpp2
-rw-r--r--application/pages/instance/InstanceSettingsPage.ui6
-rw-r--r--application/pages/instance/LogPage.cpp6
-rw-r--r--application/pages/instance/ModFolderPage.cpp2
-rw-r--r--application/pages/instance/ResourcePackPage.h3
-rw-r--r--application/pages/instance/TexturePackPage.h2
-rw-r--r--application/pages/instance/VersionPage.cpp20
-rw-r--r--application/pages/instance/VersionPage.h4
-rw-r--r--application/pages/instance/VersionPage.ui18
-rw-r--r--application/pages/modplatform/ImportPage.cpp2
-rw-r--r--application/pages/modplatform/VanillaPage.cpp13
-rw-r--r--application/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp209
-rw-r--r--application/pages/modplatform/atlauncher/AtlOptionalModDialog.h66
-rw-r--r--application/pages/modplatform/atlauncher/AtlOptionalModDialog.ui65
-rw-r--r--application/pages/modplatform/atlauncher/AtlPage.cpp30
-rw-r--r--application/pages/modplatform/atlauncher/AtlPage.h3
-rw-r--r--application/pages/modplatform/atlauncher/AtlPage.ui3
-rw-r--r--application/pages/modplatform/flame/FlamePage.cpp9
-rw-r--r--application/pages/modplatform/ftb/FtbPage.cpp38
-rw-r--r--application/pages/modplatform/ftb/FtbPage.ui9
-rw-r--r--application/pages/modplatform/legacy_ftb/Page.cpp79
-rw-r--r--application/pages/modplatform/legacy_ftb/Page.ui9
-rw-r--r--application/pages/modplatform/technic/TechnicModel.cpp15
-rw-r--r--application/pages/modplatform/technic/TechnicPage.cpp103
-rw-r--r--application/pages/modplatform/technic/TechnicPage.ui6
-rw-r--r--application/resources/MultiMC.icobin85182 -> 55224 bytes
-rw-r--r--application/resources/multimc/16x16/patreon.pngbin682 -> 840 bytes
-rw-r--r--application/resources/multimc/22x22/patreon.pngbin976 -> 939 bytes
-rw-r--r--application/resources/multimc/24x24/patreon.pngbin1034 -> 977 bytes
-rw-r--r--application/resources/multimc/32x32/patreon.pngbin1450 -> 1086 bytes
-rw-r--r--application/resources/multimc/48x48/patreon.pngbin2317 -> 1390 bytes
-rw-r--r--application/resources/multimc/64x64/patreon.pngbin3212 -> 1667 bytes
-rw-r--r--application/widgets/JavaSettingsWidget.cpp2
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 &current, 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
index 1846964e..a86a1f0d 100644
--- a/application/resources/MultiMC.ico
+++ b/application/resources/MultiMC.ico
Binary files differ
diff --git a/application/resources/multimc/16x16/patreon.png b/application/resources/multimc/16x16/patreon.png
index cde2b326..9150c478 100644
--- a/application/resources/multimc/16x16/patreon.png
+++ b/application/resources/multimc/16x16/patreon.png
Binary files differ
diff --git a/application/resources/multimc/22x22/patreon.png b/application/resources/multimc/22x22/patreon.png
index b6235ad2..f2c2076c 100644
--- a/application/resources/multimc/22x22/patreon.png
+++ b/application/resources/multimc/22x22/patreon.png
Binary files differ
diff --git a/application/resources/multimc/24x24/patreon.png b/application/resources/multimc/24x24/patreon.png
index c1da080f..add80668 100644
--- a/application/resources/multimc/24x24/patreon.png
+++ b/application/resources/multimc/24x24/patreon.png
Binary files differ
diff --git a/application/resources/multimc/32x32/patreon.png b/application/resources/multimc/32x32/patreon.png
index f5ae8a5e..70085aa1 100644
--- a/application/resources/multimc/32x32/patreon.png
+++ b/application/resources/multimc/32x32/patreon.png
Binary files differ
diff --git a/application/resources/multimc/48x48/patreon.png b/application/resources/multimc/48x48/patreon.png
index 2708a85a..7aec4d7d 100644
--- a/application/resources/multimc/48x48/patreon.png
+++ b/application/resources/multimc/48x48/patreon.png
Binary files differ
diff --git a/application/resources/multimc/64x64/patreon.png b/application/resources/multimc/64x64/patreon.png
index 7b4814ec..ef5d690e 100644
--- a/application/resources/multimc/64x64/patreon.png
+++ b/application/resources/multimc/64x64/patreon.png
Binary files differ
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");