Merge branch 'develop' into fix/network_and_signals
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@ -1337,6 +1337,20 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
||||
if (response != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
auto linkedInstances = APPLICATION->instances()->getLinkedInstancesById(id);
|
||||
if (!linkedInstances.empty()) {
|
||||
response = CustomMessageBox::selectable(
|
||||
this, tr("There are linked instances"),
|
||||
tr("The following instance(s) might reference files in this instance:\n\n"
|
||||
"%1\n\n"
|
||||
"Deleting it could break the other instance(s), \n\n"
|
||||
"Do you wish to proceed?", nullptr, linkedInstances.count()).arg(linkedInstances.join("\n")),
|
||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No
|
||||
)->exec();
|
||||
if (response != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
if (APPLICATION->instances()->trashInstance(id)) {
|
||||
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
|
||||
return;
|
||||
|
@ -195,7 +195,7 @@ void BlockedModsDialog::watchPath(QString path, bool watch_recursive)
|
||||
auto to_watch = QFileInfo(path);
|
||||
auto to_watch_path = to_watch.canonicalFilePath();
|
||||
if (m_watcher.directories().contains(to_watch_path))
|
||||
return; // don't watch the same path twice (no loops!)
|
||||
return; // don't watch the same path twice (no loops!)
|
||||
|
||||
qDebug() << "[Blocked Mods Dialog] Adding Watch Path:" << path;
|
||||
m_watcher.addPath(to_watch_path);
|
||||
@ -203,10 +203,9 @@ void BlockedModsDialog::watchPath(QString path, bool watch_recursive)
|
||||
if (!to_watch.isDir() || !watch_recursive)
|
||||
return;
|
||||
|
||||
|
||||
QDirIterator it(to_watch_path, QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot, QDirIterator::NoIteratorFlags);
|
||||
while (it.hasNext()) {
|
||||
QString watch_dir = QDir(it.next()).canonicalPath(); // resolve symlinks and relative paths
|
||||
QString watch_dir = QDir(it.next()).canonicalPath(); // resolve symlinks and relative paths
|
||||
watchPath(watch_dir, watch_recursive);
|
||||
}
|
||||
}
|
||||
@ -302,11 +301,35 @@ bool BlockedModsDialog::checkValidPath(QString path)
|
||||
{
|
||||
const QFileInfo file = QFileInfo(path);
|
||||
const QString filename = file.fileName();
|
||||
QString laxFilename(filename);
|
||||
laxFilename.replace('+', ' ');
|
||||
|
||||
auto compare = [](QString fsfilename, QString metadataFilename) {
|
||||
return metadataFilename.compare(fsfilename, Qt::CaseInsensitive) == 0;
|
||||
auto compare = [](QString fsFilename, QString metadataFilename) {
|
||||
return metadataFilename.compare(fsFilename, Qt::CaseInsensitive) == 0;
|
||||
};
|
||||
|
||||
// super lax compare (but not fuzzy)
|
||||
// convert to lowercase
|
||||
// convert all speratores to whitespace
|
||||
// simplify sequence of internal whitespace to a single space
|
||||
// efectivly compare two strings ignoring all separators and case
|
||||
auto laxCompare = [](QString fsfilename, QString metadataFilename) {
|
||||
// allowed character seperators
|
||||
QList<QChar> allowedSeperators = { '-', '+', '.' , '_'};
|
||||
|
||||
// copy in lowercase
|
||||
auto fsName = fsfilename.toLower();
|
||||
auto metaName = metadataFilename.toLower();
|
||||
|
||||
// replace all potential allowed seperatores with whitespace
|
||||
for (auto sep : allowedSeperators) {
|
||||
fsName = fsName.replace(sep, ' ');
|
||||
metaName = metaName.replace(sep, ' ');
|
||||
}
|
||||
|
||||
// remove extraneous whitespace
|
||||
fsName = fsName.simplified();
|
||||
metaName = metaName.simplified();
|
||||
|
||||
return fsName.compare(metaName) == 0;
|
||||
};
|
||||
|
||||
for (auto& mod : m_mods) {
|
||||
@ -314,7 +337,7 @@ bool BlockedModsDialog::checkValidPath(QString path)
|
||||
qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path;
|
||||
return true;
|
||||
}
|
||||
if (compare(laxFilename, mod.name)) {
|
||||
if (laxCompare(filename, mod.name)) {
|
||||
qDebug() << "[Blocked Mods Dialog] Lax name match found:" << mod.name << "| From path:" << path;
|
||||
return true;
|
||||
}
|
||||
|
@ -37,18 +37,21 @@
|
||||
#include <QPushButton>
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "CopyInstanceDialog.h"
|
||||
#include "ui_CopyInstanceDialog.h"
|
||||
|
||||
#include "ui/dialogs/IconPickerDialog.h"
|
||||
|
||||
#include "BaseVersion.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "BaseVersion.h"
|
||||
#include "DesktopServices.h"
|
||||
#include "FileSystem.h"
|
||||
#include "InstanceList.h"
|
||||
#include "icons/IconList.h"
|
||||
|
||||
CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
:QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget* parent)
|
||||
: QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
@ -71,8 +74,7 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(APPLICATION->instances()->getInstanceGroup(m_original->id()));
|
||||
if(index == -1)
|
||||
{
|
||||
if (index == -1) {
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
@ -85,6 +87,35 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
ui->copyServersCheckbox->setChecked(m_selectedOptions.isCopyServersEnabled());
|
||||
ui->copyModsCheckbox->setChecked(m_selectedOptions.isCopyModsEnabled());
|
||||
ui->copyScreenshotsCheckbox->setChecked(m_selectedOptions.isCopyScreenshotsEnabled());
|
||||
|
||||
ui->symbolicLinksCheckbox->setChecked(m_selectedOptions.isUseSymLinksEnabled());
|
||||
ui->hardLinksCheckbox->setChecked(m_selectedOptions.isUseHardLinksEnabled());
|
||||
|
||||
ui->recursiveLinkCheckbox->setChecked(m_selectedOptions.isLinkRecursivelyEnabled());
|
||||
ui->dontLinkSavesCheckbox->setChecked(m_selectedOptions.isDontLinkSavesEnabled());
|
||||
|
||||
auto detectedFS = FS::statFS(m_original->instanceRoot()).fsType;
|
||||
|
||||
m_cloneSupported = FS::canCloneOnFS(detectedFS);
|
||||
m_linkSupported = FS::canLinkOnFS(detectedFS);
|
||||
|
||||
if (m_cloneSupported) {
|
||||
ui->cloneSupportedLabel->setText(tr("Reflinks are supported on %1").arg(FS::getFilesystemTypeName(detectedFS)));
|
||||
} else {
|
||||
ui->cloneSupportedLabel->setText(tr("Reflinks aren't supported on %1").arg(FS::getFilesystemTypeName(detectedFS)));
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
ui->symbolicLinksCheckbox->setIcon(style()->standardIcon(QStyle::SP_VistaShield));
|
||||
ui->symbolicLinksCheckbox->setToolTip(tr("Use symbolic links instead of copying files.") +
|
||||
"\n" + tr("On Windows, symbolic links may require admin permission to create."));
|
||||
#endif
|
||||
|
||||
updateLinkOptions();
|
||||
updateUseCloneCheckbox();
|
||||
|
||||
auto HelpButton = ui->buttonBox->button(QDialogButtonBox::Help);
|
||||
connect(HelpButton, &QPushButton::clicked, this, &CopyInstanceDialog::help);
|
||||
}
|
||||
|
||||
CopyInstanceDialog::~CopyInstanceDialog()
|
||||
@ -96,8 +127,7 @@ void CopyInstanceDialog::updateDialogState()
|
||||
{
|
||||
auto allowOK = !instName().isEmpty();
|
||||
auto OkButton = ui->buttonBox->button(QDialogButtonBox::Ok);
|
||||
if(OkButton->isEnabled() != allowOK)
|
||||
{
|
||||
if (OkButton->isEnabled() != allowOK) {
|
||||
OkButton->setEnabled(allowOK);
|
||||
}
|
||||
}
|
||||
@ -105,8 +135,7 @@ void CopyInstanceDialog::updateDialogState()
|
||||
QString CopyInstanceDialog::instName() const
|
||||
{
|
||||
auto result = ui->instNameTextBox->text().trimmed();
|
||||
if(result.size())
|
||||
{
|
||||
if (result.size()) {
|
||||
return result;
|
||||
}
|
||||
return QString();
|
||||
@ -127,6 +156,11 @@ const InstanceCopyPrefs& CopyInstanceDialog::getChosenOptions() const
|
||||
return m_selectedOptions;
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::help()
|
||||
{
|
||||
DesktopServices::openUrl(QUrl(BuildConfig.HELP_URL.arg("instance-copy")));
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::checkAllCheckboxes(const bool& b)
|
||||
{
|
||||
ui->keepPlaytimeCheckbox->setChecked(b);
|
||||
@ -147,20 +181,46 @@ void CopyInstanceDialog::updateSelectAllCheckbox()
|
||||
ui->selectAllCheckbox->blockSignals(false);
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::updateUseCloneCheckbox()
|
||||
{
|
||||
ui->useCloneCheckbox->setEnabled(m_cloneSupported && !ui->symbolicLinksCheckbox->isChecked() && !ui->hardLinksCheckbox->isChecked());
|
||||
ui->useCloneCheckbox->setChecked(m_cloneSupported && m_selectedOptions.isUseCloneEnabled() && !ui->symbolicLinksCheckbox->isChecked() &&
|
||||
!ui->hardLinksCheckbox->isChecked());
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::updateLinkOptions()
|
||||
{
|
||||
ui->symbolicLinksCheckbox->setEnabled(m_linkSupported && !ui->hardLinksCheckbox->isChecked() && !ui->useCloneCheckbox->isChecked());
|
||||
ui->hardLinksCheckbox->setEnabled(m_linkSupported && !ui->symbolicLinksCheckbox->isChecked() && !ui->useCloneCheckbox->isChecked());
|
||||
|
||||
ui->symbolicLinksCheckbox->setChecked(m_linkSupported && m_selectedOptions.isUseSymLinksEnabled() &&
|
||||
!ui->useCloneCheckbox->isChecked());
|
||||
ui->hardLinksCheckbox->setChecked(m_linkSupported && m_selectedOptions.isUseHardLinksEnabled() && !ui->useCloneCheckbox->isChecked());
|
||||
|
||||
bool linksInUse = (ui->symbolicLinksCheckbox->isChecked() || ui->hardLinksCheckbox->isChecked());
|
||||
ui->recursiveLinkCheckbox->setEnabled(m_linkSupported && linksInUse && !ui->hardLinksCheckbox->isChecked());
|
||||
ui->dontLinkSavesCheckbox->setEnabled(m_linkSupported && linksInUse);
|
||||
ui->recursiveLinkCheckbox->setChecked(m_linkSupported && linksInUse && m_selectedOptions.isLinkRecursivelyEnabled());
|
||||
ui->dontLinkSavesCheckbox->setChecked(m_linkSupported && linksInUse && m_selectedOptions.isDontLinkSavesEnabled());
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
auto OkButton = ui->buttonBox->button(QDialogButtonBox::Ok);
|
||||
OkButton->setIcon(m_selectedOptions.isUseSymLinksEnabled() ? style()->standardIcon(QStyle::SP_VistaShield) : QIcon());
|
||||
#endif
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.execWithSelection(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
if (dlg.result() == QDialog::Accepted) {
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString& arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
}
|
||||
@ -175,10 +235,10 @@ void CopyInstanceDialog::on_selectAllCheckbox_stateChanged(int state)
|
||||
void CopyInstanceDialog::on_copySavesCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableCopySaves(state == Qt::Checked);
|
||||
ui->dontLinkSavesCheckbox->setChecked((state == Qt::Checked) && ui->dontLinkSavesCheckbox->isChecked());
|
||||
updateSelectAllCheckbox();
|
||||
}
|
||||
|
||||
|
||||
void CopyInstanceDialog::on_keepPlaytimeCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableKeepPlaytime(state == Qt::Checked);
|
||||
@ -220,3 +280,38 @@ void CopyInstanceDialog::on_copyScreenshotsCheckbox_stateChanged(int state)
|
||||
m_selectedOptions.enableCopyScreenshots(state == Qt::Checked);
|
||||
updateSelectAllCheckbox();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_symbolicLinksCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableUseSymLinks(state == Qt::Checked);
|
||||
updateUseCloneCheckbox();
|
||||
updateLinkOptions();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_hardLinksCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableUseHardLinks(state == Qt::Checked);
|
||||
if (state == Qt::Checked && !ui->recursiveLinkCheckbox->isChecked()) {
|
||||
ui->recursiveLinkCheckbox->setChecked(true);
|
||||
}
|
||||
updateUseCloneCheckbox();
|
||||
updateLinkOptions();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_recursiveLinkCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableLinkRecursively(state == Qt::Checked);
|
||||
updateLinkOptions();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_dontLinkSavesCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableDontLinkSaves(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_useCloneCheckbox_stateChanged(int state)
|
||||
{
|
||||
m_selectedOptions.enableUseClone(m_cloneSupported && (state == Qt::Checked));
|
||||
updateUseCloneCheckbox();
|
||||
updateLinkOptions();
|
||||
}
|
||||
|
@ -16,22 +16,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "BaseInstance.h"
|
||||
#include "BaseVersion.h"
|
||||
#include "InstanceCopyPrefs.h"
|
||||
|
||||
class BaseInstance;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
namespace Ui {
|
||||
class CopyInstanceDialog;
|
||||
}
|
||||
|
||||
class CopyInstanceDialog : public QDialog
|
||||
{
|
||||
class CopyInstanceDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0);
|
||||
public:
|
||||
explicit CopyInstanceDialog(InstancePtr original, QWidget* parent = 0);
|
||||
~CopyInstanceDialog();
|
||||
|
||||
void updateDialogState();
|
||||
@ -41,10 +40,12 @@ public:
|
||||
QString iconKey() const;
|
||||
const InstanceCopyPrefs& getChosenOptions() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
public slots:
|
||||
void help();
|
||||
|
||||
private slots:
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
void on_instNameTextBox_textChanged(const QString& arg1);
|
||||
// Checkboxes
|
||||
void on_selectAllCheckbox_stateChanged(int state);
|
||||
void on_copySavesCheckbox_stateChanged(int state);
|
||||
@ -55,13 +56,23 @@ slots:
|
||||
void on_copyServersCheckbox_stateChanged(int state);
|
||||
void on_copyModsCheckbox_stateChanged(int state);
|
||||
void on_copyScreenshotsCheckbox_stateChanged(int state);
|
||||
void on_symbolicLinksCheckbox_stateChanged(int state);
|
||||
void on_hardLinksCheckbox_stateChanged(int state);
|
||||
void on_recursiveLinkCheckbox_stateChanged(int state);
|
||||
void on_dontLinkSavesCheckbox_stateChanged(int state);
|
||||
void on_useCloneCheckbox_stateChanged(int state);
|
||||
|
||||
private:
|
||||
private:
|
||||
void checkAllCheckboxes(const bool& b);
|
||||
void updateSelectAllCheckbox();
|
||||
void updateUseCloneCheckbox();
|
||||
void updateLinkOptions();
|
||||
|
||||
/* data */
|
||||
Ui::CopyInstanceDialog *ui;
|
||||
Ui::CopyInstanceDialog* ui;
|
||||
QString InstIconKey;
|
||||
InstancePtr m_original;
|
||||
InstanceCopyPrefs m_selectedOptions;
|
||||
bool m_cloneSupported = false;
|
||||
bool m_linkSupported = false;
|
||||
};
|
||||
|
@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>341</width>
|
||||
<height>399</height>
|
||||
<width>575</width>
|
||||
<height>695</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -113,93 +113,268 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="selectAllButtonLayout">
|
||||
<widget class="QGroupBox" name="copyOptionsGroup">
|
||||
<property name="title">
|
||||
<string>Instance Copy Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="copyOptionsLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="keepPlaytimeCheckbox">
|
||||
<property name="text">
|
||||
<string>Keep play time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="copyModsCheckbox">
|
||||
<property name="toolTip">
|
||||
<string>Disabling this will still keep the mod loader (ex: Fabric, Quilt, etc.) but erase the mods folder and their configs.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy mods</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="copyResPacksCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy resource packs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="copyGameOptionsCheckbox">
|
||||
<property name="toolTip">
|
||||
<string>Copy the in-game options like FOV, max framerate, etc.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy game options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="copyShaderPacksCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy shader packs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="copyServersCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy servers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="copySavesCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy saves</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="copyScreenshotsCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy screenshots</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="selectAllCheckbox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select all</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="advancedOptionsLabel">
|
||||
<property name="text">
|
||||
<string>Advanced Copy Options</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="copyModeLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="selectAllCheckbox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<widget class="QGroupBox" name="linkFilesGroup">
|
||||
<property name="toolTip">
|
||||
<string>Use symbolic or hard links instead of copying files.</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
<property name="title">
|
||||
<string>Symbolic and Hard Link Options</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select all</string>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="linkOptionsLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="linkOptionsLabel">
|
||||
<property name="text">
|
||||
<string>Links are supported on most filesystems except FAT</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="linkOptionsGridLayout" rowstretch="0,0,0,0" columnstretch="0,0" rowminimumheight="0,0,0,0" columnminimumwidth="0,0">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="recursiveLinkCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Link each resource individually instead of linking whole folders at once</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Link files recursively</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="dontLinkSavesCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>If "copy saves" is selected world save data will be copied instead of linked and thus not shared between instances.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Don't link saves</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="hardLinksCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Use hard links instead of copying files.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use hard links</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="symbolicLinksCheckbox">
|
||||
<property name="toolTip">
|
||||
<string>Use symbolic links instead of copying files.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use symbolic links</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="copyOptionsLayout">
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="copyModsCheckbox">
|
||||
<property name="toolTip">
|
||||
<string>Disabling this will still keep the mod loader (ex: Fabric, Quilt, etc.) but erase the mods folder and their configs.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy mods</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="copyGameOptionsCheckbox">
|
||||
<property name="toolTip">
|
||||
<string>Copy the in-game options like FOV, max framerate, etc.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy game options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="copySavesCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy saves</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="copyShaderPacksCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy shader packs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="copyServersCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy servers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="copyResPacksCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy resource packs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="keepPlaytimeCheckbox">
|
||||
<property name="text">
|
||||
<string>Keep play time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="copyScreenshotsCheckbox">
|
||||
<property name="text">
|
||||
<string>Copy screenshots</string>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="horizontalGroupBox">
|
||||
<property name="title">
|
||||
<string>CoW (Copy-on-Write) Options</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="useCloneLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useCloneCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Files cloned with reflinks take up no extra space until they are modified.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clone instead of copying</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="CoWSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="cloneSupportedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Your filesystem and/or OS doesn't support reflinks</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -210,7 +385,7 @@
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -220,10 +395,21 @@
|
||||
<tabstop>iconButton</tabstop>
|
||||
<tabstop>instNameTextBox</tabstop>
|
||||
<tabstop>groupBox</tabstop>
|
||||
<tabstop>keepPlaytimeCheckbox</tabstop>
|
||||
<tabstop>copyScreenshotsCheckbox</tabstop>
|
||||
<tabstop>copySavesCheckbox</tabstop>
|
||||
<tabstop>copyShaderPacksCheckbox</tabstop>
|
||||
<tabstop>copyGameOptionsCheckbox</tabstop>
|
||||
<tabstop>copyServersCheckbox</tabstop>
|
||||
<tabstop>copyResPacksCheckbox</tabstop>
|
||||
<tabstop>copyModsCheckbox</tabstop>
|
||||
<tabstop>symbolicLinksCheckbox</tabstop>
|
||||
<tabstop>recursiveLinkCheckbox</tabstop>
|
||||
<tabstop>hardLinksCheckbox</tabstop>
|
||||
<tabstop>dontLinkSavesCheckbox</tabstop>
|
||||
<tabstop>useCloneCheckbox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../graphics.qrc"/>
|
||||
</resources>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
@ -232,8 +418,8 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>254</x>
|
||||
<y>316</y>
|
||||
<x>269</x>
|
||||
<y>692</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
@ -248,8 +434,8 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>322</x>
|
||||
<y>316</y>
|
||||
<x>337</x>
|
||||
<y>692</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include <QDebug>
|
||||
#include <QSaveFile>
|
||||
#include <QStack>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include "SeparatorPrefixTree.h"
|
||||
#include "Application.h"
|
||||
@ -429,7 +431,8 @@ bool ExportInstanceDialog::doExport()
|
||||
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
|
||||
return false;
|
||||
}
|
||||
if (!MMCZip::compressDirFiles(output, m_instance->instanceRoot(), files))
|
||||
|
||||
if (!MMCZip::compressDirFiles(output, m_instance->instanceRoot(), files, true))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
|
||||
return false;
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "ui/widgets/PageContainer.h"
|
||||
#include "ui/pages/modplatform/VanillaPage.h"
|
||||
#include "ui/pages/modplatform/atlauncher/AtlPage.h"
|
||||
#include "ui/pages/modplatform/ftb/FtbPage.h"
|
||||
#include "ui/pages/modplatform/legacy_ftb/Page.h"
|
||||
#include "ui/pages/modplatform/flame/FlamePage.h"
|
||||
#include "ui/pages/modplatform/ImportPage.h"
|
||||
@ -168,7 +167,6 @@ QList<BasePage *> NewInstanceDialog::getPages()
|
||||
pages.append(new AtlPage(this));
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame)
|
||||
pages.append(new FlamePage(this));
|
||||
pages.append(new FtbPage(this));
|
||||
pages.append(new LegacyFTB::Page(this));
|
||||
pages.append(new ModrinthPage(this));
|
||||
pages.append(new TechnicPage(this));
|
||||
|
@ -1,29 +1,69 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
/// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PrismLaucher - Minecraft Launcher
|
||||
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||
*
|
||||
* 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 "ProgressDialog.h"
|
||||
#include "ui_ProgressDialog.h"
|
||||
|
||||
#include <limits>
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "tasks/Task.h"
|
||||
|
||||
#include "ui/widgets/SubTaskProgressBar.h"
|
||||
|
||||
|
||||
// map a value in a numeric range of an arbitrary type to between 0 and INT_MAX
|
||||
// for getting the best precision out of the qt progress bar
|
||||
template<typename T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true>
|
||||
std::tuple<int, int> map_int_zero_max(T current, T range_max, T range_min)
|
||||
{
|
||||
int int_max = std::numeric_limits<int>::max();
|
||||
|
||||
auto type_range = range_max - range_min;
|
||||
double percentage = static_cast<double>(current - range_min) / static_cast<double>(type_range);
|
||||
int mapped_current = percentage * int_max;
|
||||
|
||||
return {mapped_current, int_max};
|
||||
}
|
||||
|
||||
|
||||
ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ProgressDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->taskProgressScrollArea->setHidden(true);
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true);
|
||||
setSkipButton(false);
|
||||
@ -54,10 +94,24 @@ ProgressDialog::~ProgressDialog()
|
||||
}
|
||||
|
||||
void ProgressDialog::updateSize()
|
||||
{
|
||||
{
|
||||
QSize lastSize = this->size();
|
||||
QSize qSize = QSize(480, minimumSizeHint().height());
|
||||
resize(qSize);
|
||||
setFixedSize(qSize);
|
||||
|
||||
// if the current window is too small
|
||||
if ((lastSize != qSize) && (lastSize.height() < qSize.height()))
|
||||
{
|
||||
resize(qSize);
|
||||
|
||||
// keep the dialog in the center after a resize
|
||||
this->move(
|
||||
this->parentWidget()->x() + (this->parentWidget()->width() - this->width()) / 2,
|
||||
this->parentWidget()->y() + (this->parentWidget()->height() - this->height()) / 2
|
||||
);
|
||||
}
|
||||
|
||||
setMinimumSize(qSize);
|
||||
|
||||
}
|
||||
|
||||
int ProgressDialog::execWithTask(Task* task)
|
||||
@ -79,17 +133,15 @@ int ProgressDialog::execWithTask(Task* task)
|
||||
connect(task, &Task::failed, this, &ProgressDialog::onTaskFailed);
|
||||
connect(task, &Task::succeeded, this, &ProgressDialog::onTaskSucceeded);
|
||||
connect(task, &Task::status, this, &ProgressDialog::changeStatus);
|
||||
connect(task, &Task::stepStatus, this, &ProgressDialog::changeStatus);
|
||||
connect(task, &Task::details, this, &ProgressDialog::changeStatus);
|
||||
connect(task, &Task::stepProgress, this, &ProgressDialog::changeStepProgress);
|
||||
connect(task, &Task::progress, this, &ProgressDialog::changeProgress);
|
||||
|
||||
connect(task, &Task::aborted, this, &ProgressDialog::hide);
|
||||
connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled);
|
||||
|
||||
m_is_multi_step = task->isMultiStep();
|
||||
if (!m_is_multi_step) {
|
||||
ui->globalStatusLabel->setHidden(true);
|
||||
ui->globalProgressBar->setHidden(true);
|
||||
}
|
||||
ui->taskProgressScrollArea->setHidden(!m_is_multi_step);
|
||||
updateSize();
|
||||
|
||||
// It's a good idea to start the task after we entered the dialog's event loop :^)
|
||||
if (!task->isRunning()) {
|
||||
@ -149,23 +201,53 @@ void ProgressDialog::onTaskSucceeded()
|
||||
void ProgressDialog::changeStatus(const QString& status)
|
||||
{
|
||||
ui->globalStatusLabel->setText(task->getStatus());
|
||||
ui->statusLabel->setText(task->getStepStatus());
|
||||
ui->globalStatusDetailsLabel->setText(task->getDetails());
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void ProgressDialog::addTaskProgress(TaskStepProgress const& progress)
|
||||
{
|
||||
SubTaskProgressBar* task_bar = new SubTaskProgressBar(this);
|
||||
taskProgress.insert(progress.uid, task_bar);
|
||||
ui->taskProgressLayout->addWidget(task_bar);
|
||||
}
|
||||
|
||||
void ProgressDialog::changeStepProgress(TaskStepProgress const& task_progress)
|
||||
{
|
||||
m_is_multi_step = true;
|
||||
if(ui->taskProgressScrollArea->isHidden()) {
|
||||
ui->taskProgressScrollArea->setHidden(false);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
if (!taskProgress.contains(task_progress.uid))
|
||||
addTaskProgress(task_progress);
|
||||
auto task_bar = taskProgress.value(task_progress.uid);
|
||||
|
||||
|
||||
auto const [mapped_current, mapped_total] = map_int_zero_max<qint64>(task_progress.current, task_progress.total, 0);
|
||||
if (task_progress.total <= 0) {
|
||||
task_bar->setRange(0, 0);
|
||||
} else {
|
||||
task_bar->setRange(0, mapped_total);
|
||||
}
|
||||
|
||||
task_bar->setValue(mapped_current);
|
||||
task_bar->setStatus(task_progress.status);
|
||||
task_bar->setDetails(task_progress.details);
|
||||
|
||||
if (task_progress.isDone()) {
|
||||
task_bar->setVisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ProgressDialog::changeProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->globalProgressBar->setMaximum(total);
|
||||
ui->globalProgressBar->setValue(current);
|
||||
|
||||
if (!m_is_multi_step) {
|
||||
ui->taskProgressBar->setMaximum(total);
|
||||
ui->taskProgressBar->setValue(current);
|
||||
} else {
|
||||
ui->taskProgressBar->setMaximum(task->getStepProgress());
|
||||
ui->taskProgressBar->setValue(task->getStepTotalProgress());
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::keyPressEvent(QKeyEvent* e)
|
||||
|
@ -1,22 +1,50 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
/// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PrismLaucher - Minecraft Launcher
|
||||
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||
*
|
||||
* 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 <QDialog>
|
||||
#include <memory>
|
||||
#include <QHash>
|
||||
#include <QUuid>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
#include "ui/widgets/SubTaskProgressBar.h"
|
||||
|
||||
class Task;
|
||||
class SequentialTask;
|
||||
@ -52,6 +80,7 @@ slots:
|
||||
|
||||
void changeStatus(const QString &status);
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
void changeStepProgress(TaskStepProgress const& task_progress);
|
||||
|
||||
|
||||
private
|
||||
@ -64,6 +93,7 @@ protected:
|
||||
|
||||
private:
|
||||
bool handleImmediateResult(QDialog::DialogCode &result);
|
||||
void addTaskProgress(TaskStepProgress const& progress);
|
||||
|
||||
private:
|
||||
Ui::ProgressDialog *ui;
|
||||
@ -71,4 +101,8 @@ private:
|
||||
Task *task;
|
||||
|
||||
bool m_is_multi_step = false;
|
||||
QHash<QUuid, SubTaskProgressBar*> taskProgress;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -2,26 +2,129 @@
|
||||
<ui version="4.0">
|
||||
<class>ProgressDialog</class>
|
||||
<widget class="QDialog" name="ProgressDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>210</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>16777215</height>
|
||||
<width>480</width>
|
||||
<height>210</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Please wait...</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0">
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="globalStatusLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Global Task Status...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="globalStatusDetailsLabel">
|
||||
<property name="text">
|
||||
<string>Global Status Details...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="globalProgressBar">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="taskProgressScrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="taskProgressContainer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>464</width>
|
||||
<height>96</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="taskProgressLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="skipButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@ -31,49 +134,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="globalStatusLabel">
|
||||
<property name="text">
|
||||
<string>Global Task Status...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Task Status...</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QProgressBar" name="taskProgressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QProgressBar" name="globalProgressBar">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -46,7 +46,6 @@
|
||||
MinecraftPage::MinecraftPage(QWidget *parent) : QWidget(parent), ui(new Ui::MinecraftPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
loadSettings();
|
||||
updateCheckboxStuff();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>936</width>
|
||||
<height>1134</height>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -39,7 +39,7 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="minecraftTab">
|
||||
<attribute name="title">
|
||||
<string notr="true">Minecraft</string>
|
||||
<string notr="true">General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
@ -111,68 +111,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="nativeLibWorkaroundGroupBox">
|
||||
<property name="title">
|
||||
<string>Native library workarounds</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useNativeGLFWCheck">
|
||||
<property name="text">
|
||||
<string>Use system installation of &GLFW</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useNativeOpenALCheck">
|
||||
<property name="text">
|
||||
<string>Use system installation of &OpenAL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="perfomanceGroupBox">
|
||||
<property name="title">
|
||||
<string>Performance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableFeralGamemodeCheck">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable Feral Interactive's GameMode, to potentially improve gaming performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Feral GameMode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableMangoHud">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable MangoHud's advanced performance overlay.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable MangoHud</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useDiscreteGpuCheck">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use the discrete GPU instead of the primary GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use discrete GPU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gameTimeGroupBox">
|
||||
<property name="title">
|
||||
@ -247,6 +185,88 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tweaks</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="nativeLibWorkaroundGroupBox">
|
||||
<property name="title">
|
||||
<string>Native library workarounds</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useNativeGLFWCheck">
|
||||
<property name="text">
|
||||
<string>Use system installation of &GLFW</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useNativeOpenALCheck">
|
||||
<property name="text">
|
||||
<string>Use system installation of &OpenAL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="perfomanceGroupBox">
|
||||
<property name="title">
|
||||
<string>Performance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableFeralGamemodeCheck">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable Feral Interactive's GameMode, to potentially improve gaming performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Feral GameMode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableMangoHud">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable MangoHud's advanced performance overlay.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable MangoHud</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useDiscreteGpuCheck">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use the discrete GPU instead of the primary GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use discrete GPU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -255,11 +275,6 @@
|
||||
<tabstop>maximizedCheckBox</tabstop>
|
||||
<tabstop>windowWidthSpinBox</tabstop>
|
||||
<tabstop>windowHeightSpinBox</tabstop>
|
||||
<tabstop>useNativeGLFWCheck</tabstop>
|
||||
<tabstop>useNativeOpenALCheck</tabstop>
|
||||
<tabstop>enableFeralGamemodeCheck</tabstop>
|
||||
<tabstop>enableMangoHud</tabstop>
|
||||
<tabstop>useDiscreteGpuCheck</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -107,6 +107,7 @@ WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worl
|
||||
auto head = ui->worldTreeView->header();
|
||||
head->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
head->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
head->setSectionResizeMode(4, QHeaderView::ResizeToContents);
|
||||
|
||||
connect(ui->worldTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &WorldListPage::worldChanged);
|
||||
worldChanged(QModelIndex(), QModelIndex());
|
||||
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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 "FtbFilterModel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "modplatform/modpacksch/FTBPackManifest.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
currentSorting = Sorting::ByPlays;
|
||||
sortings.insert(tr("Sort by Plays"), Sorting::ByPlays);
|
||||
sortings.insert(tr("Sort by Installs"), Sorting::ByInstalls);
|
||||
sortings.insert(tr("Sort by Name"), Sorting::ByName);
|
||||
}
|
||||
|
||||
const QMap<QString, FilterModel::Sorting> FilterModel::getAvailableSortings()
|
||||
{
|
||||
return sortings;
|
||||
}
|
||||
|
||||
QString FilterModel::translateCurrentSorting()
|
||||
{
|
||||
return sortings.key(currentSorting);
|
||||
}
|
||||
|
||||
void FilterModel::setSorting(Sorting sorting)
|
||||
{
|
||||
currentSorting = sorting;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
FilterModel::Sorting FilterModel::getCurrentSorting()
|
||||
{
|
||||
return currentSorting;
|
||||
}
|
||||
|
||||
void FilterModel::setSearchTerm(const QString& term)
|
||||
{
|
||||
searchTerm = term.trimmed();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (searchTerm.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
auto pack = sourceModel()->data(index, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
return pack.name.contains(searchTerm, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
ModpacksCH::Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
ModpacksCH::Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
|
||||
if (currentSorting == ByPlays) {
|
||||
return leftPack.plays < rightPack.plays;
|
||||
}
|
||||
else if (currentSorting == ByInstalls) {
|
||||
return leftPack.installs < rightPack.installs;
|
||||
}
|
||||
else if (currentSorting == ByName) {
|
||||
return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
|
||||
}
|
||||
|
||||
// Invalid sorting set, somehow...
|
||||
qWarning() << "Invalid sorting set!";
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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 <QtCore/QSortFilterProxyModel>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
class FilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterModel(QObject* parent = Q_NULLPTR);
|
||||
enum Sorting {
|
||||
ByPlays,
|
||||
ByInstalls,
|
||||
ByName,
|
||||
};
|
||||
const QMap<QString, Sorting> getAvailableSortings();
|
||||
QString translateCurrentSorting();
|
||||
void setSorting(Sorting sorting);
|
||||
Sorting getCurrentSorting();
|
||||
void setSearchTerm(const QString& term);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
private:
|
||||
QMap<QString, Sorting> sortings;
|
||||
Sorting currentSorting;
|
||||
QString searchTerm { "" };
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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 "FtbListModel.h"
|
||||
|
||||
#include "BuildConfig.h"
|
||||
#include "Application.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ListModel::~ListModel()
|
||||
{
|
||||
}
|
||||
|
||||
int ListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : modpacks.size();
|
||||
}
|
||||
|
||||
int ListModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
}
|
||||
|
||||
QVariant ListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int pos = index.row();
|
||||
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
|
||||
{
|
||||
return QString("INVALID INDEX %1").arg(pos);
|
||||
}
|
||||
|
||||
ModpacksCH::Modpack pack = modpacks.at(pos);
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
return pack.name;
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
return pack.synopsis;
|
||||
}
|
||||
else if(role == Qt::DecorationRole)
|
||||
{
|
||||
QIcon placeholder = APPLICATION->getThemedIcon("screenshot-placeholder");
|
||||
|
||||
auto iter = m_logoMap.find(pack.name);
|
||||
if (iter != m_logoMap.end()) {
|
||||
auto & logo = *iter;
|
||||
if(!logo.result.isNull()) {
|
||||
return logo.result;
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
for(auto art : pack.art) {
|
||||
if(art.type == "square") {
|
||||
((ListModel *)this)->requestLogo(pack.name, art.url);
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
else if(role == Qt::UserRole)
|
||||
{
|
||||
QVariant v;
|
||||
v.setValue(pack);
|
||||
return v;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
|
||||
{
|
||||
if(m_logoMap.contains(logo))
|
||||
{
|
||||
callback(APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
requestLogo(logo, logoUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::request()
|
||||
{
|
||||
m_aborted = false;
|
||||
|
||||
beginResetModel();
|
||||
modpacks.clear();
|
||||
endResetModel();
|
||||
|
||||
auto netJob = makeShared<NetJob>("Ftb::Request", APPLICATION->network());
|
||||
auto url = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/all");
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::requestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::requestFailed);
|
||||
}
|
||||
|
||||
void ListModel::abortRequest()
|
||||
{
|
||||
m_aborted = jobPtr->abort();
|
||||
jobPtr.reset();
|
||||
}
|
||||
|
||||
void ListModel::requestFinished()
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.clear();
|
||||
|
||||
QJsonParseError parse_error {};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
|
||||
if(parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << response;
|
||||
return;
|
||||
}
|
||||
|
||||
auto packs = doc.object().value("packs").toArray();
|
||||
for(auto pack : packs) {
|
||||
auto packId = pack.toInt();
|
||||
remainingPacks.append(packId);
|
||||
}
|
||||
|
||||
if(!remainingPacks.isEmpty()) {
|
||||
currentPack = remainingPacks.at(0);
|
||||
requestPack();
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::requestFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.clear();
|
||||
}
|
||||
|
||||
void ListModel::requestPack()
|
||||
{
|
||||
auto netJob = makeShared<NetJob>("Ftb::Search", APPLICATION->network());
|
||||
auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/%1").arg(currentPack);
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::packRequestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::packRequestFailed);
|
||||
}
|
||||
|
||||
void ListModel::packRequestFinished()
|
||||
{
|
||||
if (!jobPtr || m_aborted)
|
||||
return;
|
||||
|
||||
jobPtr.reset();
|
||||
remainingPacks.removeOne(currentPack);
|
||||
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
|
||||
|
||||
if(parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << response;
|
||||
return;
|
||||
}
|
||||
|
||||
auto obj = doc.object();
|
||||
|
||||
ModpacksCH::Modpack pack;
|
||||
try
|
||||
{
|
||||
ModpacksCH::loadModpack(pack, obj);
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
qDebug() << QString::fromUtf8(response);
|
||||
qWarning() << "Error while reading pack manifest from ModpacksCH: " << e.cause();
|
||||
return;
|
||||
}
|
||||
|
||||
// Since there is no guarantee that packs have a version, this will just
|
||||
// ignore those "dud" packs.
|
||||
if (pack.versions.empty())
|
||||
{
|
||||
qWarning() << "ModpacksCH Pack " << pack.id << " ignored. reason: lacking any versions";
|
||||
}
|
||||
else
|
||||
{
|
||||
beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size());
|
||||
modpacks.append(pack);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
if(!remainingPacks.isEmpty()) {
|
||||
currentPack = remainingPacks.at(0);
|
||||
requestPack();
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::packRequestFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.removeOne(currentPack);
|
||||
}
|
||||
|
||||
void ListModel::logoLoaded(QString logo, bool stale)
|
||||
{
|
||||
auto & logoObj = m_logoMap[logo];
|
||||
logoObj.downloadJob.reset();
|
||||
QString smallPath = logoObj.fullpath + ".small";
|
||||
|
||||
QFileInfo smallInfo(smallPath);
|
||||
|
||||
if(stale || !smallInfo.exists()) {
|
||||
QImage image(logoObj.fullpath);
|
||||
if (image.isNull())
|
||||
{
|
||||
logoObj.failed = true;
|
||||
return;
|
||||
}
|
||||
QImage small;
|
||||
if (image.width() > image.height()) {
|
||||
small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation);
|
||||
}
|
||||
else {
|
||||
small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation);
|
||||
}
|
||||
QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2);
|
||||
QImage square(QSize(256, 256), QImage::Format_ARGB32);
|
||||
square.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&square);
|
||||
painter.drawImage(offset, small);
|
||||
painter.end();
|
||||
|
||||
square.save(logoObj.fullpath + ".small", "PNG");
|
||||
}
|
||||
|
||||
logoObj.result = QIcon(logoObj.fullpath + ".small");
|
||||
for(int i = 0; i < modpacks.size(); i++) {
|
||||
if(modpacks[i].name == logo) {
|
||||
emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::logoFailed(QString logo)
|
||||
{
|
||||
m_logoMap[logo].failed = true;
|
||||
m_logoMap[logo].downloadJob.reset();
|
||||
}
|
||||
|
||||
void ListModel::requestLogo(QString logo, QString url)
|
||||
{
|
||||
if(m_logoMap.contains(logo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0)));
|
||||
|
||||
bool stale = entry->isStale();
|
||||
|
||||
auto job = makeShared<NetJob>(QString("ModpacksCH Icon Download %1").arg(logo), APPLICATION->network());
|
||||
job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
|
||||
|
||||
auto fullPath = entry->getFullPath();
|
||||
QObject::connect(job.get(), &NetJob::finished, this, [this, logo, fullPath, stale]
|
||||
{
|
||||
logoLoaded(logo, stale);
|
||||
});
|
||||
|
||||
QObject::connect(job.get(), &NetJob::failed, this, [this, logo]
|
||||
{
|
||||
logoFailed(logo);
|
||||
});
|
||||
|
||||
auto &newLogoEntry = m_logoMap[logo];
|
||||
newLogoEntry.downloadJob = job;
|
||||
newLogoEntry.fullpath = fullPath;
|
||||
job->start();
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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 <QAbstractListModel>
|
||||
|
||||
#include "modplatform/modpacksch/FTBPackManifest.h"
|
||||
#include "net/NetJob.h"
|
||||
#include <QIcon>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
struct Logo {
|
||||
QString fullpath;
|
||||
NetJob::Ptr downloadJob;
|
||||
QIcon result;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
typedef QMap<QString, Logo> LogoMap;
|
||||
typedef std::function<void(QString)> LogoCallback;
|
||||
|
||||
class ListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListModel(QObject *parent);
|
||||
virtual ~ListModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
void request();
|
||||
void abortRequest();
|
||||
|
||||
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
|
||||
|
||||
[[nodiscard]] bool isMakingRequest() const { return jobPtr.get(); }
|
||||
[[nodiscard]] bool wasAborted() const { return m_aborted; }
|
||||
|
||||
private slots:
|
||||
void requestFinished();
|
||||
void requestFailed(QString reason);
|
||||
|
||||
void requestPack();
|
||||
void packRequestFinished();
|
||||
void packRequestFailed(QString reason);
|
||||
|
||||
void logoFailed(QString logo);
|
||||
void logoLoaded(QString logo, bool stale);
|
||||
|
||||
private:
|
||||
void requestLogo(QString file, QString url);
|
||||
|
||||
private:
|
||||
bool m_aborted = false;
|
||||
|
||||
QList<ModpacksCH::Modpack> modpacks;
|
||||
LogoMap m_logoMap;
|
||||
|
||||
NetJob::Ptr jobPtr;
|
||||
int currentPack;
|
||||
QList<int> remainingPacks;
|
||||
QByteArray response;
|
||||
};
|
||||
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2021 Philip T <me@phit.link>
|
||||
*
|
||||
* 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 "FtbPage.h"
|
||||
#include "ui_FtbPage.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "ui/dialogs/NewInstanceDialog.h"
|
||||
#include "modplatform/modpacksch/FTBPackInstallTask.h"
|
||||
|
||||
#include "Markdown.h"
|
||||
|
||||
FtbPage::FtbPage(NewInstanceDialog* dialog, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::FtbPage), dialog(dialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
filterModel = new Ftb::FilterModel(this);
|
||||
listModel = new Ftb::ListModel(this);
|
||||
filterModel->setSourceModel(listModel);
|
||||
ui->packView->setModel(filterModel);
|
||||
ui->packView->setSortingEnabled(true);
|
||||
ui->packView->header()->hide();
|
||||
ui->packView->setIndentation(0);
|
||||
|
||||
ui->searchEdit->installEventFilter(this);
|
||||
|
||||
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
|
||||
|
||||
for(int i = 0; i < filterModel->getAvailableSortings().size(); i++)
|
||||
{
|
||||
ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i));
|
||||
}
|
||||
ui->sortByBox->setCurrentText(filterModel->translateCurrentSorting());
|
||||
|
||||
connect(ui->searchEdit, &QLineEdit::textChanged, this, &FtbPage::triggerSearch);
|
||||
connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &FtbPage::onSortingSelectionChanged);
|
||||
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FtbPage::onSelectionChanged);
|
||||
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FtbPage::onVersionSelectionChanged);
|
||||
|
||||
ui->packDescription->setMetaEntry("FTBPacks");
|
||||
}
|
||||
|
||||
FtbPage::~FtbPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool FtbPage::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->key() == Qt::Key_Return) {
|
||||
triggerSearch();
|
||||
keyEvent->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
bool FtbPage::shouldDisplay() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FtbPage::retranslate()
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
void FtbPage::openedImpl()
|
||||
{
|
||||
if(!initialised || listModel->wasAborted())
|
||||
{
|
||||
listModel->request();
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void FtbPage::closedImpl()
|
||||
{
|
||||
if (listModel->isMakingRequest())
|
||||
listModel->abortRequest();
|
||||
}
|
||||
|
||||
void FtbPage::suggestCurrent()
|
||||
{
|
||||
if(!isOpened)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedVersion.isEmpty())
|
||||
{
|
||||
dialog->setSuggestedPack();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog->setSuggestedPack(selected.name, selectedVersion, new ModpacksCH::PackInstallTask(selected, selectedVersion, this));
|
||||
for(auto art : selected.art) {
|
||||
if(art.type == "square") {
|
||||
QString editedLogoName;
|
||||
editedLogoName = selected.name;
|
||||
|
||||
listModel->getLogo(selected.name, art.url, [this, editedLogoName](QString logo)
|
||||
{
|
||||
dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FtbPage::triggerSearch()
|
||||
{
|
||||
filterModel->setSearchTerm(ui->searchEdit->text());
|
||||
}
|
||||
|
||||
void FtbPage::onSortingSelectionChanged(QString data)
|
||||
{
|
||||
auto toSet = filterModel->getAvailableSortings().value(data);
|
||||
filterModel->setSorting(toSet);
|
||||
}
|
||||
|
||||
void FtbPage::onSelectionChanged(QModelIndex first, QModelIndex second)
|
||||
{
|
||||
ui->versionSelectionBox->clear();
|
||||
|
||||
if(!first.isValid())
|
||||
{
|
||||
if(isOpened)
|
||||
{
|
||||
dialog->setSuggestedPack();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
selected = filterModel->data(first, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
|
||||
QString output = markdownToHTML(selected.description.toUtf8());
|
||||
ui->packDescription->setHtml(output);
|
||||
|
||||
// reverse foreach, so that the newest versions are first
|
||||
for (auto i = selected.versions.size(); i--;) {
|
||||
ui->versionSelectionBox->addItem(selected.versions.at(i).name);
|
||||
}
|
||||
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void FtbPage::onVersionSelectionChanged(QString data)
|
||||
{
|
||||
if(data.isNull() || data.isEmpty())
|
||||
{
|
||||
selectedVersion = "";
|
||||
return;
|
||||
}
|
||||
|
||||
selectedVersion = data;
|
||||
suggestCurrent();
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 "FtbFilterModel.h"
|
||||
#include "FtbListModel.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class FtbPage;
|
||||
}
|
||||
|
||||
class NewInstanceDialog;
|
||||
|
||||
class FtbPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FtbPage(NewInstanceDialog* dialog, QWidget *parent = 0);
|
||||
virtual ~FtbPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return "FTB";
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return APPLICATION->getThemedIcon("ftb_logo");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "ftb";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "FTB-platform";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
void retranslate() override;
|
||||
|
||||
void openedImpl() override;
|
||||
void closedImpl() override;
|
||||
|
||||
bool eventFilter(QObject * watched, QEvent * event) override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
|
||||
private slots:
|
||||
void triggerSearch();
|
||||
|
||||
void onSortingSelectionChanged(QString data);
|
||||
void onSelectionChanged(QModelIndex first, QModelIndex second);
|
||||
void onVersionSelectionChanged(QString data);
|
||||
|
||||
private:
|
||||
Ui::FtbPage *ui = nullptr;
|
||||
NewInstanceDialog* dialog = nullptr;
|
||||
Ftb::ListModel* listModel = nullptr;
|
||||
Ftb::FilterModel* filterModel = nullptr;
|
||||
|
||||
ModpacksCH::Modpack selected;
|
||||
QString selectedVersion;
|
||||
|
||||
bool initialised { false };
|
||||
};
|
@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FtbPage</class>
|
||||
<widget class="QWidget" name="FtbPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>875</width>
|
||||
<height>745</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0" rowminimumheight="0" columnminimumwidth="0,0,0">
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="versionSelectionBox"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Version selected:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="sortByBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeView" name="packView">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ProjectDescriptionPage</class>
|
||||
<extends>QTextBrowser</extends>
|
||||
<header>ui/widgets/ProjectDescriptionPage.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>searchEdit</tabstop>
|
||||
<tabstop>versionSelectionBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -51,6 +51,7 @@ void ProgressWidget::watch(const Task* task)
|
||||
|
||||
connect(m_task, &Task::finished, this, &ProgressWidget::handleTaskFinish);
|
||||
connect(m_task, &Task::status, this, &ProgressWidget::handleTaskStatus);
|
||||
// TODO: should we connect &Task::details
|
||||
connect(m_task, &Task::progress, this, &ProgressWidget::handleTaskProgress);
|
||||
connect(m_task, &Task::destroyed, this, &ProgressWidget::taskDestroyed);
|
||||
|
||||
|
58
launcher/ui/widgets/SubTaskProgressBar.cpp
Normal file
58
launcher/ui/widgets/SubTaskProgressBar.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PrismLaucher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SubTaskProgressBar.h"
|
||||
#include "ui_SubTaskProgressBar.h"
|
||||
|
||||
unique_qobject_ptr<SubTaskProgressBar> SubTaskProgressBar::create(QWidget* parent)
|
||||
{
|
||||
auto progress_bar = new SubTaskProgressBar(parent);
|
||||
return unique_qobject_ptr<SubTaskProgressBar>(progress_bar);
|
||||
}
|
||||
|
||||
SubTaskProgressBar::SubTaskProgressBar(QWidget* parent)
|
||||
: ui(new Ui::SubTaskProgressBar)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
SubTaskProgressBar::~SubTaskProgressBar()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SubTaskProgressBar::setRange(int min, int max)
|
||||
{
|
||||
ui->progressBar->setRange(min, max);
|
||||
}
|
||||
|
||||
void SubTaskProgressBar::setValue(int value)
|
||||
{
|
||||
ui->progressBar->setValue(value);
|
||||
}
|
||||
|
||||
void SubTaskProgressBar::setStatus(QString status)
|
||||
{
|
||||
ui->statusLabel->setText(status);
|
||||
}
|
||||
|
||||
void SubTaskProgressBar::setDetails(QString details)
|
||||
{
|
||||
ui->statusDetailsLabel->setText(details);
|
||||
}
|
||||
|
48
launcher/ui/widgets/SubTaskProgressBar.h
Normal file
48
launcher/ui/widgets/SubTaskProgressBar.h
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PrismLaucher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
namespace Ui {
|
||||
class SubTaskProgressBar;
|
||||
}
|
||||
|
||||
class SubTaskProgressBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static unique_qobject_ptr<SubTaskProgressBar> create(QWidget* parent = nullptr);
|
||||
|
||||
SubTaskProgressBar(QWidget* parent = nullptr);
|
||||
~SubTaskProgressBar();
|
||||
|
||||
void setRange(int min, int max);
|
||||
void setValue(int value);
|
||||
void setStatus(QString status);
|
||||
void setDetails(QString details);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Ui::SubTaskProgressBar* ui;
|
||||
|
||||
};
|
94
launcher/ui/widgets/SubTaskProgressBar.ui
Normal file
94
launcher/ui/widgets/SubTaskProgressBar.ui
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SubTaskProgressBar</class>
|
||||
<widget class="QWidget" name="SubTaskProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>312</width>
|
||||
<height>86</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sub Task Status...</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="statusDetailsLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status Details</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Reference in New Issue
Block a user