diff options
Diffstat (limited to 'launcher')
26 files changed, 236 insertions, 63 deletions
| diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index 06682782..b16a40ba 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -45,7 +45,10 @@ QString InstanceName::name() const  {      if (!m_modified_name.isEmpty())          return modifiedName(); -    return QString("%1 %2").arg(m_original_name, m_original_version); +    if (!m_original_version.isEmpty()) +        return QString("%1 %2").arg(m_original_name, m_original_version); + +    return m_original_name;  }  QString InstanceName::originalName() const diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 6aba268d..e5c66566 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,7 +1,8 @@  // SPDX-License-Identifier: GPL-3.0-only  /* - *  PolyMC - Minecraft Launcher + *  Prism Launcher - Minecraft Launcher   *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>   *   *  This program is free software: you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -54,9 +55,14 @@ public:      bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const      {          const auto &filters = m_parent->filters(); +        const QString &search = m_parent->search(); +        const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + +        if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) +            return false; +          for (auto it = filters.begin(); it != filters.end(); ++it)          { -            auto idx = sourceModel()->index(source_row, 0, source_parent);              auto data = sourceModel()->data(idx, it.key());              auto match = data.toString();              if(!it.value()->accepts(match)) @@ -206,10 +212,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const                                  return tr("Latest");                              }                          } -                        else if(index.row() == 0) -                        { -                            return tr("Latest"); -                        }                      }                  }                  default: @@ -239,10 +241,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const                                  return APPLICATION->getThemedIcon("bug");                              }                          } -                        else if(index.row() == 0) -                        { -                            return APPLICATION->getThemedIcon("bug"); -                        }                          QPixmap pixmap;                          QPixmapCache::find("placeholder", &pixmap);                          if(!pixmap) @@ -431,6 +429,7 @@ QModelIndex VersionProxyModel::getVersion(const QString& version) const  void VersionProxyModel::clearFilters()  {      m_filters.clear(); +    m_search.clear();      filterModel->filterChanged();  } @@ -440,11 +439,21 @@ void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filt      filterModel->filterChanged();  } +void VersionProxyModel::setSearch(const QString &search) { +    m_search = search; +    filterModel->filterChanged(); +} +  const VersionProxyModel::FilterMap &VersionProxyModel::filters() const  {      return m_filters;  } +const QString &VersionProxyModel::search() const +{ +    return m_search; +} +  void VersionProxyModel::sourceAboutToBeReset()  {      beginResetModel(); diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 8991c31b..6434376c 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -38,7 +38,9 @@ public:      virtual void setSourceModel(QAbstractItemModel *sourceModel) override;      const FilterMap &filters() const; +    const QString &search() const;      void setFilter(const BaseVersionList::ModelRoles column, Filter * filter); +    void setSearch(const QString &search);      void clearFilters();      QModelIndex getRecommended() const;      QModelIndex getVersion(const QString & version) const; @@ -59,6 +61,7 @@ private slots:  private:      QList<Column> m_columns;      FilterMap m_filters; +    QString m_search;      BaseVersionList::RoleList roles;      VersionFilterModel * filterModel;      bool hasRecommended = false; diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index b29af857..3407fdf7 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -1,7 +1,8 @@  // SPDX-License-Identifier: GPL-3.0-only  /* - *  PolyMC - Minecraft Launcher + *  Prism Launcher - Minecraft Launcher   *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>   *   *  This program is free software: you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -98,6 +99,8 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const      auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]);      switch (role)      { +        case SortRole: +            return -index.row();          case VersionPointerRole:              return QVariant::fromValue(m_vlist[index.row()]);          case VersionIdRole: diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 2c624a36..f8ed5214 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -149,9 +149,10 @@ void MinecraftInstance::loadSpecificSettings()          // special!          m_settings->registerPassthrough(global_settings->getSetting("JavaTimestamp"), javaOrLocation); -        m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation);          m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation);          m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation); +        m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation); +        m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), javaOrLocation);          // Window Size          auto windowSetting = m_settings->registerSetting("OverrideWindow", false); diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index cb909ae7..d16256b9 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -50,7 +50,7 @@ INIFile::INIFile() {}  bool INIFile::saveFile(QString fileName)  {      if (!contains("ConfigVersion")) -        insert("ConfigVersion", "1.1"); +        insert("ConfigVersion", "1.2");      QSettings _settings_obj{ fileName, QSettings::Format::IniFormat };      _settings_obj.setFallbacksEnabled(false); @@ -97,6 +97,20 @@ QString unescape(QString orig)      }      return out;  } + +QString unquote(QString str) +{ +    if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") && str.startsWith("\"")) { +#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) +        str = str.remove(0, 1); +        str = str.remove(str.size() - 1, 1); +#else +        str = str.removeFirst().removeLast(); +#endif +    } +    return str; +} +  bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map)  {      QTextStream in(device.readAll()); @@ -124,7 +138,7 @@ bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map)          QString key = line.left(eqPos).trimmed();          QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); -        valueStr = unescape(valueStr); +        valueStr = unquote(unescape(valueStr));          QVariant value(valueStr);          map.insert(key, value); @@ -154,7 +168,17 @@ bool INIFile::loadFile(QString fileName)          file.close();          for (auto&& key : map.keys())              insert(key, map.value(key)); -        insert("ConfigVersion", "1.1"); +        insert("ConfigVersion", "1.2"); +    } else if (_settings_obj.value("ConfigVersion").toString() == "1.1") { +        for (auto&& key : _settings_obj.allKeys()) { +            if (auto valueStr = _settings_obj.value(key).toString(); +                (valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && +                valueStr.endsWith("\"") && valueStr.startsWith("\"")) { +                insert(key, unquote(valueStr)); +            } else +                insert(key, _settings_obj.value(key)); +        } +        insert("ConfigVersion", "1.2");      } else          for (auto&& key : _settings_obj.allKeys())              insert(key, _settings_obj.value(key)); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 1addfe21..e04011ca 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1234,6 +1234,12 @@ void MainWindow::on_actionViewInstanceFolder_triggered()      DesktopServices::openDirectory(str);  } +void MainWindow::on_actionViewLauncherRootFolder_triggered() +{ +    const QString dataPath = QDir::currentPath(); +    DesktopServices::openDirectory(dataPath); +} +  void MainWindow::refreshInstances()  {      APPLICATION->instances()->loadList(); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index a0f912df..3bb20c4a 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -113,6 +113,8 @@ private slots:      void on_actionViewInstanceFolder_triggered(); +    void on_actionViewLauncherRootFolder_triggered(); +      void on_actionViewSelectedInstFolder_triggered();      void refreshInstances(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 9e639ab0..f67fb185 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -187,6 +187,7 @@       <bool>true</bool>      </property>      <addaction name="actionViewInstanceFolder"/> +    <addaction name="actionViewLauncherRootFolder"/>      <addaction name="actionViewCentralModsFolder"/>     </widget>     <widget class="QMenu" name="accountsMenu"> @@ -541,6 +542,18 @@      <string>Open the instance folder in a file browser.</string>     </property>    </action> +  <action name="actionViewLauncherRootFolder"> +   <property name="icon"> +    <iconset theme="viewfolder"> +     <normaloff>.</normaloff>.</iconset> +   </property> +   <property name="text"> +    <string>&View Launcher Root Folder</string> +   </property> +   <property name="toolTip"> +    <string>Open the launcher's root folder in a file browser.</string> +   </property> +  </action>    <action name="actionViewCentralModsFolder">     <property name="icon">      <iconset theme="centralmods"> diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index d7880334..5feb70d2 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + *  Prism Launcher - Minecraft Launcher + *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>   * - * 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 + *  This program is free software: you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation, version 3.   * - *     http://www.apache.org/licenses/LICENSE-2.0 + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details.   * - * 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. + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + *      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.   */  #include "VersionSelectDialog.h" @@ -22,15 +42,10 @@  #include <QtWidgets/QVBoxLayout>  #include <QDebug> -#include "ui/dialogs/ProgressDialog.h"  #include "ui/widgets/VersionSelectWidget.h" -#include "ui/dialogs/CustomMessageBox.h"  #include "BaseVersion.h"  #include "BaseVersionList.h" -#include "tasks/Task.h" -#include "Application.h" -#include "VersionProxyModel.h"  VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable)      : QDialog(parent) @@ -40,7 +55,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title,      m_verticalLayout = new QVBoxLayout(this);      m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); -    m_versionWidget = new VersionSelectWidget(parent); +    m_versionWidget = new VersionSelectWidget(true, parent);      m_verticalLayout->addWidget(m_versionWidget);      m_horizontalLayout = new QHBoxLayout(); diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index afd8b292..b7537890 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -6,12 +6,14 @@  #include "minecraft/MinecraftInstance.h"  #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h"  #include <QMessageBox> +#include <algorithm>  namespace ResourceDownload { -ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} +ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {}  /******** Make data requests ********/ @@ -24,7 +26,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()      std::optional<std::list<Version>> versions{}; -    { // Version filter +    {  // Version filter          if (!m_filter->versions.empty())              versions = m_filter->versions;      } @@ -67,4 +69,14 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte      refresh();  } +bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const +{ +    auto allMods = static_cast<MinecraftInstance&>(m_base_instance).loaderModList()->allMods(); +    return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) { +        if (auto meta = mod->metadata(); meta) +            return meta->provider == pack->provider && meta->project_id == pack->addonId; +        return false; +    }); +} +  }  // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 5d4a7785..805d8b9a 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -24,7 +24,7 @@ class ModModel : public ResourceModel {      Q_OBJECT     public: -    ModModel(const BaseInstance&, ResourceAPI* api); +    ModModel(BaseInstance&, ResourceAPI* api);      /* Ask the API for more information */      void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed); @@ -42,9 +42,10 @@ class ModModel : public ResourceModel {     protected:      auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; +    virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override;     protected: -    const BaseInstance& m_base_instance; +    BaseInstance& m_base_instance;      std::shared_ptr<ModFilterWidget::Filter> m_filter = nullptr;  }; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index a5ea1ca9..49405a02 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -77,6 +77,8 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant              return pack->description;          case UserDataTypes::SELECTED:              return pack->isAnyVersionSelected(); +        case UserDataTypes::INSTALLED: +            return this->isPackInstalled(pack);          default:              break;      } @@ -95,6 +97,7 @@ QHash<int, QByteArray> ResourceModel::roleNames() const      roles[UserDataTypes::TITLE] = "title";      roles[UserDataTypes::DESCRIPTION] = "description";      roles[UserDataTypes::SELECTED] = "selected"; +    roles[UserDataTypes::INSTALLED] = "installed";      return roles;  } diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 69e23473..6533d9c6 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -116,6 +116,8 @@ class ResourceModel : public QAbstractListModel {      virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);      virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); +    virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const { return false; } +     protected:      /* Basic search parameters */      enum class SearchState { None, CanFetchMore, ResetRequested, Finished } m_search_state = SearchState::None; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 5961ea02..d9d5ef5b 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -60,6 +60,8 @@ QVariant ListModel::data(const QModelIndex& index, int role) const              return pack.description;          case UserDataTypes::SELECTED:              return false; +        case UserDataTypes::INSTALLED: +            return false;          default:              break;      } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index e3d0bc14..667a52d0 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -11,7 +11,7 @@  namespace ResourceDownload { -FlameModModel::FlameModModel(BaseInstance const& base) : ModModel(base, new FlameAPI) {} +FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {}  void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)  { diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 0252ac40..221c8f7a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -14,7 +14,7 @@ class FlameModModel : public ModModel {      Q_OBJECT     public: -    FlameModModel(const BaseInstance&); +    FlameModModel(BaseInstance&);      ~FlameModModel() override = default;     private: diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 346a00b0..55d287b0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -106,6 +106,8 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian              return pack.description;          case UserDataTypes::SELECTED:              return false; +        case UserDataTypes::INSTALLED: +            return false;          default:              break;      } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index f5d1cc28..7f857485 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -25,7 +25,7 @@  namespace ResourceDownload { -ModrinthModModel::ModrinthModModel(BaseInstance const& base) : ModModel(base, new ModrinthAPI) {} +ModrinthModModel::ModrinthModModel(BaseInstance& base) : ModModel(base, new ModrinthAPI) {}  void ModrinthModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)  { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index b351b19b..66461807 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -30,7 +30,7 @@ class ModrinthModModel : public ModModel {      Q_OBJECT     public: -    ModrinthModModel(const BaseInstance&); +    ModrinthModModel(BaseInstance&);      ~ModrinthModModel() override = default;     private: diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 15994319..c94fdd8d 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -46,7 +46,7 @@ void JavaSettingsWidget::setupUi()      m_verticalLayout = new QVBoxLayout(this);      m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); -    m_versionWidget = new VersionSelectWidget(this); +    m_versionWidget = new VersionSelectWidget(true, this);      m_verticalLayout->addWidget(m_versionWidget);      m_horizontalLayout = new QHBoxLayout(); diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index d1ff9dbc..0085d6b2 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -64,6 +64,17 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o              font.setBold(true);              font.setUnderline(true);          } +        if (index.data(UserDataTypes::INSTALLED).toBool()) { +            auto hRect = opt.rect; +            hRect.setX(hRect.x() + 1); +            hRect.setY(hRect.y() + 1); +            hRect.setHeight(hRect.height() - 2); +            hRect.setWidth(hRect.width() - 2); +            // Set nice font +            font.setItalic(true); +            font.setOverline(true); +            painter->drawRect(hRect); +        }          font.setPointSize(font.pointSize() + 2);          painter->setFont(font); diff --git a/launcher/ui/widgets/ProjectItem.h b/launcher/ui/widgets/ProjectItem.h index f668edf6..196055ea 100644 --- a/launcher/ui/widgets/ProjectItem.h +++ b/launcher/ui/widgets/ProjectItem.h @@ -6,7 +6,8 @@  enum UserDataTypes {      TITLE = 257,        // QString      DESCRIPTION = 258,  // QString -    SELECTED = 259      // bool +    SELECTED = 259,     // bool +    INSTALLED = 260     // bool  };  /** This is an item delegate composed of: diff --git a/launcher/ui/widgets/VersionListView.cpp b/launcher/ui/widgets/VersionListView.cpp index 0e126c65..06e58d22 100644 --- a/launcher/ui/widgets/VersionListView.cpp +++ b/launcher/ui/widgets/VersionListView.cpp @@ -1,7 +1,8 @@  // SPDX-License-Identifier: GPL-3.0-only  /* - *  PolyMC - Minecraft Launcher + *  Prism Launcher - Minecraft Launcher   *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>   *   *  This program is free software: you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -125,14 +126,9 @@ void VersionListView::paintEvent(QPaintEvent *event)  QString VersionListView::currentEmptyString() const  { -    if(m_itemCount) { -        return QString(); -    }      switch(m_emptyMode)      {          default: -        case VersionListView::Empty: -            return QString();          case VersionListView::String:              return m_emptyString;          case VersionListView::ErrorString: diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 404860d9..a956ddb3 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -1,15 +1,20 @@  #include "VersionSelectWidget.h" +#include <QApplication> +#include <QEvent> +#include <QHeaderView> +#include <QKeyEvent>  #include <QProgressBar>  #include <QVBoxLayout> -#include <QHeaderView>  #include "VersionProxyModel.h"  #include "ui/dialogs/CustomMessageBox.h" -VersionSelectWidget::VersionSelectWidget(QWidget* parent) -    : QWidget(parent) +VersionSelectWidget::VersionSelectWidget(QWidget* parent) : VersionSelectWidget(false, parent) {} + +VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) +    : QWidget(parent), focusSearch(focusSearch)  {      setObjectName(QStringLiteral("VersionSelectWidget"));      verticalLayout = new QVBoxLayout(this); @@ -30,6 +35,21 @@ VersionSelectWidget::VersionSelectWidget(QWidget* parent)      listView->setModel(m_proxyModel);      verticalLayout->addWidget(listView); +    search = new QLineEdit(this); +    search->setPlaceholderText(tr("Search")); +    search->setClearButtonEnabled(true); +    verticalLayout->addWidget(search); +    connect(search, &QLineEdit::textEdited, [this](const QString& value) { +        m_proxyModel->setSearch(value); +        if (!value.isEmpty() || !listView->selectionModel()->hasSelection()) { +            const QModelIndex first = listView->model()->index(0, 0); +            listView->selectionModel()->setCurrentIndex(first, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +            listView->scrollToTop(); +        } else +            listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter); +    }); +    search->installEventFilter(this); +      sneakyProgressBar = new QProgressBar(this);      sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar"));      sneakyProgressBar->setFormat(QStringLiteral("%p%")); @@ -72,6 +92,23 @@ void VersionSelectWidget::setResizeOn(int column)      listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);  } +bool VersionSelectWidget::eventFilter(QObject *watched, QEvent *event) { +    if (watched == search && event->type() == QEvent::KeyPress) { +        const QKeyEvent* keyEvent = (QKeyEvent*)event; +        const bool up = keyEvent->key() == Qt::Key_Up; +        const bool down = keyEvent->key() == Qt::Key_Down; +        if (up || down) { +            const QModelIndex index = listView->model()->index(listView->currentIndex().row() + (up ? -1 : 1), 0); +            if (index.row() >= 0 && index.row() < listView->model()->rowCount()) { +                listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +                return true; +            } +        } +    } + +    return QObject::eventFilter(watched, event); +} +  void VersionSelectWidget::initialize(BaseVersionList *vlist)  {      m_vlist = vlist; @@ -79,6 +116,9 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist)      listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);      listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); +    if (focusSearch) +        search->setFocus(); +      if (!m_vlist->isLoaded())      {          loadList(); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index e75efc6f..be4ba768 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -1,22 +1,43 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + *  Prism Launcher - Minecraft Launcher + *  Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>   * - * 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 + *  This program is free software: you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation, version 3.   * - *     http://www.apache.org/licenses/LICENSE-2.0 + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details.   * - * 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. + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + *      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 <QSortFilterProxyModel> +#include <QLineEdit>  #include "BaseVersionList.h"  #include "VersionListView.h" @@ -30,7 +51,8 @@ class VersionSelectWidget: public QWidget  {      Q_OBJECT  public: -    explicit VersionSelectWidget(QWidget *parent = 0); +    explicit VersionSelectWidget(QWidget *parent); +    explicit VersionSelectWidget(bool focusSearch = false, QWidget *parent = 0);      ~VersionSelectWidget();      //! loads the list if needed. @@ -52,6 +74,7 @@ public:      void setEmptyErrorString(QString emptyErrorString);      void setEmptyMode(VersionListView::EmptyMode mode);      void setResizeOn(int column); +    bool eventFilter(QObject* watched, QEvent* event) override;  signals:      void selectedVersionChanged(BaseVersion::Ptr version); @@ -75,9 +98,10 @@ private:      int resizeOnColumn = 0;      Task * loadTask;      bool preselectedAlready = false; +    bool focusSearch; -private:      QVBoxLayout *verticalLayout = nullptr;      VersionListView *listView = nullptr; +    QLineEdit *search;      QProgressBar *sneakyProgressBar = nullptr;  }; | 
