aboutsummaryrefslogtreecommitdiff
path: root/launcher/ui/pages/modplatform
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/ui/pages/modplatform')
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.cpp132
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.h70
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.ui52
-rw-r--r--launcher/ui/pages/modplatform/VanillaPage.cpp103
-rw-r--r--launcher/ui/pages/modplatform/VanillaPage.h75
-rw-r--r--launcher/ui/pages/modplatform/VanillaPage.ui169
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp81
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h34
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp193
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlListModel.h52
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp209
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h66
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui65
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp171
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlPage.h86
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlPage.ui92
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModel.cpp258
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModel.h76
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.cpp186
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.h80
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.ui90
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbFilterModel.cpp76
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbFilterModel.h35
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbListModel.cpp278
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbListModel.h61
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbPage.cpp150
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbPage.h83
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbPage.ui79
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp259
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/ListModel.h78
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/Page.cpp371
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/Page.h119
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/Page.ui135
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicData.h42
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicModel.cpp237
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicModel.h70
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicPage.cpp201
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicPage.h78
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicPage.ui95
39 files changed, 4787 insertions, 0 deletions
diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp
new file mode 100644
index 00000000..c9e24ead
--- /dev/null
+++ b/launcher/ui/pages/modplatform/ImportPage.cpp
@@ -0,0 +1,132 @@
+#include "ImportPage.h"
+#include "ui_ImportPage.h"
+
+#include <QFileDialog>
+#include <QValidator>
+
+#include "ui/dialogs/NewInstanceDialog.h"
+
+#include "InstanceImportTask.h"
+
+
+class UrlValidator : public QValidator
+{
+public:
+ using QValidator::QValidator;
+
+ State validate(QString &in, int &pos) const
+ {
+ const QUrl url(in);
+ if (url.isValid() && !url.isRelative() && !url.isEmpty())
+ {
+ return Acceptable;
+ }
+ else if (QFile::exists(in))
+ {
+ return Acceptable;
+ }
+ else
+ {
+ return Intermediate;
+ }
+ }
+};
+
+ImportPage::ImportPage(NewInstanceDialog* dialog, QWidget *parent)
+ : QWidget(parent), ui(new Ui::ImportPage), dialog(dialog)
+{
+ ui->setupUi(this);
+ ui->modpackEdit->setValidator(new UrlValidator(ui->modpackEdit));
+ connect(ui->modpackEdit, &QLineEdit::textChanged, this, &ImportPage::updateState);
+}
+
+ImportPage::~ImportPage()
+{
+ delete ui;
+}
+
+bool ImportPage::shouldDisplay() const
+{
+ return true;
+}
+
+void ImportPage::openedImpl()
+{
+ updateState();
+}
+
+void ImportPage::updateState()
+{
+ if(!isOpened)
+ {
+ return;
+ }
+ if(ui->modpackEdit->hasAcceptableInput())
+ {
+ QString input = ui->modpackEdit->text();
+ auto url = QUrl::fromUserInput(input);
+ if(url.isLocalFile())
+ {
+ // FIXME: actually do some validation of what's inside here... this is fake AF
+ QFileInfo fi(input);
+ if(fi.exists() && fi.suffix() == "zip")
+ {
+ QFileInfo fi(url.fileName());
+ dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url));
+ dialog->setSuggestedIcon("default");
+ }
+ }
+ else
+ {
+ if(input.endsWith("?client=y")) {
+ input.chop(9);
+ input.append("/file");
+ url = QUrl::fromUserInput(input);
+ }
+ // hook, line and sinker.
+ QFileInfo fi(url.fileName());
+ dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url));
+ dialog->setSuggestedIcon("default");
+ }
+ }
+ else
+ {
+ dialog->setSuggestedPack();
+ }
+}
+
+void ImportPage::setUrl(const QString& url)
+{
+ ui->modpackEdit->setText(url);
+ updateState();
+}
+
+void ImportPage::on_modpackBtn_clicked()
+{
+ const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), tr("Zip (*.zip)"));
+ if (url.isValid())
+ {
+ if (url.isLocalFile())
+ {
+ ui->modpackEdit->setText(url.toLocalFile());
+ }
+ else
+ {
+ ui->modpackEdit->setText(url.toString());
+ }
+ }
+}
+
+
+QUrl ImportPage::modpackUrl() const
+{
+ const QUrl url(ui->modpackEdit->text());
+ if (url.isValid() && !url.isRelative() && !url.host().isEmpty())
+ {
+ return url;
+ }
+ else
+ {
+ return QUrl::fromLocalFile(ui->modpackEdit->text());
+ }
+}
diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h
new file mode 100644
index 00000000..aba4def0
--- /dev/null
+++ b/launcher/ui/pages/modplatform/ImportPage.h
@@ -0,0 +1,70 @@
+/* Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+#include "ui/pages/BasePage.h"
+#include <Application.h>
+#include "tasks/Task.h"
+
+namespace Ui
+{
+class ImportPage;
+}
+
+class NewInstanceDialog;
+
+class ImportPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit ImportPage(NewInstanceDialog* dialog, QWidget *parent = 0);
+ virtual ~ImportPage();
+ virtual QString displayName() const override
+ {
+ return tr("Import from zip");
+ }
+ virtual QIcon icon() const override
+ {
+ return APPLICATION->getThemedIcon("viewfolder");
+ }
+ virtual QString id() const override
+ {
+ return "import";
+ }
+ virtual QString helpPage() const override
+ {
+ return "Zip-import";
+ }
+ virtual bool shouldDisplay() const override;
+
+ void setUrl(const QString & url);
+ void openedImpl() override;
+
+private slots:
+ void on_modpackBtn_clicked();
+ void updateState();
+
+private:
+ QUrl modpackUrl() const;
+
+private:
+ Ui::ImportPage *ui = nullptr;
+ NewInstanceDialog* dialog = nullptr;
+};
+
diff --git a/launcher/ui/pages/modplatform/ImportPage.ui b/launcher/ui/pages/modplatform/ImportPage.ui
new file mode 100644
index 00000000..eb63cbe9
--- /dev/null
+++ b/launcher/ui/pages/modplatform/ImportPage.ui
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImportPage</class>
+ <widget class="QWidget" name="ImportPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>546</width>
+ <height>405</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="1">
+ <widget class="QPushButton" name="modpackBtn">
+ <property name="text">
+ <string>Browse</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLineEdit" name="modpackEdit">
+ <property name="placeholderText">
+ <string notr="true">http://</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="modpackLabel">
+ <property name="text">
+ <string>Local file or link to a direct download:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/launcher/ui/pages/modplatform/VanillaPage.cpp b/launcher/ui/pages/modplatform/VanillaPage.cpp
new file mode 100644
index 00000000..5c58c1f1
--- /dev/null
+++ b/launcher/ui/pages/modplatform/VanillaPage.cpp
@@ -0,0 +1,103 @@
+#include "VanillaPage.h"
+#include "ui_VanillaPage.h"
+
+#include <QTabBar>
+
+#include "Application.h"
+#include "meta/Index.h"
+#include "meta/VersionList.h"
+#include "ui/dialogs/NewInstanceDialog.h"
+#include "Filter.h"
+#include "InstanceCreationTask.h"
+
+VanillaPage::VanillaPage(NewInstanceDialog *dialog, QWidget *parent)
+ : QWidget(parent), dialog(dialog), ui(new Ui::VanillaPage)
+{
+ ui->setupUi(this);
+ ui->tabWidget->tabBar()->hide();
+ connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &VanillaPage::setSelectedVersion);
+ filterChanged();
+ connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->betaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->oldSnapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged);
+ connect(ui->refreshBtn, &QPushButton::clicked, this, &VanillaPage::refresh);
+}
+
+void VanillaPage::openedImpl()
+{
+ if(!initialized)
+ {
+ auto vlist = APPLICATION->metadataIndex()->get("net.minecraft");
+ ui->versionList->initialize(vlist.get());
+ initialized = true;
+ }
+ else
+ {
+ suggestCurrent();
+ }
+}
+
+void VanillaPage::refresh()
+{
+ ui->versionList->loadList();
+}
+
+void VanillaPage::filterChanged()
+{
+ QStringList out;
+ if(ui->alphaFilter->isChecked())
+ out << "(old_alpha)";
+ if(ui->betaFilter->isChecked())
+ out << "(old_beta)";
+ if(ui->snapshotFilter->isChecked())
+ out << "(snapshot)";
+ if(ui->oldSnapshotFilter->isChecked())
+ out << "(old_snapshot)";
+ if(ui->releaseFilter->isChecked())
+ out << "(release)";
+ if(ui->experimentsFilter->isChecked())
+ out << "(experiment)";
+ auto regexp = out.join('|');
+ ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false));
+}
+
+VanillaPage::~VanillaPage()
+{
+ delete ui;
+}
+
+bool VanillaPage::shouldDisplay() const
+{
+ return true;
+}
+
+BaseVersionPtr VanillaPage::selectedVersion() const
+{
+ return m_selectedVersion;
+}
+
+void VanillaPage::suggestCurrent()
+{
+ if (!isOpened)
+ {
+ return;
+ }
+
+ if(!m_selectedVersion)
+ {
+ dialog->setSuggestedPack();
+ return;
+ }
+
+ dialog->setSuggestedPack(m_selectedVersion->descriptor(), new InstanceCreationTask(m_selectedVersion));
+ dialog->setSuggestedIcon("default");
+}
+
+void VanillaPage::setSelectedVersion(BaseVersionPtr version)
+{
+ m_selectedVersion = version;
+ suggestCurrent();
+}
diff --git a/launcher/ui/pages/modplatform/VanillaPage.h b/launcher/ui/pages/modplatform/VanillaPage.h
new file mode 100644
index 00000000..fd4c2daa
--- /dev/null
+++ b/launcher/ui/pages/modplatform/VanillaPage.h
@@ -0,0 +1,75 @@
+/* Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+#include "ui/pages/BasePage.h"
+#include <Application.h>
+#include "tasks/Task.h"
+
+namespace Ui
+{
+class VanillaPage;
+}
+
+class NewInstanceDialog;
+
+class VanillaPage : public QWidget, public BasePage
+{
+ Q_OBJECT
+
+public:
+ explicit VanillaPage(NewInstanceDialog *dialog, QWidget *parent = 0);
+ virtual ~VanillaPage();
+ virtual QString displayName() const override
+ {
+ return tr("Vanilla");
+ }
+ virtual QIcon icon() const override
+ {
+ return APPLICATION->getThemedIcon("minecraft");
+ }
+ virtual QString id() const override
+ {
+ return "vanilla";
+ }
+ virtual QString helpPage() const override
+ {
+ return "Vanilla-platform";
+ }
+ virtual bool shouldDisplay() const override;
+ void openedImpl() override;
+
+ BaseVersionPtr selectedVersion() const;
+
+public slots:
+ void setSelectedVersion(BaseVersionPtr version);
+
+private slots:
+ void filterChanged();
+
+private:
+ void refresh();
+ void suggestCurrent();
+
+private:
+ bool initialized = false;
+ NewInstanceDialog *dialog = nullptr;
+ Ui::VanillaPage *ui = nullptr;
+ bool m_versionSetByUser = false;
+ BaseVersionPtr m_selectedVersion;
+};
diff --git a/launcher/ui/pages/modplatform/VanillaPage.ui b/launcher/ui/pages/modplatform/VanillaPage.ui
new file mode 100644
index 00000000..870ff161
--- /dev/null
+++ b/launcher/ui/pages/modplatform/VanillaPage.ui
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>VanillaPage</class>
+ <widget class="QWidget" name="VanillaPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>815</width>
+ <height>607</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string notr="true"/>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="releaseFilter">
+ <property name="text">
+ <string>Releases</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="snapshotFilter">
+ <property name="text">
+ <string>Snapshots</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="oldSnapshotFilter">
+ <property name="text">
+ <string>Old Snapshots</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="betaFilter">
+ <property name="text">
+ <string>Betas</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="alphaFilter">
+ <property name="text">
+ <string>Alphas</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="experimentsFilter">
+ <property name="text">
+ <string>Experiments</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="refreshBtn">
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="VersionSelectWidget" name="versionList" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>VersionSelectWidget</class>
+ <extends>QWidget</extends>
+ <header>ui/widgets/VersionSelectWidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>releaseFilter</tabstop>
+ <tabstop>snapshotFilter</tabstop>
+ <tabstop>oldSnapshotFilter</tabstop>
+ <tabstop>betaFilter</tabstop>
+ <tabstop>alphaFilter</tabstop>
+ <tabstop>experimentsFilter</tabstop>
+ <tabstop>refreshBtn</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
new file mode 100644
index 00000000..b5d8f22b
--- /dev/null
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
@@ -0,0 +1,81 @@
+#include "AtlFilterModel.h"
+
+#include <QDebug>
+
+#include <modplatform/atlauncher/ATLPackIndex.h>
+#include <Version.h>
+#include <MMCStrings.h>
+
+namespace Atl {
+
+FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
+{
+ currentSorting = Sorting::ByPopularity;
+ sortings.insert(tr("Sort by popularity"), Sorting::ByPopularity);
+ sortings.insert(tr("Sort by name"), Sorting::ByName);
+ sortings.insert(tr("Sort by game version"), Sorting::ByGameVersion);
+
+ searchTerm = "";
+}
+
+const QMap<QString, FilterModel::Sorting> FilterModel::getAvailableSortings()
+{
+ return sortings;
+}
+
+QString FilterModel::translateCurrentSorting()
+{
+ return sortings.key(currentSorting);
+}
+
+void FilterModel::setSorting(Sorting sorting)
+{
+ currentSorting = sorting;
+ invalidate();
+}
+
+FilterModel::Sorting FilterModel::getCurrentSorting()
+{
+ return currentSorting;
+}
+
+void FilterModel::setSearchTerm(const QString term)
+{
+ searchTerm = term.trimmed();
+ invalidate();
+}
+
+bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ if (searchTerm.isEmpty()) {
+ return true;
+ }
+
+ QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
+ ATLauncher::IndexedPack pack = sourceModel()->data(index, Qt::UserRole).value<ATLauncher::IndexedPack>();
+ return pack.name.contains(searchTerm, Qt::CaseInsensitive);
+}
+
+bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
+{
+ ATLauncher::IndexedPack leftPack = sourceModel()->data(left, Qt::UserRole).value<ATLauncher::IndexedPack>();
+ ATLauncher::IndexedPack rightPack = sourceModel()->data(right, Qt::UserRole).value<ATLauncher::IndexedPack>();
+
+ if (currentSorting == ByPopularity) {
+ return leftPack.position > rightPack.position;
+ }
+ else if (currentSorting == ByGameVersion) {
+ Version lv(leftPack.versions.at(0).minecraft);
+ Version rv(rightPack.versions.at(0).minecraft);
+ return lv < rv;
+ }
+ else if (currentSorting == ByName) {
+ return Strings::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
+ }
+
+ // Invalid sorting set, somehow...
+ qWarning() << "Invalid sorting set!";
+ return true;
+}
+
+}
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h
new file mode 100644
index 00000000..bd72ad91
--- /dev/null
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <QtCore/QSortFilterProxyModel>
+
+namespace Atl {
+