Add a dialog to Batch PKG Install

Dialog allows users to preview the order in which PKG's will be installed
and allows users to move items around if needed.

Because clicking "Install" on this new dialog acts as a confirmation
and user has a second chance to eyeball what is to be installed,
"Install package X?" dialogs have been removed and instead user
is only notified of success. In case of failure, batch installation
aborts with a descriptive error.
This commit is contained in:
Silent 2020-01-03 19:27:47 +01:00 committed by Megamouse
parent 872be25ed1
commit e7ddc5187a
7 changed files with 258 additions and 44 deletions

View File

@ -472,6 +472,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_pkg_install_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_register_editor_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@ -667,6 +672,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_pkg_install_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_register_editor_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
@ -882,6 +892,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_pkg_install_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_register_editor_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
@ -1077,6 +1092,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_pkg_install_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_register_editor_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@ -1151,6 +1171,7 @@
<ClCompile Include="rpcs3qt\gui_application.cpp" />
<ClCompile Include="rpcs3qt\input_dialog.cpp" />
<ClCompile Include="rpcs3qt\osk_dialog_frame.cpp" />
<ClCompile Include="rpcs3qt\pkg_install_dialog.cpp" />
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
<ClCompile Include="rpcs3qt\update_manager.cpp" />
<ClCompile Include="rpcs3qt\_discord_utils.cpp" />
@ -1712,6 +1733,24 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\pkg_install_dialog.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB "-DBRANCH=$(BRANCH)" -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-IC:\Program Files (x86)\Visual Leak Detector\include"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-IC:\Program Files (x86)\Visual Leak Detector\include"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-IC:\Program Files (x86)\Visual Leak Detector\include"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-IC:\Program Files (x86)\Visual Leak Detector\include"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\stylesheets.h" />
<ClInclude Include="rpcs3qt\skylander_dialog.h" />
<CustomBuild Include="rpcs3qt\update_manager.h">
@ -2191,4 +2230,4 @@
<UserProperties MocDir=".\QTGeneratedFiles\$(ConfigurationName)" UicDir=".\QTGeneratedFiles" RccDir=".\QTGeneratedFiles" Qt5Version_x0020_x64="$(DefaultQtVersion)" />
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@ -788,6 +788,21 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_cheat_manager.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_pkg_install_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_pkg_install_dialog.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_pkg_install_dialog.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_pkg_install_dialog.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\pkg_install_dialog.cpp">
<Filter>Gui\misc dialogs</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="\rpcs3qt\*.h">
@ -1041,6 +1056,9 @@
<CustomBuild Include="rpcs3qt\cheat_manager.h">
<Filter>Gui\cheat manager</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\pkg_install_dialog.h">
<Filter>Gui\misc dialogs</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Image Include="rpcs3.ico" />

View File

@ -29,6 +29,7 @@
msg_dialog_frame.cpp
osk_dialog_frame.cpp
pad_settings_dialog.cpp
pkg_install_dialog.cpp
progress_dialog.cpp
qt_utils.cpp
register_editor_dialog.cpp

View File

