Merge pull request #3875 from jamierocks/feature/gh-3033

GH-3033 Add filtering for version components
This commit is contained in:
Petr Mrázek 2021-06-19 12:50:21 +02:00 committed by GitHub
commit 5f8d07c009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 165 additions and 36 deletions

View File

@ -302,6 +302,10 @@ set(MINECRAFT_SOURCES
minecraft/mod/ModFolderLoadTask.cpp minecraft/mod/ModFolderLoadTask.cpp
minecraft/mod/LocalModParseTask.h minecraft/mod/LocalModParseTask.h
minecraft/mod/LocalModParseTask.cpp minecraft/mod/LocalModParseTask.cpp
minecraft/mod/ResourcePackFolderModel.h
minecraft/mod/ResourcePackFolderModel.cpp
minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp
# Assets # Assets
minecraft/AssetsUtils.h minecraft/AssetsUtils.h

View File

@ -29,6 +29,8 @@
#include "meta/VersionList.h" #include "meta/VersionList.h"
#include "mod/ModFolderModel.h" #include "mod/ModFolderModel.h"
#include "mod/ResourcePackFolderModel.h"
#include "mod/TexturePackFolderModel.h"
#include "WorldList.h" #include "WorldList.h"
#include "icons/IIconList.h" #include "icons/IIconList.h"
@ -986,7 +988,7 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::resourcePackList() const
{ {
if (!m_resource_pack_list) if (!m_resource_pack_list)
{ {
m_resource_pack_list.reset(new ModFolderModel(resourcePacksDir())); m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir()));
m_resource_pack_list->disableInteraction(isRunning()); m_resource_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ModFolderModel::disableInteraction); connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ModFolderModel::disableInteraction);
} }
@ -997,7 +999,7 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::texturePackList() const
{ {
if (!m_texture_pack_list) if (!m_texture_pack_list)
{ {
m_texture_pack_list.reset(new ModFolderModel(texturePacksDir())); m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir()));
m_texture_pack_list->disableInteraction(isRunning()); m_texture_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_texture_pack_list.get(), &ModFolderModel::disableInteraction); connect(this, &BaseInstance::runningStatusChanged, m_texture_pack_list.get(), &ModFolderModel::disableInteraction);
} }

View File

@ -15,7 +15,7 @@ void CreateGameFolders::executeTask()
if(!FS::ensureFolderPathExists(minecraftInstance->gameRoot())) if(!FS::ensureFolderPathExists(minecraftInstance->gameRoot()))
{ {
emit logLine("Couldn't create the main game folder", MessageLevel::Error); emit logLine("Couldn't create the main game folder", MessageLevel::Error);
emitFailed("Couldn't create the main game folder"); emitFailed(tr("Couldn't create the main game folder"));
return; return;
} }

View File

