diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index b9a671b3..31b0e62c 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -143,6 +143,8 @@ SET(MULTIMC_SOURCES ColumnResizer.cpp InstanceProxyModel.h InstanceProxyModel.cpp + VersionProxyModel.h + VersionProxyModel.cpp # GUI - windows MainWindow.h diff --git a/application/VersionProxyModel.cpp b/application/VersionProxyModel.cpp new file mode 100644 index 00000000..2bfafd47 --- /dev/null +++ b/application/VersionProxyModel.cpp @@ -0,0 +1,382 @@ +#include "VersionProxyModel.h" +#include "MultiMC.h" +#include +#include +#include + +class VersionFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + VersionFilterModel(VersionProxyModel *parent) : QSortFilterProxyModel(parent) + { + m_parent = parent; + } + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + { + const auto &filters = m_parent->filters(); + for (auto it = filters.begin(); it != filters.end(); ++it) + { + auto role = it.key(); + auto idx = sourceModel()->index(source_row, 0, source_parent); + auto data = sourceModel()->data(idx, role); + + switch(role) + { + case BaseVersionList::ParentGameVersionRole: + case BaseVersionList::VersionIdRole: + { + auto versionString = data.toString(); + if(it.value().exact) + { + if (versionString != it.value().string) + { + return false; + } + } + else if (!Util::versionIsInInterval(versionString, it.value().string)) + { + return false; + } + } + default: + { + auto match = data.toString(); + if(it.value().exact) + { + if (match != it.value().string) + { + return false; + } + } + else if (match.contains(it.value().string)) + { + return false; + } + } + } + } + return true; + } +private: + VersionProxyModel *m_parent; +}; + +VersionProxyModel::VersionProxyModel(QObject *parent) : QAbstractProxyModel(parent) +{ + filterModel = new VersionFilterModel(this); + connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged); + // FIXME: implement when needed + /* + connect(replacing, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted); + connect(replacing, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted); + connect(replacing, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved); + connect(replacing, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved); + connect(replacing, &QAbstractItemModel::rowsAboutToBeMoved, this, &VersionProxyModel::sourceRowsAboutToBeMoved); + connect(replacing, &QAbstractItemModel::rowsMoved, this, &VersionProxyModel::sourceRowsMoved); + connect(replacing, &QAbstractItemModel::layoutAboutToBeChanged, this, &VersionProxyModel::sourceLayoutAboutToBeChanged); + connect(replacing, &QAbstractItemModel::layoutChanged, this, &VersionProxyModel::sourceLayoutChanged); + */ + connect(filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset); + connect(filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset); + + QAbstractProxyModel::setSourceModel(filterModel); +} + +QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(section < 0 || section >= m_columns.size()) + return QVariant(); + if(orientation != Qt::Horizontal) + return QVariant(); + auto column = m_columns[section]; + if(role == Qt::DisplayRole) + { + switch(column) + { + case Name: + return tr("Version"); + case ParentVersion: + return tr("Minecraft"); //FIXME: this should come from metadata + case Branch: + return tr("Branch"); + case Type: + return tr("Type"); + case Architecture: + return tr("Architecture"); + case Path: + return tr("Path"); + } + } + else if(role == Qt::ToolTipRole) + { + switch(column) + { + case Name: + return tr("The name of the version."); + case ParentVersion: + return tr("Minecraft version"); //FIXME: this should come from metadata + case Branch: + return tr("The version's branch"); + case Type: + return tr("The version's type"); + case Architecture: + return tr("CPU Architecture"); + case Path: + return tr("Filesystem path to this version"); + } + } + return QVariant(); +} + +QVariant VersionProxyModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + { + return QVariant(); + } + auto column = m_columns[index.column()]; + auto parentIndex = mapToSource(index); + switch(role) + { + case Qt::DisplayRole: + { + switch(column) + { + case Name: + return sourceModel()->data(parentIndex, BaseVersionList::VersionRole); + case ParentVersion: + return sourceModel()->data(parentIndex, BaseVersionList::ParentGameVersionRole); + case Branch: + return sourceModel()->data(parentIndex, BaseVersionList::BranchRole); + case Type: + return sourceModel()->data(parentIndex, BaseVersionList::TypeRole); + case Architecture: + return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole); + case Path: + return sourceModel()->data(parentIndex, BaseVersionList::PathRole); + default: + return QVariant(); + } + } + case Qt::ToolTipRole: + { + switch(column) + { + case Name: + { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) + { + return tr("Recommended"); + } + else if(index.row() == 0) + { + return tr("Latest"); + } + } + default: + { + return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); + } + } + } + case Qt::DecorationRole: + { + switch(column) + { + case Name: + { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) + { + return MMC->getThemedIcon("star"); + } + else if(index.row() == 0) + { + return MMC->getThemedIcon("bug"); + } + auto pixmap = QPixmapCache::find("placeholder"); + if(!pixmap) + { + QPixmap px(16,16); + px.fill(Qt::transparent); + QPixmapCache::insert("placeholder", px); + return px; + } + return *pixmap; + } + default: + { + return QVariant(); + } + } + } + default: + { + if(roles.contains((BaseVersionList::ModelRoles)role)) + { + return sourceModel()->data(parentIndex, role); + } + return QVariant(); + } + } +}; + +QModelIndex VersionProxyModel::parent(const QModelIndex &child) const +{ + return QModelIndex(); +} + +QModelIndex VersionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + if(sourceIndex.isValid()) + { + return index(sourceIndex.row(), 0); + } + return QModelIndex(); +} + +QModelIndex VersionProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if(proxyIndex.isValid()) + { + return sourceModel()->index(proxyIndex.row(), 0); + } + return QModelIndex(); +} + +QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + // no trees here... shoo + if(parent.isValid()) + { + return QModelIndex(); + } + if(row < 0 || row >= sourceModel()->rowCount()) + return QModelIndex(); + if(column < 0 || column >= columnCount()) + return QModelIndex(); + return QAbstractItemModel::createIndex(row, column); +} + +int VersionProxyModel::columnCount(const QModelIndex &parent) const +{ + return m_columns.size(); +} + +int VersionProxyModel::rowCount(const QModelIndex &parent) const +{ + if(sourceModel()) + { + return sourceModel()->rowCount(); + } + return 0; +} + +void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left, + const QModelIndex &source_bottom_right) +{ + if(source_top_left.parent() != source_bottom_right.parent()) + return; + + // whole row is getting changed + auto topLeft = createIndex(source_top_left.row(), 0); + auto bottomRight = createIndex(source_bottom_right.row(), columnCount() - 1); + emit dataChanged(topLeft, bottomRight); +} + +void VersionProxyModel::setSourceModel(BaseVersionList *replacing) +{ + beginResetModel(); + + if(!replacing) + { + m_columns.clear(); + roles.clear(); + filterModel->setSourceModel(replacing); + return; + } + + roles = replacing->providesRoles(); + if(roles.contains(BaseVersionList::VersionRole)) + { + m_columns.push_back(Name); + } + /* + if(roles.contains(BaseVersionList::ParentGameVersionRole)) + { + m_columns.push_back(ParentVersion); + } + */ + if(roles.contains(BaseVersionList::ArchitectureRole)) + { + m_columns.push_back(Architecture); + } + if(roles.contains(BaseVersionList::PathRole)) + { + m_columns.push_back(Path); + } + if(roles.contains(BaseVersionList::BranchRole)) + { + m_columns.push_back(Branch); + } + if(roles.contains(BaseVersionList::TypeRole)) + { + m_columns.push_back(Type); + } + filterModel->setSourceModel(replacing); + + endResetModel(); +} + +QModelIndex VersionProxyModel::getRecommended() const +{ + if(!roles.contains(BaseVersionList::RecommendedRole)) + { + return index(0, 0); + } + int recommended = 0; + for (int i = 0; i < rowCount(); i++) + { + auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole); + if (value.toBool()) + { + recommended = i; + } + } + return index(recommended, 0); +} + +void VersionProxyModel::clearFilters() +{ + m_filters.clear(); + filterModel->invalidate(); +} + +void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, const QString &filter, const bool exact) +{ + Filter f; + f.string = filter; + f.exact = exact; + m_filters[column] = f; + filterModel->invalidate(); +} + +const VersionProxyModel::FilterMap &VersionProxyModel::filters() const +{ + return m_filters; +} + +void VersionProxyModel::sourceAboutToBeReset() +{ + beginResetModel(); +} + +void VersionProxyModel::sourceReset() +{ + endResetModel(); +} + +#include "VersionProxyModel.moc" diff --git a/application/VersionProxyModel.h b/application/VersionProxyModel.h new file mode 100644 index 00000000..456268f0 --- /dev/null +++ b/application/VersionProxyModel.h @@ -0,0 +1,56 @@ +#pragma once +#include +#include "BaseVersionList.h" + +class VersionFilterModel; + +class VersionProxyModel: public QAbstractProxyModel +{ + Q_OBJECT +public: + struct Filter + { + QString string; + bool exact = false; + }; + enum Column + { + Name, + ParentVersion, + Branch, + Type, + Architecture, + Path + }; + typedef QHash FilterMap; + +public: + VersionProxyModel ( QObject* parent = 0 ); + virtual ~VersionProxyModel() {}; + + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + virtual QModelIndex parent(const QModelIndex &child) const override; + void setSourceModel(BaseVersionList *sourceModel); + + const FilterMap &filters() const; + void setFilter(const BaseVersionList::ModelRoles column, const QString &filter, const bool exact); + void clearFilters(); + QModelIndex getRecommended() const; +private slots: + + void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right); + void sourceAboutToBeReset(); + void sourceReset(); + +private: + QList m_columns; + FilterMap m_filters; + BaseVersionList::RoleList roles; + VersionFilterModel * filterModel; +}; diff --git a/application/dialogs/VersionSelectDialog.cpp b/application/dialogs/VersionSelectDialog.cpp index d1be4ad0..354857e7 100644 --- a/application/dialogs/VersionSelectDialog.cpp +++ b/application/dialogs/VersionSelectDialog.cpp @@ -26,66 +26,8 @@ #include #include #include - -class VersionSelectProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - VersionSelectProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) - { - } - - struct Filter - { - QString string; - bool exact = false; - }; - - QHash filters() const - { - return m_filters; - } - void setFilter(const int column, const QString &filter, const bool exact) - { - Filter f; - f.string = filter; - f.exact = exact; - m_filters[column] = f; - invalidateFilter(); - } - void clearFilters() - { - m_filters.clear(); - invalidateFilter(); - } - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const - { - for (auto it = m_filters.begin(); it != m_filters.end(); ++it) - { - const QString version = - sourceModel()->index(source_row, it.key()).data().toString(); - - if (it.value().exact) - { - if (version != it.value().string) - { - return false; - } - continue; - } - - if (!Util::versionIsInInterval(version, it.value().string)) - { - return false; - } - } - return true; - } - - QHash m_filters; -}; +#include "MultiMC.h" +#include VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) @@ -98,7 +40,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_vlist = vlist; - m_proxyModel = new VersionSelectProxyModel(this); + m_proxyModel = new VersionProxyModel(this); m_proxyModel->setSourceModel(vlist); ui->listView->setModel(m_proxyModel); @@ -135,7 +77,12 @@ int VersionSelectDialog::exec() { loadList(); } - m_proxyModel->invalidate(); + auto idx = m_proxyModel->getRecommended(); + if(idx.isValid()) + { + ui->listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + ui->listView->scrollTo(idx, QAbstractItemView::PositionAtCenter); + } return QDialog::exec(); } @@ -164,14 +111,14 @@ void VersionSelectDialog::on_refreshButton_clicked() loadList(); } -void VersionSelectDialog::setExactFilter(int column, QString filter) +void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(column, filter, true); + m_proxyModel->setFilter(role, filter, true); } -void VersionSelectDialog::setFuzzyFilter(int column, QString filter) +void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(column, filter, false); + m_proxyModel->setFilter(role, filter, false); } #include "VersionSelectDialog.moc" diff --git a/application/dialogs/VersionSelectDialog.h b/application/dialogs/VersionSelectDialog.h index 69e52fe6..23bd158a 100644 --- a/application/dialogs/VersionSelectDialog.h +++ b/application/dialogs/VersionSelectDialog.h @@ -18,16 +18,14 @@ #include #include -#include "BaseVersion.h" - -class BaseVersionList; +#include "BaseVersionList.h" namespace Ui { class VersionSelectDialog; } -class VersionSelectProxyModel; +class VersionProxyModel; class VersionSelectDialog : public QDialog { @@ -45,8 +43,8 @@ public: BaseVersionPtr selectedVersion() const; - void setFuzzyFilter(int column, QString filter); - void setExactFilter(int column, QString filter); + void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactFilter(BaseVersionList::ModelRoles role, QString filter); void setEmptyString(QString emptyString); void setResizeOn(int column); void setUseLatest(const bool useLatest); @@ -60,7 +58,7 @@ private: BaseVersionList *m_vlist; - VersionSelectProxyModel *m_proxyModel; + VersionProxyModel *m_proxyModel; int resizeOnColumn = 0; }; diff --git a/application/pages/VersionPage.cpp b/application/pages/VersionPage.cpp index 6b220017..056bb958 100644 --- a/application/pages/VersionPage.cpp +++ b/application/pages/VersionPage.cpp @@ -269,7 +269,7 @@ void VersionPage::on_changeMCVersionBtn_clicked() void VersionPage::on_forgeBtn_clicked() { VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); - vselect.setExactFilter(1, m_inst->currentVersionId()); + vselect.setExactFilter(BaseVersionList::ParentGameVersionRole, m_inst->currentVersionId()); vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_inst->currentVersionId()); if (vselect.exec() && vselect.selectedVersion()) @@ -284,7 +284,7 @@ void VersionPage::on_liteloaderBtn_clicked() { VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"), this); - vselect.setExactFilter(1, m_inst->currentVersionId()); + vselect.setExactFilter(BaseVersionList::ParentGameVersionRole, m_inst->currentVersionId()); vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_inst->currentVersionId()); if (vselect.exec() && vselect.selectedVersion()) diff --git a/application/pages/global/JavaPage.cpp b/application/pages/global/JavaPage.cpp index ab02b3a3..1b480376 100644 --- a/application/pages/global/JavaPage.cpp +++ b/application/pages/global/JavaPage.cpp @@ -97,7 +97,6 @@ void JavaPage::on_javaDetectBtn_clicked() JavaVersionPtr java; VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true); - vselect.setResizeOn(2); vselect.exec(); if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) diff --git a/application/resources/multimc/16x16/star.png b/application/resources/multimc/16x16/star.png new file mode 100644 index 00000000..4963e6ec Binary files /dev/null and b/application/resources/multimc/16x16/star.png differ diff --git a/application/resources/multimc/24x24/star.png b/application/resources/multimc/24x24/star.png new file mode 100644 index 00000000..7f16618a Binary files /dev/null and b/application/resources/multimc/24x24/star.png differ diff --git a/application/resources/multimc/32x32/star.png b/application/resources/multimc/32x32/star.png new file mode 100644 index 00000000..b271f0d1 Binary files /dev/null and b/application/resources/multimc/32x32/star.png differ diff --git a/application/resources/multimc/48x48/star.png b/application/resources/multimc/48x48/star.png new file mode 100644 index 00000000..d9468e7e Binary files /dev/null and b/application/resources/multimc/48x48/star.png differ diff --git a/application/resources/multimc/64x64/star.png b/application/resources/multimc/64x64/star.png new file mode 100644 index 00000000..4ed5d978 Binary files /dev/null and b/application/resources/multimc/64x64/star.png differ diff --git a/application/resources/multimc/multimc.qrc b/application/resources/multimc/multimc.qrc index d02d0e0e..4ced586a 100644 --- a/application/resources/multimc/multimc.qrc +++ b/application/resources/multimc/multimc.qrc @@ -17,6 +17,13 @@ scalable/java.svg + + 16x16/star.png + 24x24/star.png + 32x32/star.png + 48x48/star.png + 64x64/star.png + 16x16/minecraft.png 24x24/minecraft.png diff --git a/logic/BaseVersionList.cpp b/logic/BaseVersionList.cpp index 7752b14c..fe17a905 100644 --- a/logic/BaseVersionList.cpp +++ b/logic/BaseVersionList.cpp @@ -50,63 +50,26 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const switch (role) { - case Qt::DisplayRole: - switch (index.column()) - { - case NameColumn: - return version->name(); - - case TypeColumn: - return version->typeString(); - - default: - return QVariant(); - } - - case Qt::ToolTipRole: - return version->descriptor(); - case VersionPointerRole: return qVariantFromValue(version); + case VersionRole: + return version->name(); + + case VersionIdRole: + return version->descriptor(); + + case TypeRole: + return version->typeString(); + default: return QVariant(); } } -QVariant BaseVersionList::headerData(int section, Qt::Orientation orientation, int role) const +BaseVersionList::RoleList BaseVersionList::providesRoles() { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case NameColumn: - return tr("Name"); - - case TypeColumn: - return tr("Type"); - - default: - return QVariant(); - } - - case Qt::ToolTipRole: - switch (section) - { - case NameColumn: - return tr("The name of the version."); - - case TypeColumn: - return tr("The version's type."); - - default: - return QVariant(); - } - - default: - return QVariant(); - } + return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole}; } int BaseVersionList::rowCount(const QModelIndex &parent) const @@ -117,5 +80,5 @@ int BaseVersionList::rowCount(const QModelIndex &parent) const int BaseVersionList::columnCount(const QModelIndex &parent) const { - return 2; + return 1; } diff --git a/logic/BaseVersionList.h b/logic/BaseVersionList.h index 584d6ca7..6089c31c 100644 --- a/logic/BaseVersionList.h +++ b/logic/BaseVersionList.h @@ -41,20 +41,17 @@ class BaseVersionList : public QAbstractListModel public: enum ModelRoles { - VersionPointerRole = 0x34B1CB48 - }; - - enum VListColumns - { - // First column - Name - NameColumn = 0, - - // Second column - Type - TypeColumn, - - // Third column - Timestamp - TimeColumn + VersionPointerRole = Qt::UserRole, + VersionRole, + VersionIdRole, + ParentGameVersionRole, + RecommendedRole, + TypeRole, + BranchRole, + PathRole, + ArchitectureRole }; + typedef QList RoleList; explicit BaseVersionList(QObject *parent = 0); @@ -78,10 +75,12 @@ public: //////// List Model Functions //////// virtual QVariant data(const QModelIndex &index, int role) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; virtual int rowCount(const QModelIndex &parent) const; virtual int columnCount(const QModelIndex &parent) const; + //! which roles are provided by this version list? + virtual RoleList providesRoles(); + /*! * \brief Finds a version by its descriptor. * \param The descriptor of the version to find. diff --git a/logic/forge/ForgeVersionList.cpp b/logic/forge/ForgeVersionList.cpp index 56ffad11..b2320a6d 100644 --- a/logic/forge/ForgeVersionList.cpp +++ b/logic/forge/ForgeVersionList.cpp @@ -51,7 +51,7 @@ int ForgeVersionList::count() const int ForgeVersionList::columnCount(const QModelIndex &parent) const { - return 3; + return 1; } QVariant ForgeVersionList::data(const QModelIndex &index, int role) const @@ -65,71 +65,32 @@ QVariant ForgeVersionList::data(const QModelIndex &index, int role) const auto version = std::dynamic_pointer_cast(m_vlist[index.row()]); switch (role) { - case Qt::DisplayRole: - switch (index.column()) - { - case 0: - return version->name(); - - case 1: - return version->mcver_sane; - - case 2: - return version->typeString(); - default: - return QVariant(); - } - - case Qt::ToolTipRole: - return version->descriptor(); - case VersionPointerRole: return qVariantFromValue(m_vlist[index.row()]); + case VersionRole: + return version->name(); + + case VersionIdRole: + return version->descriptor(); + + case ParentGameVersionRole: + return version->mcver_sane; + + case RecommendedRole: + return version->is_recommended; + + case BranchRole: + return version->branch; + default: return QVariant(); } } -QVariant ForgeVersionList::headerData(int section, Qt::Orientation orientation, int role) const +QList ForgeVersionList::providesRoles() { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case 0: - return tr("Version"); - - case 1: - return tr("Minecraft"); - - case 2: - return tr("Type"); - - default: - return QVariant(); - } - - case Qt::ToolTipRole: - switch (section) - { - case 0: - return tr("The name of the version."); - - case 1: - return tr("Minecraft version"); - - case 2: - return tr("The version's type."); - - default: - return QVariant(); - } - - default: - return QVariant(); - } + return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, RecommendedRole, BranchRole}; } BaseVersionPtr ForgeVersionList::getLatestStable() const @@ -296,6 +257,7 @@ bool ForgeListLoadTask::parseForgeList(QList &out) bool ForgeListLoadTask::parseForgeGradleList(QList &out) { + QMap> lookup; QByteArray data; { auto dlJob = gradleListDownload; @@ -402,6 +364,29 @@ bool ForgeListLoadTask::parseForgeGradleList(QList &out) fVersion->installer_filename = installer_filename; fVersion->type = ForgeVersion::Gradle; out.append(fVersion); + lookup[fVersion->m_buildnr] = fVersion; + } + QJsonObject promos = root.value("promos").toObject(); + for (auto it = promos.begin(); it != promos.end(); ++it) + { + QString key = it.key(); + int build = it.value().toInt(); + QRegularExpression regexp("^(?[0-9]+(.[0-9]+)*)-(?