@ -30,6 +30,7 @@
#include "progress_dialog.h"
#include "skylander_dialog.h"
#include "cheat_manager.h"
#include "pkg_install_dialog.h"
#include <thread>
@ -369,59 +370,28 @@ void main_window::BootRsxCapture(std::string path)
}
}
void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
bool main_window::InstallPkg(const QString& dropPath, bool show_confirm, bool show_success)
{
QString filePath = dropPath;
if (m_install_bulk == QMessageBox::NoToAll)
{
LOG_NOTICE(LOADER, "PKG: Skipped installation from drop. File: %s", sstr(filePath));
return;
}
else if (m_install_bulk == QMessageBox::YesToAll)
{
LOG_NOTICE(LOADER, "PKG: Continuing bulk installation from drop. File: %s", sstr(filePath));
}
else if (filePath.isEmpty())
if (filePath.isEmpty())
{
QString path_last_PKG = guiSettings->GetValue(gui::fd_install_pkg).toString();
filePath = QFileDialog::getOpenFileName(this, tr("Select PKG To Install"), path_last_PKG, tr("PKG files (*.pkg);;All files (*.*)"));
}
else if (is_bulk)
{
QMessageBox::StandardButton ret = QMessageBox::question(this, tr("PKG Decrypter / Installer"), tr("Install package: %1?").arg(filePath),
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::NoToAll | QMessageBox::No, QMessageBox::No);
if (ret == QMessageBox::No)
{
LOG_NOTICE(LOADER, "PKG: Cancelled installation from drop. File: %s", sstr(filePath));
return;
}
else if (ret == QMessageBox::NoToAll)
{
LOG_NOTICE(LOADER, "PKG: Cancelled bulk installation from drop. File: %s", sstr(filePath));
m_install_bulk = ret;
return;
}
else if (ret == QMessageBox::YesToAll)
{
LOG_NOTICE(LOADER, "PKG: Accepted bulk installation from drop. File: %s", sstr(filePath));
m_install_bulk = ret;
}
}
else
else if (show_confirm)
{
if (QMessageBox::question(this, tr("PKG Decrypter / Installer"), tr("Install package: %1?").arg(filePath),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
{
LOG_NOTICE(LOADER, "PKG: Cancelled installation from drop. File: %s", sstr(filePath));
return;
return false;
}
}
if (filePath.isEmpty())
{
return;
return false;
}
Emu.SetForceBoot(true);
@ -479,13 +449,18 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
{
m_gameListFrame->Refresh(true);
LOG_SUCCESS(GENERAL, "Successfully installed %s.", fileName);
guiSettings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package!"), gui::ib_pkg_success, this);
if (show_success)
{
guiSettings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package(s)!"), gui::ib_pkg_success, this);
}
return true;
}
else if (!cancelled)
{
LOG_ERROR(GENERAL, "Failed to install %s.", fileName);
QMessageBox::critical(this, tr("Failure!"), tr("Failed to install software from package %1!").arg(filePath));
}
return false;
}
void main_window::InstallPup(const QString& dropPath)
@ -1922,11 +1897,25 @@ void main_window::dropEvent(QDropEvent* event)
case drop_type::drop_error:
break;
case drop_type::drop_pkg: // install the packages
for (const auto& path : dropPaths)
if (dropPaths.count() > 1)
{
InstallPkg(path, dropPaths.count() > 1);
pkg_install_dialog dlg(dropPaths, this);
connect(&dlg, &QDialog::accepted, [this, &dlg]()
{
const QStringList paths = dlg.GetPathsToInstall();
for (int i = 0, count = paths.count(); i < count; i++)
{
if (!InstallPkg(paths.at(i), false, i == count - 1))
break;
}
});
dlg.exec();
}
else
{
InstallPkg(dropPaths.front(), true);
}
m_install_bulk = QMessageBox::NoButton;
break;
case drop_type::drop_pup: // install the firmware
InstallPup(dropPaths.first());

View File

@ -116,7 +116,7 @@ private:
void CreateDockWindows();
void EnableMenus(bool enabled);
void ShowTitleBars(bool show);
void InstallPkg(const QString& dropPath = "", bool is_bulk = false);
bool InstallPkg(const QString& dropPath = "", bool show_confirm = true, bool show_success = true);
void InstallPup(const QString& dropPath = "");
int IsValidFile(const QMimeData& md, QStringList* dropPaths = nullptr);
@ -134,8 +134,6 @@ private:
QActionGroup* m_listModeActGroup = nullptr;
QActionGroup* m_categoryVisibleActGroup = nullptr;
QMessageBox::StandardButton m_install_bulk = QMessageBox::NoButton;
// Dockable widget frames
QMainWindow *m_mw = nullptr;
log_frame* m_logFrame = nullptr;

View File

@ -0,0 +1,151 @@
#include "pkg_install_dialog.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QFileInfo>
#include <QLayout>
#include <QLabel>
#include <QToolButton>
constexpr int FullPathRole = Qt::UserRole + 0;
constexpr int BaseDisplayRole = Qt::UserRole + 1;
pkg_install_dialog::pkg_install_dialog(const QStringList& paths, QWidget* parent)
: QDialog(parent)
{
m_dir_list = new QListWidget(this);
class numbered_widget_item final : public QListWidgetItem
{
public:
explicit numbered_widget_item(const QString& text, QListWidget* listview = nullptr, int type = QListWidgetItem::Type)
: QListWidgetItem(text, listview, type)
{
}
QVariant data(int role) const override
{
QVariant result;
switch (role)
{
case Qt::DisplayRole:
result = QStringLiteral("%1. %2").arg(listWidget()->row(this) + 1).arg(data(BaseDisplayRole).toString());
break;
case BaseDisplayRole:
result = QListWidgetItem::data(Qt::DisplayRole);
break;
default:
result = QListWidgetItem::data(role);
break;
}
return result;
}
bool operator<(const QListWidgetItem& other) const override
{
return data(BaseDisplayRole).toString() < other.data(BaseDisplayRole).toString();
}
};
for (const QString& path : paths)
{
QListWidgetItem* item = new numbered_widget_item(QFileInfo(path).fileName(), m_dir_list);
// Save full path in a custom data role
item->setData(FullPathRole, path);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
}
m_dir_list->sortItems();
m_dir_list->setCurrentRow(0);
m_dir_list->setMinimumWidth((m_dir_list->sizeHintForColumn(0) * 125) / 100);
// Create buttons
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
buttons->button(QDialogButtonBox::Ok)->setText(tr("Install"));
buttons->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttons, &QDialogButtonBox::clicked, [this, buttons](QAbstractButton* button)
{
if (button == buttons->button(QDialogButtonBox::Ok))
{
accept();
}
else if (button == buttons->button(QDialogButtonBox::Cancel))
{
reject();
}
});
connect(m_dir_list, &QListWidget::itemChanged, [this, buttons](QListWidgetItem*)
{
bool any_checked = false;
for (int i = 0; i < m_dir_list->count(); i++)
{
if (m_dir_list->item(i)->checkState() == Qt::Checked)
{
any_checked = true;
break;
}
}
buttons->button(QDialogButtonBox::Ok)->setEnabled(any_checked);
});
QToolButton* move_up = new QToolButton;
move_up->setArrowType(Qt::UpArrow);
move_up->setToolTip(tr("Move selected item up"));
connect(move_up, &QToolButton::clicked, [this]() { MoveItem(-1); });
QToolButton* move_down = new QToolButton;
move_down->setArrowType(Qt::DownArrow);
move_down->setToolTip(tr("Move selected item down"));
connect(move_down, &QToolButton::clicked, [this]() { MoveItem(1); });
QHBoxLayout* hbox = new QHBoxLayout;
hbox->addStretch();
hbox->addWidget(move_up);
hbox->addWidget(move_down);
QLabel* description = new QLabel(tr("You are about to install multiple packages.\nReorder and/or exclude them if needed, then click \"Install\" to proceed."));
QVBoxLayout* vbox = new QVBoxLayout;
vbox->addWidget(description);
vbox->addLayout(hbox);
vbox->addWidget(m_dir_list);
vbox->addWidget(buttons);
setLayout(vbox);
setWindowTitle(tr("Batch PKG Installation"));
setObjectName("pkg_install_dialog");
}
void pkg_install_dialog::MoveItem(int offset)
{
const int src_index = m_dir_list->currentRow();
const int dest_index = src_index + offset;
if (src_index >= 0 && src_index < m_dir_list->count() &&
dest_index >= 0 && dest_index < m_dir_list->count())
{
QListWidgetItem* item = m_dir_list->takeItem(src_index);
m_dir_list->insertItem(dest_index, item);
m_dir_list->setCurrentItem(item);
}
}
QStringList pkg_install_dialog::GetPathsToInstall() const
{
QStringList result;
for (int i = 0; i < m_dir_list->count(); i++)
{
const QListWidgetItem* item = m_dir_list->item(i);
if (item->checkState() == Qt::Checked)
{
result.append(item->data(FullPathRole).toString());
}
}
return result;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <QDialog>
#include <QListWidget>
class pkg_install_dialog : public QDialog
{
Q_OBJECT
public:
explicit pkg_install_dialog(const QStringList& paths, QWidget* parent = nullptr);
QStringList GetPathsToInstall() const;
private:
void MoveItem(int offset);
QListWidget* m_dir_list;
};