@ -66,9 +66,9 @@ void DirectJavaLaunch::executeTask()
auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
if (realWrapperCommand.isEmpty()) if (realWrapperCommand.isEmpty())
{ {
QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); const char *reason = QT_TR_NOOP("The wrapper command \"%1\" couldn't be found.");
emit logLine(reason, MessageLevel::Fatal); emit logLine(QString(reason).arg(wrapperCommand), MessageLevel::Fatal);
emitFailed(reason); emitFailed(tr(reason).arg(wrapperCommand));
return; return;
} }
emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
@ -87,18 +87,17 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
{ {
case LoggedProcess::FailedToStart: case LoggedProcess::FailedToStart:
{ {
//: Error message displayed if instace can't start //: Error message displayed if instance can't start
QString reason = tr("Could not launch minecraft!"); const char *reason = QT_TR_NOOP("Could not launch minecraft!");
emit logLine(reason, MessageLevel::Fatal); emit logLine(reason, MessageLevel::Fatal);
emitFailed(reason); emitFailed(tr(reason));
return; return;
} }
case LoggedProcess::Aborted: case LoggedProcess::Aborted:
case LoggedProcess::Crashed: case LoggedProcess::Crashed:
{ {
m_parent->setPid(-1); m_parent->setPid(-1);
emitFailed("Game crashed."); emitFailed(tr("Game crashed."));
return; return;
} }
case LoggedProcess::Finished: case LoggedProcess::Finished:
@ -108,7 +107,7 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
auto exitCode = m_process.exitCode(); auto exitCode = m_process.exitCode();
if(exitCode != 0) if(exitCode != 0)
{ {
emitFailed("Game crashed."); emitFailed(tr("Game crashed."));
return; return;
} }
//FIXME: make this work again //FIXME: make this work again
@ -118,7 +117,7 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
break; break;
} }
case LoggedProcess::Running: case LoggedProcess::Running:
emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); emit logLine(QString("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
m_parent->setPid(m_process.processId()); m_parent->setPid(m_process.processId());
m_parent->instance()->setLastLaunch(); m_parent->instance()->setLastLaunch();
break; break;

View File

@ -94,9 +94,9 @@ void ExtractNatives::executeTask()
{ {
if(!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW)) if(!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW))
{ {
auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath); const char *reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'");
emit logLine(reason, MessageLevel::Fatal); emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal);
emitFailed(reason); emitFailed(tr(reason).arg(source, outputPath));
} }
} }
emitSucceeded(); emitSucceeded();

View File

@ -118,9 +118,9 @@ void LauncherPartLaunch::executeTask()
auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
if (realWrapperCommand.isEmpty()) if (realWrapperCommand.isEmpty())
{ {
QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); const char *reason = QT_TR_NOOP("The wrapper command \"%1\" couldn't be found.");
emit logLine(reason, MessageLevel::Fatal); emit logLine(QString(reason).arg(wrapperCommand), MessageLevel::Fatal);
emitFailed(reason); emitFailed(tr(reason).arg(wrapperCommand));
return; return;
} }
emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
@ -140,17 +140,16 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
case LoggedProcess::FailedToStart: case LoggedProcess::FailedToStart:
{ {
//: Error message displayed if instace can't start //: Error message displayed if instace can't start
QString reason = tr("Could not launch minecraft!"); const char *reason = QT_TR_NOOP("Could not launch minecraft!");
emit logLine(reason, MessageLevel::Fatal); emit logLine(reason, MessageLevel::Fatal);
emitFailed(reason); emitFailed(tr(reason));
return; return;
} }
case LoggedProcess::Aborted: case LoggedProcess::Aborted:
case LoggedProcess::Crashed: case LoggedProcess::Crashed:
{ {
m_parent->setPid(-1); m_parent->setPid(-1);
emitFailed("Game crashed."); emitFailed(tr("Game crashed."));
return; return;
} }
case LoggedProcess::Finished: case LoggedProcess::Finished:
@ -160,7 +159,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
auto exitCode = m_process.exitCode(); auto exitCode = m_process.exitCode();
if(exitCode != 0) if(exitCode != 0)
{ {
emitFailed("Game crashed."); emitFailed(tr("Game crashed."));
return; return;
} }
//FIXME: make this work again //FIXME: make this work again
@ -170,7 +169,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
break; break;
} }
case LoggedProcess::Running: case LoggedProcess::Running:
emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); emit logLine(QString("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
m_parent->setPid(m_process.processId()); m_parent->setPid(m_process.processId());
m_parent->instance()->setLastLaunch(); m_parent->instance()->setLastLaunch();
// send the launch script to the launcher part // send the launch script to the launcher part

View File

@ -0,0 +1,23 @@
#include "ResourcePackFolderModel.h"
ResourcePackFolderModel::ResourcePackFolderModel(const QString &dir) : ModFolderModel(dir) {
}
QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::ToolTipRole) {
switch (section) {
case ActiveColumn:
return tr("Is the resource pack enabled?");
case NameColumn:
return tr("The name of the resource pack.");
case VersionColumn:
return tr("The version of the resource pack.");
case DateColumn:
return tr("The date and time this resource pack was last changed (or added).");
default:
return QVariant();
}
}
return ModFolderModel::headerData(section, orientation, role);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "ModFolderModel.h"
class MULTIMC_LOGIC_EXPORT ResourcePackFolderModel : public ModFolderModel
{
Q_OBJECT
public:
explicit ResourcePackFolderModel(const QString &dir);
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
};

View File

@ -0,0 +1,23 @@
#include "TexturePackFolderModel.h"
TexturePackFolderModel::TexturePackFolderModel(const QString &dir) : ModFolderModel(dir) {
}
QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::ToolTipRole) {
switch (section) {
case ActiveColumn:
return tr("Is the texture pack enabled?");
case NameColumn:
return tr("The name of the texture pack.");
case VersionColumn:
return tr("The version of the texture pack.");
case DateColumn:
return tr("The date and time this texture pack was last changed (or added).");
default:
return QVariant();
}
}
return ModFolderModel::headerData(section, orientation, role);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "ModFolderModel.h"
class MULTIMC_LOGIC_EXPORT TexturePackFolderModel : public ModFolderModel
{
Q_OBJECT
public:
explicit TexturePackFolderModel(const QString &dir);
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
};

