mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2025-06-12 13:17:41 +02:00
Merge remote-tracking branch 'upstream/develop' into unify-mc-settings
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
@ -51,11 +51,35 @@
|
||||
#include <settings/SettingsObject.h>
|
||||
#include "Application.h"
|
||||
|
||||
constexpr int MaxMclogsLines = 25000;
|
||||
constexpr int InitialMclogsLines = 10000;
|
||||
constexpr int FinalMclogsLines = 14900;
|
||||
|
||||
QString truncateLogForMclogs(const QString& logContent)
|
||||
{
|
||||
QStringList lines = logContent.split("\n");
|
||||
if (lines.size() > MaxMclogsLines) {
|
||||
QString truncatedLog = lines.mid(0, InitialMclogsLines).join("\n");
|
||||
truncatedLog +=
|
||||
"\n\n\n\n\n\n\n\n\n\n"
|
||||
"------------------------------------------------------------\n"
|
||||
"----------------------- Log truncated ----------------------\n"
|
||||
"------------------------------------------------------------\n"
|
||||
"----- Middle portion omitted to fit mclo.gs size limits ----\n"
|
||||
"------------------------------------------------------------\n"
|
||||
"\n\n\n\n\n\n\n\n\n\n";
|
||||
truncatedLog += lines.mid(lines.size() - FinalMclogsLines - 1).join("\n");
|
||||
return truncatedLog;
|
||||
}
|
||||
return logContent;
|
||||
}
|
||||
|
||||
std::optional<QString> GuiUtil::uploadPaste(const QString& name, const QString& text, QWidget* parentWidget)
|
||||
{
|
||||
ProgressDialog dialog(parentWidget);
|
||||
auto pasteTypeSetting = static_cast<PasteUpload::PasteType>(APPLICATION->settings()->get("PastebinType").toInt());
|
||||
auto pasteCustomAPIBaseSetting = APPLICATION->settings()->get("PastebinCustomAPIBase").toString();
|
||||
bool shouldTruncate = false;
|
||||
|
||||
{
|
||||
QUrl baseUrl;
|
||||
@ -75,10 +99,36 @@ std::optional<QString> GuiUtil::uploadPaste(const QString& name, const QString&
|
||||
|
||||
if (response != QMessageBox::Yes)
|
||||
return {};
|
||||
|
||||
if (baseUrl.toString() == "https://api.mclo.gs" && text.count("\n") > MaxMclogsLines) {
|
||||
auto truncateResponse = CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Confirm Truncation"),
|
||||
QObject::tr("The log has %1 lines, exceeding mclo.gs' limit of %2.\n"
|
||||
"The launcher can keep the first %3 and last %4 lines, trimming the middle.\n\n"
|
||||
"If you choose 'No', mclo.gs will only keep the first %2 lines, cutting off "
|
||||
"potentially useful info like crashes at the end.\n\n"
|
||||
"Proceed with truncation?")
|
||||
.arg(text.count("\n"))
|
||||
.arg(MaxMclogsLines)
|
||||
.arg(InitialMclogsLines)
|
||||
.arg(FinalMclogsLines),
|
||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No)
|
||||
->exec();
|
||||
|
||||
if (truncateResponse == QMessageBox::Cancel) {
|
||||
return {};
|
||||
}
|
||||
shouldTruncate = truncateResponse == QMessageBox::Yes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text, pasteCustomAPIBaseSetting, pasteTypeSetting));
|
||||
QString textToUpload = text;
|
||||
if (shouldTruncate) {
|
||||
textToUpload = truncateLogForMclogs(text);
|
||||
}
|
||||
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, textToUpload, pasteCustomAPIBaseSetting, pasteTypeSetting));
|
||||
|
||||
dialog.execWithTask(paste.get());
|
||||
if (!paste->wasSuccessful()) {
|
||||
|
@ -288,6 +288,8 @@ void BlockedModsDialog::checkMatchHash(QString hash, QString path)
|
||||
|
||||
qDebug() << "[Blocked Mods Dialog] Checking for match on hash: " << hash << "| From path:" << path;
|
||||
|
||||
auto downloadDir = QFileInfo(APPLICATION->settings()->get("DownloadsDir").toString()).absoluteFilePath();
|
||||
auto moveFiles = APPLICATION->settings()->get("MoveModsFromDownloadsDir").toBool();
|
||||
for (auto& mod : m_mods) {
|
||||
if (mod.matched) {
|
||||
continue;
|
||||
@ -295,6 +297,9 @@ void BlockedModsDialog::checkMatchHash(QString hash, QString path)
|
||||
if (mod.hash.compare(hash, Qt::CaseInsensitive) == 0) {
|
||||
mod.matched = true;
|
||||
mod.localPath = path;
|
||||
if (moveFiles) {
|
||||
mod.move = QFileInfo(path).absoluteFilePath().startsWith(downloadDir);
|
||||
}
|
||||
match = true;
|
||||
|
||||
qDebug() << "[Blocked Mods Dialog] Hash match found:" << mod.name << hash << "| From path:" << path;
|
||||
@ -346,6 +351,8 @@ bool BlockedModsDialog::checkValidPath(QString path)
|
||||
return fsName.compare(metaName) == 0;
|
||||
};
|
||||
|
||||
auto downloadDir = QFileInfo(APPLICATION->settings()->get("DownloadsDir").toString()).absoluteFilePath();
|
||||
auto moveFiles = APPLICATION->settings()->get("MoveModsFromDownloadsDir").toBool();
|
||||
for (auto& mod : m_mods) {
|
||||
if (compare(filename, mod.name)) {
|
||||
// if the mod is not yet matched and doesn't have a hash then
|
||||
@ -353,6 +360,9 @@ bool BlockedModsDialog::checkValidPath(QString path)
|
||||
if (!mod.matched && mod.hash.isEmpty()) {
|
||||
mod.matched = true;
|
||||
mod.localPath = path;
|
||||
if (moveFiles) {
|
||||
mod.move = QFileInfo(path).absoluteFilePath().startsWith(downloadDir);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path;
|
||||
|
@ -42,6 +42,7 @@ struct BlockedMod {
|
||||
bool matched;
|
||||
QString localPath;
|
||||
QString targetFolder;
|
||||
bool move = false;
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -1,64 +0,0 @@
|
||||
/* 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 "EditAccountDialog.h"
|
||||
#include <DesktopServices.h>
|
||||
#include <QPushButton>
|
||||
#include <QUrl>
|
||||
#include "ui_EditAccountDialog.h"
|
||||
|
||||
EditAccountDialog::EditAccountDialog(const QString& text, QWidget* parent, int flags) : QDialog(parent), ui(new Ui::EditAccountDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->label->setText(text);
|
||||
ui->label->setVisible(!text.isEmpty());
|
||||
|
||||
ui->userTextBox->setEnabled(flags & UsernameField);
|
||||
ui->passTextBox->setEnabled(flags & PasswordField);
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
|
||||
}
|
||||
|
||||
EditAccountDialog::~EditAccountDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditAccountDialog::on_label_linkActivated(const QString& link)
|
||||
{
|
||||
DesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
|
||||
void EditAccountDialog::setUsername(const QString& user) const
|
||||
{
|
||||
ui->userTextBox->setText(user);
|
||||
}
|
||||
|
||||
QString EditAccountDialog::username() const
|
||||
{
|
||||
return ui->userTextBox->text();
|
||||
}
|
||||
|
||||
void EditAccountDialog::setPassword(const QString& pass) const
|
||||
{
|
||||
ui->passTextBox->setText(pass);
|
||||
}
|
||||
|
||||
QString EditAccountDialog::password() const
|
||||
{
|
||||
return ui->passTextBox->text();
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* 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>
|
||||
|
||||
namespace Ui {
|
||||
class EditAccountDialog;
|
||||
}
|
||||
|
||||
class EditAccountDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditAccountDialog(const QString& text = "", QWidget* parent = 0, int flags = UsernameField | PasswordField);
|
||||
~EditAccountDialog();
|
||||
|
||||
void setUsername(const QString& user) const;
|
||||
void setPassword(const QString& pass) const;
|
||||
|
||||
QString username() const;
|
||||
QString password() const;
|
||||
|
||||
enum Flags {
|
||||
NoFlags = 0,
|
||||
|
||||
//! Specifies that the dialog should have a username field.
|
||||
UsernameField,
|
||||
|
||||
//! Specifies that the dialog should have a password field.
|
||||
PasswordField,
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_label_linkActivated(const QString& link);
|
||||
|
||||
private:
|
||||
Ui::EditAccountDialog* ui;
|
||||
};
|
@ -1,94 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditAccountDialog</class>
|
||||
<widget class="QDialog" name="EditAccountDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>148</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>EditAccountDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>EditAccountDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -15,7 +15,9 @@
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QKeyEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
@ -33,6 +35,15 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
|
||||
searchBar = new QLineEdit(this);
|
||||
searchBar->setPlaceholderText(tr("Search..."));
|
||||
ui->verticalLayout->insertWidget(0, searchBar);
|
||||
|
||||
proxyModel = new QSortFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(APPLICATION->icons().get());
|
||||
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
ui->iconView->setModel(proxyModel);
|
||||
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->setViewMode(QListView::IconMode);
|
||||
contentsWidget->setFlow(QListView::LeftToRight);
|
||||
@ -57,7 +68,7 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui
|
||||
|
||||
contentsWidget->installEventFilter(this);
|
||||
|
||||
contentsWidget->setModel(APPLICATION->icons().get());
|
||||
contentsWidget->setModel(proxyModel);
|
||||
|
||||
// NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win.
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
|
||||
@ -76,6 +87,9 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui
|
||||
|
||||
auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole);
|
||||
connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder);
|
||||
connect(searchBar, &QLineEdit::textChanged, this, &IconPickerDialog::filterIcons);
|
||||
// Prevent incorrect indices from e.g. filesystem changes
|
||||
connect(APPLICATION->icons().get(), &IconList::iconUpdated, this, [this]() { proxyModel->invalidate(); });
|
||||
}
|
||||
|
||||
bool IconPickerDialog::eventFilter(QObject* obj, QEvent* evt)
|
||||
@ -162,5 +176,10 @@ IconPickerDialog::~IconPickerDialog()
|
||||
|
||||
void IconPickerDialog::openFolder()
|
||||
{
|
||||
DesktopServices::openPath(APPLICATION->icons()->getDirectory(), true);
|
||||
DesktopServices::openPath(APPLICATION->icons()->iconDirectory(selectedIconKey), true);
|
||||
}
|
||||
|
||||
void IconPickerDialog::filterIcons(const QString& query)
|
||||
{
|
||||
proxyModel->setFilterFixedString(query);
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
#pragma once
|
||||
#include <QDialog>
|
||||
#include <QItemSelection>
|
||||
#include <QLineEdit>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
namespace Ui {
|
||||
class IconPickerDialog;
|
||||
@ -36,6 +38,8 @@ class IconPickerDialog : public QDialog {
|
||||
private:
|
||||
Ui::IconPickerDialog* ui;
|
||||
QPushButton* buttonRemove;
|
||||
QLineEdit* searchBar;
|
||||
QSortFilterProxyModel* proxyModel;
|
||||
|
||||
private slots:
|
||||
void selectionChanged(QItemSelection, QItemSelection);
|
||||
@ -44,4 +48,5 @@ class IconPickerDialog : public QDialog {
|
||||
void addNewIcon();
|
||||
void removeSelectedIcon();
|
||||
void openFolder();
|
||||
void filterIcons(const QString& text);
|
||||
};
|
||||
|
@ -30,6 +30,9 @@ Choose your name carefully:</string>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>nameEdit</cstring>
|
||||
</property>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "ResourceUpdateDialog.h"
|
||||
#include "Application.h"
|
||||
#include "ChooseProviderDialog.h"
|
||||
#include "CustomMessageBox.h"
|
||||
#include "ProgressDialog.h"
|
||||
@ -7,6 +8,7 @@
|
||||
#include "minecraft/mod/tasks/GetModDependenciesTask.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/flame/FlameAPI.h"
|
||||
#include "tasks/SequentialTask.h"
|
||||
#include "ui_ReviewMessageBox.h"
|
||||
|
||||
#include "Markdown.h"
|
||||
@ -411,8 +413,14 @@ void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool try_others,
|
||||
connect(task.get(), &EnsureMetadataTask::metadataFailed, [this](Resource* candidate) { onMetadataFailed(candidate, false); });
|
||||
connect(task.get(), &EnsureMetadataTask::failed,
|
||||
[this](const QString& reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||
|
||||
m_second_try_metadata->addTask(task);
|
||||
if (task->getHashingTask()) {
|
||||
auto seq = makeShared<SequentialTask>();
|
||||
seq->addTask(task->getHashingTask());
|
||||
seq->addTask(task);
|
||||
m_second_try_metadata->addTask(seq);
|
||||
} else {
|
||||
m_second_try_metadata->addTask(task);
|
||||
}
|
||||
} else {
|
||||
QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") };
|
||||
|
||||
|
@ -207,7 +207,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/#section/Authentication">documentation</a> for more information.</p></body></html></string>
|
||||
<string><html><head/><body><p>Note: you only need to set this to access private data. Read the <a href="https://docs.modrinth.com/api/#authentication">documentation</a> for more information.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
@ -232,6 +232,7 @@ void LauncherPage::applySettings()
|
||||
s->set("SkinsDir", ui->skinsDirTextBox->text());
|
||||
s->set("JavaDir", ui->javaDirTextBox->text());
|
||||
s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked());
|
||||
s->set("MoveModsFromDownloadsDir", ui->downloadsDirMoveCheckBox->isChecked());
|
||||
|
||||
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
|
||||
switch (sortMode) {
|
||||
@ -296,6 +297,7 @@ void LauncherPage::loadSettings()
|
||||
ui->skinsDirTextBox->setText(s->get("SkinsDir").toString());
|
||||
ui->javaDirTextBox->setText(s->get("JavaDir").toString());
|
||||
ui->downloadsDirWatchRecursiveCheckBox->setChecked(s->get("DownloadsDirWatchRecursive").toBool());
|
||||
ui->downloadsDirMoveCheckBox->setChecked(s->get("MoveModsFromDownloadsDir").toBool());
|
||||
|
||||
QString sortMode = s->get("InstSortMode").toString();
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>511</width>
|
||||
<width>562</width>
|
||||
<height>726</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -38,7 +38,7 @@
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="featuresTab">
|
||||
<attribute name="title">
|
||||
@ -48,7 +48,7 @@
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
@ -58,8 +58,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>473</width>
|
||||
<height>690</height>
|
||||
<width>570</width>
|
||||
<height>692</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
@ -156,14 +156,28 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="downloadsDirWatchRecursiveCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge).</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Check downloads folder recursively</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="downloadModsCheckLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="downloadsDirWatchRecursiveCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>When enabled, in addition to the downloads folder, its sub folders will also be searched when looking for resources (e.g. when looking for blocked mods on CurseForge).</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Check downloads folder recursively</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="downloadsDirMoveCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>When enabled, it will move blocked resources instead of copying them.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move blocked resources</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="downloadsDirTextBox"/>
|
||||
@ -585,7 +599,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
@ -637,15 +651,33 @@
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>autoUpdateCheckBox</tabstop>
|
||||
<tabstop>updateIntervalSpinBox</tabstop>
|
||||
<tabstop>instDirTextBox</tabstop>
|
||||
<tabstop>instDirBrowseBtn</tabstop>
|
||||
<tabstop>modsDirTextBox</tabstop>
|
||||
<tabstop>modsDirBrowseBtn</tabstop>
|
||||
<tabstop>iconsDirTextBox</tabstop>
|
||||
<tabstop>iconsDirBrowseBtn</tabstop>
|
||||
<tabstop>javaDirTextBox</tabstop>
|
||||
<tabstop>javaDirBrowseBtn</tabstop>
|
||||
<tabstop>skinsDirTextBox</tabstop>
|
||||
<tabstop>skinsDirBrowseBtn</tabstop>
|
||||
<tabstop>downloadsDirTextBox</tabstop>
|
||||
<tabstop>downloadsDirBrowseBtn</tabstop>
|
||||
<tabstop>downloadsDirWatchRecursiveCheckBox</tabstop>
|
||||
<tabstop>metadataDisableBtn</tabstop>
|
||||
<tabstop>dependenciesDisableBtn</tabstop>
|
||||
<tabstop>skipModpackUpdatePromptBtn</tabstop>
|
||||
<tabstop>numberOfConcurrentTasksSpinBox</tabstop>
|
||||
<tabstop>numberOfConcurrentDownloadsSpinBox</tabstop>
|
||||
<tabstop>numberOfManualRetriesSpinBox</tabstop>
|
||||
<tabstop>timeoutSecondsSpinBox</tabstop>
|
||||
<tabstop>sortLastLaunchedBtn</tabstop>
|
||||
<tabstop>sortByNameBtn</tabstop>
|
||||
<tabstop>catOpacitySpinBox</tabstop>
|
||||
<tabstop>preferMenuBarCheckBox</tabstop>
|
||||
<tabstop>lineLimitSpinBox</tabstop>
|
||||
<tabstop>checkStopLogging</tabstop>
|
||||
<tabstop>consoleFont</tabstop>
|
||||
|
@ -60,7 +60,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
<enum>QAbstractItemView::DropOnly</enum>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
|
@ -252,8 +252,11 @@ void VersionPage::updateButtons(int row)
|
||||
bool VersionPage::reloadPackProfile()
|
||||
{
|
||||
try {
|
||||
m_profile->reload(Net::Mode::Online);
|
||||
return true;
|
||||
auto result = m_profile->reload(Net::Mode::Online);
|
||||
if (!result) {
|
||||
QMessageBox::critical(this, tr("Error"), result.error);
|
||||
}
|
||||
return result;
|
||||
} catch (const Exception& e) {
|
||||
QMessageBox::critical(this, tr("Error"), e.cause());
|
||||
return false;
|
||||
|
@ -13,6 +13,11 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Note: If your FTB instances are not in the default location, select it using the button next to search.</string>
|
||||
</property>
|
||||
|
@ -36,6 +36,9 @@
|
||||
|
||||
ThemeManager::ThemeManager()
|
||||
{
|
||||
QIcon::setFallbackThemeName(QIcon::themeName());
|
||||
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << m_iconThemeFolder.path());
|
||||
|
||||
themeDebugLog() << "Determining System Widget Theme...";
|
||||
const auto& style = QApplication::style();
|
||||
m_defaultStyle = style->objectName();
|
||||
@ -93,10 +96,6 @@ void ThemeManager::initializeIcons()
|
||||
// set icon theme search path!
|
||||
themeDebugLog() << "<> Initializing Icon Themes";
|
||||
|
||||
auto searchPaths = QIcon::themeSearchPaths();
|
||||
searchPaths.append(m_iconThemeFolder.path());
|
||||
QIcon::setThemeSearchPaths(searchPaths);
|
||||
|
||||
for (const QString& id : builtinIcons) {
|
||||
IconTheme theme(id, QString(":/icons/%1").arg(id));
|
||||
if (!theme.load()) {
|
||||
@ -348,4 +347,4 @@ void ThemeManager::refresh()
|
||||
|
||||
initializeThemes();
|
||||
initializeCatPacks();
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
#include "DropLabel.h"
|
||||
|
||||
#include <QDropEvent>
|
||||
#include <QMimeData>
|
||||
|
||||
DropLabel::DropLabel(QWidget* parent) : QLabel(parent)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void DropLabel::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void DropLabel::dragMoveEvent(QDragMoveEvent* event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void DropLabel::dragLeaveEvent(QDragLeaveEvent* event)
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void DropLabel::dropEvent(QDropEvent* event)
|
||||
{
|
||||
const QMimeData* mimeData = event->mimeData();
|
||||
|
||||
if (!mimeData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mimeData->hasUrls()) {
|
||||
auto urls = mimeData->urls();
|
||||
emit droppedURLs(urls);
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class DropLabel : public QLabel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DropLabel(QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent* event) override;
|
||||
};
|
@ -279,16 +279,17 @@ void ModFilterWidget::onSideFilterChanged()
|
||||
{
|
||||
QString side;
|
||||
|
||||
if (ui->clientSide->isChecked() != ui->serverSide->isChecked()) {
|
||||
if (ui->clientSide->isChecked())
|
||||
side = "client";
|
||||
else
|
||||
side = "server";
|
||||
if (ui->clientSide->isChecked() && !ui->serverSide->isChecked()) {
|
||||
side = "client";
|
||||
} else if (!ui->clientSide->isChecked() && ui->serverSide->isChecked()) {
|
||||
side = "server";
|
||||
} else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) {
|
||||
side = "both";
|
||||
} else {
|
||||
// both are checked or none are checked; in either case no filtering will happen
|
||||
side = "";
|
||||
}
|
||||
|
||||
|
||||
m_filter_changed = side != m_filter->side;
|
||||
m_filter->side = side;
|
||||
if (m_filter_changed)
|
||||
|
@ -47,6 +47,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -68,6 +71,9 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
Reference in New Issue
Block a user