From 8321187a20eec9871f327aa23f421e79dcfdd409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 12 Mar 2017 16:00:06 +0100 Subject: NOISSUE fix downloading of metadata files --- api/logic/meta/Util.cpp | 2 +- api/logic/meta/VersionList.cpp | 2 +- api/logic/meta/format/Format.cpp | 28 ++-- api/logic/meta/format/FormatV1.cpp | 119 +++++++------- application/CMakeLists.txt | 6 +- application/MultiMC.cpp | 2 + application/VersionProxyModel.cpp | 2 +- application/pages/global/MetadataPage.cpp | 242 ---------------------------- application/pages/global/MetadataPage.h | 57 ------- application/pages/global/MetadataPage.ui | 252 ------------------------------ application/pages/global/PackagesPage.cpp | 242 ++++++++++++++++++++++++++++ application/pages/global/PackagesPage.h | 57 +++++++ application/pages/global/PackagesPage.ui | 252 ++++++++++++++++++++++++++++++ 13 files changed, 640 insertions(+), 623 deletions(-) delete mode 100644 application/pages/global/MetadataPage.cpp delete mode 100644 application/pages/global/MetadataPage.h delete mode 100644 application/pages/global/MetadataPage.ui create mode 100644 application/pages/global/PackagesPage.cpp create mode 100644 application/pages/global/PackagesPage.h create mode 100644 application/pages/global/PackagesPage.ui diff --git a/api/logic/meta/Util.cpp b/api/logic/meta/Util.cpp index 2ccbe5c4..76941f83 100644 --- a/api/logic/meta/Util.cpp +++ b/api/logic/meta/Util.cpp @@ -34,7 +34,7 @@ QUrl indexUrl() QUrl versionListUrl(const QString &uid) { - return rootUrl().resolved(uid + ".json"); + return rootUrl().resolved(uid + "/index.json"); } QUrl versionUrl(const QString &uid, const QString &version) diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp index 11e20c12..aab3e0f7 100644 --- a/api/logic/meta/VersionList.cpp +++ b/api/logic/meta/VersionList.cpp @@ -178,7 +178,7 @@ std::unique_ptr VersionList::localUpdateTask() QString VersionList::localFilename() const { - return m_uid + ".json"; + return m_uid + "/index.json"; } QJsonObject VersionList::serialized() const { diff --git a/api/logic/meta/format/Format.cpp b/api/logic/meta/format/Format.cpp index a3f9f730..e0fddb0b 100644 --- a/api/logic/meta/format/Format.cpp +++ b/api/logic/meta/format/Format.cpp @@ -39,46 +39,52 @@ void Format::parseIndex(const QJsonObject &obj, Index *ptr) { const int version = formatVersion(obj); switch (version) { - case 1: + case 0: ptr->merge(FormatV1().parseIndexInternal(obj)); break; default: throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version)); } } -void Format::parseVersion(const QJsonObject &obj, Version *ptr) + +void Format::parseVersionList(const QJsonObject &obj, VersionList *ptr) { const int version = formatVersion(obj); switch (version) { - case 1: - ptr->merge(FormatV1().parseVersionInternal(obj)); + case 0: + ptr->merge(FormatV1().parseVersionListInternal(obj)); break; default: throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version)); } } -void Format::parseVersionList(const QJsonObject &obj, VersionList *ptr) + +void Format::parseVersion(const QJsonObject &obj, Version *ptr) { const int version = formatVersion(obj); switch (version) { - case 10: - ptr->merge(FormatV1().parseVersionListInternal(obj)); + case 0: + ptr->merge(FormatV1().parseVersionInternal(obj)); break; default: throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version)); } } + QJsonObject Format::serializeIndex(const Index *ptr) { return FormatV1().serializeIndexInternal(ptr); } -QJsonObject Format::serializeVersion(const Version *ptr) -{ - return FormatV1().serializeVersionInternal(ptr); -} + QJsonObject Format::serializeVersionList(const VersionList *ptr) { return FormatV1().serializeVersionListInternal(ptr); } + +QJsonObject Format::serializeVersion(const Version *ptr) +{ + return FormatV1().serializeVersionInternal(ptr); +} + } diff --git a/api/logic/meta/format/FormatV1.cpp b/api/logic/meta/format/FormatV1.cpp index 23f57100..ee2c5291 100644 --- a/api/logic/meta/format/FormatV1.cpp +++ b/api/logic/meta/format/FormatV1.cpp @@ -27,6 +27,44 @@ using namespace Json; namespace Meta { + +static const int currentFormatVersion = 0; + +// Index + +BaseEntity::Ptr FormatV1::parseIndexInternal(const QJsonObject &obj) const +{ + const QVector objects = requireIsArrayOf(obj, "packages"); + QVector lists; + lists.reserve(objects.size()); + std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj) + { + VersionListPtr list = std::make_shared(requireString(obj, "uid")); + list->setName(ensureString(obj, "name", QString())); + return list; + }); + return std::make_shared(lists); +} + +QJsonObject FormatV1::serializeIndexInternal(const Index *ptr) const +{ + QJsonArray packages; + for (const VersionListPtr &list : ptr->lists()) + { + QJsonObject out; + out["uid"] = list->uid(); + out["name"] = list->name(); + packages.append(out); + } + QJsonObject out; + out["formatVersion"] = currentFormatVersion; + out["packages"] = packages; + return out; +} + + +// Version + static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) { const QVector requiresRaw = obj.contains("requires") ? requireIsArrayOf(obj, "requires") : QVector(); @@ -40,18 +78,22 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) }); VersionPtr version = std::make_shared(uid, requireString(obj, "version")); - if (obj.value("time").isString()) - { - version->setTime(QDateTime::fromString(requireString(obj, "time"), Qt::ISODate).toMSecsSinceEpoch() / 1000); - } - else - { - version->setTime(requireInteger(obj, "time")); - } + version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000); version->setType(ensureString(obj, "type", QString())); version->setRequires(requires); return version; } + +BaseEntity::Ptr FormatV1::parseVersionInternal(const QJsonObject &obj) const +{ + VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj); + + version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj), + QString("%1/%2.json").arg(version->uid(), version->version()), + obj.contains("order"))); + return version; +} + static void serializeCommonVersion(const Version *version, QJsonObject &obj) { QJsonArray requires; @@ -74,32 +116,25 @@ static void serializeCommonVersion(const Version *version, QJsonObject &obj) obj.insert("version", version->version()); obj.insert("type", version->type()); - obj.insert("time", version->time().toString(Qt::ISODate)); + obj.insert("releaseTime", version->time().toString(Qt::ISODate)); obj.insert("requires", requires); } -BaseEntity::Ptr FormatV1::parseIndexInternal(const QJsonObject &obj) const -{ - const QVector objects = requireIsArrayOf(obj, "index"); - QVector lists; - lists.reserve(objects.size()); - std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj) - { - VersionListPtr list = std::make_shared(requireString(obj, "uid")); - list->setName(ensureString(obj, "name", QString())); - return list; - }); - return std::make_shared(lists); -} -BaseEntity::Ptr FormatV1::parseVersionInternal(const QJsonObject &obj) const +QJsonObject FormatV1::serializeVersionInternal(const Version *ptr) const { - VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj); + QJsonObject obj = OneSixVersionFormat::versionFileToJson(ptr->data(), true).object(); + serializeCommonVersion(ptr, obj); + obj.insert("formatVersion", currentFormatVersion); + obj.insert("uid", ptr->uid()); + // TODO: the name should be looked up in the UI based on the uid + obj.insert("name", ENV.metadataIndex()->getListGuaranteed(ptr->uid())->name()); - version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj), - QString("%1/%2.json").arg(version->uid(), version->version()), - obj.contains("order"))); - return version; + return obj; } + + +// Version list / package + BaseEntity::Ptr FormatV1::parseVersionListInternal(const QJsonObject &obj) const { const QString uid = requireString(obj, "uid"); @@ -116,32 +151,6 @@ BaseEntity::Ptr FormatV1::parseVersionListInternal(const QJsonObject &obj) const return list; } -QJsonObject FormatV1::serializeIndexInternal(const Index *ptr) const -{ - QJsonArray index; - for (const VersionListPtr &list : ptr->lists()) - { - QJsonObject out; - out["uid"] = list->uid(); - out["version"] = list->name(); - index.append(out); - } - QJsonObject out; - out["formatVersion"] = 1; - out["index"] = index; - return out; -} -QJsonObject FormatV1::serializeVersionInternal(const Version *ptr) const -{ - QJsonObject obj = OneSixVersionFormat::versionFileToJson(ptr->data(), true).object(); - serializeCommonVersion(ptr, obj); - obj.insert("formatVersion", 1); - obj.insert("uid", ptr->uid()); - // TODO: the name should be looked up in the UI based on the uid - obj.insert("name", ENV.metadataIndex()->getListGuaranteed(ptr->uid())->name()); - - return obj; -} QJsonObject FormatV1::serializeVersionListInternal(const VersionList *ptr) const { QJsonArray versions; @@ -152,7 +161,7 @@ QJsonObject FormatV1::serializeVersionListInternal(const VersionList *ptr) const versions.append(obj); } QJsonObject out; - out["formatVersion"] = 10; + out["formatVersion"] = currentFormatVersion; out["uid"] = ptr->uid(); out["name"] = ptr->name().isNull() ? QJsonValue() : ptr->name(); out["versions"] = versions; diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 55457b1c..1b6ff3fd 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -184,8 +184,8 @@ SET(MULTIMC_SOURCES pages/global/ProxyPage.h pages/global/PasteEEPage.cpp pages/global/PasteEEPage.h - pages/global/MetadataPage.cpp - pages/global/MetadataPage.h + pages/global/PackagesPage.cpp + pages/global/PackagesPage.h # GUI - dialogs dialogs/AboutDialog.cpp @@ -284,7 +284,7 @@ SET(MULTIMC_UIS pages/global/MultiMCPage.ui pages/global/ProxyPage.ui pages/global/PasteEEPage.ui - pages/global/MetadataPage.ui + pages/global/PackagesPage.ui # Dialogs dialogs/CopyInstanceDialog.ui diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index 081de41c..3a91fb5f 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -10,6 +10,7 @@ #include "pages/global/ExternalToolsPage.h" #include "pages/global/AccountListPage.h" #include "pages/global/PasteEEPage.h" +#include "pages/global/PackagesPage.h" #include "themes/ITheme.h" #include "themes/SystemTheme.h" @@ -842,6 +843,7 @@ void MultiMC::initGlobalSettings() m_globalSettingsProvider->addPage(); m_globalSettingsProvider->addPage(); m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); m_globalSettingsProvider->addPage(); m_globalSettingsProvider->addPage(); m_globalSettingsProvider->addPage(); diff --git a/application/VersionProxyModel.cpp b/application/VersionProxyModel.cpp index 22df7e09..50b94d9e 100644 --- a/application/VersionProxyModel.cpp +++ b/application/VersionProxyModel.cpp @@ -313,9 +313,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) auto replacing = dynamic_cast(replacingRaw); beginResetModel(); + m_columns.clear(); if(!replacing) { - m_columns.clear(); roles.clear(); filterModel->setSourceModel(replacing); return; diff --git a/application/pages/global/MetadataPage.cpp b/application/pages/global/MetadataPage.cpp deleted file mode 100644 index 4e355997..00000000 --- a/application/pages/global/MetadataPage.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* Copyright 2015-2017 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. - */ - -#include "MetadataPage.h" -#include "ui_MetadataPage.h" - -#include -#include -#include - -#include "dialogs/ProgressDialog.h" -#include "VersionProxyModel.h" - -#include "meta/Index.h" -#include "meta/VersionList.h" -#include "meta/Version.h" -#include "Env.h" -#include "MultiMC.h" - -using namespace Meta; - -static QString formatRequires(const VersionPtr &version) -{ - QStringList lines; - for (const Reference &ref : version->requires()) - { - const QString readable = ENV.metadataIndex()->hasUid(ref.uid()) ? ENV.metadataIndex()->getList(ref.uid())->humanReadable() : ref.uid(); - if (ref.version().isEmpty()) - { - lines.append(readable); - } - else - { - lines.append(QString("%1 (%2)").arg(readable, ref.version())); - } - } - return lines.join('\n'); -} - -MetadataPage::MetadataPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::MetadataPage) -{ - ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); - - m_fileProxy = new QSortFilterProxyModel(this); - m_fileProxy->setSortRole(Qt::DisplayRole); - m_fileProxy->setSortCaseSensitivity(Qt::CaseInsensitive); - m_fileProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_fileProxy->setFilterRole(Qt::DisplayRole); - m_fileProxy->setFilterKeyColumn(0); - m_fileProxy->sort(0); - m_fileProxy->setSourceModel(ENV.metadataIndex().get()); - ui->indexView->setModel(m_fileProxy); - - m_filterProxy = new QSortFilterProxyModel(this); - m_filterProxy->setSortRole(VersionList::SortRole); - m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_filterProxy->setFilterRole(Qt::DisplayRole); - m_filterProxy->setFilterKeyColumn(0); - m_filterProxy->sort(0, Qt::DescendingOrder); - ui->versionsView->setModel(m_filterProxy); - - m_versionProxy = new VersionProxyModel(this); - m_filterProxy->setSourceModel(m_versionProxy); - - connect(ui->indexView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MetadataPage::updateCurrentVersionList); - connect(ui->versionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MetadataPage::updateVersion); - connect(m_filterProxy, &QSortFilterProxyModel::dataChanged, this, &MetadataPage::versionListDataChanged); - - updateCurrentVersionList(QModelIndex()); - updateVersion(); -} - -MetadataPage::~MetadataPage() -{ - delete ui; -} - -QIcon MetadataPage::icon() const -{ - return MMC->getThemedIcon("looney"); -} - -void MetadataPage::on_refreshIndexBtn_clicked() -{ - ProgressDialog(this).execWithTask(ENV.metadataIndex()->remoteUpdateTask()); -} -void MetadataPage::on_refreshFileBtn_clicked() -{ - VersionListPtr list = ui->indexView->currentIndex().data(Index::ListPtrRole).value(); - if (!list) - { - return; - } - ProgressDialog(this).execWithTask(list->remoteUpdateTask()); -} -void MetadataPage::on_refreshVersionBtn_clicked() -{ - VersionPtr version = ui->versionsView->currentIndex().data(VersionList::VersionPtrRole).value(); - if (!version) - { - return; - } - ProgressDialog(this).execWithTask(version->remoteUpdateTask()); -} - -void MetadataPage::on_fileSearchEdit_textChanged(const QString &search) -{ - if (search.isEmpty()) - { - m_fileProxy->setFilterFixedString(QString()); - } - else - { - QStringList parts = search.split(' '); - std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape); - m_fileProxy->setFilterRegExp(".*" + parts.join(".*") + ".*"); - } -} -void MetadataPage::on_versionSearchEdit_textChanged(const QString &search) -{ - if (search.isEmpty()) - { - m_filterProxy->setFilterFixedString(QString()); - } - else - { - QStringList parts = search.split(' '); - std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape); - m_filterProxy->setFilterRegExp(".*" + parts.join(".*") + ".*"); - } -} - -void MetadataPage::updateCurrentVersionList(const QModelIndex &index) -{ - if (index.isValid()) - { - VersionListPtr list = index.data(Index::ListPtrRole).value(); - ui->versionsBox->setEnabled(true); - ui->refreshFileBtn->setEnabled(true); - ui->fileUidLabel->setEnabled(true); - ui->fileUid->setText(list->uid()); - ui->fileNameLabel->setEnabled(true); - ui->fileName->setText(list->name()); - m_versionProxy->setSourceModel(list.get()); - ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable())); - - if (!list->isLocalLoaded()) - { - std::unique_ptr task = list->localUpdateTask(); - connect(task.get(), &Task::finished, this, [this, list]() - { - if (list->count() == 0 && !list->isRemoteLoaded()) - { - ProgressDialog(this).execWithTask(list->remoteUpdateTask()); - } - }); - ProgressDialog(this).execWithTask(task); - } - } - else - { - ui->versionsBox->setEnabled(false); - ui->refreshFileBtn->setEnabled(false); - ui->fileUidLabel->setEnabled(false); - ui->fileUid->clear(); - ui->fileNameLabel->setEnabled(false); - ui->fileName->clear(); - m_versionProxy->setSourceModel(nullptr); - ui->refreshFileBtn->setText(tr("Refresh ___")); - } -} - -void MetadataPage::versionListDataChanged(const QModelIndex &tl, const QModelIndex &br) -{ - if (QItemSelection(tl, br).contains(ui->versionsView->currentIndex())) - { - updateVersion(); - } -} - -void MetadataPage::updateVersion() -{ - VersionPtr version = std::dynamic_pointer_cast( - ui->versionsView->currentIndex().data(VersionList::VersionPointerRole).value()); - if (version) - { - ui->refreshVersionBtn->setEnabled(true); - ui->versionVersionLabel->setEnabled(true); - ui->versionVersion->setText(version->version()); - ui->versionTimeLabel->setEnabled(true); - ui->versionTime->setText(version->time().toString("yyyy-MM-dd HH:mm")); - ui->versionTypeLabel->setEnabled(true); - ui->versionType->setText(version->type()); - ui->versionRequiresLabel->setEnabled(true); - ui->versionRequires->setText(formatRequires(version)); - ui->refreshVersionBtn->setText(tr("Refresh %1").arg(version->version())); - } - else - { - ui->refreshVersionBtn->setEnabled(false); - ui->versionVersionLabel->setEnabled(false); - ui->versionVersion->clear(); - ui->versionTimeLabel->setEnabled(false); - ui->versionTime->clear(); - ui->versionTypeLabel->setEnabled(false); - ui->versionType->clear(); - ui->versionRequiresLabel->setEnabled(false); - ui->versionRequires->clear(); - ui->refreshVersionBtn->setText(tr("Refresh ___")); - } -} - -void MetadataPage::opened() -{ - if (!ENV.metadataIndex()->isLocalLoaded()) - { - std::unique_ptr task = ENV.metadataIndex()->localUpdateTask(); - connect(task.get(), &Task::finished, this, [this]() - { - if (!ENV.metadataIndex()->isRemoteLoaded()) - { - ProgressDialog(this).execWithTask(ENV.metadataIndex()->remoteUpdateTask()); - } - }); - ProgressDialog(this).execWithTask(task); - } -} diff --git a/application/pages/global/MetadataPage.h b/application/pages/global/MetadataPage.h deleted file mode 100644 index f75b4952..00000000 --- a/application/pages/global/MetadataPage.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2015-2017 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 - -#include "pages/BasePage.h" - -namespace Ui { -class MetadataPage; -} - -class QSortFilterProxyModel; -class VersionProxyModel; - -class MetadataPage : public QWidget, public BasePage -{ - Q_OBJECT -public: - explicit MetadataPage(QWidget *parent = 0); - ~MetadataPage(); - - QString id() const override { return "metadata-global"; } - QString displayName() const override { return tr("Metadata"); } - QIcon icon() const override; - void opened() override; - -private slots: - void on_refreshIndexBtn_clicked(); - void on_refreshFileBtn_clicked(); - void on_refreshVersionBtn_clicked(); - void on_fileSearchEdit_textChanged(const QString &search); - void on_versionSearchEdit_textChanged(const QString &search); - void updateCurrentVersionList(const QModelIndex &index); - void versionListDataChanged(const QModelIndex &tl, const QModelIndex &br); - -private: - Ui::MetadataPage *ui; - QSortFilterProxyModel *m_fileProxy; - QSortFilterProxyModel *m_filterProxy; - VersionProxyModel *m_versionProxy; - - void updateVersion(); -}; diff --git a/application/pages/global/MetadataPage.ui b/application/pages/global/MetadataPage.ui deleted file mode 100644 index 0bd33f32..00000000 --- a/application/pages/global/MetadataPage.ui +++ /dev/null @@ -1,252 +0,0 @@ - - - MetadataPage - - - - 0 - 0 - 640 - 480 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - Tab 1 - - - - - - Versions - - - - - - Search... - - - true - - - - - - - true - - - false - - - - - - - - - Refresh ___ - - - - - - - - - - - Version: - - - - - - - - - - - - - - Time: - - - - - - - - - - - - - - Type: - - - - - - - - - - - - - - Dependencies: - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Resources - - - - - - Search... - - - true - - - - - - - true - - - false - - - - - - - - - Refresh ___ - - - - - - - - - - - UID: - - - - - - - - - - - - - - Name: - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Refresh Index - - - - - - - - - - - - diff --git a/application/pages/global/PackagesPage.cpp b/application/pages/global/PackagesPage.cpp new file mode 100644 index 00000000..52efaf9a --- /dev/null +++ b/application/pages/global/PackagesPage.cpp @@ -0,0 +1,242 @@ +/* Copyright 2015-2017 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. + */ + +#include "PackagesPage.h" +#include "ui_PackagesPage.h" + +#include +#include +#include + +#include "dialogs/ProgressDialog.h" +#include "VersionProxyModel.h" + +#include "meta/Index.h" +#include "meta/VersionList.h" +#include "meta/Version.h" +#include "Env.h" +#include "MultiMC.h" + +using namespace Meta; + +static QString formatRequires(const VersionPtr &version) +{ + QStringList lines; + for (const Reference &ref : version->requires()) + { + const QString readable = ENV.metadataIndex()->hasUid(ref.uid()) ? ENV.metadataIndex()->getList(ref.uid())->humanReadable() : ref.uid(); + if (ref.version().isEmpty()) + { + lines.append(readable); + } + else + { + lines.append(QString("%1 (%2)").arg(readable, ref.version())); + } + } + return lines.join('\n'); +} + +PackagesPage::PackagesPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::PackagesPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + + m_fileProxy = new QSortFilterProxyModel(this); + m_fileProxy->setSortRole(Qt::DisplayRole); + m_fileProxy->setSortCaseSensitivity(Qt::CaseInsensitive); + m_fileProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_fileProxy->setFilterRole(Qt::DisplayRole); + m_fileProxy->setFilterKeyColumn(0); + m_fileProxy->sort(0); + m_fileProxy->setSourceModel(ENV.metadataIndex().get()); + ui->indexView->setModel(m_fileProxy); + + m_filterProxy = new QSortFilterProxyModel(this); + m_filterProxy->setSortRole(VersionList::SortRole); + m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_filterProxy->setFilterRole(Qt::DisplayRole); + m_filterProxy->setFilterKeyColumn(0); + m_filterProxy->sort(0, Qt::DescendingOrder); + ui->versionsView->setModel(m_filterProxy); + + m_versionProxy = new VersionProxyModel(this); + m_filterProxy->setSourceModel(m_versionProxy); + + connect(ui->indexView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateCurrentVersionList); + connect(ui->versionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateVersion); + connect(m_filterProxy, &QSortFilterProxyModel::dataChanged, this, &PackagesPage::versionListDataChanged); + + updateCurrentVersionList(QModelIndex()); + updateVersion(); +} + +PackagesPage::~PackagesPage() +{ + delete ui; +} + +QIcon PackagesPage::icon() const +{ + return MMC->getThemedIcon("packages"); +} + +void PackagesPage::on_refreshIndexBtn_clicked() +{ + ProgressDialog(this).execWithTask(ENV.metadataIndex()->remoteUpdateTask()); +} +void PackagesPage::on_refreshFileBtn_clicked() +{ + VersionListPtr list = ui->indexView->currentIndex().data(Index::ListPtrRole).value(); + if (!list) + { + return; + } + ProgressDialog(this).execWithTask(list->remoteUpdateTask()); +} +void PackagesPage::on_refreshVersionBtn_clicked() +{ + VersionPtr version = ui->versionsView->currentIndex().data(VersionList::VersionPtrRole).value(); + if (!version) + { + return; + } + ProgressDialog(this).execWithTask(version->remoteUpdateTask()); +} + +void PackagesPage::on_fileSearchEdit_textChanged(const QString &search) +{ + if (search.isEmpty()) + { + m_fileProxy->setFilterFixedString(QString()); + } + else + { + QStringList parts = search.split(' '); + std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape); + m_fileProxy->setFilterRegExp(".*" + parts.join(".*") + ".*"); + } +} +void PackagesPage::on_versionSearchEdit_textChanged(const QString &search) +{ + if (search.isEmpty()) + { + m_filterProxy->setFilterFixedString(QString()); + } + else + { + QStringList parts = search.split(' '); + std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape); + m_filterProxy->setFilterRegExp(".*" + parts.join(".*") + ".*"); + } +} + +void PackagesPage::updateCurrentVersionList(const QModelIndex &index) +{ + if (index.isValid()) + { + VersionListPtr list = index.data(Index::ListPtrRole).value(); + ui->versionsBox->setEnabled(true); + ui->refreshFileBtn->setEnabled(true); + ui->fileUidLabel->setEnabled(true); + ui->fileUid->setText(list->uid()); + ui->fileNameLabel->setEnabled(true); + ui->fileName->setText(list->name()); + m_versionProxy->setSourceModel(list.get()); + ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable())); + + if (!list->isLocalLoaded()) + { + std::unique_ptr task = list->localUpdateTask(); + connect(task.get(), &Task::finished, this, [this, list]() + { + if (list->count() == 0 && !list->isRemoteLoaded()) + { + ProgressDialog(this).execWithTask(list->remoteUpdateTask()); + } + }); + ProgressDialog(this).execWithTask(task); + } + } + else + { + ui->versionsBox->setEnabled(false); + ui->refreshFileBtn->setEnabled(false); + ui->fileUidLabel->setEnabled(false); + ui->fileUid->clear(); + ui->fileNameLabel->setEnabled(false); + ui->fileName->clear(); + m_versionProxy->setSourceModel(nullptr); + ui->refreshFileBtn->setText(tr("Refresh")); + } +} + +void PackagesPage::versionListDataChanged(const QModelIndex &tl, const QModelIndex &br) +{ + if (QItemSelection(tl, br).contains(ui->versionsView->currentIndex())) + { + updateVersion(); + } +} + +void PackagesPage::updateVersion() +{ + VersionPtr version = std::dynamic_pointer_cast( + ui->versionsView->currentIndex().data(VersionList::VersionPointerRole).value()); + if (version) + { + ui->refreshVersionBtn->setEnabled(true); + ui->versionVersionLabel->setEnabled(true); + ui->versionVersion->setText(version->version()); + ui->versionTimeLabel->setEnabled(true); + ui->versionTime->setText(version->time().toString("yyyy-MM-dd HH:mm")); + ui->versionTypeLabel->setEnabled(true); + ui->versionType->setText(version->type()); + ui->versionRequiresLabel->setEnabled(true); + ui->versionRequires->setText(formatRequires(version)); + ui->refreshVersionBtn->setText(tr("Refresh %1").arg(version->version())); + } + else + { + ui->refreshVersionBtn->setEnabled(false); + ui->versionVersionLabel->setEnabled(false); + ui->versionVersion->clear(); + ui->versionTimeLabel->setEnabled(false); + ui->versionTime->clear(); + ui->versionTypeLabel->setEnabled(false); + ui->versionType->clear(); + ui->versionRequiresLabel->setEnabled(false); + ui->versionRequires->clear(); + ui->refreshVersionBtn->setText(tr("Refresh")); + } +} + +void PackagesPage::opened() +{ + if (!ENV.metadataIndex()->isLocalLoaded()) + { + std::unique_ptr task = ENV.metadataIndex()->localUpdateTask(); + connect(task.get(), &Task::finished, this, [this]() + { + if (!ENV.metadataIndex()->isRemoteLoaded()) + { + ProgressDialog(this).execWithTask(ENV.metadataIndex()->remoteUpdateTask()); + } + }); + ProgressDialog(this).execWithTask(task); + } +} diff --git a/application/pages/global/PackagesPage.h b/application/pages/global/PackagesPage.h new file mode 100644 index 00000000..80c2886d --- /dev/null +++ b/application/pages/global/PackagesPage.h @@ -0,0 +1,57 @@ +/* Copyright 2015-2017 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 + +#include "pages/BasePage.h" + +namespace Ui { +class PackagesPage; +} + +class QSortFilterProxyModel; +class VersionProxyModel; + +class PackagesPage : public QWidget, public BasePage +{ + Q_OBJECT +public: + explicit PackagesPage(QWidget *parent = 0); + ~PackagesPage(); + + QString id() const override { return "packages-global"; } + QString displayName() const override { return tr("Packages"); } + QIcon icon() const override; + void opened() override; + +private slots: + void on_refreshIndexBtn_clicked(); + void on_refreshFileBtn_clicked(); + void on_refreshVersionBtn_clicked(); + void on_fileSearchEdit_textChanged(const QString &search); + void on_versionSearchEdit_textChanged(const QString &search); + void updateCurrentVersionList(const QModelIndex &index); + void versionListDataChanged(const QModelIndex &tl, const QModelIndex &br); + +private: + Ui::PackagesPage *ui; + QSortFilterProxyModel *m_fileProxy; + QSortFilterProxyModel *m_filterProxy; + VersionProxyModel *m_versionProxy; + + void updateVersion(); +}; diff --git a/application/pages/global/PackagesPage.ui b/application/pages/global/PackagesPage.ui new file mode 100644 index 00000000..158bf1b4 --- /dev/null +++ b/application/pages/global/PackagesPage.ui @@ -0,0 +1,252 @@ + + + PackagesPage + + + + 0 + 0 + 636 + 621 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Tab 1 + + + + + + Versions + + + + + + Search... + + + true + + + + + + + true + + + false + + + + + + + + + Refresh + + + + + + + + + + + Version: + + + + + + + + + + + + + + Time: + + + + + + + + + + + + + + Type: + + + + + + + + + + + + + + Dependencies: + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Resources + + + + + + Search... + + + true + + + + + + + true + + + false + + + + + + + + + Refresh + + + + + + + + + + + UID: + + + + + + + + + + + + + + Name: + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Refresh Index + + + + + + + + + + + + -- cgit v1.2.3