View File

@ -738,7 +738,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
repopulateAccountsMenu(); repopulateAccountsMenu();
accountMenuButton = new QToolButton(this); accountMenuButton = new QToolButton(this);
accountMenuButton->setText(tr("Profiles"));
accountMenuButton->setMenu(accountMenu); accountMenuButton->setMenu(accountMenu);
accountMenuButton->setPopupMode(QToolButton::InstantPopup); accountMenuButton->setPopupMode(QToolButton::InstantPopup);
accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@ -837,6 +836,21 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
// removing this looks stupid // removing this looks stupid
view->setFocus(); view->setFocus();
retranslateUi();
}
void MainWindow::retranslateUi()
{
accountMenuButton->setText(tr("Profiles"));
if (m_selectedInstance) {
m_statusLeft->setText(m_selectedInstance->getStatusbarDescription());
} else {
m_statusLeft->setText(tr("No instance selected"));
}
ui->retranslateUi(this);
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -1751,7 +1765,7 @@ void MainWindow::changeEvent(QEvent* event)
{ {
if (event->type() == QEvent::LanguageChange) if (event->type() == QEvent::LanguageChange)
{ {
ui->retranslateUi(this); retranslateUi();
} }
QMainWindow::changeEvent(event); QMainWindow::changeEvent(event);
} }

View File

@ -187,6 +187,8 @@ private slots:
void globalSettingsClosed(); void globalSettingsClosed();
private: private:
void retranslateUi();
void addInstance(QString url = QString()); void addInstance(QString url = QString());
void activateInstance(InstancePtr instance); void activateInstance(InstancePtr instance);
void setCatBackground(bool enabled); void setCatBackground(bool enabled);

View File

@ -236,15 +236,15 @@ void LogPage::on_btnPaste_clicked()
return; return;
//FIXME: turn this into a proper task and move the upload logic out of GuiUtil! //FIXME: turn this into a proper task and move the upload logic out of GuiUtil!
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)));
auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this); auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this);
if(!url.isEmpty()) if(!url.isEmpty())
{ {
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log uploaded to: %1").arg(url)); m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log uploaded to: %1").arg(url));
} }
else else
{ {
m_model->append(MessageLevel::Error, tr("MultiMC: Log upload failed!")); m_model->append(MessageLevel::Error, "MultiMC: Log upload failed!");
} }
} }

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "ModFolderPage.h" #include "ModFolderPage.h"
#include "ui_ModFolderPage.h" #include "ui_ModFolderPage.h"
@ -12,8 +13,8 @@ public:
{ {
ui->actionView_configs->setVisible(false); ui->actionView_configs->setVisible(false);
} }
virtual ~ResourcePackPage() {} virtual ~ResourcePackPage() {}
virtual bool shouldDisplay() const override virtual bool shouldDisplay() const override
{ {
return !m_inst->traits().contains("no-texturepacks") && return !m_inst->traits().contains("no-texturepacks") &&

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "ModFolderPage.h" #include "ModFolderPage.h"
#include "ui_ModFolderPage.h" #include "ui_ModFolderPage.h"
@ -13,6 +14,7 @@ public:
ui->actionView_configs->setVisible(false); ui->actionView_configs->setVisible(false);
} }
virtual ~TexturePackPage() {} virtual ~TexturePackPage() {}
virtual bool shouldDisplay() const override virtual bool shouldDisplay() const override
{ {
return m_inst->traits().contains("texturepacks"); return m_inst->traits().contains("texturepacks");

View File

@ -120,7 +120,15 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent)
auto proxy = new IconProxy(ui->packageView); auto proxy = new IconProxy(ui->packageView);
proxy->setSourceModel(m_profile.get()); proxy->setSourceModel(m_profile.get());
ui->packageView->setModel(proxy);
m_filterModel = new QSortFilterProxyModel();
m_filterModel->setDynamicSortFilter(true);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSourceModel(proxy);
m_filterModel->setFilterKeyColumn(-1);
ui->packageView->setModel(m_filterModel);
ui->packageView->installEventFilter(this); ui->packageView->installEventFilter(this);
ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection); ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->packageView->setContextMenuPolicy(Qt::CustomContextMenu); ui->packageView->setContextMenuPolicy(Qt::CustomContextMenu);
@ -134,7 +142,8 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent)
updateVersionControls(); updateVersionControls();
preselect(0); preselect(0);
connect(m_inst, &BaseInstance::runningStatusChanged, this, &VersionPage::updateRunningStatus); connect(m_inst, &BaseInstance::runningStatusChanged, this, &VersionPage::updateRunningStatus);
connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::ShowContextMenu); connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::showContextMenu);
connect(ui->filterEdit, &QLineEdit::textChanged, this, &VersionPage::onFilterTextChanged);
} }
VersionPage::~VersionPage() VersionPage::~VersionPage()
@ -142,7 +151,7 @@ VersionPage::~VersionPage()
delete ui; delete ui;
} }
void VersionPage::ShowContextMenu(const QPoint& pos) void VersionPage::showContextMenu(const QPoint& pos)
{ {
auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); auto menu = ui->toolBar->createContextMenu(this, tr("Context menu"));
menu->exec(ui->packageView->mapToGlobal(pos)); menu->exec(ui->packageView->mapToGlobal(pos));
@ -620,5 +629,10 @@ void VersionPage::on_actionRevert_triggered()
m_container->refreshContainer(); m_container->refreshContainer();
} }
void VersionPage::onFilterTextChanged(const QString &newContents)
{
m_filterModel->setFilterFixedString(newContents);
}
#include "VersionPage.moc" #include "VersionPage.moc"

View File

@ -86,6 +86,7 @@ protected:
private: private:
Ui::VersionPage *ui; Ui::VersionPage *ui;
QSortFilterProxyModel *m_filterModel;
std::shared_ptr<PackProfile> m_profile; std::shared_ptr<PackProfile> m_profile;
MinecraftInstance *m_inst; MinecraftInstance *m_inst;
int currentIdx = 0; int currentIdx = 0;
@ -98,5 +99,6 @@ private slots:
void updateRunningStatus(bool running); void updateRunningStatus(bool running);
void onGameUpdateError(QString error); void onGameUpdateError(QString error);
void packageCurrent(const QModelIndex &current, const QModelIndex &previous); void packageCurrent(const QModelIndex &current, const QModelIndex &previous);
void ShowContextMenu(const QPoint &pos); void showContextMenu(const QPoint &pos);
void onFilterTextChanged(const QString & newContents);
}; };

View File

@ -45,6 +45,24 @@
</attribute> </attribute>
</widget> </widget>
</item> </item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QLineEdit" name="filterEdit">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="filterLabel">
<property name="text">
<string>Filter:</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="MCModInfoFrame" name="frame"> <widget class="MCModInfoFrame" name="frame">
<property name="sizePolicy"> <property name="sizePolicy">