chore(clang-tidy): modernize the code

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2026-05-10 23:16:46 +03:00
parent 170d59de2a
commit 1af838db2e
No known key found for this signature in database
GPG key ID: 55EF5DA53DB36318
38 changed files with 1088 additions and 956 deletions

View file

@ -46,7 +46,7 @@ class PixmapCache final : public QObject {
Q_OBJECT
public:
PixmapCache(QObject* parent) : QObject(parent) {}
explicit PixmapCache(QObject* parent) : QObject(parent) {}
~PixmapCache() override = default;
static PixmapCache& instance() { return *s_instance; }
@ -90,8 +90,9 @@ class PixmapCache final : public QObject {
}
bool _replace(const QPixmapCache::Key& key, const QPixmap& pixmap)
{
if (!key.isValid())
if (!key.isValid()) {
return false;
}
remove(key);
const_cast<QPixmapCache::Key&>(key) = insert(pixmap);
return key.isValid();
@ -108,33 +109,33 @@ class PixmapCache final : public QObject {
*/
bool _markCacheMissByEviciton()
{
static constexpr uint maxCache = static_cast<uint>(std::numeric_limits<int>::max()) / 4;
static constexpr uint step = 10240;
static constexpr int oneSecond = 1000;
static constexpr uint s_maxCache = static_cast<uint>(std::numeric_limits<int>::max()) / 4;
static constexpr uint s_step = 10240;
static constexpr int s_oneSecond = 1000;
auto now = QTime::currentTime();
if (!m_last_cache_miss_by_eviciton.isNull()) {
auto diff = m_last_cache_miss_by_eviciton.msecsTo(now);
if (diff < oneSecond) { // less than a second ago
++m_consecutive_fast_evicitons;
if (!m_lastCacheMissByEviciton.isNull()) {
auto diff = m_lastCacheMissByEviciton.msecsTo(now);
if (diff < s_oneSecond) { // less than a second ago
++m_consecutiveFastEvicitons;
} else {
m_consecutive_fast_evicitons = 0;
m_consecutiveFastEvicitons = 0;
}
}
m_last_cache_miss_by_eviciton = now;
if (m_consecutive_fast_evicitons >= m_consecutive_fast_evicitons_threshold) {
m_lastCacheMissByEviciton = now;
if (m_consecutiveFastEvicitons >= m_consecutiveFastEvicitonsThreshold) {
// increase the cache size
uint newSize = _cacheLimit() + step;
if (newSize >= maxCache) { // increase it until you overflow :D
newSize = maxCache;
qDebug() << m_consecutive_fast_evicitons
uint newSize = _cacheLimit() + s_step;
if (newSize >= s_maxCache) { // increase it until you overflow :D
newSize = s_maxCache;
qDebug() << m_consecutiveFastEvicitons
<< tr("pixmap cache misses by eviction happened too fast, doing nothing as the cache size reached it's limit");
} else {
qDebug() << m_consecutive_fast_evicitons
<< tr("pixmap cache misses by eviction happened too fast, increasing cache size to") << static_cast<int>(newSize);
qDebug() << m_consecutiveFastEvicitons << tr("pixmap cache misses by eviction happened too fast, increasing cache size to")
<< static_cast<int>(newSize);
}
_setCacheLimit(static_cast<int>(newSize));
m_consecutive_fast_evicitons = 0;
m_consecutiveFastEvicitons = 0;
return true;
}
return false;
@ -142,13 +143,13 @@ class PixmapCache final : public QObject {
bool _setFastEvictionThreshold(int threshold)
{
m_consecutive_fast_evicitons_threshold = threshold;
m_consecutiveFastEvicitonsThreshold = threshold;
return true;
}
private:
static PixmapCache* s_instance;
QTime m_last_cache_miss_by_eviciton;
int m_consecutive_fast_evicitons = 0;
int m_consecutive_fast_evicitons_threshold = 15;
QTime m_lastCacheMissByEviciton;
int m_consecutiveFastEvicitons = 0;
int m_consecutiveFastEvicitonsThreshold = 15;
};

View file

@ -44,21 +44,21 @@
class VersionFilterModel : public QSortFilterProxyModel {
Q_OBJECT
public:
VersionFilterModel(VersionProxyModel* parent) : QSortFilterProxyModel(parent)
explicit VersionFilterModel(VersionProxyModel* parent) : QSortFilterProxyModel(parent), m_parent(parent)
{
m_parent = parent;
setSortRole(BaseVersionList::SortRole);
sort(0, Qt::DescendingOrder);
}
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override
{
const auto& filters = m_parent->filters();
const QString& search = m_parent->search();
const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent);
const QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive))
if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) {
return false;
}
for (auto it = filters.begin(); it != filters.end(); ++it) {
auto data = sourceModel()->data(idx, it.key());
@ -84,14 +84,13 @@ class VersionFilterModel : public QSortFilterProxyModel {
VersionProxyModel* m_parent;
};
VersionProxyModel::VersionProxyModel(QObject* parent) : QAbstractProxyModel(parent)
VersionProxyModel::VersionProxyModel(QObject* parent) : QAbstractProxyModel(parent), m_filterModel(new VersionFilterModel(this))
{
filterModel = new VersionFilterModel(this);
connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged);
connect(filterModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted);
connect(filterModel, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted);
connect(filterModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved);
connect(filterModel, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved);
connect(m_filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged);
connect(m_filterModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted);
connect(m_filterModel, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted);
connect(m_filterModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved);
connect(m_filterModel, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved);
// FIXME: implement when needed
/*
connect(replacing, &QAbstractItemModel::rowsAboutToBeMoved, this, &VersionProxyModel::sourceRowsAboutToBeMoved);
@ -99,18 +98,20 @@ VersionProxyModel::VersionProxyModel(QObject* parent) : QAbstractProxyModel(pare
connect(replacing, &QAbstractItemModel::layoutAboutToBeChanged, this, &VersionProxyModel::sourceLayoutAboutToBeChanged);
connect(replacing, &QAbstractItemModel::layoutChanged, this, &VersionProxyModel::sourceLayoutChanged);
*/
connect(filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset);
connect(filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset);
connect(m_filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset);
connect(m_filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset);
QAbstractProxyModel::setSourceModel(filterModel);
QAbstractProxyModel::setSourceModel(m_filterModel);
}
QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (section < 0 || section >= m_columns.size())
return QVariant();
if (orientation != Qt::Horizontal)
return QVariant();
if (section < 0 || section >= m_columns.size()) {
return {};
}
if (orientation != Qt::Horizontal) {
return {};
}
auto column = m_columns[section];
if (role == Qt::DisplayRole) {
switch (column) {
@ -161,7 +162,7 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid()) {
return QVariant();
return {};
}
auto column = m_columns[index.column()];
auto parentIndex = mapToSource(index);
@ -196,11 +197,12 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
}
}
case Qt::ToolTipRole: {
if (column == Name && hasRecommended) {
if (column == Name && m_hasRecommended) {
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
if (value.toBool()) {
return tr("Recommended");
} else if (hasLatest) {
}
if (m_hasLatest) {
auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (latest.toBool()) {
return tr("Latest");
@ -210,11 +212,12 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole);
}
case Qt::DecorationRole: {
if (column == Name && hasRecommended) {
if (column == Name && m_hasRecommended) {
auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
if (recommenced.toBool()) {
return QIcon::fromTheme("star");
} else if (hasLatest) {
}
if (m_hasLatest) {
auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (latest.toBool()) {
return QIcon::fromTheme("bug");
@ -233,7 +236,7 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
return QVariant();
}
default: {
if (roles.contains((BaseVersionList::ModelRoles)role)) {
if (m_roles.contains((BaseVersionList::ModelRoles)role)) {
return sourceModel()->data(parentIndex, role);
}
return QVariant();
@ -266,18 +269,20 @@ QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex& par
{
// no trees here... shoo
if (parent.isValid()) {
return QModelIndex();
return {};
}
if (row < 0 || row >= sourceModel()->rowCount()) {
return {};
}
if (column < 0 || column >= columnCount()) {
return {};
}
if (row < 0 || row >= sourceModel()->rowCount())
return QModelIndex();
if (column < 0 || column >= columnCount())
return QModelIndex();
return QAbstractItemModel::createIndex(row, column);
}
int VersionProxyModel::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : m_columns.size();
return parent.isValid() ? 0 : static_cast<int>(m_columns.size());
}
int VersionProxyModel::rowCount(const QModelIndex& parent) const
@ -288,30 +293,31 @@ int VersionProxyModel::rowCount(const QModelIndex& parent) const
return 0;
}
void VersionProxyModel::sourceDataChanged(const QModelIndex& source_top_left, const QModelIndex& source_bottom_right)
void VersionProxyModel::sourceDataChanged(const QModelIndex& sourceTopLeft, const QModelIndex& sourceBottomRight)
{
if (source_top_left.parent() != source_bottom_right.parent())
return;
// whole row is getting changed
auto topLeft = createIndex(source_top_left.row(), 0);
auto bottomRight = createIndex(source_bottom_right.row(), columnCount() - 1);
emit dataChanged(topLeft, bottomRight);
}
void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
{
auto replacing = dynamic_cast<BaseVersionList*>(replacingRaw);
m_columns.clear();
if (!replacing) {
roles.clear();
filterModel->setSourceModel(replacing);
if (sourceTopLeft.parent() != sourceBottomRight.parent()) {
return;
}
roles = replacing->providesRoles();
if (roles.contains(BaseVersionList::VersionRole)) {
// whole row is getting changed
auto topLeft = createIndex(sourceTopLeft.row(), 0);
auto bottomRight = createIndex(sourceBottomRight.row(), columnCount() - 1);
emit dataChanged(topLeft, bottomRight);
}
void VersionProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
{
auto* replacing = dynamic_cast<BaseVersionList*>(sourceModel);
m_columns.clear();
if (!replacing) {
m_roles.clear();
m_filterModel->setSourceModel(replacing);
return;
}
m_roles = replacing->providesRoles();
if (m_roles.contains(BaseVersionList::VersionRole)) {
m_columns.push_back(Name);
}
/*
@ -320,39 +326,39 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
m_columns.push_back(ParentVersion);
}
*/
if (roles.contains(BaseVersionList::CPUArchitectureRole)) {
if (m_roles.contains(BaseVersionList::CPUArchitectureRole)) {
m_columns.push_back(CPUArchitecture);
}
if (roles.contains(BaseVersionList::PathRole)) {
if (m_roles.contains(BaseVersionList::PathRole)) {
m_columns.push_back(Path);
}
if (roles.contains(BaseVersionList::JavaNameRole)) {
if (m_roles.contains(BaseVersionList::JavaNameRole)) {
m_columns.push_back(JavaName);
}
if (roles.contains(BaseVersionList::JavaMajorRole)) {
if (m_roles.contains(BaseVersionList::JavaMajorRole)) {
m_columns.push_back(JavaMajor);
}
if (roles.contains(Meta::VersionList::TimeRole)) {
if (m_roles.contains(Meta::VersionList::TimeRole)) {
m_columns.push_back(Time);
}
if (roles.contains(BaseVersionList::BranchRole)) {
if (m_roles.contains(BaseVersionList::BranchRole)) {
m_columns.push_back(Branch);
}
if (roles.contains(BaseVersionList::TypeRole)) {
if (m_roles.contains(BaseVersionList::TypeRole)) {
m_columns.push_back(Type);
}
if (roles.contains(BaseVersionList::RecommendedRole)) {
hasRecommended = true;
if (m_roles.contains(BaseVersionList::RecommendedRole)) {
m_hasRecommended = true;
}
if (roles.contains(BaseVersionList::LatestRole)) {
hasLatest = true;
if (m_roles.contains(BaseVersionList::LatestRole)) {
m_hasLatest = true;
}
filterModel->setSourceModel(replacing);
m_filterModel->setSourceModel(replacing);
}
QModelIndex VersionProxyModel::getRecommended() const
{
if (!roles.contains(BaseVersionList::RecommendedRole)) {
if (!m_roles.contains(BaseVersionList::RecommendedRole)) {
return index(0, 0);
}
int recommended = 0;
@ -384,19 +390,19 @@ void VersionProxyModel::clearFilters()
{
m_filters.clear();
m_search.clear();
filterModel->filterChanged();
m_filterModel->filterChanged();
}
void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter f)
{
m_filters[column] = std::move(f);
filterModel->filterChanged();
m_filterModel->filterChanged();
}
void VersionProxyModel::setSearch(const QString& search)
{
m_search = search;
filterModel->filterChanged();
m_filterModel->filterChanged();
}
const VersionProxyModel::FilterMap& VersionProxyModel::filters() const

View file

@ -9,22 +9,22 @@ class VersionFilterModel;
class VersionProxyModel : public QAbstractProxyModel {
Q_OBJECT
public:
enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaMajor };
enum Column : std::uint8_t { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaMajor };
using FilterMap = QHash<BaseVersionList::ModelRoles, Filter>;
public:
VersionProxyModel(QObject* parent = 0);
virtual ~VersionProxyModel() {};
explicit VersionProxyModel(QObject* parent = nullptr);
~VersionProxyModel() override = default;
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override;
virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
virtual QModelIndex parent(const QModelIndex& child) const override;
virtual void setSourceModel(QAbstractItemModel* sourceModel) override;
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override;
QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QModelIndex parent(const QModelIndex& child) const override;
void setSourceModel(QAbstractItemModel* sourceModel) override;
const FilterMap& filters() const;
const QString& search() const;
@ -36,7 +36,7 @@ class VersionProxyModel : public QAbstractProxyModel {
void setCurrentVersion(const QString& version);
private slots:
void sourceDataChanged(const QModelIndex& source_top_left, const QModelIndex& source_bottom_right);
void sourceDataChanged(const QModelIndex& sourceTopLeft, const QModelIndex& sourceBottomRight);
void sourceAboutToBeReset();
void sourceReset();
@ -51,9 +51,9 @@ class VersionProxyModel : public QAbstractProxyModel {
QList<Column> m_columns;
FilterMap m_filters;
QString m_search;
BaseVersionList::RoleList roles;
VersionFilterModel* filterModel;
bool hasRecommended = false;
bool hasLatest = false;
BaseVersionList::RoleList m_roles;
VersionFilterModel* m_filterModel;
bool m_hasRecommended = false;
bool m_hasLatest = false;
QString m_currentVersion;
};

View file

@ -27,8 +27,9 @@ QString Meta::Version::descriptor() const
}
QString Meta::Version::name() const
{
if (m_data)
if (m_data) {
return m_data->name;
}
return m_uid;
}
QString Meta::Version::typeString() const
@ -110,9 +111,9 @@ void Meta::Version::setRequires(const Meta::RequireSet& reqs, const Meta::Requir
emit requiresChanged();
}
void Meta::Version::setVolatile(bool volatile_)
void Meta::Version::setVolatile(bool volatileVar)
{
m_volatile = volatile_;
m_volatile = volatileVar;
}
void Meta::Version::setData(const VersionFilePtr& data)

View file

@ -38,7 +38,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity {
using Ptr = std::shared_ptr<Version>;
explicit Version(const QString& uid, const QString& version);
virtual ~Version() = default;
~Version() override = default;
QString descriptor() const override;
QString name() const override;
@ -66,7 +66,7 @@ class Version : public QObject, public BaseVersion, public BaseEntity {
void setType(const QString& type);
void setTime(qint64 time);
void setRequires(const Meta::RequireSet& reqs, const Meta::RequireSet& conflicts);
void setVolatile(bool volatile_);
void setVolatile(bool volatileVar);
void setRecommended(bool recommended);
void setProvidesRecommendations();
void setData(const VersionFilePtr& data);

View file

@ -1,6 +1,7 @@
#include <QDebug>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <utility>
#include "minecraft/auth/AccountData.h"
#include "minecraft/auth/steps/EntitlementsStep.h"
@ -17,7 +18,7 @@
#include <Application.h>
AuthFlow::AuthFlow(AccountData* data, Action action) : Task(), m_data(data)
AuthFlow::AuthFlow(AccountData* data, Action action) : m_data(data)
{
if (data->type == AccountType::MSA) {
if (action == Action::DeviceCode) {
@ -75,11 +76,12 @@ void AuthFlow::nextStep()
void AuthFlow::stepFinished(AccountTaskState resultingState, QString message)
{
if (changeState(resultingState, message))
if (changeState(resultingState, std::move(message))) {
nextStep();
}
}
bool AuthFlow::changeState(AccountTaskState newState, QString reason)
bool AuthFlow::changeState(AccountTaskState newState, const QString& reason)
{
m_taskState = newState;
setDetails(reason);
@ -148,8 +150,9 @@ bool AuthFlow::changeState(AccountTaskState newState, QString reason)
}
bool AuthFlow::abort()
{
if (m_currentStep)
if (m_currentStep) {
m_currentStep->abort();
}
emitAborted();
return true;
}

View file

@ -13,10 +13,10 @@ class AuthFlow : public Task {
Q_OBJECT
public:
enum class Action { Refresh, Login, DeviceCode };
enum class Action : std::uint8_t { Refresh, Login, DeviceCode };
explicit AuthFlow(AccountData* data, Action action = Action::Refresh);
virtual ~AuthFlow() = default;
~AuthFlow() override = default;
void executeTask() override;
@ -35,7 +35,7 @@ class AuthFlow : public Task {
private slots:
// NOTE: true -> non-terminal state, false -> terminal state
bool changeState(AccountTaskState newState, QString reason = QString());
bool changeState(AccountTaskState newState, const QString& reason = {});
void stepFinished(AccountTaskState resultingState, QString message);
private:

View file

@ -73,7 +73,7 @@ MSADeviceCodeStep::MSADeviceCodeStep(AccountData* data) : AuthStep(data)
emit finished(state, message);
});
connect(&m_oauth2, &QOAuth2DeviceAuthorizationFlow::serverReportedErrorOccurred, this,
[this](const QString& error, const QString& errorDescription, const QUrl& uri) {
[this](const QString& error, const QString& errorDescription, const QUrl& /*uri*/) {
qWarning() << "Failed to login because" << error << errorDescription;
emit finished(AccountTaskState::STATE_FAILED_HARD, errorDescription);
});
@ -97,21 +97,11 @@ void MSADeviceCodeStep::perform()
m_oauth2.grant();
}
struct DeviceAuthorizationResponse {
QString device_code;
QString user_code;
QString verification_uri;
int expires_in;
int interval;
QString error;
QString error_description;
};
void MSADeviceCodeStep::abort()
{
if (m_oauth2.isPolling())
if (m_oauth2.isPolling()) {
m_oauth2.stopTokenPolling();
}
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Task aborted"));
}

View file

@ -44,7 +44,7 @@ class MSADeviceCodeStep : public AuthStep {
Q_OBJECT
public:
explicit MSADeviceCodeStep(AccountData* data);
virtual ~MSADeviceCodeStep() noexcept = default;
~MSADeviceCodeStep() noexcept override = default;
void perform() override;

View file

@ -36,19 +36,19 @@
#include "MSAStep.h"
#include <QAbstractOAuth2>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QOAuthHttpServerReplyHandler>
#include <QOAuthOobReplyHandler>
#include "Application.h"
#include "BuildConfig.h"
#include "FileSystem.h"
#include <QProcess>
#include <QSettings>
#include <QStandardPaths>
namespace {
bool isSchemeHandlerRegistered()
{
#ifdef Q_OS_LINUX
@ -110,6 +110,7 @@ class LoggingOAuthHttpServerReplyHandler final : public QOAuthHttpServerReplyHan
QOAuthHttpServerReplyHandler::networkReplyFinished(reply);
}
};
} // namespace
MSAStep::MSAStep(AccountData* data, bool silent) : AuthStep(data), m_silent(silent)
{
@ -117,7 +118,7 @@ MSAStep::MSAStep(AccountData* data, bool silent) : AuthStep(data), m_silent(sile
if (QCoreApplication::applicationFilePath().startsWith("/tmp/.mount_") || APPLICATION->isPortable() || !isSchemeHandlerRegistered())
{
auto replyHandler = new LoggingOAuthHttpServerReplyHandler(this);
auto* replyHandler = new LoggingOAuthHttpServerReplyHandler(this);
replyHandler->setCallbackText(QString(R"XXX(
<noscript>
<meta http-equiv="Refresh" content="0; URL=%1" />
@ -165,7 +166,7 @@ MSAStep::MSAStep(AccountData* data, bool silent) : AuthStep(data), m_silent(sile
emit finished(state, message);
});
connect(&m_oauth2, &QOAuth2AuthorizationCodeFlow::serverReportedErrorOccurred, this,
[this](const QString& error, const QString& errorDescription, const QUrl& uri) {
[this](const QString& error, const QString& errorDescription, const QUrl& /*uri*/) {
qWarning() << "Failed to login because" << error << errorDescription;
emit finished(AccountTaskState::STATE_FAILED_HARD, errorDescription);
});
@ -198,7 +199,7 @@ void MSAStep::perform()
m_oauth2.refreshTokens();
} else {
m_oauth2.setModifyParametersFunction(
[](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* map) { map->insert("prompt", "select_account"); });
[](QAbstractOAuth::Stage /*stage*/, QMultiMap<QString, QVariant>* map) { map->insert("prompt", "select_account"); });
*m_data = AccountData();
m_data->msaClientID = m_clientId;

View file

@ -44,7 +44,7 @@ class MSAStep : public AuthStep {
Q_OBJECT
public:
explicit MSAStep(AccountData* data, bool silent = false);
virtual ~MSAStep() noexcept = default;
~MSAStep() noexcept override = default;
void perform() override;

View file

@ -847,7 +847,7 @@ void ResourceFolderModel::onParseFailed(int ticket, const QString& resourceId)
// update index
m_resourcesIndex.clear();
int idx = 0;
for (const auto& mod : qAsConst(m_resources)) {
for (const auto& mod : std::as_const(m_resources)) {
m_resourcesIndex[mod->internalId()] = idx;
idx++;
}
@ -954,7 +954,7 @@ void ResourceFolderModel::applyUpdates(QSet<QString>& currentSet, QSet<QString>&
{
m_resourcesIndex.clear();
int idx = 0;
for (const auto& mod : qAsConst(m_resources)) {
for (const auto& mod : std::as_const(m_resources)) {
m_resourcesIndex[mod->internalId()] = idx;
idx++;
}

View file

@ -20,13 +20,16 @@
#include "SkinModel.h"
#include <QFileInfo>
#include <QPainter>
#include <array>
#include <bit>
#include "FileSystem.h"
static void setAlpha(QImage& image, const QRect& region, const int alpha)
namespace {
void setAlpha(QImage& image, const QRect& region, const int alpha)
{
for (int y = region.top(); y < region.bottom(); ++y) {
QRgb* line = reinterpret_cast<QRgb*>(image.scanLine(y));
auto line = std::span(std::bit_cast<QRgb*>(image.scanLine(y)), image.width());
for (int x = region.left(); x < region.right(); ++x) {
QRgb pixel = line[x];
line[x] = qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), alpha);
@ -34,10 +37,10 @@ static void setAlpha(QImage& image, const QRect& region, const int alpha)
}
}
static void doNotchTransparencyHack(QImage& image)
void doNotchTransparencyHack(QImage& image)
{
for (int y = 0; y < 32; y++) {
QRgb* line = reinterpret_cast<QRgb*>(image.scanLine(y));
auto line = std::span(std::bit_cast<QRgb*>(image.scanLine(y)), image.width());
for (int x = 32; x < 64; x++) {
if (qAlpha(line[x]) < 128) {
return;
@ -48,7 +51,7 @@ static void doNotchTransparencyHack(QImage& image)
setAlpha(image, { 32, 0, 32, 32 }, 0);
}
static QImage improveSkin(QImage skin)
QImage improveSkin(QImage skin)
{
int height = skin.height();
int width = skin.width();
@ -75,43 +78,53 @@ static QImage improveSkin(QImage skin)
p.drawImage(startX + offsetX, startY + offsetY, region);
};
static const struct {
struct FaceRect {
int x;
int y;
int offsetX;
int offsetY;
int width;
int height;
} faces[] = {
{ 4, 16, 16, 32, 4, 4 }, { 8, 16, 16, 32, 4, 4 }, { 0, 20, 24, 32, 4, 12 }, { 4, 20, 16, 32, 4, 12 },
{ 8, 20, 8, 32, 4, 12 }, { 12, 20, 16, 32, 4, 12 }, { 44, 16, -8, 32, 4, 4 }, { 48, 16, -8, 32, 4, 4 },
{ 40, 20, 0, 32, 4, 12 }, { 44, 20, -8, 32, 4, 12 }, { 48, 20, -16, 32, 4, 12 }, { 52, 20, -8, 32, 4, 12 },
};
static constexpr std::array s_faces = {
FaceRect{ .x = 4, .y = 16, .offsetX = 16, .offsetY = 32, .width = 4, .height = 4 },
FaceRect{ .x = 8, .y = 16, .offsetX = 16, .offsetY = 32, .width = 4, .height = 4 },
FaceRect{ .x = 0, .y = 20, .offsetX = 24, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 4, .y = 20, .offsetX = 16, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 8, .y = 20, .offsetX = 8, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 12, .y = 20, .offsetX = 16, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 44, .y = 16, .offsetX = -8, .offsetY = 32, .width = 4, .height = 4 },
FaceRect{ .x = 48, .y = 16, .offsetX = -8, .offsetY = 32, .width = 4, .height = 4 },
FaceRect{ .x = 40, .y = 20, .offsetX = 0, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 44, .y = 20, .offsetX = -8, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 48, .y = 20, .offsetX = -16, .offsetY = 32, .width = 4, .height = 12 },
FaceRect{ .x = 52, .y = 20, .offsetX = -8, .offsetY = 32, .width = 4, .height = 12 },
};
for (const auto& face : faces) {
for (const auto& face : s_faces) {
copyRect(face.x, face.y, face.offsetX, face.offsetY, face.width, face.height);
}
doNotchTransparencyHack(newSkin);
skin = newSkin;
}
static const QRect opaqueParts[] = {
{ 0, 0, 32, 16 },
{ 0, 16, 64, 16 },
{ 16, 48, 32, 16 },
static constexpr std::array s_opaqueParts = {
QRect{ 0, 0, 32, 16 },
QRect{ 0, 16, 64, 16 },
QRect{ 16, 48, 32, 16 },
};
for (const auto& p : opaqueParts) {
for (const auto& p : s_opaqueParts) {
setAlpha(skin, p, 255);
}
return skin;
}
static QImage getSkin(const QString path)
QImage getSkin(const QString& path)
{
return improveSkin(QImage(path));
}
static QImage generatePreviews(QImage texture, bool slim)
QImage generatePreviews(const QImage& texture, bool slim)
{
QImage preview(36, 36, QImage::Format_ARGB32);
preview.fill(Qt::transparent);
@ -162,13 +175,14 @@ static QImage generatePreviews(QImage texture, bool slim)
return preview;
}
SkinModel::SkinModel(QString path) : m_path(path), m_texture(getSkin(path)), m_model(Model::CLASSIC)
} // namespace
SkinModel::SkinModel(const QString& path) : m_path(path), m_texture(getSkin(path))
{
m_preview = generatePreviews(m_texture, false);
}
SkinModel::SkinModel(QDir skinDir, QJsonObject obj)
: m_capeId(obj["capeId"].toString()), m_model(Model::CLASSIC), m_url(obj["url"].toString())
SkinModel::SkinModel(const QDir& skinDir, QJsonObject obj) : m_capeId(obj["capeId"].toString()), m_url(obj["url"].toString())
{
auto name = obj["name"].toString();
@ -185,14 +199,14 @@ QString SkinModel::name() const
return QFileInfo(m_path).completeBaseName();
}
bool SkinModel::rename(QString newName)
bool SkinModel::rename(const QString& newName)
{
auto info = QFileInfo(m_path);
auto new_path = FS::PathCombine(info.absolutePath(), newName + ".png");
if (QFileInfo::exists(new_path)) {
auto newPath = FS::PathCombine(info.absolutePath(), newName + ".png");
if (QFileInfo::exists(newPath)) {
return false;
}
m_path = new_path;
m_path = newPath;
return FS::move(info.absoluteFilePath(), m_path);
}

View file

@ -21,14 +21,15 @@
#include <QDir>
#include <QImage>
#include <QJsonObject>
#include <utility>
class SkinModel {
public:
enum Model { CLASSIC, SLIM };
enum Model : std::uint8_t { CLASSIC, SLIM };
SkinModel() = default;
SkinModel(QString path);
SkinModel(QDir skinDir, QJsonObject obj);
explicit SkinModel(const QString& path);
SkinModel(const QDir& skinDir, QJsonObject obj);
virtual ~SkinModel() = default;
QString name() const;
@ -41,10 +42,10 @@ class SkinModel {
Model getModel() const { return m_model; }
QString getURL() const { return m_url; }
bool rename(QString newName);
void setCapeId(QString capeID) { m_capeId = capeID; }
bool rename(const QString& newName);
void setCapeId(QString capeID) { m_capeId = std::move(capeID); }
void setModel(Model model);
void setURL(QString url) { m_url = url; }
void setURL(QString url) { m_url = std::move(url); }
void refresh();
QJsonObject toJSON() const;
@ -54,6 +55,6 @@ class SkinModel {
QImage m_texture;
QImage m_preview;
QString m_capeId;
Model m_model;
Model m_model = Model::CLASSIC;
QString m_url;
};

View file

@ -34,10 +34,8 @@
*/
#include "PackFetchTask.h"
#include "PrivatePackManager.h"
#include <QDomDocument>
#include "Application.h"
#include "BuildConfig.h"
#include "net/ApiDownload.h"
@ -46,37 +44,37 @@ namespace LegacyFTB {
void PackFetchTask::fetch()
{
publicPacks.clear();
thirdPartyPacks.clear();
m_publicPacks.clear();
m_thirdPartyPacks.clear();
jobPtr.reset(new NetJob("LegacyFTB::ModpackFetch", m_network));
m_jobPtr.reset(new NetJob("LegacyFTB::ModpackFetch", m_network));
QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml");
qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
auto [publicAction, publicResponse] = Net::ApiDownload::makeByteArray(publicPacksUrl);
jobPtr->addNetAction(publicAction);
m_jobPtr->addNetAction(publicAction);
QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml");
qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
auto [thirdPartyAction, thirdPartyResponse] = Net::Download::makeByteArray(thirdPartyUrl);
jobPtr->addNetAction(thirdPartyAction);
m_jobPtr->addNetAction(thirdPartyAction);
connect(jobPtr.get(), &NetJob::succeeded, this,
connect(m_jobPtr.get(), &NetJob::succeeded, this,
[this, publicResponse, thirdPartyResponse] { fileDownloadFinished(publicResponse, thirdPartyResponse); });
connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed);
connect(jobPtr.get(), &NetJob::aborted, this, &PackFetchTask::fileDownloadAborted);
connect(m_jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed);
connect(m_jobPtr.get(), &NetJob::aborted, this, &PackFetchTask::fileDownloadAborted);
jobPtr->start();
m_jobPtr->start();
}
void PackFetchTask::fetchPrivate(const QStringList& toFetch)
{
QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml";
for (auto& packCode : toFetch) {
NetJob* job = new NetJob("Fetching private pack", m_network);
for (const auto& packCode : toFetch) {
auto* job = new NetJob("Fetching private pack", m_network);
auto [action, data] = Net::ApiDownload::makeByteArray(privatePackBaseUrl.arg(packCode));
job->addNetAction(action);
@ -93,7 +91,7 @@ void PackFetchTask::fetchPrivate(const QStringList& toFetch)
job->deleteLater();
});
connect(job, &NetJob::failed, this, [this, job, packCode](QString reason) {
connect(job, &NetJob::failed, this, [this, job, packCode](const QString& reason) {
emit privateFileDownloadFailed(reason, packCode);
job->deleteLater();
});
@ -112,21 +110,21 @@ void PackFetchTask::fileDownloadFinished(QByteArray* publicPtr, QByteArray* thir
{
QStringList failedLists;
if (!parseAndAddPacks(*publicPtr, PackType::Public, publicPacks)) {
if (!parseAndAddPacks(*publicPtr, PackType::Public, m_publicPacks)) {
failedLists.append(tr("Public Packs"));
}
if (!parseAndAddPacks(*thirdPartyPtr, PackType::ThirdParty, thirdPartyPacks)) {
if (!parseAndAddPacks(*thirdPartyPtr, PackType::ThirdParty, m_thirdPartyPacks)) {
failedLists.append(tr("Third Party Packs"));
}
// NOTE(TheKodeToad): we don't want to reset the jobPtr earlier as it may invalidate the responses!
jobPtr.reset();
m_jobPtr.reset();
if (failedLists.size() > 0) {
emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- ")));
} else {
emit finished(publicPacks, thirdPartyPacks);
emit finished(m_publicPacks, m_thirdPartyPacks);
}
}
@ -159,7 +157,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray& data, PackType packType, Modpac
modpack.bugged = false;
// remove empty if the xml is bugged
for (QString curr : modpack.oldVersions) {
for (const QString& curr : modpack.oldVersions) {
if (curr.isNull() || curr.isEmpty()) {
modpack.oldVersions.removeAll(curr);
modpack.bugged = true;
@ -190,7 +188,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray& data, PackType packType, Modpac
return true;
}
void PackFetchTask::fileDownloadFailed(QString reason)
void PackFetchTask::fileDownloadFailed(const QString& reason)
{
qWarning() << "Fetching FTBPacks failed:" << reason;
emit failed(reason);

View file

@ -12,32 +12,32 @@ class PackFetchTask : public QObject {
Q_OBJECT
public:
PackFetchTask(QNetworkAccessManager* network) : QObject(nullptr), m_network(network) {};
virtual ~PackFetchTask() = default;
explicit PackFetchTask(QNetworkAccessManager* network) : QObject(nullptr), m_network(network) {};
~PackFetchTask() override = default;
void fetch();
void fetchPrivate(const QStringList& toFetch);
private:
QNetworkAccessManager* m_network;
NetJob::Ptr jobPtr;
NetJob::Ptr m_jobPtr;
bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list);
ModpackList publicPacks;
ModpackList thirdPartyPacks;
static bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list);
ModpackList m_publicPacks;
ModpackList m_thirdPartyPacks;
protected slots:
void fileDownloadFinished(QByteArray* publicResponse, QByteArray* thirdPartyResponse);
void fileDownloadFailed(QString reason);
void fileDownloadFinished(QByteArray* publicPtr, QByteArray* thirdPartyPtr);
void fileDownloadFailed(const QString& reason);
void fileDownloadAborted();
signals:
void finished(ModpackList publicPacks, ModpackList thirdPartyPacks);
void failed(QString reason);
void failed(const QString& reason);
void aborted();
void privateFileDownloadFinished(const Modpack& modpack);
void privateFileDownloadFailed(QString reason, QString packCode);
void privateFileDownloadFailed(const QString& reason, const QString& packCode);
};
} // namespace LegacyFTB

View file

@ -41,11 +41,7 @@
#include <QDebug>
#include "Application.h"
NewsChecker::NewsChecker(QNetworkAccessManager* network, const QString& feedUrl)
{
m_network = network;
m_feedUrl = feedUrl;
}
NewsChecker::NewsChecker(QNetworkAccessManager* network, const QString& feedUrl) : m_feedUrl(feedUrl), m_network(network) {}
void NewsChecker::reloadNews()
{
@ -112,7 +108,7 @@ void NewsChecker::rssDownloadFinished()
succeed();
}
void NewsChecker::rssDownloadFailed(QString reason)
void NewsChecker::rssDownloadFailed(const QString& reason)
{
// Set an error message and fail.
fail(tr("Failed to load news RSS feed:\n%1").arg(reason));

View file

@ -69,7 +69,7 @@ class NewsChecker : public QObject {
protected slots:
void rssDownloadFinished();
void rssDownloadFailed(QString reason);
void rssDownloadFailed(const QString& reason);
protected: /* data */
//! The URL for the RSS feed to fetch.
@ -82,7 +82,7 @@ class NewsChecker : public QObject {
NetJob::Ptr m_newsNetJob;
//! True if news has been loaded.
bool m_loadedNews;
bool m_loadedNews = false;
//! The cache entry for the feed.
MetaEntryPtr m_entry;

View file

@ -31,48 +31,50 @@
#include <QJsonDocument>
#include <QMessageBox>
#include <QPushButton>
#include <utility>
const QHash<ExportToModList::Formats, QString> ExportToModListDialog::exampleLines = {
const QHash<ExportToModList::Formats, QString> ExportToModListDialog::ExampleLines = {
{ ExportToModList::HTML, "<li><a href=\"{url}\">{name}</a> [{version}] by {authors}</li>" },
{ ExportToModList::MARKDOWN, "[{name}]({url}) [{version}] by {authors}" },
{ ExportToModList::PLAINTXT, "{name} ({url}) [{version}] by {authors}" },
{ ExportToModList::JSON, "{\"name\":\"{name}\",\"url\":\"{url}\",\"version\":\"{version}\",\"authors\":\"{authors}\"}," },
{ ExportToModList::JSON, R"({"name":"{name}","url":"{url}","version":"{version}","authors":"{authors}"},)" },
{ ExportToModList::CSV, "{name},{url},{version},\"{authors}\"" },
};
ExportToModListDialog::ExportToModListDialog(QString name, QList<Mod*> mods, QWidget* parent)
: QDialog(parent), m_mods(mods), m_template_changed(false), m_name(name), ui(new Ui::ExportToModListDialog)
: QDialog(parent), m_mods(std::move(mods)), m_templateChanged(false), m_name(std::move(name)), m_ui(new Ui::ExportToModListDialog)
{
ui->setupUi(this);
m_ui->setupUi(this);
enableCustom(false);
connect(ui->formatComboBox, &QComboBox::currentIndexChanged, this, &ExportToModListDialog::formatChanged);
connect(ui->authorsCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(ui->versionCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(ui->urlCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(ui->filenameCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(ui->authorsButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Authors); });
connect(ui->versionButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Version); });
connect(ui->urlButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Url); });
connect(ui->filenameButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::FileName); });
connect(ui->templateText, &QTextEdit::textChanged, this, [this] {
if (ui->templateText->toPlainText() != exampleLines[m_format])
ui->formatComboBox->setCurrentIndex(5);
connect(m_ui->formatComboBox, &QComboBox::currentIndexChanged, this, &ExportToModListDialog::formatChanged);
connect(m_ui->authorsCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(m_ui->versionCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(m_ui->urlCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(m_ui->filenameCheckBox, &QCheckBox::checkStateChanged, this, &ExportToModListDialog::trigger);
connect(m_ui->authorsButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Authors); });
connect(m_ui->versionButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Version); });
connect(m_ui->urlButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::Url); });
connect(m_ui->filenameButton, &QPushButton::clicked, this, [this](bool) { addExtra(ExportToModList::FileName); });
connect(m_ui->templateText, &QTextEdit::textChanged, this, [this] {
if (m_ui->templateText->toPlainText() != ExampleLines[m_format]) {
m_ui->formatComboBox->setCurrentIndex(5);
}
triggerImp();
});
connect(ui->copyButton, &QPushButton::clicked, this, [this](bool) {
this->ui->finalText->selectAll();
this->ui->finalText->copy();
connect(m_ui->copyButton, &QPushButton::clicked, this, [this](bool) {
this->m_ui->finalText->selectAll();
this->m_ui->finalText->copy();
});
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save"));
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
m_ui->buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save"));
triggerImp();
}
ExportToModListDialog::~ExportToModListDialog()
{
delete ui;
delete m_ui;
}
void ExportToModListDialog::formatChanged(int index)
@ -80,41 +82,43 @@ void ExportToModListDialog::formatChanged(int index)
switch (index) {
case 0: {
enableCustom(false);
ui->resultText->show();
m_ui->resultText->show();
m_format = ExportToModList::HTML;
break;
}
case 1: {
enableCustom(false);
ui->resultText->show();
m_ui->resultText->show();
m_format = ExportToModList::MARKDOWN;
break;
}
case 2: {
enableCustom(false);
ui->resultText->hide();
m_ui->resultText->hide();
m_format = ExportToModList::PLAINTXT;
break;
}
case 3: {
enableCustom(false);
ui->resultText->hide();
m_ui->resultText->hide();
m_format = ExportToModList::JSON;
break;
}
case 4: {
enableCustom(false);
ui->resultText->hide();
m_ui->resultText->hide();
m_format = ExportToModList::CSV;
break;
}
case 5: {
m_template_changed = true;
m_templateChanged = true;
enableCustom(true);
ui->resultText->hide();
m_ui->resultText->hide();
m_format = ExportToModList::CUSTOM;
break;
}
default:
break;
}
triggerImp();
}
@ -122,39 +126,40 @@ void ExportToModListDialog::formatChanged(int index)
void ExportToModListDialog::triggerImp()
{
if (m_format == ExportToModList::CUSTOM) {
ui->finalText->setPlainText(ExportToModList::exportToModList(m_mods, ui->templateText->toPlainText()));
m_ui->finalText->setPlainText(ExportToModList::exportToModList(m_mods, m_ui->templateText->toPlainText()));
return;
}
auto opt = 0;
if (ui->authorsCheckBox->isChecked())
auto opt = 0U;
if (m_ui->authorsCheckBox->isChecked()) {
opt |= ExportToModList::Authors;
if (ui->versionCheckBox->isChecked())
}
if (m_ui->versionCheckBox->isChecked()) {
opt |= ExportToModList::Version;
if (ui->urlCheckBox->isChecked())
}
if (m_ui->urlCheckBox->isChecked()) {
opt |= ExportToModList::Url;
if (ui->filenameCheckBox->isChecked())
}
if (m_ui->filenameCheckBox->isChecked()) {
opt |= ExportToModList::FileName;
}
auto txt = ExportToModList::exportToModList(m_mods, m_format, static_cast<ExportToModList::OptionalData>(opt));
ui->finalText->setPlainText(txt);
m_ui->finalText->setPlainText(txt);
switch (m_format) {
case ExportToModList::CUSTOM:
return;
case ExportToModList::HTML:
ui->resultText->setHtml(StringUtils::htmlListPatch(txt));
m_ui->resultText->setHtml(StringUtils::htmlListPatch(txt));
break;
case ExportToModList::MARKDOWN:
ui->resultText->setHtml(StringUtils::htmlListPatch(markdownToHTML(txt)));
m_ui->resultText->setHtml(StringUtils::htmlListPatch(markdownToHTML(txt)));
break;
case ExportToModList::PLAINTXT:
break;
case ExportToModList::JSON:
break;
case ExportToModList::CSV:
default:
break;
}
auto exampleLine = exampleLines[m_format];
if (!m_template_changed && ui->templateText->toPlainText() != exampleLine)
ui->templateText->setPlainText(exampleLine);
auto exampleLine = ExampleLines[m_format];
if (!m_templateChanged && m_ui->templateText->toPlainText() != exampleLine) {
m_ui->templateText->setPlainText(exampleLine);
}
}
void ExportToModListDialog::done(int result)
@ -165,11 +170,12 @@ void ExportToModListDialog::done(int result)
QFileDialog::getSaveFileName(this, tr("Export %1").arg(m_name), FS::PathCombine(QDir::homePath(), filename + extension()),
tr("File") + " (*.txt *.html *.md *.json *.csv)", nullptr);
if (output.isEmpty())
if (output.isEmpty()) {
return;
}
try {
FS::write(output, ui->finalText->toPlainText().toUtf8());
FS::write(output, m_ui->finalText->toPlainText().toUtf8());
} catch (const FS::FileSystemException& e) {
qCritical() << "Failed to save mod list file :" << e.cause();
}
@ -186,7 +192,6 @@ QString ExportToModListDialog::extension()
case ExportToModList::MARKDOWN:
return ".md";
case ExportToModList::PLAINTXT:
return ".txt";
case ExportToModList::CUSTOM:
return ".txt";
case ExportToModList::JSON:
@ -199,34 +204,35 @@ QString ExportToModListDialog::extension()
void ExportToModListDialog::addExtra(ExportToModList::OptionalData option)
{
if (m_format != ExportToModList::CUSTOM)
if (m_format != ExportToModList::CUSTOM) {
return;
}
switch (option) {
case ExportToModList::Authors:
ui->templateText->insertPlainText("{authors}");
m_ui->templateText->insertPlainText("{authors}");
break;
case ExportToModList::Url:
ui->templateText->insertPlainText("{url}");
m_ui->templateText->insertPlainText("{url}");
break;
case ExportToModList::Version:
ui->templateText->insertPlainText("{version}");
m_ui->templateText->insertPlainText("{version}");
break;
case ExportToModList::FileName:
ui->templateText->insertPlainText("{filename}");
m_ui->templateText->insertPlainText("{filename}");
break;
}
}
void ExportToModListDialog::enableCustom(bool enabled)
{
ui->authorsCheckBox->setHidden(enabled);
ui->authorsButton->setHidden(!enabled);
m_ui->authorsCheckBox->setHidden(enabled);
m_ui->authorsButton->setHidden(!enabled);
ui->versionCheckBox->setHidden(enabled);
ui->versionButton->setHidden(!enabled);
m_ui->versionCheckBox->setHidden(enabled);
m_ui->versionButton->setHidden(!enabled);
ui->urlCheckBox->setHidden(enabled);
ui->urlButton->setHidden(!enabled);
m_ui->urlCheckBox->setHidden(enabled);
m_ui->urlButton->setHidden(!enabled);
ui->filenameCheckBox->setHidden(enabled);
ui->filenameButton->setHidden(!enabled);
m_ui->filenameCheckBox->setHidden(enabled);
m_ui->filenameButton->setHidden(!enabled);
}

View file

@ -32,14 +32,14 @@ class ExportToModListDialog : public QDialog {
public:
explicit ExportToModListDialog(QString name, QList<Mod*> mods, QWidget* parent = nullptr);
~ExportToModListDialog();
~ExportToModListDialog() override;
void done(int result) override;
protected slots:
void formatChanged(int index);
void triggerImp();
void trigger(Qt::CheckState) { triggerImp(); };
void trigger(Qt::CheckState /*unused*/) { triggerImp(); };
void addExtra(ExportToModList::OptionalData option);
private:
@ -47,9 +47,9 @@ class ExportToModListDialog : public QDialog {
void enableCustom(bool enabled);
QList<Mod*> m_mods;
bool m_template_changed;
bool m_templateChanged;
QString m_name;
ExportToModList::Formats m_format = ExportToModList::Formats::HTML;
Ui::ExportToModListDialog* ui;
static const QHash<ExportToModList::Formats, QString> exampleLines;
Ui::ExportToModListDialog* m_ui;
static const QHash<ExportToModList::Formats, QString> ExampleLines;
};

View file

@ -46,27 +46,28 @@
#include <QClipboard>
#include <QColor>
#include <QPainter>
#include <QPixmap>
#include <QPainterPath>
#include <QSize>
#include <QUrl>
#include <QtWidgets/QPushButton>
#include <span>
#include "qrencode.h"
MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MSALoginDialog)
MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), m_ui(new Ui::MSALoginDialog)
{
ui->setupUi(this);
m_ui->setupUi(this);
// make font monospace
QFont font;
font.setPixelSize(ui->code->fontInfo().pixelSize());
font.setPixelSize(m_ui->code->fontInfo().pixelSize());
font.setFamily(APPLICATION->settings()->get("ConsoleFont").toString());
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
ui->code->setFont(font);
m_ui->code->setFont(font);
connect(ui->copyCode, &QPushButton::clicked, this, [this] { QApplication::clipboard()->setText(ui->code->text()); });
connect(ui->loginButton, &QPushButton::clicked, this, [this] {
connect(m_ui->copyCode, &QPushButton::clicked, this, [this] { QApplication::clipboard()->setText(m_ui->code->text()); });
connect(m_ui->loginButton, &QPushButton::clicked, this, [this] {
if (m_url.isValid()) {
if (!DesktopServices::openUrl(m_url)) {
QApplication::clipboard()->setText(m_url.toString());
@ -74,79 +75,80 @@ MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MS
}
});
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
}
int MSALoginDialog::exec()
{
// Setup the login task and start it
m_account = MinecraftAccount::createBlankMSA();
m_authflow_task = m_account->login(false);
connect(m_authflow_task.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_authflow_task.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_authflow_task.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_authflow_task.get(), &Task::status, this, &MSALoginDialog::onAuthFlowStatus);
connect(m_authflow_task.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_authflow_task.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflow_task.get(), &Task::abort);
m_authflowTask = m_account->login(false);
connect(m_authflowTask.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_authflowTask.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_authflowTask.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_authflowTask.get(), &Task::status, this, &MSALoginDialog::onAuthFlowStatus);
connect(m_authflowTask.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_authflowTask.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflowTask.get(), &Task::abort);
m_devicecode_task.reset(new AuthFlow(m_account->accountData(), AuthFlow::Action::DeviceCode));
connect(m_devicecode_task.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_devicecode_task.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_devicecode_task.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_devicecode_task.get(), &Task::status, this, &MSALoginDialog::onDeviceFlowStatus);
connect(m_devicecode_task.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_devicecode_task.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecode_task.get(), &Task::abort);
QMetaObject::invokeMethod(m_authflow_task.get(), &Task::start, Qt::QueuedConnection);
QMetaObject::invokeMethod(m_devicecode_task.get(), &Task::start, Qt::QueuedConnection);
m_devicecodeTask.reset(new AuthFlow(m_account->accountData(), AuthFlow::Action::DeviceCode));
connect(m_devicecodeTask.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_devicecodeTask.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_devicecodeTask.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_devicecodeTask.get(), &Task::status, this, &MSALoginDialog::onDeviceFlowStatus);
connect(m_devicecodeTask.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_devicecodeTask.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecodeTask.get(), &Task::abort);
QMetaObject::invokeMethod(m_authflowTask.get(), &Task::start, Qt::QueuedConnection);
QMetaObject::invokeMethod(m_devicecodeTask.get(), &Task::start, Qt::QueuedConnection);
return QDialog::exec();
}
MSALoginDialog::~MSALoginDialog()
{
delete ui;
delete m_ui;
}
void MSALoginDialog::onTaskFailed(QString reason)
void MSALoginDialog::onTaskFailed(const QString& reason)
{
// Set message
m_authflow_task->disconnect();
m_devicecode_task->disconnect();
ui->stackedWidget->setCurrentIndex(0);
m_authflowTask->disconnect();
m_devicecodeTask->disconnect();
m_ui->stackedWidget->setCurrentIndex(0);
auto lines = reason.split('\n');
QString processed;
for (auto line : lines) {
if (line.size()) {
for (const auto& line : lines) {
if (line.size() != 0) {
processed += "<font color='red'>" + line + "</font><br />";
} else {
processed += "<br />";
}
}
ui->status->setText(processed);
auto task = m_authflow_task;
m_ui->status->setText(processed);
auto task = m_authflowTask;
if (task->failReason().isEmpty()) {
task = m_devicecode_task;
task = m_devicecodeTask;
}
if (task) {
ui->loadingLabel->setText(task->getStatus());
m_ui->loadingLabel->setText(task->getStatus());
}
disconnect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflow_task.get(), &Task::abort);
disconnect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecode_task.get(), &Task::abort);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &MSALoginDialog::reject);
disconnect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflowTask.get(), &Task::abort);
disconnect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecodeTask.get(), &Task::abort);
connect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &MSALoginDialog::reject);
}
void MSALoginDialog::authorizeWithBrowser(const QUrl& url)
{
ui->stackedWidget2->setCurrentIndex(1);
ui->stackedWidget2->adjustSize();
ui->stackedWidget2->updateGeometry();
m_ui->stackedWidget2->setCurrentIndex(1);
m_ui->stackedWidget2->adjustSize();
m_ui->stackedWidget2->updateGeometry();
this->adjustSize();
ui->loginButton->setToolTip(QString("<div style='width: 200px;'>%1</div>").arg(url.toString()));
m_ui->loginButton->setToolTip(QString("<div style='width: 200px;'>%1</div>").arg(url.toString()));
m_url = url;
}
namespace {
void paintQR(QPainter& painter, const QSize canvasSize, const QString& data, QColor fg)
{
const auto* qr = QRcode_encodeString(data.toUtf8().constData(), 0, QRecLevel::QR_ECLEVEL_M, QRencodeMode::QR_MODE_8, 1);
@ -165,25 +167,27 @@ void paintQR(QPainter& painter, const QSize canvasSize, const QString& data, QCo
const auto scale = 0.8 * std::min(canvasWidth / qrSize, canvasHeight / qrSize);
// Find an offset to center it in the canvas
const auto offsetX = (canvasWidth - qrSize * scale) / 2;
const auto offsetY = (canvasHeight - qrSize * scale) / 2;
const auto offsetX = (canvasWidth - (qrSize * scale)) / 2;
const auto offsetY = (canvasHeight - (qrSize * scale)) / 2;
auto qrData = std::span(qr->data, static_cast<long>(qrSize) * qrSize);
for (int y = 0; y < qrSize; y++) {
for (int x = 0; x < qrSize; x++) {
auto shouldFillIn = qr->data[y * qrSize + x] & 1;
if (shouldFillIn) {
QRectF r(offsetX + x * scale, offsetY + y * scale, scale, scale);
auto shouldFillIn = qrData[(y * qrSize) + x] & 1U;
if (shouldFillIn != 0) {
QRectF r(offsetX + (x * scale), offsetY + (y * scale), scale, scale);
painter.drawRects(&r, 1);
}
}
}
}
} // namespace
void MSALoginDialog::authorizeWithBrowserWithExtra(const QUrl& verificationUrl, const QString& code, const QUrl& completeVerificationUrl)
{
ui->stackedWidget->setCurrentIndex(1);
ui->stackedWidget->adjustSize();
ui->stackedWidget->updateGeometry();
m_ui->stackedWidget->setCurrentIndex(1);
m_ui->stackedWidget->adjustSize();
m_ui->stackedWidget->updateGeometry();
this->adjustSize();
auto url = verificationUrl.toString();
@ -195,7 +199,7 @@ void MSALoginDialog::authorizeWithBrowserWithExtra(const QUrl& verificationUrl,
if (!completeVerificationUrl.isValid() && url == "https://www.microsoft.com/link" && !code.isEmpty()) {
url += QString("?otc=%1").arg(code);
}
ui->code->setText(code);
m_ui->code->setText(code);
auto size = QSize(150, 150);
QPixmap pixmap(size);
@ -205,27 +209,27 @@ void MSALoginDialog::authorizeWithBrowserWithExtra(const QUrl& verificationUrl,
paintQR(painter, size, url, Qt::black);
// Set the generated pixmap to the label
ui->qr->setPixmap(pixmap);
m_ui->qr->setPixmap(pixmap);
ui->qrMessage->setText(tr("Open %1 or scan the QR and enter the above code if needed.").arg(linkString));
m_ui->qrMessage->setText(tr("Open %1 or scan the QR and enter the above code if needed.").arg(linkString));
}
void MSALoginDialog::onDeviceFlowStatus(QString status)
void MSALoginDialog::onDeviceFlowStatus(const QString& status)
{
ui->stackedWidget->setCurrentIndex(0);
ui->stackedWidget->adjustSize();
ui->stackedWidget->updateGeometry();
m_ui->stackedWidget->setCurrentIndex(0);
m_ui->stackedWidget->adjustSize();
m_ui->stackedWidget->updateGeometry();
this->adjustSize();
ui->status->setText(status);
m_ui->status->setText(status);
}
void MSALoginDialog::onAuthFlowStatus(QString status)
void MSALoginDialog::onAuthFlowStatus(const QString& status)
{
ui->stackedWidget2->setCurrentIndex(0);
ui->stackedWidget2->adjustSize();
ui->stackedWidget2->updateGeometry();
m_ui->stackedWidget2->setCurrentIndex(0);
m_ui->stackedWidget2->adjustSize();
m_ui->stackedWidget2->updateGeometry();
this->adjustSize();
ui->status2->setText(status);
m_ui->status2->setText(status);
}
// Public interface

View file

@ -29,26 +29,26 @@ class MSALoginDialog : public QDialog {
Q_OBJECT
public:
~MSALoginDialog();
~MSALoginDialog() override;
static MinecraftAccountPtr newAccount(QWidget* parent);
int exec() override;
private:
explicit MSALoginDialog(QWidget* parent = 0);
explicit MSALoginDialog(QWidget* parent = nullptr);
protected slots:
void onTaskFailed(QString reason);
void onDeviceFlowStatus(QString status);
void onAuthFlowStatus(QString status);
void onTaskFailed(const QString& reason);
void onDeviceFlowStatus(const QString& status);
void onAuthFlowStatus(const QString& status);
void authorizeWithBrowser(const QUrl& url);
void authorizeWithBrowserWithExtra(const QUrl& verificationUrl, const QString& code, const QUrl& completeVerificationUrl);
private:
Ui::MSALoginDialog* ui;
Ui::MSALoginDialog* m_ui;
MinecraftAccountPtr m_account;
shared_qobject_ptr<AuthFlow> m_devicecode_task;
shared_qobject_ptr<AuthFlow> m_authflow_task;
shared_qobject_ptr<AuthFlow> m_devicecodeTask;
shared_qobject_ptr<AuthFlow> m_authflowTask;
QUrl m_url;
};

View file

@ -34,10 +34,9 @@
#include <QUrl>
#include "Application.h"
#include "settings/SettingsObject.h"
#include "DesktopServices.h"
#include "Json.h"
#include "QObjectPtr.h"
#include "settings/SettingsObject.h"
#include "minecraft/auth/Parsers.h"
#include "minecraft/skins/CapeChange.h"
@ -54,7 +53,7 @@
#include "ui/dialogs/ProgressDialog.h"
#include "ui/instanceview/InstanceDelegate.h"
SkinManageDialog::SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct)
SkinManageDialog::SkinManageDialog(QWidget* parent, const MinecraftAccountPtr& acct)
: QDialog(parent), m_acct(acct), m_ui(new Ui::SkinManageDialog), m_list(this, APPLICATION->settings()->get("SkinsDir").toString(), acct)
{
m_ui->setupUi(this);
@ -68,7 +67,7 @@ SkinManageDialog::SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct)
setWindowModality(Qt::WindowModal);
auto contentsWidget = m_ui->listView;
auto* contentsWidget = m_ui->listView;
contentsWidget->setViewMode(QListView::IconMode);
contentsWidget->setFlow(QListView::LeftToRight);
contentsWidget->setIconSize(QSize(48, 48));
@ -122,9 +121,8 @@ SkinManageDialog::SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct)
SkinManageDialog::~SkinManageDialog()
{
delete m_ui;
if (m_skinPreview) {
delete m_skinPreview;
}
delete m_skinPreview;
}
void SkinManageDialog::activated(QModelIndex index)
@ -133,18 +131,21 @@ void SkinManageDialog::activated(QModelIndex index)
accept();
}
void SkinManageDialog::selectionChanged(QItemSelection selected, [[maybe_unused]] QItemSelection deselected)
void SkinManageDialog::selectionChanged(const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected)
{
if (selected.empty())
if (selected.empty()) {
return;
}
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
if (key.isEmpty())
if (key.isEmpty()) {
return;
}
m_selectedSkinKey = key;
auto skin = getSelectedSkin();
if (!skin)
auto* skin = getSelectedSkin();
if (!skin) {
return;
}
if (m_skinPreview) {
m_skinPreview->updateScene(skin);
@ -157,10 +158,10 @@ void SkinManageDialog::selectionChanged(QItemSelection selected, [[maybe_unused]
m_ui->alexBtn->setChecked(skin->getModel() == SkinModel::SLIM);
}
void SkinManageDialog::delayed_scroll(QModelIndex model_index)
void SkinManageDialog::delayed_scroll(QModelIndex modelIndex)
{
auto contentsWidget = m_ui->listView;
contentsWidget->scrollTo(model_index);
auto* contentsWidget = m_ui->listView;
contentsWidget->scrollTo(modelIndex);
}
void SkinManageDialog::on_openDirBtn_clicked()
@ -171,24 +172,25 @@ void SkinManageDialog::on_openDirBtn_clicked()
void SkinManageDialog::on_fileBtn_clicked()
{
auto filter = QMimeDatabase().mimeTypeForName("image/png").filterString();
QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), filter);
if (raw_path.isNull()) {
QString rawPath = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), filter);
if (rawPath.isNull()) {
return;
}
auto message = m_list.installSkin(raw_path, {});
auto message = m_list.installSkin(rawPath, {});
if (!message.isEmpty()) {
CustomMessageBox::selectable(this, tr("Selected file is not a valid skin"), message, QMessageBox::Critical)->show();
return;
}
}
QPixmap previewCape(QImage capeImage, bool elytra = false)
namespace {
QPixmap previewCape(const QImage& capeImage, bool elytra = false)
{
if (elytra) {
auto wing = capeImage.copy(34, 2, 12, 20);
QImage mirrored = wing.flipped(Qt::Horizontal);
QImage combined(wing.width() * 2 + 1, wing.height() + 14, capeImage.format());
QImage combined((wing.width() * 2) + 1, wing.height() + 14, capeImage.format());
combined.fill(Qt::transparent);
QPainter painter(&combined);
@ -199,6 +201,7 @@ QPixmap previewCape(QImage capeImage, bool elytra = false)
}
return QPixmap::fromImage(capeImage.copy(1, 1, 10, 16).scaled(80, 128, Qt::IgnoreAspectRatio, Qt::FastTransformation));
}
} // namespace
void SkinManageDialog::setupCapes()
{
@ -216,7 +219,7 @@ void SkinManageDialog::setupCapes()
bool needsToDownload = false;
for (auto& cape : accountData.minecraftProfile.capes) {
auto path = FS::PathCombine(capesDir, cape.id + ".png");
if (cape.data.size()) {
if (cape.data.size() != 0) {
QImage capeImage;
if (capeImage.loadFromData(cape.data, "PNG") && capeImage.save(path)) {
m_capes[cape.id] = capeImage;
@ -254,7 +257,7 @@ void SkinManageDialog::setupCapes()
}
}
void SkinManageDialog::on_capeCombo_currentIndexChanged(int index)
void SkinManageDialog::on_capeCombo_currentIndexChanged(int /*index*/)
{
auto id = m_ui->capeCombo->currentData();
auto cape = m_capes.value(id.toString(), {});
@ -267,7 +270,7 @@ void SkinManageDialog::on_capeCombo_currentIndexChanged(int index)
if (m_skinPreview) {
m_skinPreview->updateCape(cape);
}
if (auto skin = getSelectedSkin(); skin) {
if (auto* skin = getSelectedSkin(); skin) {
skin->setCapeId(id.toString());
if (m_skinPreview) {
m_skinPreview->updateScene(skin);
@ -280,7 +283,7 @@ void SkinManageDialog::on_capeCombo_currentIndexChanged(int index)
void SkinManageDialog::on_steveBtn_toggled(bool checked)
{
if (auto skin = getSelectedSkin(); skin) {
if (auto* skin = getSelectedSkin(); skin) {
skin->setModel(checked ? SkinModel::CLASSIC : SkinModel::SLIM);
if (m_skinPreview) {
m_skinPreview->updateScene(skin);
@ -293,7 +296,7 @@ void SkinManageDialog::on_steveBtn_toggled(bool checked)
void SkinManageDialog::accept()
{
auto skin = m_list.skin(m_selectedSkinKey);
auto* skin = m_list.skin(m_selectedSkinKey);
if (!skin) {
reject();
return;
@ -353,7 +356,7 @@ bool SkinManageDialog::eventFilter(QObject* obj, QEvent* ev)
{
if (obj == m_ui->listView) {
if (ev->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
auto* keyEvent = static_cast<QKeyEvent*>(ev);
switch (keyEvent->key()) {
case Qt::Key_Delete:
on_action_Delete_Skin_triggered(false);
@ -369,26 +372,28 @@ bool SkinManageDialog::eventFilter(QObject* obj, QEvent* ev)
return QDialog::eventFilter(obj, ev);
}
void SkinManageDialog::on_action_Rename_Skin_triggered(bool)
void SkinManageDialog::on_action_Rename_Skin_triggered(bool /*unused*/)
{
if (!m_selectedSkinKey.isEmpty()) {
m_ui->listView->edit(m_ui->listView->currentIndex());
}
}
void SkinManageDialog::on_action_Delete_Skin_triggered(bool)
void SkinManageDialog::on_action_Delete_Skin_triggered(bool /*unused*/)
{
if (m_selectedSkinKey.isEmpty())
if (m_selectedSkinKey.isEmpty()) {
return;
}
if (m_list.getSkinIndex(m_selectedSkinKey) == m_list.getSelectedAccountSkin()) {
CustomMessageBox::selectable(this, tr("Delete error"), tr("Can not delete skin that is in use."), QMessageBox::Warning)->exec();
return;
}
auto skin = m_list.skin(m_selectedSkinKey);
if (!skin)
auto* skin = m_list.skin(m_selectedSkinKey);
if (!skin) {
return;
}
auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
tr("You are about to delete \"%1\".\n"
@ -435,10 +440,11 @@ void SkinManageDialog::on_urlBtn_clicked()
}
}
namespace {
class WaitTask : public Task {
public:
WaitTask() : m_loop(), m_done(false) {};
virtual ~WaitTask() = default;
WaitTask() = default;
~WaitTask() override = default;
public slots:
void quit()
@ -448,17 +454,19 @@ class WaitTask : public Task {
}
protected:
virtual void executeTask()
void executeTask() override
{
if (!m_done)
if (!m_done) {
m_loop.exec();
}
emitSucceeded();
};
private:
QEventLoop m_loop;
bool m_done;
bool m_done{};
};
} // namespace
void SkinManageDialog::on_userBtn_clicked()
{
@ -482,29 +490,29 @@ void SkinManageDialog::on_userBtn_clicked()
QString failReason;
connect(getUUID.get(), &Task::aborted, uuidLoop.get(), &WaitTask::quit);
connect(getUUID.get(), &Task::failed, this, [&failReason](QString reason) {
connect(getUUID.get(), &Task::failed, this, [&failReason](const QString& reason) {
qCritical() << "Couldn't get user UUID:" << reason;
failReason = tr("failed to get user UUID");
});
connect(getUUID.get(), &Task::failed, uuidLoop.get(), &WaitTask::quit);
connect(getProfile.get(), &Task::aborted, profileLoop.get(), &WaitTask::quit);
connect(getProfile.get(), &Task::failed, profileLoop.get(), &WaitTask::quit);
connect(getProfile.get(), &Task::failed, this, [&failReason](QString reason) {
connect(getProfile.get(), &Task::failed, this, [&failReason](const QString& reason) {
qCritical() << "Couldn't get user profile:" << reason;
failReason = tr("failed to get user profile");
});
connect(downloadSkin.get(), &Task::failed, this, [&failReason](QString reason) {
connect(downloadSkin.get(), &Task::failed, this, [&failReason](const QString& reason) {
qCritical() << "Couldn't download skin:" << reason;
failReason = tr("failed to download skin");
});
connect(getUUID.get(), &Task::succeeded, this, [uuidLoop, uuidOut, job, getProfile, &failReason] {
try {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*uuidOut, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Minecraft skin service at" << parse_error.offset
<< "reason:" << parse_error.errorString();
QJsonParseError parseError{};
QJsonDocument doc = QJsonDocument::fromJson(*uuidOut, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Minecraft skin service at" << parseError.offset
<< "reason:" << parseError.errorString();
failReason = tr("failed to parse get user UUID response");
uuidLoop->quit();
return;
@ -564,7 +572,7 @@ void SkinManageDialog::on_userBtn_clicked()
void SkinManageDialog::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
QDialog::resizeEvent(event);
QSize s = size() * (1. / 3);
auto id = m_ui->capeCombo->currentData();
@ -574,7 +582,7 @@ void SkinManageDialog::resizeEvent(QResizeEvent* event)
} else {
m_ui->capeImage->clear();
}
if (auto skin = getSelectedSkin(); skin && !m_skinPreview) {
if (auto* skin = getSelectedSkin(); skin && !m_skinPreview) {
m_skinPreviewLabel->setPixmap(
QPixmap::fromImage(skin->getPreview()).scaled(m_skinPreviewLabel->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
}
@ -582,7 +590,7 @@ void SkinManageDialog::resizeEvent(QResizeEvent* event)
SkinModel* SkinManageDialog::getSelectedSkin()
{
if (auto skin = m_list.skin(m_selectedSkinKey); skin && skin->isValid()) {
if (auto* skin = m_list.skin(m_selectedSkinKey); skin && skin->isValid()) {
return skin;
}
return nullptr;

View file

@ -34,15 +34,15 @@ class SkinManageDialog;
class SkinManageDialog : public QDialog, public SkinProvider {
Q_OBJECT
public:
explicit SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct);
explicit SkinManageDialog(QWidget* parent, const MinecraftAccountPtr& acct);
virtual ~SkinManageDialog();
void resizeEvent(QResizeEvent* event) override;
virtual SkinModel* getSelectedSkin() override;
virtual QHash<QString, QImage> capes() override;
SkinModel* getSelectedSkin() override;
QHash<QString, QImage> capes() override;
public slots:
void selectionChanged(QItemSelection, QItemSelection);
void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
void activated(QModelIndex);
void delayed_scroll(QModelIndex);
void on_openDirBtn_clicked();

View file

@ -25,7 +25,10 @@
#include <QOpenGLWindow>
namespace opengl {
Scene::Scene(const QImage& skin, bool slim, const QImage& cape) : QOpenGLFunctions(), m_slim(slim), m_capeVisible(!cape.isNull())
Scene::Scene(const QImage& skin, bool slim, const QImage& cape)
: m_cape(new opengl::BoxGeometry(QVector3D(10, 16, 1), QVector3D(0, -8, 2.5), QPoint(0, 0), QVector3D(10, 16, 1), QSize(64, 32)))
, m_slim(slim)
, m_capeVisible(!cape.isNull())
{
initializeOpenGLFunctions();
m_staticComponents = {
@ -34,9 +37,9 @@ Scene::Scene(const QImage& skin, bool slim, const QImage& cape) : QOpenGLFunctio
// body
new opengl::BoxGeometry(QVector3D(8, 12, 4), QVector3D(0, -6, 0), QPoint(16, 16), QVector3D(8, 12, 4)),
// right leg
new opengl::BoxGeometry(QVector3D(4, 12, 4), QVector3D(-1.9f, -18, -0.1f), QPoint(0, 16), QVector3D(4, 12, 4)),
new opengl::BoxGeometry(QVector3D(4, 12, 4), QVector3D(-1.9F, -18, -0.1F), QPoint(0, 16), QVector3D(4, 12, 4)),
// left leg
new opengl::BoxGeometry(QVector3D(4, 12, 4), QVector3D(1.9f, -18, -0.1f), QPoint(16, 48), QVector3D(4, 12, 4)),
new opengl::BoxGeometry(QVector3D(4, 12, 4), QVector3D(1.9F, -18, -0.1F), QPoint(16, 48), QVector3D(4, 12, 4)),
};
m_staticComponentsOverlay = {
@ -45,9 +48,9 @@ Scene::Scene(const QImage& skin, bool slim, const QImage& cape) : QOpenGLFunctio
// body
new opengl::BoxGeometry(QVector3D(8.5, 12.5, 4.5), QVector3D(0, -6, 0), QPoint(16, 32), QVector3D(8, 12, 4)),
// right leg
new opengl::BoxGeometry(QVector3D(4.5f, 12.5f, 4.5f), QVector3D(-1.9f, -18, -0.1f), QPoint(0, 32), QVector3D(4, 12, 4)),
new opengl::BoxGeometry(QVector3D(4.5F, 12.5F, 4.5F), QVector3D(-1.9F, -18, -0.1F), QPoint(0, 32), QVector3D(4, 12, 4)),
// left leg
new opengl::BoxGeometry(QVector3D(4.5f, 12.5f, 4.5f), QVector3D(1.9f, -18, -0.1f), QPoint(0, 48), QVector3D(4, 12, 4)),
new opengl::BoxGeometry(QVector3D(4.5F, 12.5F, 4.5F), QVector3D(1.9F, -18, -0.1F), QPoint(0, 48), QVector3D(4, 12, 4)),
};
m_normalArms = {
@ -78,16 +81,15 @@ Scene::Scene(const QImage& skin, bool slim, const QImage& cape) : QOpenGLFunctio
new opengl::BoxGeometry(QVector3D(3.5, 12.5, 4.5), QVector3D(5.5, -6, 0), QPoint(48, 48), QVector3D(3, 12, 4)),
};
m_cape = new opengl::BoxGeometry(QVector3D(10, 16, 1), QVector3D(0, -8, 2.5), QPoint(0, 0), QVector3D(10, 16, 1), QSize(64, 32));
m_cape->rotate(10.8f, QVector3D(1, 0, 0));
m_cape->rotate(10.8F, QVector3D(1, 0, 0));
m_cape->rotate(180, QVector3D(0, 1, 0));
auto leftWing =
auto* leftWing =
new opengl::BoxGeometry(QVector3D(12, 22, 4), QVector3D(0, -13, -2), QPoint(22, 0), QVector3D(10, 20, 2), QSize(64, 32));
leftWing->rotate(15, QVector3D(1, 0, 0));
leftWing->rotate(15, QVector3D(0, 0, 1));
leftWing->rotate(1, QVector3D(1, 0, 0));
auto rightWing =
auto* rightWing =
new opengl::BoxGeometry(QVector3D(12, 22, 4), QVector3D(0, -13, -2), QPoint(22, 0), QVector3D(10, 20, 2), QSize(64, 32));
rightWing->scale(QVector3D(-1, 1, 1));
rightWing->rotate(15, QVector3D(1, 0, 0));
@ -106,9 +108,9 @@ Scene::Scene(const QImage& skin, bool slim, const QImage& cape) : QOpenGLFunctio
}
Scene::~Scene()
{
for (auto array :
for (const auto& array :
{ m_staticComponents, m_normalArms, m_slimArms, m_elytra, m_staticComponentsOverlay, m_normalArmsOverlay, m_slimArmsOverlay }) {
for (auto g : array) {
for (auto* g : array) {
delete g;
}
}
@ -125,9 +127,9 @@ void Scene::draw(QOpenGLShaderProgram* program)
{
m_skinTexture->bind();
program->setUniformValue("texture", 0);
for (auto toDraw : { m_staticComponents, m_slim ? m_slimArms : m_normalArms, m_staticComponentsOverlay,
m_slim ? m_slimArmsOverlay : m_normalArmsOverlay }) {
for (auto g : toDraw) {
for (const auto& toDraw : { m_staticComponents, m_slim ? m_slimArms : m_normalArms, m_staticComponentsOverlay,
m_slim ? m_slimArmsOverlay : m_normalArmsOverlay }) {
for (auto* g : toDraw) {
g->draw(program);
}
}
@ -138,7 +140,7 @@ void Scene::draw(QOpenGLShaderProgram* program)
if (!m_elytraVisible) {
m_cape->draw(program);
} else {
for (auto e : m_elytra) {
for (auto* e : m_elytra) {
e->draw(program);
}
}
@ -146,11 +148,13 @@ void Scene::draw(QOpenGLShaderProgram* program)
}
}
namespace {
void updateTexture(QOpenGLTexture* texture, const QImage& img)
{
if (texture) {
if (texture->isBound())
if (texture->isBound()) {
texture->release();
}
texture->destroy();
texture->create();
texture->setSize(img.width(), img.height());
@ -159,6 +163,7 @@ void updateTexture(QOpenGLTexture* texture, const QImage& img)
texture->setMagnificationFilter(QOpenGLTexture::Nearest);
}
}
} // namespace
void Scene::setSkin(const QImage& skin)
{

View file

@ -24,6 +24,7 @@
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <utility>
#include "Application.h"
#include "BaseVersionList.h"
@ -31,104 +32,115 @@
#include "Filter.h"
#include "java/download/ArchiveDownloadTask.h"
#include "java/download/ManifestDownloadTask.h"
#include "java/download/SymlinkTask.h"
#include "meta/Index.h"
#include "meta/VersionList.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "tasks/SequentialTask.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/ProgressDialog.h"
#include "ui/java/VersionList.h"
#include "ui/widgets/PageContainer.h"
#include "ui/widgets/VersionSelectWidget.h"
#if defined(Q_OS_MACOS)
#include "java/download/SymlinkTask.h"
#include "tasks/SequentialTask.h"
#endif
namespace {
class InstallJavaPage : public QWidget, public BasePage {
public:
Q_OBJECT
public:
explicit InstallJavaPage(const QString& id, const QString& iconName, const QString& name, QWidget* parent = nullptr)
: QWidget(parent), uid(id), iconName(iconName), name(name)
explicit InstallJavaPage(QString id, QString iconName, QString name, QWidget* parent = nullptr)
: QWidget(parent)
, m_uid(std::move(id))
, m_iconName(std::move(iconName))
, m_name(std::move(name))
, m_horizontalLayout(new QHBoxLayout(this))
, m_majorVersionSelect(new VersionSelectWidget(this))
, m_javaVersionSelect(new VersionSelectWidget(this))
{
setObjectName(QStringLiteral("VersionSelectWidget"));
horizontalLayout = new QHBoxLayout(this);
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
horizontalLayout->setContentsMargins(0, 0, 0, 0);
majorVersionSelect = new VersionSelectWidget(this);
majorVersionSelect->selectCurrent();
majorVersionSelect->setEmptyString(tr("No Java versions are currently available in the meta."));
majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the Java version lists!"));
horizontalLayout->addWidget(majorVersionSelect, 1);
javaVersionSelect = new VersionSelectWidget(this);
javaVersionSelect->setEmptyString(tr("No Java versions are currently available for your OS."));
javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the Java version lists!"));
horizontalLayout->addWidget(javaVersionSelect, 4);
connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::setSelectedVersion);
connect(majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
connect(javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
m_horizontalLayout->setContentsMargins(0, 0, 0, 0);
m_majorVersionSelect->selectCurrent();
m_majorVersionSelect->setEmptyString(tr("No Java versions are currently available in the meta."));
m_majorVersionSelect->setEmptyErrorString(tr("Couldn't load or download the Java version lists!"));
m_horizontalLayout->addWidget(m_majorVersionSelect, 1);
m_javaVersionSelect->setEmptyString(tr("No Java versions are currently available for your OS."));
m_javaVersionSelect->setEmptyErrorString(tr("Couldn't load or download the Java version lists!"));
m_horizontalLayout->addWidget(m_javaVersionSelect, 4);
connect(m_majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::setSelectedVersion);
connect(m_majorVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
connect(m_javaVersionSelect, &VersionSelectWidget::selectedVersionChanged, this, &InstallJavaPage::selectionChanged);
QMetaObject::connectSlotsByName(this);
}
~InstallJavaPage()
~InstallJavaPage() override
{
delete horizontalLayout;
delete majorVersionSelect;
delete javaVersionSelect;
delete m_horizontalLayout;
delete m_majorVersionSelect;
delete m_javaVersionSelect;
}
//! loads the list if needed.
void initialize(Meta::VersionList::Ptr vlist)
void initialize(const Meta::VersionList::Ptr& vlist)
{
vlist->setProvidedRoles({ BaseVersionList::JavaMajorRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole });
majorVersionSelect->initialize(vlist.get());
m_majorVersionSelect->initialize(vlist.get());
}
void setSelectedVersion(BaseVersion::Ptr version)
void setSelectedVersion(const BaseVersion::Ptr& version)
{
auto dcast = std::dynamic_pointer_cast<Meta::Version>(version);
if (!dcast) {
return;
}
javaVersionSelect->initialize(new Java::VersionList(dcast, this));
javaVersionSelect->selectCurrent();
m_javaVersionSelect->initialize(new Java::VersionList(dcast, this));
m_javaVersionSelect->selectCurrent();
}
QString id() const override { return uid; }
QString displayName() const override { return name; }
QIcon icon() const override { return QIcon::fromTheme(iconName); }
QString id() const override { return m_uid; }
QString displayName() const override { return m_name; }
QIcon icon() const override { return QIcon::fromTheme(m_iconName); }
void openedImpl() override
{
if (loaded)
if (m_loaded) {
return;
}
const auto versions = APPLICATION->metadataIndex()->get(uid);
if (!versions)
const auto versions = APPLICATION->metadataIndex()->get(m_uid);
if (!versions) {
return;
}
initialize(versions);
loaded = true;
m_loaded = true;
}
void setParentContainer(BasePageContainer* container) override
{
auto dialog = dynamic_cast<QDialog*>(dynamic_cast<PageContainer*>(container)->parent());
connect(javaVersionSelect->view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept);
auto* dialog = dynamic_cast<QDialog*>(dynamic_cast<PageContainer*>(container)->parent());
connect(m_javaVersionSelect->view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept);
}
BaseVersion::Ptr selectedVersion() const { return javaVersionSelect->selectedVersion(); }
void selectSearch() { javaVersionSelect->selectSearch(); }
BaseVersion::Ptr selectedVersion() const { return m_javaVersionSelect->selectedVersion(); }
void selectSearch() { m_javaVersionSelect->selectSearch(); }
void loadList()
{
majorVersionSelect->loadList(true);
javaVersionSelect->loadList(true);
m_majorVersionSelect->loadList(true);
m_javaVersionSelect->loadList(true);
}
public slots:
void setRecommendedMajors(const QStringList& majors)
{
m_recommended_majors = majors;
m_recommendedMajors = majors;
recommendedFilterChanged();
}
void setRecommend(bool recommend)
@ -139,9 +151,9 @@ class InstallJavaPage : public QWidget, public BasePage {
void recommendedFilterChanged()
{
if (m_recommend) {
majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny(m_recommended_majors));
m_majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny(m_recommendedMajors));
} else {
majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny());
m_majorVersionSelect->setFilter(BaseVersionList::ModelRoles::JavaMajorRole, Filters::equalsAny());
}
}
@ -149,30 +161,30 @@ class InstallJavaPage : public QWidget, public BasePage {
void selectionChanged();
private:
const QString uid;
const QString iconName;
const QString name;
bool loaded = false;
const QString m_uid;
const QString m_iconName;
const QString m_name;
bool m_loaded = false;
QHBoxLayout* horizontalLayout = nullptr;
VersionSelectWidget* majorVersionSelect = nullptr;
VersionSelectWidget* javaVersionSelect = nullptr;
QHBoxLayout* m_horizontalLayout = nullptr;
VersionSelectWidget* m_majorVersionSelect = nullptr;
VersionSelectWidget* m_javaVersionSelect = nullptr;
QStringList m_recommended_majors;
bool m_recommend;
QStringList m_recommendedMajors;
bool m_recommend{};
};
static InstallJavaPage* pageCast(BasePage* page)
InstallJavaPage* pageCast(BasePage* page)
{
auto result = dynamic_cast<InstallJavaPage*>(page);
auto* result = dynamic_cast<InstallJavaPage*>(page);
Q_ASSERT(result != nullptr);
return result;
}
namespace Java {
QStringList getRecommendedJavaVersionsFromVersionList(Meta::VersionList::Ptr list)
QStringList getRecommendedJavaVersionsFromVersionList(const Meta::VersionList::Ptr& list)
{
QStringList recommendedJavas;
for (auto ver : list->versions()) {
for (const auto& ver : list->versions()) {
auto major = ver->version();
if (major.startsWith("java")) {
major = "Java " + major.mid(4);
@ -181,34 +193,37 @@ QStringList getRecommendedJavaVersionsFromVersionList(Meta::VersionList::Ptr lis
}
return recommendedJavas;
}
} // namespace
namespace Java {
InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget* parent)
: QDialog(parent), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this))
: QDialog(parent), m_container(new PageContainer(this, QString(), this)), m_buttons(new QDialogButtonBox(this))
{
auto layout = new QVBoxLayout(this);
// small margins look ugly on macOS on modal windows
#ifndef Q_OS_MACOS
auto* layout = new QVBoxLayout(this);
// small margins look ugly on macOS on modal windows
#ifndef Q_OS_MACOS
layout->setContentsMargins(0, 0, 0, 0);
#endif
container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
layout->addWidget(container);
#endif
m_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
layout->addWidget(m_container);
auto buttonLayout = new QHBoxLayout(this);
// small margins look ugly on macOS on modal windows
#ifndef Q_OS_MACOS
auto* buttonLayout = new QHBoxLayout(this);
// small margins look ugly on macOS on modal windows
#ifndef Q_OS_MACOS
buttonLayout->setContentsMargins(0, 0, 6, 6);
#endif
#endif
auto refreshLayout = new QHBoxLayout(this);
auto* refreshLayout = new QHBoxLayout(this);
auto refreshButton = new QPushButton(tr("&Refresh"), this);
connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); });
auto* refreshButton = new QPushButton(tr("&Refresh"), this);
connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(m_container->selectedPage())->loadList(); });
refreshLayout->addWidget(refreshButton);
auto recommendedCheckBox = new QCheckBox("Recommended", this);
auto* recommendedCheckBox = new QCheckBox("Recommended", this);
recommendedCheckBox->setCheckState(Qt::CheckState::Checked);
connect(recommendedCheckBox, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) {
for (BasePage* page : container->getPages()) {
for (BasePage* page : m_container->getPages()) {
pageCast(page)->setRecommend(state == Qt::Checked);
}
});
@ -216,22 +231,22 @@ InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget
refreshLayout->addWidget(recommendedCheckBox);
buttonLayout->addLayout(refreshLayout);
buttons->setOrientation(Qt::Horizontal);
buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
buttons->button(QDialogButtonBox::Ok)->setText(tr("Download"));
buttons->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
buttonLayout->addWidget(buttons);
m_buttons->setOrientation(Qt::Horizontal);
m_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
m_buttons->button(QDialogButtonBox::Ok)->setText(tr("Download"));
m_buttons->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
buttonLayout->addWidget(m_buttons);
container->addButtons(buttonLayout);
m_container->addButtons(buttonLayout);
setWindowTitle(dialogTitle());
setWindowModality(Qt::WindowModal);
resize(840, 480);
QStringList recommendedJavas;
if (auto mcInst = dynamic_cast<MinecraftInstance*>(instance); mcInst) {
if (auto* mcInst = dynamic_cast<MinecraftInstance*>(instance); mcInst) {
auto mc = mcInst->getPackProfile()->getComponent("net.minecraft");
if (mc) {
auto file = mc->getVersionFile(); // no need for load as it should already be loaded
@ -251,32 +266,35 @@ InstallDialog::InstallDialog(const QString& uid, BaseInstance* instance, QWidget
if (newTask) {
connect(newTask.get(), &Task::succeeded, this, [this, versions] {
auto recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions);
for (BasePage* page : container->getPages()) {
for (BasePage* page : m_container->getPages()) {
pageCast(page)->setRecommendedMajors(recommendedJavas);
}
});
if (!newTask->isRunning())
if (!newTask->isRunning()) {
newTask->start();
}
} else {
recommendedJavas = getRecommendedJavaVersionsFromVersionList(versions);
}
}
}
}
for (BasePage* page : container->getPages()) {
if (page->id() == uid)
container->selectPage(page->id());
for (BasePage* page : m_container->getPages()) {
if (page->id() == uid) {
m_container->selectPage(page->id());
}
auto cast = pageCast(page);
auto* cast = pageCast(page);
cast->setRecommend(true);
connect(cast, &InstallJavaPage::selectionChanged, this, [this, cast] { validate(cast); });
if (!recommendedJavas.isEmpty()) {
cast->setRecommendedMajors(recommendedJavas);
}
}
connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* selected) { validate(selected); });
pageCast(container->selectedPage())->selectSearch();
validate(container->selectedPage());
connect(m_container, &PageContainer::selectedPageChanged, this,
[this](BasePage* /*previous*/, BasePage* selected) { validate(selected); });
pageCast(m_container->selectedPage())->selectSearch();
validate(m_container->selectedPage());
}
QList<BasePage*> InstallDialog::getPages()
@ -289,9 +307,9 @@ QList<BasePage*> InstallDialog::getPages()
// Azul
new InstallJavaPage("com.azul.java", "azul", tr("Azul Zulu")),
// IBM
/* Must watch out in case the AdoptOpenJDK infrastructure is deprecated.
In case of happening, IBM does not seem to provide as of today (03/2026) an API like Adoptium does and rather uses GitHub directly in its website: `developer.ibm.com`.
GitHub is known for rate limiting requests that do not use an API key from an account. */
/* Must watch out in case the AdoptOpenJDK infrastructure is deprecated.
In case of happening, IBM does not seem to provide as of today (03/2026) an API like Adoptium does and rather uses GitHub directly
in its website: `developer.ibm.com`. GitHub is known for rate limiting requests that do not use an API key from an account. */
new InstallJavaPage("com.ibm.java", "openj9_hex_custom", tr("IBM Semeru Open")),
};
}
@ -303,25 +321,25 @@ QString InstallDialog::dialogTitle()
void InstallDialog::validate(BasePage* selected)
{
buttons->button(QDialogButtonBox::Ok)->setEnabled(!!std::dynamic_pointer_cast<Java::Metadata>(pageCast(selected)->selectedVersion()));
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(!!std::dynamic_pointer_cast<Java::Metadata>(pageCast(selected)->selectedVersion()));
}
void InstallDialog::done(int result)
{
if (result == Accepted) {
auto* page = pageCast(container->selectedPage());
auto* page = pageCast(m_container->selectedPage());
if (page->selectedVersion()) {
auto meta = std::dynamic_pointer_cast<Java::Metadata>(page->selectedVersion());
if (meta) {
Task::Ptr task;
auto final_path = FS::PathCombine(APPLICATION->javaPath(), meta->m_name);
auto deletePath = [final_path] { FS::deletePath(final_path); };
auto finalPath = FS::PathCombine(APPLICATION->javaPath(), meta->m_name);
auto deletePath = [finalPath] { FS::deletePath(finalPath); };
switch (meta->downloadType) {
case Java::DownloadType::Manifest:
task = makeShared<ManifestDownloadTask>(meta->url, final_path, meta->checksumType, meta->checksumHash);
task = makeShared<ManifestDownloadTask>(meta->url, finalPath, meta->checksumType, meta->checksumHash);
break;
case Java::DownloadType::Archive:
task = makeShared<ArchiveDownloadTask>(meta->url, final_path, meta->checksumType, meta->checksumHash);
task = makeShared<ArchiveDownloadTask>(meta->url, finalPath, meta->checksumType, meta->checksumHash);
break;
case Java::DownloadType::Unknown:
QString error = QString(tr("Could not determine Java download type!"));
@ -332,10 +350,10 @@ void InstallDialog::done(int result)
#if defined(Q_OS_MACOS)
auto seq = makeShared<SequentialTask>(tr("Install Java"));
seq->addTask(task);
seq->addTask(makeShared<Java::SymlinkTask>(final_path));
seq->addTask(makeShared<Java::SymlinkTask>(finalPath));
task = seq;
#endif
connect(task.get(), &Task::failed, this, [this, &deletePath](QString reason) {
connect(task.get(), &Task::failed, this, [this, &deletePath](const QString& reason) {
QString error = QString("Java download failed: %1").arg(reason);
CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show();
deletePath();

View file

@ -41,7 +41,7 @@ class InstallDialog final : public QDialog, private BasePageProvider {
void done(int result) override;
private:
PageContainer* container;
QDialogButtonBox* buttons;
PageContainer* m_container;
QDialogButtonBox* m_buttons;
};
} // namespace Java

View file

@ -37,42 +37,42 @@
#include "ui_CustomPage.h"
#include <QTabBar>
#include <utility>
#include "Application.h"
#include "Filter.h"
#include "Version.h"
#include "meta/Index.h"
#include "meta/VersionList.h"
#include "minecraft/VanillaInstanceCreationTask.h"
#include "ui/dialogs/NewInstanceDialog.h"
CustomPage::CustomPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog(dialog), ui(new Ui::CustomPage)
CustomPage::CustomPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), m_dialog(dialog), m_ui(new Ui::CustomPage)
{
ui->setupUi(this);
connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedVersion);
m_ui->setupUi(this);
connect(m_ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedVersion);
filterChanged();
connect(ui->alphaFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(ui->betaFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(ui->snapshotFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(ui->releaseFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(ui->experimentsFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(ui->refreshBtn, &QPushButton::clicked, this, &CustomPage::refresh);
connect(m_ui->alphaFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(m_ui->betaFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(m_ui->snapshotFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(m_ui->releaseFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(m_ui->experimentsFilter, &QCheckBox::checkStateChanged, this, &CustomPage::filterChanged);
connect(m_ui->refreshBtn, &QPushButton::clicked, this, &CustomPage::refresh);
connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedLoaderVersion);
connect(ui->noneFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->forgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->fabricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh);
connect(m_ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedLoaderVersion);
connect(m_ui->noneFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(m_ui->forgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(m_ui->fabricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(m_ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(m_ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(m_ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh);
}
void CustomPage::openedImpl()
{
if (!initialized) {
if (!m_initialized) {
auto vlist = APPLICATION->metadataIndex()->get("net.minecraft");
ui->versionList->initialize(vlist.get());
initialized = true;
m_ui->versionList->initialize(vlist.get());
m_initialized = true;
} else {
suggestCurrent();
}
@ -80,31 +80,37 @@ void CustomPage::openedImpl()
void CustomPage::refresh()
{
ui->versionList->loadList(true);
m_ui->versionList->loadList(true);
}
void CustomPage::loaderRefresh()
{
if (ui->noneFilter->isChecked())
if (m_ui->noneFilter->isChecked()) {
return;
ui->loaderVersionList->loadList(true);
}
m_ui->loaderVersionList->loadList(true);
}
void CustomPage::filterChanged()
{
QStringList out;
if (ui->alphaFilter->isChecked())
if (m_ui->alphaFilter->isChecked()) {
out << "(alpha)";
if (ui->betaFilter->isChecked())
}
if (m_ui->betaFilter->isChecked()) {
out << "(beta)";
if (ui->snapshotFilter->isChecked())
}
if (m_ui->snapshotFilter->isChecked()) {
out << "(snapshot)";
if (ui->releaseFilter->isChecked())
}
if (m_ui->releaseFilter->isChecked()) {
out << "(release)";
if (ui->experimentsFilter->isChecked())
}
if (m_ui->experimentsFilter->isChecked()) {
out << "(experiment)";
}
auto regexp = out.join('|');
ui->versionList->setFilter(BaseVersionList::TypeRole, Filters::regexp(QRegularExpression(regexp)));
m_ui->versionList->setFilter(BaseVersionList::TypeRole, Filters::regexp(QRegularExpression(regexp)));
}
void CustomPage::loaderFilterChanged()
@ -113,50 +119,53 @@ void CustomPage::loaderFilterChanged()
if (m_selectedVersion) {
minecraftVersion = m_selectedVersion->descriptor();
} else {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list
ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected."));
ui->loaderVersionList->setEmptyMode(VersionListView::String);
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list
m_ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected."));
m_ui->loaderVersionList->setEmptyMode(VersionListView::String);
return;
}
if (ui->noneFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list
ui->loaderVersionList->setEmptyString(tr("No mod loader is selected."));
ui->loaderVersionList->setEmptyMode(VersionListView::String);
if (m_ui->noneFilter->isChecked()) {
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list
m_ui->loaderVersionList->setEmptyString(tr("No mod loader is selected."));
m_ui->loaderVersionList->setEmptyMode(VersionListView::String);
return;
} else if (ui->neoForgeFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
}
if (m_ui->neoForgeFilter->isChecked()) {
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "net.neoforged";
} else if (ui->forgeFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
} else if (m_ui->forgeFilter->isChecked()) {
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "net.minecraftforge";
} else if (ui->fabricFilter->isChecked()) {
} else if (m_ui->fabricFilter->isChecked()) {
// FIXME: dirty hack because the launcher is unaware of Fabric's dependencies
if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
else // Fabric/Quilt unsupported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
if (Version(minecraftVersion) >= Version("1.14")) { // Fabric/Quilt supported
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
} else { // Fabric/Quilt unsupported
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
}
m_selectedLoader = "net.fabricmc.fabric-loader";
} else if (ui->quiltFilter->isChecked()) {
} else if (m_ui->quiltFilter->isChecked()) {
// FIXME: dirty hack because the launcher is unaware of Quilt's dependencies (same as Fabric)
if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
else // Fabric/Quilt unsupported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
if (Version(minecraftVersion) >= Version("1.14")) { // Fabric/Quilt supported
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
} else { // Fabric/Quilt unsupported
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
}
m_selectedLoader = "org.quiltmc.quilt-loader";
} else if (ui->liteLoaderFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
} else if (m_ui->liteLoaderFilter->isChecked()) {
m_ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "com.mumfrey.liteloader";
}
auto vlist = APPLICATION->metadataIndex()->get(m_selectedLoader);
ui->loaderVersionList->initialize(vlist.get());
ui->loaderVersionList->selectRecommended();
ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion));
m_ui->loaderVersionList->initialize(vlist.get());
m_ui->loaderVersionList->selectRecommended();
m_ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion));
}
CustomPage::~CustomPage()
{
delete ui;
delete m_ui;
}
bool CustomPage::shouldDisplay() const
@ -166,7 +175,7 @@ bool CustomPage::shouldDisplay() const
void CustomPage::retranslate()
{
ui->retranslateUi(this);
m_ui->retranslateUi(this);
}
BaseVersion::Ptr CustomPage::selectedVersion() const
@ -191,29 +200,29 @@ void CustomPage::suggestCurrent()
}
if (!m_selectedVersion) {
dialog->setSuggestedPack();
m_dialog->setSuggestedPack();
return;
}
// There isn't a selected version if the version list is empty
if (ui->loaderVersionList->selectedVersion() == nullptr)
dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion));
else {
dialog->setSuggestedPack(m_selectedVersion->descriptor(),
new VanillaCreationTask(m_selectedVersion, m_selectedLoader, m_selectedLoaderVersion));
if (m_ui->loaderVersionList->selectedVersion() == nullptr) {
m_dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion));
} else {
m_dialog->setSuggestedPack(m_selectedVersion->descriptor(),
new VanillaCreationTask(m_selectedVersion, m_selectedLoader, m_selectedLoaderVersion));
}
dialog->setSuggestedIcon("default");
m_dialog->setSuggestedIcon("default");
}
void CustomPage::setSelectedVersion(BaseVersion::Ptr version)
{
m_selectedVersion = version;
m_selectedVersion = std::move(version);
suggestCurrent();
loaderFilterChanged();
}
void CustomPage::setSelectedLoaderVersion(BaseVersion::Ptr version)
{
m_selectedLoaderVersion = version;
m_selectedLoaderVersion = std::move(version);
suggestCurrent();
}

View file

@ -38,7 +38,6 @@
#include <QWidget>
#include "BaseVersion.h"
#include "tasks/Task.h"
#include "ui/pages/BasePage.h"
namespace Ui {
@ -51,13 +50,13 @@ class CustomPage : public QWidget, public BasePage {
Q_OBJECT
public:
explicit CustomPage(NewInstanceDialog* dialog, QWidget* parent = 0);
virtual ~CustomPage();
virtual QString displayName() const override { return tr("Custom"); }
virtual QIcon icon() const override { return QIcon::fromTheme("minecraft"); }
virtual QString id() const override { return "vanilla"; }
virtual QString helpPage() const override { return "Vanilla-platform"; }
virtual bool shouldDisplay() const override;
explicit CustomPage(NewInstanceDialog* dialog, QWidget* parent = nullptr);
~CustomPage() override;
QString displayName() const override { return tr("Custom"); }
QIcon icon() const override { return QIcon::fromTheme("minecraft"); }
QString id() const override { return "vanilla"; }
QString helpPage() const override { return "Vanilla-platform"; }
bool shouldDisplay() const override;
void retranslate() override;
void openedImpl() override;
@ -80,9 +79,9 @@ class CustomPage : public QWidget, public BasePage {
void suggestCurrent();
private:
bool initialized = false;
NewInstanceDialog* dialog = nullptr;
Ui::CustomPage* ui = nullptr;
bool m_initialized = false;
NewInstanceDialog* m_dialog = nullptr;
Ui::CustomPage* m_ui = nullptr;
bool m_versionSetByUser = false;
BaseVersion::Ptr m_selectedVersion;
BaseVersion::Ptr m_selectedLoaderVersion;

View file

@ -44,7 +44,6 @@
#include "FileSystem.h"
#include "HardwareInfo.h"
#include "JavaCommon.h"
#include "SysInfo.h"
#include "java/JavaInstallList.h"
#include "java/JavaUtils.h"
#include "settings/Setting.h"
@ -64,8 +63,9 @@ JavaSettingsWidget::JavaSettingsWidget(BaseInstance* instance, QWidget* parent)
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
connect(m_ui->autodetectJavaCheckBox, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) {
m_ui->autodownloadJavaCheckBox->setEnabled(state);
if (state != Qt::Checked)
if (state != Qt::Checked) {
m_ui->autodownloadJavaCheckBox->setChecked(false);
}
});
} else {
m_ui->autodownloadJavaCheckBox->hide();
@ -88,10 +88,10 @@ JavaSettingsWidget::JavaSettingsWidget(BaseInstance* instance, QWidget* parent)
[this, settings] { m_ui->javaPathTextBox->setText(settings->get("JavaPath").toString()); });
connect(m_ui->javaDownloadBtn, &QPushButton::clicked, this, [this] {
auto javaDialog = new Java::InstallDialog({}, m_instance, this);
auto* javaDialog = new Java::InstallDialog({}, m_instance, this);
javaDialog->exec();
});
connect(m_ui->javaPathTextBox, &QLineEdit::textChanged, [this](QString newValue) {
connect(m_ui->javaPathTextBox, &QLineEdit::textChanged, [this](const QString& newValue) {
if (m_instance->settings()->get("JavaPath").toString() != newValue) {
m_instance->settings()->set("AutomaticJava", false);
}
@ -116,12 +116,13 @@ JavaSettingsWidget::~JavaSettingsWidget()
void JavaSettingsWidget::loadSettings()
{
SettingsObject* settings;
SettingsObject* settings = nullptr;
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings = m_instance->settings();
else
} else {
settings = APPLICATION->settings();
}
// Java Settings
m_ui->javaInstallationGroupBox->setChecked(settings->get("OverrideJavaLocation").toBool());
@ -159,20 +160,22 @@ void JavaSettingsWidget::loadSettings()
void JavaSettingsWidget::saveSettings()
{
SettingsObject* settings;
SettingsObject* settings = nullptr;
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings = m_instance->settings();
else
} else {
settings = APPLICATION->settings();
}
SettingsObject::Lock lock(settings);
// Java Install Settings
bool javaInstall = m_instance == nullptr || m_ui->javaInstallationGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideJavaLocation", javaInstall);
}
if (javaInstall) {
settings->set("JavaPath", m_ui->javaPathTextBox->text());
@ -191,8 +194,9 @@ void JavaSettingsWidget::saveSettings()
// Memory
bool memory = m_instance == nullptr || m_ui->memoryGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideMemory", memory);
}
if (memory) {
int min = m_ui->minMemSpinBox->value();
@ -216,8 +220,9 @@ void JavaSettingsWidget::saveSettings()
// Java arguments
bool javaArgs = m_instance == nullptr || m_ui->javaArgumentsGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideJavaArgs", javaArgs);
}
if (javaArgs) {
settings->set("JvmArgs", m_ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
@ -245,15 +250,17 @@ void JavaSettingsWidget::onJavaBrowse()
void JavaSettingsWidget::onJavaTest()
{
if (m_checker != nullptr)
if (m_checker != nullptr) {
return;
}
QString jvmArgs;
if (m_instance == nullptr || m_ui->javaArgumentsGroupBox->isChecked())
if (m_instance == nullptr || m_ui->javaArgumentsGroupBox->isChecked()) {
jvmArgs = m_ui->jvmArgsTextBox->toPlainText().replace("\n", " ");
else
} else {
jvmArgs = APPLICATION->settings()->get("JvmArgs").toString();
}
m_checker.reset(new JavaCommon::TestCheck(this, m_ui->javaPathTextBox->text(), jvmArgs, m_ui->minMemSpinBox->value(),
m_ui->maxMemSpinBox->value(), m_ui->permGenSpinBox->value()));
@ -298,7 +305,7 @@ void JavaSettingsWidget::updateThresholds()
m_ui->labelMaxMemNotice->setText(
QString("<span style='color:red'>%1</span>").arg(tr("Your maximum memory allocation exceeds your system memory capacity.")));
m_ui->labelMaxMemNotice->show();
} else if (maxMem > (sysMiB * 0.9)) {
} else if (maxMem > (static_cast<double>(sysMiB) * 0.9)) {
m_ui->labelMaxMemNotice->setText(warningColour.arg(tr("Your maximum memory allocation is close to your system memory capacity.")));
m_ui->labelMaxMemNotice->show();
} else if (maxMem < minMem) {

View file

@ -12,6 +12,7 @@
#include <QSpinBox>
#include <QToolButton>
#include <QVBoxLayout>
#include <algorithm>
#include "DesktopServices.h"
#include "FileSystem.h"
@ -29,14 +30,13 @@
#include "BuildConfig.h"
#include "HardwareInfo.h"
JavaWizardWidget::JavaWizardWidget(QWidget* parent) : QWidget(parent)
JavaWizardWidget::JavaWizardWidget(QWidget* parent)
: QWidget(parent), m_availableMemory(HardwareInfo::totalRamMiB()), m_memoryTimer(new QTimer(this))
{
m_availableMemory = HardwareInfo::totalRamMiB();
m_goodIcon = QIcon::fromTheme("status-good");
m_yellowIcon = QIcon::fromTheme("status-yellow");
m_badIcon = QIcon::fromTheme("status-bad");
goodIcon = QIcon::fromTheme("status-good");
yellowIcon = QIcon::fromTheme("status-yellow");
badIcon = QIcon::fromTheme("status-bad");
m_memoryTimer = new QTimer(this);
setupUi();
connect(m_minMemSpinBox, &QSpinBox::valueChanged, this, &JavaWizardWidget::onSpinBoxValueChanged);
@ -44,11 +44,11 @@ JavaWizardWidget::JavaWizardWidget(QWidget* parent) : QWidget(parent)
connect(m_permGenSpinBox, &QSpinBox::valueChanged, this, &JavaWizardWidget::onSpinBoxValueChanged);
connect(m_memoryTimer, &QTimer::timeout, this, &JavaWizardWidget::memoryValueChanged);
connect(m_versionWidget, &VersionSelectWidget::selectedVersionChanged, this, &JavaWizardWidget::javaVersionSelected);
connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaWizardWidget::on_javaBrowseBtn_clicked);
connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaWizardWidget::onJavaBrowseBtnClicked);
connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaWizardWidget::javaPathEdited);
connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaWizardWidget::on_javaStatusBtn_clicked);
connect(m_javaStatusBtn, &QToolButton::clicked, this, &JavaWizardWidget::onJavaStatusBtnClicked);
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaWizardWidget::javaDownloadBtn_clicked);
connect(m_javaDownloadBtn, &QPushButton::clicked, this, &JavaWizardWidget::javaDownloadBtnClicked);
}
}
@ -73,18 +73,18 @@ void JavaWizardWidget::setupUi()
m_horizontalLayout->addWidget(m_javaBrowseBtn);
m_javaStatusBtn = new QToolButton(this);
m_javaStatusBtn->setIcon(yellowIcon);
m_javaStatusBtn->setIcon(m_yellowIcon);
m_horizontalLayout->addWidget(m_javaStatusBtn);
m_memoryGroupBox = new QGroupBox(this);
m_memoryGroupBox->setObjectName(QStringLiteral("memoryGroupBox"));
m_gridLayout_2 = new QGridLayout(m_memoryGroupBox);
m_gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
m_gridLayout_2->setColumnStretch(0, 1);
m_gridLayout2 = new QGridLayout(m_memoryGroupBox);
m_gridLayout2->setObjectName(QStringLiteral("gridLayout_2"));
m_gridLayout2->setColumnStretch(0, 1);
m_labelMinMem = new QLabel(m_memoryGroupBox);
m_labelMinMem->setObjectName(QStringLiteral("labelMinMem"));
m_gridLayout_2->addWidget(m_labelMinMem, 0, 0, 1, 1);
m_gridLayout2->addWidget(m_labelMinMem, 0, 0, 1, 1);
m_minMemSpinBox = new QSpinBox(m_memoryGroupBox);
m_minMemSpinBox->setObjectName(QStringLiteral("minMemSpinBox"));
@ -93,11 +93,11 @@ void JavaWizardWidget::setupUi()
m_minMemSpinBox->setMaximum(1048576);
m_minMemSpinBox->setSingleStep(128);
m_labelMinMem->setBuddy(m_minMemSpinBox);
m_gridLayout_2->addWidget(m_minMemSpinBox, 0, 1, 1, 1);
m_gridLayout2->addWidget(m_minMemSpinBox, 0, 1, 1, 1);
m_labelMaxMem = new QLabel(m_memoryGroupBox);
m_labelMaxMem->setObjectName(QStringLiteral("labelMaxMem"));
m_gridLayout_2->addWidget(m_labelMaxMem, 1, 0, 1, 1);
m_gridLayout2->addWidget(m_labelMaxMem, 1, 0, 1, 1);
m_maxMemSpinBox = new QSpinBox(m_memoryGroupBox);
m_maxMemSpinBox->setObjectName(QStringLiteral("maxMemSpinBox"));
@ -106,16 +106,16 @@ void JavaWizardWidget::setupUi()
m_maxMemSpinBox->setMaximum(1048576);
m_maxMemSpinBox->setSingleStep(128);
m_labelMaxMem->setBuddy(m_maxMemSpinBox);
m_gridLayout_2->addWidget(m_maxMemSpinBox, 1, 1, 1, 1);
m_gridLayout2->addWidget(m_maxMemSpinBox, 1, 1, 1, 1);
m_labelMaxMemIcon = new QLabel(m_memoryGroupBox);
m_labelMaxMemIcon->setObjectName(QStringLiteral("labelMaxMemIcon"));
m_gridLayout_2->addWidget(m_labelMaxMemIcon, 1, 2, 1, 1);
m_gridLayout2->addWidget(m_labelMaxMemIcon, 1, 2, 1, 1);
m_labelPermGen = new QLabel(m_memoryGroupBox);
m_labelPermGen->setObjectName(QStringLiteral("labelPermGen"));
m_labelPermGen->setText(QStringLiteral("PermGen:"));
m_gridLayout_2->addWidget(m_labelPermGen, 2, 0, 1, 1);
m_gridLayout2->addWidget(m_labelPermGen, 2, 0, 1, 1);
m_labelPermGen->setVisible(false);
m_permGenSpinBox = new QSpinBox(m_memoryGroupBox);
@ -124,7 +124,7 @@ void JavaWizardWidget::setupUi()
m_permGenSpinBox->setMinimum(4);
m_permGenSpinBox->setMaximum(1048576);
m_permGenSpinBox->setSingleStep(8);
m_gridLayout_2->addWidget(m_permGenSpinBox, 2, 1, 1, 1);
m_gridLayout2->addWidget(m_permGenSpinBox, 2, 1, 1, 1);
m_permGenSpinBox->setVisible(false);
m_verticalLayout->addWidget(m_memoryGroupBox);
@ -154,8 +154,9 @@ void JavaWizardWidget::setupUi()
m_veriticalJavaLayout->addWidget(m_autodownloadCheckBox);
connect(m_autodetectJavaCheckBox, &QCheckBox::checkStateChanged, this, [this] {
m_autodownloadCheckBox->setEnabled(m_autodetectJavaCheckBox->isChecked());
if (!m_autodetectJavaCheckBox->isChecked())
if (!m_autodetectJavaCheckBox->isChecked()) {
m_autodownloadCheckBox->setChecked(false);
}
});
connect(m_autodownloadCheckBox, &QCheckBox::checkStateChanged, this, [this] {
@ -188,14 +189,14 @@ void JavaWizardWidget::initialize()
m_versionWidget->initialize(APPLICATION->javalist());
m_versionWidget->selectSearch();
m_versionWidget->setResizeOn(2);
auto s = APPLICATION->settings();
auto* s = APPLICATION->settings();
// Memory
observedMinMemory = s->get("MinMemAlloc").toInt();
observedMaxMemory = s->get("MaxMemAlloc").toInt();
observedPermGenMemory = s->get("PermGen").toInt();
m_minMemSpinBox->setValue(observedMinMemory);
m_maxMemSpinBox->setValue(observedMaxMemory);
m_permGenSpinBox->setValue(observedPermGenMemory);
m_observedMinMemory = s->get("MinMemAlloc").toInt();
m_observedMaxMemory = s->get("MaxMemAlloc").toInt();
m_observedPermGenMemory = s->get("PermGen").toInt();
m_minMemSpinBox->setValue(m_observedMinMemory);
m_maxMemSpinBox->setValue(m_observedMaxMemory);
m_permGenSpinBox->setValue(m_observedPermGenMemory);
updateThresholds();
if (BuildConfig.JAVA_DOWNLOADER_ENABLED) {
m_autodownloadCheckBox->setChecked(true);
@ -283,8 +284,7 @@ int JavaWizardWidget::maxHeapSize() const
{
auto min = m_minMemSpinBox->value();
auto max = m_maxMemSpinBox->value();
if (max < min)
max = min;
max = (std::max)(max, min);
return max;
}
@ -292,8 +292,7 @@ int JavaWizardWidget::minHeapSize() const
{
auto min = m_minMemSpinBox->value();
auto max = m_maxMemSpinBox->value();
if (min > max)
min = max;
min = (std::min)(min, max);
return min;
}
@ -310,19 +309,19 @@ int JavaWizardWidget::permGenSize() const
void JavaWizardWidget::memoryValueChanged()
{
bool actuallyChanged = false;
unsigned int min = m_minMemSpinBox->value();
unsigned int max = m_maxMemSpinBox->value();
unsigned int permgen = m_permGenSpinBox->value();
if (min != observedMinMemory) {
observedMinMemory = min;
int min = m_minMemSpinBox->value();
int max = m_maxMemSpinBox->value();
int permgen = m_permGenSpinBox->value();
if (min != m_observedMinMemory) {
m_observedMinMemory = min;
actuallyChanged = true;
}
if (max != observedMaxMemory) {
observedMaxMemory = max;
if (max != m_observedMaxMemory) {
m_observedMaxMemory = max;
actuallyChanged = true;
}
if (permgen != observedPermGenMemory) {
observedPermGenMemory = permgen;
if (permgen != m_observedPermGenMemory) {
m_observedPermGenMemory = permgen;
actuallyChanged = true;
}
if (actuallyChanged) {
@ -331,7 +330,7 @@ void JavaWizardWidget::memoryValueChanged()
}
}
void JavaWizardWidget::javaVersionSelected(BaseVersion::Ptr version)
void JavaWizardWidget::javaVersionSelected(const BaseVersion::Ptr& version)
{
auto java = std::dynamic_pointer_cast<JavaInstall>(version);
if (!java) {
@ -344,25 +343,25 @@ void JavaWizardWidget::javaVersionSelected(BaseVersion::Ptr version)
checkJavaPath(java->path);
}
void JavaWizardWidget::on_javaBrowseBtn_clicked()
void JavaWizardWidget::onJavaBrowseBtnClicked()
{
auto filter = QString("Java (%1)").arg(JavaUtils::javaExecutable);
auto raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
if (raw_path.isEmpty()) {
auto rawPath = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter);
if (rawPath.isEmpty()) {
return;
}
auto cooked_path = FS::NormalizePath(raw_path);
m_javaPathTextBox->setText(cooked_path);
checkJavaPath(cooked_path);
auto cookedPath = FS::NormalizePath(rawPath);
m_javaPathTextBox->setText(cookedPath);
checkJavaPath(cookedPath);
}
void JavaWizardWidget::javaDownloadBtn_clicked()
void JavaWizardWidget::javaDownloadBtnClicked()
{
auto jdialog = new Java::InstallDialog({}, nullptr, this);
auto* jdialog = new Java::InstallDialog({}, nullptr, this);
jdialog->exec();
}
void JavaWizardWidget::on_javaStatusBtn_clicked()
void JavaWizardWidget::onJavaStatusBtnClicked()
{
QString text;
bool failed = false;
@ -414,14 +413,14 @@ void JavaWizardWidget::setJavaStatus(JavaWizardWidget::JavaStatus status)
javaStatus = status;
switch (javaStatus) {
case JavaStatus::Good:
m_javaStatusBtn->setIcon(goodIcon);
m_javaStatusBtn->setIcon(m_goodIcon);
break;
case JavaStatus::NotSet:
case JavaStatus::Pending:
m_javaStatusBtn->setIcon(yellowIcon);
m_javaStatusBtn->setIcon(m_yellowIcon);
break;
default:
m_javaStatusBtn->setIcon(badIcon);
m_javaStatusBtn->setIcon(m_badIcon);
break;
}
}
@ -447,7 +446,7 @@ void JavaWizardWidget::checkJavaPathOnEdit(const QString& path)
void JavaWizardWidget::checkJavaPath(const QString& path)
{
if (m_checker) {
queuedCheck = path;
m_queuedCheck = path;
return;
}
auto realPath = FS::ResolveExecutable(path);
@ -481,9 +480,9 @@ void JavaWizardWidget::checkFinished(const JavaChecker::Result& result)
}
updateThresholds();
m_checker.reset();
if (!queuedCheck.isNull()) {
checkJavaPath(queuedCheck);
queuedCheck.clear();
if (!m_queuedCheck.isNull()) {
checkJavaPath(m_queuedCheck);
m_queuedCheck.clear();
}
}
@ -507,19 +506,16 @@ void JavaWizardWidget::updateThresholds()
{
QString iconName;
if (observedMaxMemory >= m_availableMemory) {
if (static_cast<uint64_t>(m_observedMaxMemory) >= m_availableMemory) {
iconName = "status-bad";
m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation exceeds your system memory capacity."));
} else if (observedMaxMemory > (m_availableMemory * 0.9)) {
} else if (static_cast<double>(m_observedMaxMemory) > (static_cast<double>(m_availableMemory) * 0.9)) {
iconName = "status-yellow";
m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity."));
} else if (observedMaxMemory < observedMinMemory) {
} else if (m_observedMaxMemory < m_observedMinMemory) {
iconName = "status-yellow";
m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value"));
} else if (BuildConfig.JAVA_DOWNLOADER_ENABLED && m_autodownloadCheckBox->isChecked()) {
iconName = "status-good";
m_labelMaxMemIcon->setToolTip("");
} else if (observedMaxMemory > 2048 && !m_result.is_64bit) {
} else if (m_observedMaxMemory > 2048 && !m_result.is_64bit) {
iconName = "status-bad";
m_labelMaxMemIcon->setToolTip(tr("You are exceeding the maximum allocation supported by 32-bit installations of Java."));
} else {
@ -537,7 +533,7 @@ void JavaWizardWidget::updateThresholds()
bool JavaWizardWidget::autoDownloadJava() const
{
return m_autodownloadCheckBox && m_autodownloadCheckBox->isChecked();
return (m_autodownloadCheckBox != nullptr) && m_autodownloadCheckBox->isChecked();
}
bool JavaWizardWidget::autoDetectJava() const
@ -545,7 +541,7 @@ bool JavaWizardWidget::autoDetectJava() const
return m_autodetectJavaCheckBox->isChecked();
}
void JavaWizardWidget::onSpinBoxValueChanged(int)
void JavaWizardWidget::onSpinBoxValueChanged(int /*unused*/)
{
m_memoryTimer->start(500);
}

View file

@ -24,11 +24,18 @@ class JavaWizardWidget : public QWidget {
public:
explicit JavaWizardWidget(QWidget* parent);
virtual ~JavaWizardWidget();
~JavaWizardWidget() override;
enum class JavaStatus { NotSet, Pending, Good, DoesNotExist, DoesNotStart, ReturnedInvalidData } javaStatus = JavaStatus::NotSet;
enum class JavaStatus : std::uint8_t {
NotSet,
Pending,
Good,
DoesNotExist,
DoesNotStart,
ReturnedInvalidData
} javaStatus = JavaStatus::NotSet;
enum class ValidationStatus { Bad, JavaBad, AllOK };
enum class ValidationStatus : std::uint8_t { Bad, JavaBad, AllOK };
void refresh();
void initialize();
@ -49,10 +56,10 @@ class JavaWizardWidget : public QWidget {
void onSpinBoxValueChanged(int);
void memoryValueChanged();
void javaPathEdited(const QString& path);
void javaVersionSelected(BaseVersion::Ptr version);
void on_javaBrowseBtn_clicked();
void on_javaStatusBtn_clicked();
void javaDownloadBtn_clicked();
void javaVersionSelected(const BaseVersion::Ptr& version);
void onJavaBrowseBtnClicked();
void onJavaStatusBtnClicked();
void javaDownloadBtnClicked();
void checkFinished(const JavaChecker::Result& result);
protected: /* methods */
@ -72,7 +79,7 @@ class JavaWizardWidget : public QWidget {
QHBoxLayout* m_horizontalLayout = nullptr;
QGroupBox* m_memoryGroupBox = nullptr;
QGridLayout* m_gridLayout_2 = nullptr;
QGridLayout* m_gridLayout2 = nullptr;
QSpinBox* m_maxMemSpinBox = nullptr;
QLabel* m_labelMinMem = nullptr;
QLabel* m_labelMaxMem = nullptr;
@ -83,20 +90,20 @@ class JavaWizardWidget : public QWidget {
QHBoxLayout* m_horizontalBtnLayout = nullptr;
QPushButton* m_javaDownloadBtn = nullptr;
QIcon goodIcon;
QIcon yellowIcon;
QIcon badIcon;
QIcon m_goodIcon;
QIcon m_yellowIcon;
QIcon m_badIcon;
QGroupBox* m_autoJavaGroupBox = nullptr;
QVBoxLayout* m_veriticalJavaLayout = nullptr;
QCheckBox* m_autodetectJavaCheckBox = nullptr;
QCheckBox* m_autodownloadCheckBox = nullptr;
unsigned int observedMinMemory = 0;
unsigned int observedMaxMemory = 0;
unsigned int observedPermGenMemory = 0;
QString queuedCheck;
uint64_t m_availableMemory = 0ull;
int m_observedMinMemory = 0;
int m_observedMaxMemory = 0;
int m_observedPermGenMemory = 0;
QString m_queuedCheck;
uint64_t m_availableMemory = 0ULL;
shared_qobject_ptr<JavaChecker> m_checker;
JavaChecker::Result m_result;
QTimer* m_memoryTimer;

View file

@ -6,64 +6,67 @@
#include <QTreeView>
#include <QVBoxLayout>
#include "Application.h"
#include "settings/SettingsObject.h"
#include "BuildConfig.h"
#include "settings/Setting.h"
#include "settings/SettingsObject.h"
#include "translations/TranslationsModel.h"
LanguageSelectionWidget::LanguageSelectionWidget(QWidget* parent) : QWidget(parent)
LanguageSelectionWidget::LanguageSelectionWidget(QWidget* parent)
: QWidget(parent)
, m_verticalLayout(new QVBoxLayout(this))
, m_languageView(new QTreeView(this))
, m_helpUsLabel(new QLabel(this))
, m_formatCheckbox(new QCheckBox(this))
{
verticalLayout = new QVBoxLayout(this);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
languageView = new QTreeView(this);
languageView->setObjectName(QStringLiteral("languageView"));
languageView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
languageView->setAlternatingRowColors(true);
languageView->setRootIsDecorated(false);
languageView->setItemsExpandable(false);
languageView->setWordWrap(true);
languageView->header()->setCascadingSectionResizes(true);
languageView->header()->setStretchLastSection(false);
verticalLayout->addWidget(languageView);
helpUsLabel = new QLabel(this);
helpUsLabel->setObjectName(QStringLiteral("helpUsLabel"));
helpUsLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
helpUsLabel->setOpenExternalLinks(true);
helpUsLabel->setWordWrap(true);
verticalLayout->addWidget(helpUsLabel);
m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
formatCheckbox = new QCheckBox(this);
formatCheckbox->setObjectName(QStringLiteral("formatCheckbox"));
formatCheckbox->setCheckState(APPLICATION->settings()->get("UseSystemLocale").toBool() ? Qt::Checked : Qt::Unchecked);
connect(formatCheckbox, &QCheckBox::checkStateChanged,
[this] { APPLICATION->translations()->setUseSystemLocale(formatCheckbox->isChecked()); });
verticalLayout->addWidget(formatCheckbox);
m_languageView->setObjectName(QStringLiteral("languageView"));
m_languageView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_languageView->setAlternatingRowColors(true);
m_languageView->setRootIsDecorated(false);
m_languageView->setItemsExpandable(false);
m_languageView->setWordWrap(true);
m_languageView->header()->setCascadingSectionResizes(true);
m_languageView->header()->setStretchLastSection(false);
m_verticalLayout->addWidget(m_languageView);
auto translations = APPLICATION->translations();
m_helpUsLabel->setObjectName(QStringLiteral("helpUsLabel"));
m_helpUsLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
m_helpUsLabel->setOpenExternalLinks(true);
m_helpUsLabel->setWordWrap(true);
m_verticalLayout->addWidget(m_helpUsLabel);
m_formatCheckbox->setObjectName(QStringLiteral("formatCheckbox"));
m_formatCheckbox->setCheckState(APPLICATION->settings()->get("UseSystemLocale").toBool() ? Qt::Checked : Qt::Unchecked);
connect(m_formatCheckbox, &QCheckBox::checkStateChanged,
[this] { APPLICATION->translations()->setUseSystemLocale(m_formatCheckbox->isChecked()); });
m_verticalLayout->addWidget(m_formatCheckbox);
auto* translations = APPLICATION->translations();
auto index = translations->selectedIndex();
languageView->setModel(translations);
languageView->setCurrentIndex(index);
languageView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
languageView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(languageView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &LanguageSelectionWidget::languageRowChanged);
verticalLayout->setContentsMargins(0, 0, 0, 0);
m_languageView->setModel(translations);
m_languageView->setCurrentIndex(index);
m_languageView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_languageView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(m_languageView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &LanguageSelectionWidget::languageRowChanged);
m_verticalLayout->setContentsMargins(0, 0, 0, 0);
auto language_setting = APPLICATION->settings()->getSetting("Language");
connect(language_setting.get(), &Setting::SettingChanged, this, &LanguageSelectionWidget::languageSettingChanged);
auto languageSetting = APPLICATION->settings()->getSetting("Language");
connect(languageSetting.get(), &Setting::SettingChanged, this, &LanguageSelectionWidget::languageSettingChanged);
}
QString LanguageSelectionWidget::getSelectedLanguageKey() const
{
auto translations = APPLICATION->translations();
return translations->data(languageView->currentIndex(), Qt::UserRole).toString();
auto* translations = APPLICATION->translations();
return translations->data(m_languageView->currentIndex(), Qt::UserRole).toString();
}
void LanguageSelectionWidget::retranslate()
{
QString text = tr("Don't see your language or the quality is poor?<br/><a href=\"%1\">Help us with translations!</a>")
.arg(BuildConfig.TRANSLATIONS_URL);
helpUsLabel->setText(text);
formatCheckbox->setText(tr("Use system regional standards"));
m_helpUsLabel->setText(text);
m_formatCheckbox->setText(tr("Use system regional standards"));
}
void LanguageSelectionWidget::languageRowChanged(const QModelIndex& current, const QModelIndex& previous)
@ -71,15 +74,15 @@ void LanguageSelectionWidget::languageRowChanged(const QModelIndex& current, con
if (current == previous) {
return;
}
auto translations = APPLICATION->translations();
auto* translations = APPLICATION->translations();
QString key = translations->data(current, Qt::UserRole).toString();
translations->selectLanguage(key);
translations->updateLanguage(key);
}
void LanguageSelectionWidget::languageSettingChanged(const Setting&, const QVariant&)
void LanguageSelectionWidget::languageSettingChanged(const Setting& /*unused*/, const QVariant& /*unused*/)
{
auto translations = APPLICATION->translations();
auto* translations = APPLICATION->translations();
auto index = translations->selectedIndex();
languageView->setCurrentIndex(index);
m_languageView->setCurrentIndex(index);
}

View file

@ -26,19 +26,19 @@ class QCheckBox;
class LanguageSelectionWidget : public QWidget {
Q_OBJECT
public:
explicit LanguageSelectionWidget(QWidget* parent = 0);
virtual ~LanguageSelectionWidget() {};
explicit LanguageSelectionWidget(QWidget* parent = nullptr);
~LanguageSelectionWidget() override = default;
QString getSelectedLanguageKey() const;
void retranslate();
protected slots:
void languageRowChanged(const QModelIndex& current, const QModelIndex& previous);
static void languageRowChanged(const QModelIndex& current, const QModelIndex& previous);
void languageSettingChanged(const Setting&, const QVariant&);
private:
QVBoxLayout* verticalLayout = nullptr;
QTreeView* languageView = nullptr;
QLabel* helpUsLabel = nullptr;
QCheckBox* formatCheckbox = nullptr;
QVBoxLayout* m_verticalLayout = nullptr;
QTreeView* m_languageView = nullptr;
QLabel* m_helpUsLabel = nullptr;
QCheckBox* m_formatCheckbox = nullptr;
};

View file

@ -41,7 +41,6 @@
#include <QFileDialog>
#include "Application.h"
#include "BuildConfig.h"
#include "Json.h"
#include "minecraft/PackProfile.h"
#include "minecraft/WorldList.h"
@ -49,7 +48,7 @@
#include "settings/Setting.h"
MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstance* instance, QWidget* parent)
: QWidget(parent), m_instance(std::move(instance)), m_ui(new Ui::MinecraftSettingsWidget)
: QWidget(parent), m_instance(instance), m_ui(new Ui::MinecraftSettingsWidget)
{
m_ui->setupUi(this);
@ -83,7 +82,7 @@ MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstance* instance, QW
m_quickPlaySingleplayer = m_instance->traits().contains("feature:is_quick_play_singleplayer");
if (m_quickPlaySingleplayer) {
auto worlds = m_instance->worldList();
auto* worlds = m_instance->worldList();
worlds->update();
for (const auto& world : worlds->allWorlds()) {
m_ui->worldsCb->addItem(world.folderName());
@ -102,22 +101,24 @@ MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstance* instance, QW
connect(m_ui->globalDataPacksGroupBox, &QGroupBox::toggled, this, [this](bool value) {
m_instance->settings()->set("GlobalDataPacksEnabled", value);
if (!value)
if (!value) {
m_instance->settings()->reset("GlobalDataPacksPath");
}
});
connect(m_ui->dataPacksPathEdit, &QLineEdit::editingFinished, this, &MinecraftSettingsWidget::saveDataPacksPath);
connect(m_ui->dataPacksPathBrowse, &QPushButton::clicked, this, &MinecraftSettingsWidget::selectDataPacksFolder);
connect(m_ui->loaderGroup, &QGroupBox::toggled, this, [this](bool value) {
m_instance->settings()->set("OverrideModDownloadLoaders", value);
if (value)
if (value) {
saveSelectedLoaders();
else
} else {
m_instance->settings()->reset("ModDownloadLoaders");
}
});
for (auto c : { m_ui->neoForge, m_ui->forge, m_ui->fabric, m_ui->quilt, m_ui->liteLoader, m_ui->babric, m_ui->btaBabric,
m_ui->legacyFabric, m_ui->ornithe, m_ui->rift }) {
for (auto* c : { m_ui->neoForge, m_ui->forge, m_ui->fabric, m_ui->quilt, m_ui->liteLoader, m_ui->babric, m_ui->btaBabric,
m_ui->legacyFabric, m_ui->ornithe, m_ui->rift }) {
connect(c, &QCheckBox::checkStateChanged, this, &MinecraftSettingsWidget::saveSelectedLoaders);
}
}
@ -154,12 +155,13 @@ MinecraftSettingsWidget::~MinecraftSettingsWidget()
void MinecraftSettingsWidget::loadSettings()
{
SettingsObject* settings;
SettingsObject* settings = nullptr;
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings = m_instance->settings();
else
} else {
settings = APPLICATION->settings();
}
// Game Window
m_ui->windowSizeGroupBox->setChecked(m_instance == nullptr || settings->get("OverrideWindow").toBool() ||
@ -183,8 +185,9 @@ void MinecraftSettingsWidget::loadSettings()
m_ui->autoCloseConsoleCheck->setChecked(settings->get("AutoCloseConsole").toBool());
m_ui->showConsoleErrorCheck->setChecked(settings->get("ShowConsoleOnError").toBool());
if (m_javaSettings != nullptr)
if (m_javaSettings != nullptr) {
m_javaSettings->loadSettings();
}
// Custom commands
m_ui->customCommands->initialize(m_instance != nullptr, m_instance == nullptr || settings->get("OverrideCommands").toBool(),
@ -254,7 +257,7 @@ void MinecraftSettingsWidget::loadSettings()
auto blockSignalsCheckBoxes = { m_ui->neoForge, m_ui->forge, m_ui->fabric, m_ui->quilt, m_ui->liteLoader,
m_ui->babric, m_ui->btaBabric, m_ui->legacyFabric, m_ui->ornithe, m_ui->rift };
m_ui->loaderGroup->blockSignals(true);
for (auto c : blockSignalsCheckBoxes) {
for (auto* c : blockSignalsCheckBoxes) {
c->blockSignals(true);
}
@ -277,20 +280,20 @@ void MinecraftSettingsWidget::loadSettings()
} else {
auto instLoaders = m_instance->getPackProfile()->getSupportedModLoaders().value_or(ModPlatform::ModLoaderTypes(0));
m_ui->neoForge->setChecked(instLoaders & ModPlatform::NeoForge);
m_ui->forge->setChecked(instLoaders & ModPlatform::Forge);
m_ui->fabric->setChecked(instLoaders & ModPlatform::Fabric);
m_ui->quilt->setChecked(instLoaders & ModPlatform::Quilt);
m_ui->liteLoader->setChecked(instLoaders & ModPlatform::LiteLoader);
m_ui->babric->setChecked(instLoaders & ModPlatform::Babric);
m_ui->btaBabric->setChecked(instLoaders & ModPlatform::BTA);
m_ui->legacyFabric->setChecked(instLoaders & ModPlatform::LegacyFabric);
m_ui->ornithe->setChecked(instLoaders & ModPlatform::Ornithe);
m_ui->rift->setChecked(instLoaders & ModPlatform::Rift);
m_ui->neoForge->setChecked((instLoaders & ModPlatform::NeoForge) != 0U);
m_ui->forge->setChecked((instLoaders & ModPlatform::Forge) != 0U);
m_ui->fabric->setChecked((instLoaders & ModPlatform::Fabric) != 0U);
m_ui->quilt->setChecked((instLoaders & ModPlatform::Quilt) != 0U);
m_ui->liteLoader->setChecked((instLoaders & ModPlatform::LiteLoader) != 0U);
m_ui->babric->setChecked((instLoaders & ModPlatform::Babric) != 0U);
m_ui->btaBabric->setChecked((instLoaders & ModPlatform::BTA) != 0U);
m_ui->legacyFabric->setChecked((instLoaders & ModPlatform::LegacyFabric) != 0U);
m_ui->ornithe->setChecked((instLoaders & ModPlatform::Ornithe) != 0U);
m_ui->rift->setChecked((instLoaders & ModPlatform::Rift) != 0U);
}
m_ui->loaderGroup->blockSignals(false);
for (auto c : blockSignalsCheckBoxes) {
for (auto* c : blockSignalsCheckBoxes) {
c->blockSignals(false);
}
}
@ -308,12 +311,13 @@ void MinecraftSettingsWidget::loadSettings()
void MinecraftSettingsWidget::saveSettings()
{
SettingsObject* settings;
SettingsObject* settings = nullptr;
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings = m_instance->settings();
else
} else {
settings = APPLICATION->settings();
}
{
SettingsObject::Lock lock(settings);
@ -321,8 +325,9 @@ void MinecraftSettingsWidget::saveSettings()
// Console
bool console = m_instance == nullptr || m_ui->consoleSettingsBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideConsole", console);
}
if (console) {
settings->set("ShowConsole", m_ui->showConsoleCheck->isChecked());
@ -359,8 +364,9 @@ void MinecraftSettingsWidget::saveSettings()
// Custom Commands
bool custcmd = m_instance == nullptr || m_ui->customCommands->checked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideCommands", custcmd);
}
if (custcmd) {
settings->set("PreLaunchCommand", m_ui->customCommands->prelaunchCommand());
@ -375,19 +381,22 @@ void MinecraftSettingsWidget::saveSettings()
// Environment Variables
auto env = m_instance == nullptr || m_ui->environmentVariables->override();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideEnv", env);
}
if (env)
if (env) {
settings->set("Env", Json::fromMap(m_ui->environmentVariables->value()));
else
} else {
settings->reset("Env");
}
// Workarounds
bool workarounds = m_instance == nullptr || m_ui->nativeWorkaroundsGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideNativeWorkarounds", workarounds);
}
if (workarounds) {
settings->set("UseNativeGLFW", m_ui->useNativeGLFWCheck->isChecked());
@ -404,8 +413,9 @@ void MinecraftSettingsWidget::saveSettings()
// Performance
bool performance = m_instance == nullptr || m_ui->perfomanceGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverridePerformance", performance);
}
if (performance) {
settings->set("EnableFeralGamemode", m_ui->enableFeralGamemodeCheck->isChecked());
@ -422,8 +432,9 @@ void MinecraftSettingsWidget::saveSettings()
// Game time
bool gameTime = m_instance == nullptr || m_ui->gameTimeGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideGameTime", gameTime);
}
if (gameTime) {
settings->set("ShowGameTime", m_ui->showGameTime->isChecked());
@ -463,8 +474,9 @@ void MinecraftSettingsWidget::saveSettings()
if (accountIndex != -1) {
const MinecraftAccountPtr account = APPLICATION->accounts()->at(accountIndex);
if (account != nullptr)
if (account != nullptr) {
settings->set("InstanceAccountId", account->profileId());
}
}
} else {
settings->reset("InstanceAccountId");
@ -473,8 +485,9 @@ void MinecraftSettingsWidget::saveSettings()
bool overrideLegacySettings = m_instance == nullptr || m_ui->legacySettingsGroupBox->isChecked();
if (m_instance != nullptr)
if (m_instance != nullptr) {
settings->set("OverrideLegacySettings", overrideLegacySettings);
}
if (overrideLegacySettings) {
settings->set("OnlineFixes", m_ui->onlineFixes->isChecked());
@ -483,8 +496,9 @@ void MinecraftSettingsWidget::saveSettings()
}
}
if (m_javaSettings != nullptr)
if (m_javaSettings != nullptr) {
m_javaSettings->saveSettings();
}
}
void MinecraftSettingsWidget::openGlobalSettings()
@ -493,16 +507,17 @@ void MinecraftSettingsWidget::openGlobalSettings()
qDebug() << id;
if (id == "javaPage")
if (id == "javaPage") {
APPLICATION->ShowGlobalSettings(this, "java-settings");
else // TODO select tab
} else { // TODO select tab
APPLICATION->ShowGlobalSettings(this, "minecraft-settings");
}
}
void MinecraftSettingsWidget::updateAccountsMenu(SettingsObject& settings)
{
m_ui->instanceAccountSelector->clear();
auto accounts = APPLICATION->accounts();
auto* accounts = APPLICATION->accounts();
int accountIndex = accounts->findAccountByProfileId(settings.get("InstanceAccountId").toString());
for (int i = 0; i < accounts->count(); i++) {
@ -510,12 +525,14 @@ void MinecraftSettingsWidget::updateAccountsMenu(SettingsObject& settings)
QIcon face = account->getFace();
if (face.isNull())
if (face.isNull()) {
face = QIcon::fromTheme("noaccount");
}
m_ui->instanceAccountSelector->addItem(face, account->profileName(), i);
if (i == accountIndex)
if (i == accountIndex) {
m_ui->instanceAccountSelector->setCurrentIndex(i);
}
}
}
@ -528,34 +545,45 @@ void MinecraftSettingsWidget::saveSelectedLoaders()
{
QStringList loaders;
if (m_ui->neoForge->isChecked())
if (m_ui->neoForge->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::NeoForge);
if (m_ui->forge->isChecked())
}
if (m_ui->forge->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Forge);
if (m_ui->fabric->isChecked())
}
if (m_ui->fabric->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Fabric);
if (m_ui->quilt->isChecked())
}
if (m_ui->quilt->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Quilt);
if (m_ui->liteLoader->isChecked())
}
if (m_ui->liteLoader->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::LiteLoader);
if (m_ui->babric->isChecked())
}
if (m_ui->babric->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Babric);
if (m_ui->btaBabric->isChecked())
}
if (m_ui->btaBabric->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::BTA);
if (m_ui->legacyFabric->isChecked())
}
if (m_ui->legacyFabric->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::LegacyFabric);
if (m_ui->ornithe->isChecked())
}
if (m_ui->ornithe->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Ornithe);
if (m_ui->rift->isChecked())
}
if (m_ui->rift->isChecked()) {
loaders << getModLoaderAsString(ModPlatform::Rift);
}
m_instance->settings()->set("ModDownloadLoaders", Json::fromStringList(loaders));
}
void MinecraftSettingsWidget::saveDataPacksPath()
{
if (QDir::separator() != '/')
if (QDir::separator() != '/') {
m_ui->dataPacksPathEdit->setText(m_ui->dataPacksPathEdit->text().replace(QDir::separator(), '/'));
}
m_instance->settings()->set("GlobalDataPacksPath", m_ui->dataPacksPathEdit->text());
}
@ -564,8 +592,9 @@ void MinecraftSettingsWidget::selectDataPacksFolder()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Select Global Data Packs Folder"), m_instance->gameRoot());
if (path.isEmpty())
if (path.isEmpty()) {
return;
}
// if it's inside the instance dir, set path relative to .minecraft
// (so that if it's directly in instance dir it will still lead with .. but more than two levels up are kept absolute)
@ -573,8 +602,9 @@ void MinecraftSettingsWidget::selectDataPacksFolder()
const QUrl instanceRootUrl = QUrl::fromLocalFile(m_instance->instanceRoot());
const QUrl pathUrl = QUrl::fromLocalFile(path);
if (instanceRootUrl.isParentOf(pathUrl))
if (instanceRootUrl.isParentOf(pathUrl)) {
path = QDir(m_instance->gameRoot()).relativeFilePath(path);
}
m_ui->dataPacksPathEdit->setText(path);
m_instance->settings()->set("GlobalDataPacksPath", path);

View file

@ -46,7 +46,7 @@ class MinecraftSettingsWidget;
class MinecraftSettingsWidget : public QWidget {
public:
MinecraftSettingsWidget(MinecraftInstance* instance, QWidget* parent = nullptr);
explicit MinecraftSettingsWidget(MinecraftInstance* instance, QWidget* parent = nullptr);
~MinecraftSettingsWidget() override;
void loadSettings();

View file

@ -38,7 +38,6 @@
#include <QComboBox>
#include <QListWidget>
#include <algorithm>
#include <list>
#include "BaseVersionList.h"
#include "Json.h"
#include "Version.h"
@ -55,18 +54,21 @@ std::unique_ptr<ModFilterWidget> ModFilterWidget::create(MinecraftInstance* inst
return std::unique_ptr<ModFilterWidget>(new ModFilterWidget(instance, extended));
}
namespace {
class VersionBasicModel : public QIdentityProxyModel {
Q_OBJECT
public:
explicit VersionBasicModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) {}
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
{
if (role == Qt::DisplayRole)
if (role == Qt::DisplayRole) {
return QIdentityProxyModel::data(index, BaseVersionList::VersionIdRole);
if (role == Qt::UserRole)
}
if (role == Qt::UserRole) {
return QIdentityProxyModel::data(index, BaseVersionList::VersionIdRole);
}
return {};
}
};
@ -75,7 +77,7 @@ class AllVersionProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
AllVersionProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {}
explicit AllVersionProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {}
int rowCount(const QModelIndex& parent = QModelIndex()) const override { return QSortFilterProxyModel::rowCount(parent) + 1; }
@ -107,74 +109,74 @@ class AllVersionProxyModel : public QSortFilterProxyModel {
return QSortFilterProxyModel::flags(index);
}
};
} // namespace
ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended)
: QTabWidget(), ui(new Ui::ModFilterWidget), m_instance(instance), m_filter(new Filter())
: m_ui(new Ui::ModFilterWidget), m_instance(instance), m_filter(new Filter()), m_versionsProxy(new VersionProxyModel(this))
{
ui->setupUi(this);
m_ui->setupUi(this);
m_versions_proxy = new VersionProxyModel(this);
m_versions_proxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release"));
m_versionsProxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release"));
QAbstractProxyModel* proxy = new VersionBasicModel(this);
proxy->setSourceModel(m_versions_proxy);
proxy->setSourceModel(m_versionsProxy);
if (extended) {
if (!m_instance) {
ui->environmentGroup->hide();
m_ui->environmentGroup->hide();
}
ui->versions->setSourceModel(proxy);
ui->versions->setSeparator(", ");
ui->versions->setDefaultText(tr("All Versions"));
ui->version->hide();
m_ui->versions->setSourceModel(proxy);
m_ui->versions->setSeparator(", ");
m_ui->versions->setDefaultText(tr("All Versions"));
m_ui->version->hide();
} else {
auto allVersions = new AllVersionProxyModel(this);
auto* allVersions = new AllVersionProxyModel(this);
allVersions->setSourceModel(proxy);
proxy = allVersions;
ui->version->setModel(proxy);
ui->versions->hide();
ui->showAllVersions->hide();
ui->environmentGroup->hide();
ui->openSource->hide();
m_ui->version->setModel(proxy);
m_ui->versions->hide();
m_ui->showAllVersions->hide();
m_ui->environmentGroup->hide();
m_ui->openSource->hide();
}
ui->versions->setStyleSheet("combobox-popup: 0;");
ui->version->setStyleSheet("combobox-popup: 0;");
connect(ui->showAllVersions, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onShowAllVersionsChanged);
connect(ui->versions, &QComboBox::currentIndexChanged, this, &ModFilterWidget::onVersionFilterChanged);
connect(ui->versions, &CheckComboBox::checkedItemsChanged, this, [this] { onVersionFilterChanged(0); });
connect(ui->version, &QComboBox::currentTextChanged, this, &ModFilterWidget::onVersionFilterTextChanged);
m_ui->versions->setStyleSheet("combobox-popup: 0;");
m_ui->version->setStyleSheet("combobox-popup: 0;");
connect(m_ui->showAllVersions, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onShowAllVersionsChanged);
connect(m_ui->versions, &QComboBox::currentIndexChanged, this, &ModFilterWidget::onVersionFilterChanged);
connect(m_ui->versions, &CheckComboBox::checkedItemsChanged, this, [this] { onVersionFilterChanged(0); });
connect(m_ui->version, &QComboBox::currentTextChanged, this, &ModFilterWidget::onVersionFilterTextChanged);
connect(ui->neoForge, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->forge, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->fabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->quilt, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->liteLoader, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->babric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->btaBabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->legacyFabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->ornithe, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->rift, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->neoForge, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->forge, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->fabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->quilt, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->liteLoader, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->babric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->btaBabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->legacyFabric, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->ornithe, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(m_ui->rift, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->showMoreButton, &QPushButton::clicked, this, &ModFilterWidget::onShowMoreClicked);
connect(m_ui->showMoreButton, &QPushButton::clicked, this, &ModFilterWidget::onShowMoreClicked);
if (!extended) {
ui->showMoreButton->setVisible(false);
ui->extendedModLoadersWidget->setVisible(false);
m_ui->showMoreButton->setVisible(false);
m_ui->extendedModLoadersWidget->setVisible(false);
}
if (extended) {
connect(ui->clientSide, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onSideFilterChanged);
connect(ui->serverSide, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onSideFilterChanged);
connect(m_ui->clientSide, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onSideFilterChanged);
connect(m_ui->serverSide, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onSideFilterChanged);
}
connect(ui->hideInstalled, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onHideInstalledFilterChanged);
connect(ui->openSource, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onOpenSourceFilterChanged);
connect(m_ui->hideInstalled, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onHideInstalledFilterChanged);
connect(m_ui->openSource, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onOpenSourceFilterChanged);
connect(ui->releaseCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->betaCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->alphaCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->unknownCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(m_ui->releaseCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(m_ui->betaCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(m_ui->alphaCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(m_ui->unknownCb, &QCheckBox::checkStateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
setHidden(true);
loadVersionList();
@ -183,43 +185,45 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extended)
auto ModFilterWidget::getFilter() -> std::shared_ptr<Filter>
{
m_filter_changed = false;
m_filterChanged = false;
return m_filter;
}
ModFilterWidget::~ModFilterWidget()
{
delete ui;
delete m_ui;
}
void ModFilterWidget::loadVersionList()
{
m_version_list = APPLICATION->metadataIndex()->get("net.minecraft");
if (!m_version_list->isLoaded()) {
QEventLoop load_version_list_loop;
m_versionList = APPLICATION->metadataIndex()->get("net.minecraft");
if (!m_versionList->isLoaded()) {
QEventLoop loadVersionListLoop;
QTimer time_limit_for_list_load;
time_limit_for_list_load.setTimerType(Qt::TimerType::CoarseTimer);
time_limit_for_list_load.setSingleShot(true);
time_limit_for_list_load.callOnTimeout(&load_version_list_loop, &QEventLoop::quit);
time_limit_for_list_load.start(4000);
QTimer timeLimitForListLoad;
timeLimitForListLoad.setTimerType(Qt::TimerType::CoarseTimer);
timeLimitForListLoad.setSingleShot(true);
timeLimitForListLoad.callOnTimeout(&loadVersionListLoop, &QEventLoop::quit);
timeLimitForListLoad.start(4000);
auto task = m_version_list->getLoadTask();
auto task = m_versionList->getLoadTask();
connect(task.get(), &Task::failed, [this] {
ui->versions->setEnabled(false);
ui->showAllVersions->setEnabled(false);
m_ui->versions->setEnabled(false);
m_ui->showAllVersions->setEnabled(false);
});
connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit);
connect(task.get(), &Task::finished, &loadVersionListLoop, &QEventLoop::quit);
if (!task->isRunning())
if (!task->isRunning()) {
task->start();
}
load_version_list_loop.exec();
if (time_limit_for_list_load.isActive())
time_limit_for_list_load.stop();
loadVersionListLoop.exec();
if (timeLimitForListLoad.isActive()) {
timeLimitForListLoad.stop();
}
}
m_versions_proxy->setSourceModel(m_version_list.get());
m_versionsProxy->setSourceModel(m_versionList.get());
}
void ModFilterWidget::prepareBasicFilter()
@ -230,121 +234,137 @@ void ModFilterWidget::prepareBasicFilter()
m_filter->side = ModPlatform::Side::NoSide; // or "both"
ModPlatform::ModLoaderTypes loaders;
if (m_instance->settings()->get("OverrideModDownloadLoaders").toBool()) {
for (auto loader : Json::toStringList(m_instance->settings()->get("ModDownloadLoaders").toString())) {
for (const auto& loader : Json::toStringList(m_instance->settings()->get("ModDownloadLoaders").toString())) {
loaders |= ModPlatform::getModLoaderFromString(loader);
}
} else {
loaders = m_instance->getPackProfile()->getSupportedModLoaders().value();
}
ui->neoForge->setChecked(loaders & ModPlatform::NeoForge);
ui->forge->setChecked(loaders & ModPlatform::Forge);
ui->fabric->setChecked(loaders & ModPlatform::Fabric);
ui->quilt->setChecked(loaders & ModPlatform::Quilt);
ui->liteLoader->setChecked(loaders & ModPlatform::LiteLoader);
ui->babric->setChecked(loaders & ModPlatform::Babric);
ui->btaBabric->setChecked(loaders & ModPlatform::BTA);
ui->legacyFabric->setChecked(loaders & ModPlatform::LegacyFabric);
ui->ornithe->setChecked(loaders & ModPlatform::Ornithe);
ui->rift->setChecked(loaders & ModPlatform::Rift);
m_ui->neoForge->setChecked((loaders & ModPlatform::NeoForge) != 0U);
m_ui->forge->setChecked((loaders & ModPlatform::Forge) != 0U);
m_ui->fabric->setChecked((loaders & ModPlatform::Fabric) != 0U);
m_ui->quilt->setChecked((loaders & ModPlatform::Quilt) != 0U);
m_ui->liteLoader->setChecked((loaders & ModPlatform::LiteLoader) != 0U);
m_ui->babric->setChecked((loaders & ModPlatform::Babric) != 0U);
m_ui->btaBabric->setChecked((loaders & ModPlatform::BTA) != 0U);
m_ui->legacyFabric->setChecked((loaders & ModPlatform::LegacyFabric) != 0U);
m_ui->ornithe->setChecked((loaders & ModPlatform::Ornithe) != 0U);
m_ui->rift->setChecked((loaders & ModPlatform::Rift) != 0U);
m_filter->loaders = loaders;
auto def = m_instance->getPackProfile()->getComponentVersion("net.minecraft");
m_filter->versions.emplace_back(def);
ui->versions->setCheckedItems({ def });
ui->version->setCurrentIndex(ui->version->findText(def));
m_ui->versions->setCheckedItems({ def });
m_ui->version->setCurrentIndex(m_ui->version->findText(def));
} else {
ui->hideInstalled->hide();
m_ui->hideInstalled->hide();
}
}
void ModFilterWidget::onShowAllVersionsChanged()
{
if (ui->showAllVersions->isChecked())
m_versions_proxy->clearFilters();
else
m_versions_proxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release"));
if (m_ui->showAllVersions->isChecked()) {
m_versionsProxy->clearFilters();
} else {
m_versionsProxy->setFilter(BaseVersionList::TypeRole, Filters::equals("release"));
}
}
void ModFilterWidget::onVersionFilterChanged(int)
void ModFilterWidget::onVersionFilterChanged(int /*unused*/)
{
auto versions = ui->versions->checkedItems();
auto versions = m_ui->versions->checkedItems();
versions.sort();
std::vector<Version> current_list;
std::vector<Version> currentList;
for (const QString& version : versions)
current_list.emplace_back(version);
for (const QString& version : versions) {
currentList.emplace_back(version);
}
m_filter_changed = m_filter->versions.size() != current_list.size() ||
!std::equal(m_filter->versions.begin(), m_filter->versions.end(), current_list.begin(), current_list.end());
m_filter->versions = current_list;
if (m_filter_changed)
m_filterChanged = m_filter->versions.size() != currentList.size() ||
!std::equal(m_filter->versions.begin(), m_filter->versions.end(), currentList.begin(), currentList.end());
m_filter->versions = currentList;
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onLoadersFilterChanged()
{
ModPlatform::ModLoaderTypes loaders;
if (ui->neoForge->isChecked())
if (m_ui->neoForge->isChecked()) {
loaders |= ModPlatform::NeoForge;
if (ui->forge->isChecked())
}
if (m_ui->forge->isChecked()) {
loaders |= ModPlatform::Forge;
if (ui->fabric->isChecked())
}
if (m_ui->fabric->isChecked()) {
loaders |= ModPlatform::Fabric;
if (ui->quilt->isChecked())
}
if (m_ui->quilt->isChecked()) {
loaders |= ModPlatform::Quilt;
if (ui->liteLoader->isChecked())
}
if (m_ui->liteLoader->isChecked()) {
loaders |= ModPlatform::LiteLoader;
if (ui->babric->isChecked())
}
if (m_ui->babric->isChecked()) {
loaders |= ModPlatform::Babric;
if (ui->btaBabric->isChecked())
}
if (m_ui->btaBabric->isChecked()) {
loaders |= ModPlatform::BTA;
if (ui->legacyFabric->isChecked())
}
if (m_ui->legacyFabric->isChecked()) {
loaders |= ModPlatform::LegacyFabric;
if (ui->ornithe->isChecked())
}
if (m_ui->ornithe->isChecked()) {
loaders |= ModPlatform::Ornithe;
if (ui->rift->isChecked())
}
if (m_ui->rift->isChecked()) {
loaders |= ModPlatform::Rift;
m_filter_changed = loaders != m_filter->loaders;
}
m_filterChanged = loaders != m_filter->loaders;
m_filter->loaders = loaders;
if (m_filter_changed)
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onSideFilterChanged()
{
ModPlatform::Side side;
ModPlatform::Side side = ModPlatform::Side::NoSide;
if (ui->clientSide->isChecked() && !ui->serverSide->isChecked()) {
if (m_ui->clientSide->isChecked() && !m_ui->serverSide->isChecked()) {
side = ModPlatform::Side::ClientSide;
} else if (!ui->clientSide->isChecked() && ui->serverSide->isChecked()) {
} else if (!m_ui->clientSide->isChecked() && m_ui->serverSide->isChecked()) {
side = ModPlatform::Side::ServerSide;
} else if (ui->clientSide->isChecked() && ui->serverSide->isChecked()) {
} else if (m_ui->clientSide->isChecked() && m_ui->serverSide->isChecked()) {
side = ModPlatform::Side::UniversalSide;
} else {
side = ModPlatform::Side::NoSide;
}
m_filter_changed = side != m_filter->side;
m_filterChanged = side != m_filter->side;
m_filter->side = side;
if (m_filter_changed)
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onHideInstalledFilterChanged()
{
auto hide = ui->hideInstalled->isChecked();
m_filter_changed = hide != m_filter->hideInstalled;
auto hide = m_ui->hideInstalled->isChecked();
m_filterChanged = hide != m_filter->hideInstalled;
m_filter->hideInstalled = hide;
if (m_filter_changed)
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onVersionFilterTextChanged(const QString& version)
{
m_filter->versions.clear();
if (ui->version->currentData(Qt::UserRole) != "all") {
if (m_ui->version->currentData(Qt::UserRole) != "all") {
m_filter->versions.emplace_back(version);
}
m_filter_changed = true;
m_filterChanged = true;
emit filterChanged();
}
@ -352,14 +372,14 @@ void ModFilterWidget::setCategories(const QList<ModPlatform::Category>& categori
{
m_categories = categories;
delete ui->categoryGroup->layout();
auto layout = new QVBoxLayout(ui->categoryGroup);
delete m_ui->categoryGroup->layout();
auto* layout = new QVBoxLayout(m_ui->categoryGroup);
for (const auto& category : categories) {
auto name = category.name;
name.replace("-", " ");
name.replace("&", "&&");
auto checkbox = new QCheckBox(name);
auto* checkbox = new QCheckBox(name);
auto font = checkbox->font();
font.setCapitalization(QFont::Capitalize);
checkbox->setFont(font);
@ -368,12 +388,13 @@ void ModFilterWidget::setCategories(const QList<ModPlatform::Category>& categori
const QString id = category.id;
connect(checkbox, &QCheckBox::toggled, this, [this, id](bool checked) {
if (checked)
if (checked) {
m_filter->categoryIds.append(id);
else
} else {
m_filter->categoryIds.removeOne(id);
}
m_filter_changed = true;
m_filterChanged = true;
emit filterChanged();
});
}
@ -381,34 +402,40 @@ void ModFilterWidget::setCategories(const QList<ModPlatform::Category>& categori
void ModFilterWidget::onOpenSourceFilterChanged()
{
auto open = ui->openSource->isChecked();
m_filter_changed = open != m_filter->openSource;
auto open = m_ui->openSource->isChecked();
m_filterChanged = open != m_filter->openSource;
m_filter->openSource = open;
if (m_filter_changed)
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onReleaseFilterChanged()
{
std::vector<ModPlatform::IndexedVersionType> releases;
if (ui->releaseCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType::Release);
if (ui->betaCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType::Beta);
if (ui->alphaCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType::Alpha);
if (ui->unknownCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType::Unknown);
m_filter_changed = releases != m_filter->releases;
if (m_ui->releaseCb->isChecked()) {
releases.emplace_back(ModPlatform::IndexedVersionType::Release);
}
if (m_ui->betaCb->isChecked()) {
releases.emplace_back(ModPlatform::IndexedVersionType::Beta);
}
if (m_ui->alphaCb->isChecked()) {
releases.emplace_back(ModPlatform::IndexedVersionType::Alpha);
}
if (m_ui->unknownCb->isChecked()) {
releases.emplace_back(ModPlatform::IndexedVersionType::Unknown);
}
m_filterChanged = releases != m_filter->releases;
m_filter->releases = releases;
if (m_filter_changed)
if (m_filterChanged) {
emit filterChanged();
}
}
void ModFilterWidget::onShowMoreClicked()
{
ui->extendedModLoadersWidget->setVisible(true);
ui->showMoreButton->setVisible(false);
m_ui->extendedModLoadersWidget->setVisible(true);
m_ui->showMoreButton->setVisible(false);
}
#include "ModFilterWidget.moc"

View file

@ -73,29 +73,31 @@ class ModFilterWidget : public QTabWidget {
}
bool operator!=(const Filter& other) const { return !(*this == other); }
bool checkMcVersions(QStringList value)
bool checkMcVersions(const QStringList& value)
{
for (auto mcVersion : versions)
if (value.contains(mcVersion.toString()))
for (const auto& mcVersion : versions) {
if (value.contains(mcVersion.toString())) {
return true;
}
}
return versions.empty();
}
bool checkModpackFilters(const ModPlatform::IndexedVersion& v)
{
return ((!loaders || !v.loaders || loaders & v.loaders) && // loaders
(releases.empty() || // releases
return ((!loaders || !v.loaders || ((loaders & v.loaders) != 0)) && // loaders
(releases.empty() || // releases
std::find(releases.cbegin(), releases.cend(), v.version_type) != releases.cend()) &&
checkMcVersions({ v.mcVersion })); // gameVersion}
}
};
static std::unique_ptr<ModFilterWidget> create(MinecraftInstance* instance, bool extended);
virtual ~ModFilterWidget();
~ModFilterWidget() override;
auto getFilter() -> std::shared_ptr<Filter>;
auto changed() const -> bool { return m_filter_changed; }
auto changed() const -> bool { return m_filterChanged; }
signals:
void filterChanged();
@ -121,14 +123,14 @@ class ModFilterWidget : public QTabWidget {
void onShowMoreClicked();
private:
Ui::ModFilterWidget* ui;
Ui::ModFilterWidget* m_ui;
MinecraftInstance* m_instance = nullptr;
std::shared_ptr<Filter> m_filter;
bool m_filter_changed = false;
bool m_filterChanged = false;
Meta::VersionList::Ptr m_version_list;
VersionProxyModel* m_versions_proxy = nullptr;
Meta::VersionList::Ptr m_versionList;
VersionProxyModel* m_versionsProxy = nullptr;
QList<ModPlatform::Category> m_categories;
};