From 32b3ed0a1362a4b0798ad71fac3450fb77cb7e41 Mon Sep 17 00:00:00 2001 From: Thomas Groman Date: Thu, 19 Sep 2019 00:41:48 -0700 Subject: merged from 0.6.7 codebase --- application/dialogs/AboutDialog.cpp | 158 +++--- application/dialogs/AboutDialog.h | 24 +- application/dialogs/AboutDialog.ui | 4 +- application/dialogs/CopyInstanceDialog.cpp | 104 ++-- application/dialogs/CopyInstanceDialog.h | 32 +- application/dialogs/CustomMessageBox.cpp | 24 +- application/dialogs/CustomMessageBox.h | 8 +- application/dialogs/EditAccountDialog.cpp | 26 +- application/dialogs/EditAccountDialog.h | 36 +- application/dialogs/ExportInstanceDialog.cpp | 806 +++++++++++++-------------- application/dialogs/ExportInstanceDialog.h | 26 +- application/dialogs/IconPickerDialog.cpp | 189 +++---- application/dialogs/IconPickerDialog.h | 28 +- application/dialogs/LoginDialog.cpp | 84 +-- application/dialogs/LoginDialog.h | 32 +- application/dialogs/ModEditDialogCommon.cpp | 40 -- application/dialogs/ModEditDialogCommon.h | 9 - application/dialogs/NewComponentDialog.cpp | 88 +-- application/dialogs/NewComponentDialog.h | 22 +- application/dialogs/NewComponentDialog.ui | 2 +- application/dialogs/NewInstanceDialog.cpp | 253 +++++---- application/dialogs/NewInstanceDialog.h | 56 +- application/dialogs/NotificationDialog.cpp | 116 ++-- application/dialogs/NotificationDialog.h | 32 +- application/dialogs/ProfileSelectDialog.cpp | 126 ++--- application/dialogs/ProfileSelectDialog.h | 100 ++-- application/dialogs/ProgressDialog.cpp | 210 +++---- application/dialogs/ProgressDialog.h | 42 +- application/dialogs/SkinUploadDialog.cpp | 180 +++--- application/dialogs/SkinUploadDialog.h | 18 +- application/dialogs/UpdateDialog.cpp | 258 ++++----- application/dialogs/UpdateDialog.h | 42 +- application/dialogs/VersionSelectDialog.cpp | 102 ++-- application/dialogs/VersionSelectDialog.h | 50 +- 34 files changed, 1658 insertions(+), 1669 deletions(-) delete mode 100644 application/dialogs/ModEditDialogCommon.cpp delete mode 100644 application/dialogs/ModEditDialogCommon.h (limited to 'application/dialogs') diff --git a/application/dialogs/AboutDialog.cpp b/application/dialogs/AboutDialog.cpp index 8f2e72c2..ca1dfd94 100644 --- a/application/dialogs/AboutDialog.cpp +++ b/application/dialogs/AboutDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,113 +27,113 @@ // This is a hack, but I can't think of a better way to do this easily without screwing with QTextDocument... static QString getCreditsHtml(QStringList patrons) { - QString creditsHtml = QObject::tr( - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "

MultiMC Developers

" - "

Andrew Okin <forkk@forkk.net>

" - "

Petr Mrázek <peterix@gmail.com>

" - "

Sky Welch <multimc@bunnies.io>

" - "

Jan (02JanDal) <02jandal@gmail.com>

" - "

RoboSky <@RoboSky_>

" - "" - "

With thanks to

" - "

Orochimarufan <orochimarufan.x3@gmail.com>

" - "

TakSuyu <taksuyu@gmail.com>

" - "

Kilobyte <stiepen22@gmx.de>

" - "

Rootbear75 <@rootbear75>

" - "" - "

Patrons

" - "%1" - "" - "" - ""); - if (patrons.isEmpty()) - return creditsHtml.arg(QObject::tr("

Loading...

")); - else - { - QString patronsStr; - for (QString patron : patrons) - { - patronsStr.append(QString("

%1

").arg(patron)); - } - - return creditsHtml.arg(patronsStr); - } + QString creditsHtml = QObject::tr( + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "

MultiMC Developers

" + "

Andrew Okin <forkk@forkk.net>

" + "

Petr Mrázek <peterix@gmail.com>

" + "

Sky Welch <multimc@bunnies.io>

" + "

Jan (02JanDal) <02jandal@gmail.com>

" + "

RoboSky <@RoboSky_>

" + "" + "

With thanks to

" + "

Orochimarufan <orochimarufan.x3@gmail.com>

" + "

TakSuyu <taksuyu@gmail.com>

" + "

Kilobyte <stiepen22@gmx.de>

" + "

Rootbear75 <@rootbear75>

" + "" + "

Patrons

" + "%1" + "" + "" + ""); + if (patrons.isEmpty()) + return creditsHtml.arg(QObject::tr("

Loading...

")); + else + { + QString patronsStr; + for (QString patron : patrons) + { + patronsStr.append(QString("

%1

").arg(patron)); + } + + return creditsHtml.arg(patronsStr); + } } static QString getLicenseHtml() { - HoeDown hoedown; - QFile dataFile(":/documents/COPYING.md"); - dataFile.open(QIODevice::ReadOnly); - QString output = hoedown.process(dataFile.readAll()); - return output; + HoeDown hoedown; + QFile dataFile(":/documents/COPYING.md"); + dataFile.open(QIODevice::ReadOnly); + QString output = hoedown.process(dataFile.readAll()); + return output; } AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) { - ui->setupUi(this); + ui->setupUi(this); - QString chtml = getCreditsHtml(QStringList()); - ui->creditsText->setHtml(chtml); + QString chtml = getCreditsHtml(QStringList()); + ui->creditsText->setHtml(chtml); - QString lhtml = getLicenseHtml(); - ui->licenseText->setHtml(lhtml); + QString lhtml = getLicenseHtml(); + ui->licenseText->setHtml(lhtml); - ui->urlLabel->setOpenExternalLinks(true); + ui->urlLabel->setOpenExternalLinks(true); - ui->icon->setPixmap(MMC->getThemedIcon("logo").pixmap(64)); - ui->title->setText("MultiMC 5"); + ui->icon->setPixmap(MMC->getThemedIcon("logo").pixmap(64)); + ui->title->setText("MultiMC 5"); - ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString()); - ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM); + ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString()); + ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM); - if (BuildConfig.VERSION_BUILD >= 0) - ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(BuildConfig.VERSION_BUILD)); - else - ui->buildNumLabel->setVisible(false); + if (BuildConfig.VERSION_BUILD >= 0) + ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(BuildConfig.VERSION_BUILD)); + else + ui->buildNumLabel->setVisible(false); - if (!BuildConfig.VERSION_CHANNEL.isEmpty()) - ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL); - else - ui->channelLabel->setVisible(false); + if (!BuildConfig.VERSION_CHANNEL.isEmpty()) + ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL); + else + ui->channelLabel->setVisible(false); - connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); + connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); - connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt); + connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt); - loadPatronList(); + loadPatronList(); } AboutDialog::~AboutDialog() { - delete ui; + delete ui; } void AboutDialog::loadPatronList() { - netJob.reset(new NetJob("Patreon Patron List")); - netJob->addNetAction(Net::Download::makeByteArray(QUrl("http://files.multimc.org/patrons.txt"), &dataSink)); - connect(netJob.get(), &NetJob::succeeded, this, &AboutDialog::patronListLoaded); - netJob->start(); + netJob.reset(new NetJob("Patreon Patron List")); + netJob->addNetAction(Net::Download::makeByteArray(QUrl("https://files.multimc.org/patrons.txt"), &dataSink)); + connect(netJob.get(), &NetJob::succeeded, this, &AboutDialog::patronListLoaded); + netJob->start(); } void AboutDialog::patronListLoaded() { - QString patronListStr(dataSink); - dataSink.clear(); - QString html = getCreditsHtml(patronListStr.split("\n", QString::SkipEmptyParts)); - ui->creditsText->setHtml(html); + QString patronListStr(dataSink); + dataSink.clear(); + QString html = getCreditsHtml(patronListStr.split("\n", QString::SkipEmptyParts)); + ui->creditsText->setHtml(html); } diff --git a/application/dialogs/AboutDialog.h b/application/dialogs/AboutDialog.h index 9768b866..21001c07 100644 --- a/application/dialogs/AboutDialog.h +++ b/application/dialogs/AboutDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,23 +25,23 @@ class AboutDialog; class AboutDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit AboutDialog(QWidget *parent = 0); - ~AboutDialog(); + explicit AboutDialog(QWidget *parent = 0); + ~AboutDialog(); public slots: - /// Starts loading a list of Patreon patrons. - void loadPatronList(); - - /// Slot for when the patron list loads successfully. - void patronListLoaded(); + /// Starts loading a list of Patreon patrons. + void loadPatronList(); + + /// Slot for when the patron list loads successfully. + void patronListLoaded(); private: - Ui::AboutDialog *ui; + Ui::AboutDialog *ui; - NetJobPtr netJob; - QByteArray dataSink; + NetJobPtr netJob; + QByteArray dataSink; }; diff --git a/application/dialogs/AboutDialog.ui b/application/dialogs/AboutDialog.ui index 5e8e3e68..a312aa0c 100644 --- a/application/dialogs/AboutDialog.ui +++ b/application/dialogs/AboutDialog.ui @@ -165,7 +165,7 @@ - © 2012-2018 MultiMC Contributors + © 2012-2019 MultiMC Contributors Qt::AlignCenter @@ -180,7 +180,7 @@ - <html><head/><body><p><a href="http://github.com/MultiMC/MultiMC5">http://github.com/MultiMC/MultiMC5</a></p></body></html> + <html><head/><body><p><a href="https://github.com/MultiMC/MultiMC5">https://github.com/MultiMC/MultiMC5</a></p></body></html> Qt::AlignCenter diff --git a/application/dialogs/CopyInstanceDialog.cpp b/application/dialogs/CopyInstanceDialog.cpp index 72ef00fa..6100860c 100644 --- a/application/dialogs/CopyInstanceDialog.cpp +++ b/application/dialogs/CopyInstanceDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,87 +29,97 @@ #include "InstanceList.h" CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent) - :QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original) + :QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original) { - ui->setupUi(this); - resize(minimumSizeHint()); - layout()->setSizeConstraint(QLayout::SetFixedSize); - - InstIconKey = original->iconKey(); - ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); - ui->instNameTextBox->setText(original->name()); - ui->instNameTextBox->setFocus(); - auto groups = MMC->instances()->getGroups().toSet(); - auto groupList = QStringList(groups.toList()); - groupList.sort(Qt::CaseInsensitive); - groupList.removeOne(""); - groupList.push_front(""); - ui->groupBox->addItems(groupList); - int index = groupList.indexOf(m_original->group()); - if(index == -1) - { - index = 0; - } - ui->groupBox->setCurrentIndex(index); - ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); - ui->copySavesCheckbox->setChecked(m_copySaves); + ui->setupUi(this); + resize(minimumSizeHint()); + layout()->setSizeConstraint(QLayout::SetFixedSize); + + InstIconKey = original->iconKey(); + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); + ui->instNameTextBox->setText(original->name()); + ui->instNameTextBox->setFocus(); + auto groups = MMC->instances()->getGroups().toSet(); + auto groupList = QStringList(groups.toList()); + groupList.sort(Qt::CaseInsensitive); + groupList.removeOne(""); + groupList.push_front(""); + ui->groupBox->addItems(groupList); + int index = groupList.indexOf(MMC->instances()->getInstanceGroup(m_original->id())); + if(index == -1) + { + index = 0; + } + ui->groupBox->setCurrentIndex(index); + ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); + ui->copySavesCheckbox->setChecked(m_copySaves); } CopyInstanceDialog::~CopyInstanceDialog() { - delete ui; + delete ui; } void CopyInstanceDialog::updateDialogState() { - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty()); + auto allowOK = !instName().isEmpty(); + auto OkButton = ui->buttonBox->button(QDialogButtonBox::Ok); + if(OkButton->isEnabled() != allowOK) + { + OkButton->setEnabled(allowOK); + } } QString CopyInstanceDialog::instName() const { - return ui->instNameTextBox->text(); + auto result = ui->instNameTextBox->text().trimmed(); + if(result.size()) + { + return result; + } + return QString(); } QString CopyInstanceDialog::iconKey() const { - return InstIconKey; + return InstIconKey; } QString CopyInstanceDialog::instGroup() const { - return ui->groupBox->currentText(); + return ui->groupBox->currentText(); } void CopyInstanceDialog::on_iconButton_clicked() { - IconPickerDialog dlg(this); - dlg.execWithSelection(InstIconKey); - - if (dlg.result() == QDialog::Accepted) - { - InstIconKey = dlg.selectedIconKey; - ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); - } + IconPickerDialog dlg(this); + dlg.execWithSelection(InstIconKey); + + if (dlg.result() == QDialog::Accepted) + { + InstIconKey = dlg.selectedIconKey; + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); + } } void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1) { - updateDialogState(); + updateDialogState(); } bool CopyInstanceDialog::shouldCopySaves() const { - return m_copySaves; + return m_copySaves; } void CopyInstanceDialog::on_copySavesCheckbox_stateChanged(int state) { - if(state == Qt::Unchecked) - { - m_copySaves = false; - } - else if(state == Qt::Checked) - { - m_copySaves = true; - } + if(state == Qt::Unchecked) + { + m_copySaves = false; + } + else if(state == Qt::Checked) + { + m_copySaves = true; + } } diff --git a/application/dialogs/CopyInstanceDialog.h b/application/dialogs/CopyInstanceDialog.h index 809552eb..d46e647c 100644 --- a/application/dialogs/CopyInstanceDialog.h +++ b/application/dialogs/CopyInstanceDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,28 +28,28 @@ class CopyInstanceDialog; class CopyInstanceDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0); - ~CopyInstanceDialog(); + explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0); + ~CopyInstanceDialog(); - void updateDialogState(); + void updateDialogState(); - QString instName() const; - QString instGroup() const; - QString iconKey() const; - bool shouldCopySaves() const; + QString instName() const; + QString instGroup() const; + QString iconKey() const; + bool shouldCopySaves() const; private slots: - void on_iconButton_clicked(); - void on_instNameTextBox_textChanged(const QString &arg1); - void on_copySavesCheckbox_stateChanged(int state); + void on_iconButton_clicked(); + void on_instNameTextBox_textChanged(const QString &arg1); + void on_copySavesCheckbox_stateChanged(int state); private: - Ui::CopyInstanceDialog *ui; - QString InstIconKey; - InstancePtr m_original; - bool m_copySaves = true; + Ui::CopyInstanceDialog *ui; + QString InstIconKey; + InstancePtr m_original; + bool m_copySaves = true; }; diff --git a/application/dialogs/CustomMessageBox.cpp b/application/dialogs/CustomMessageBox.cpp index a7d75263..db60b7f3 100644 --- a/application/dialogs/CustomMessageBox.cpp +++ b/application/dialogs/CustomMessageBox.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,18 +18,18 @@ namespace CustomMessageBox { QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text, - QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, - QMessageBox::StandardButton defaultButton) + QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { - QMessageBox *messageBox = new QMessageBox(parent); - messageBox->setWindowTitle(title); - messageBox->setText(text); - messageBox->setStandardButtons(buttons); - messageBox->setDefaultButton(defaultButton); - messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse); - messageBox->setIcon(icon); - messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); + QMessageBox *messageBox = new QMessageBox(parent); + messageBox->setWindowTitle(title); + messageBox->setText(text); + messageBox->setStandardButtons(buttons); + messageBox->setDefaultButton(defaultButton); + messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse); + messageBox->setIcon(icon); + messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); - return messageBox; + return messageBox; } } diff --git a/application/dialogs/CustomMessageBox.h b/application/dialogs/CustomMessageBox.h index f9c0ad4e..92291e17 100644 --- a/application/dialogs/CustomMessageBox.h +++ b/application/dialogs/CustomMessageBox.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ namespace CustomMessageBox { QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text, - QMessageBox::Icon icon = QMessageBox::NoIcon, - QMessageBox::StandardButtons buttons = QMessageBox::Ok, - QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); + QMessageBox::Icon icon = QMessageBox::NoIcon, + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); } diff --git a/application/dialogs/EditAccountDialog.cpp b/application/dialogs/EditAccountDialog.cpp index e43be1d8..9ae0c745 100644 --- a/application/dialogs/EditAccountDialog.cpp +++ b/application/dialogs/EditAccountDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,43 +19,43 @@ #include EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags) - : QDialog(parent), ui(new Ui::EditAccountDialog) + : QDialog(parent), ui(new Ui::EditAccountDialog) { - ui->setupUi(this); + ui->setupUi(this); - ui->label->setText(text); - ui->label->setVisible(!text.isEmpty()); + ui->label->setText(text); + ui->label->setVisible(!text.isEmpty()); - ui->userTextBox->setEnabled(flags & UsernameField); - ui->passTextBox->setEnabled(flags & PasswordField); + ui->userTextBox->setEnabled(flags & UsernameField); + ui->passTextBox->setEnabled(flags & PasswordField); } EditAccountDialog::~EditAccountDialog() { - delete ui; + delete ui; } void EditAccountDialog::on_label_linkActivated(const QString &link) { - DesktopServices::openUrl(QUrl(link)); + DesktopServices::openUrl(QUrl(link)); } void EditAccountDialog::setUsername(const QString & user) const { - ui->userTextBox->setText(user); + ui->userTextBox->setText(user); } QString EditAccountDialog::username() const { - return ui->userTextBox->text(); + return ui->userTextBox->text(); } void EditAccountDialog::setPassword(const QString & pass) const { - ui->passTextBox->setText(pass); + ui->passTextBox->setText(pass); } QString EditAccountDialog::password() const { - return ui->passTextBox->text(); + return ui->passTextBox->text(); } diff --git a/application/dialogs/EditAccountDialog.h b/application/dialogs/EditAccountDialog.h index f121a111..4f80284a 100644 --- a/application/dialogs/EditAccountDialog.h +++ b/application/dialogs/EditAccountDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,33 +24,33 @@ class EditAccountDialog; class EditAccountDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0, - int flags = UsernameField | PasswordField); - ~EditAccountDialog(); + explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0, + int flags = UsernameField | PasswordField); + ~EditAccountDialog(); - void setUsername(const QString & user) const; - void setPassword(const QString & pass) const; + void setUsername(const QString & user) const; + void setPassword(const QString & pass) const; - QString username() const; - QString password() const; + QString username() const; + QString password() const; - enum Flags - { - NoFlags = 0, + enum Flags + { + NoFlags = 0, - //! Specifies that the dialog should have a username field. - UsernameField, + //! Specifies that the dialog should have a username field. + UsernameField, - //! Specifies that the dialog should have a password field. - PasswordField, - }; + //! Specifies that the dialog should have a password field. + PasswordField, + }; private slots: void on_label_linkActivated(const QString &link); private: - Ui::EditAccountDialog *ui; + Ui::EditAccountDialog *ui; }; diff --git a/application/dialogs/ExportInstanceDialog.cpp b/application/dialogs/ExportInstanceDialog.cpp index 0e19b758..49c082e9 100644 --- a/application/dialogs/ExportInstanceDialog.cpp +++ b/application/dialogs/ExportInstanceDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,456 +33,450 @@ class PackIgnoreProxy : public QSortFilterProxyModel { - Q_OBJECT + Q_OBJECT public: - PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent) - { - m_instance = instance; - } - // NOTE: Sadly, we have to do sorting ourselves. - bool lessThan(const QModelIndex &left, const QModelIndex &right) const - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - if (!fsm) - { - return QSortFilterProxyModel::lessThan(left, right); - } - bool asc = sortOrder() == Qt::AscendingOrder ? true : false; - - QFileInfo leftFileInfo = fsm->fileInfo(left); - QFileInfo rightFileInfo = fsm->fileInfo(right); - - if (!leftFileInfo.isDir() && rightFileInfo.isDir()) - { - return !asc; - } - if (leftFileInfo.isDir() && !rightFileInfo.isDir()) - { - return asc; - } - - // sort and proxy model breaks the original model... - if (sortColumn() == 0) - { - return Strings::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), - Qt::CaseInsensitive) < 0; - } - if (sortColumn() == 1) - { - auto leftSize = leftFileInfo.size(); - auto rightSize = rightFileInfo.size(); - if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) - { - return Strings::naturalCompare(leftFileInfo.fileName(), - rightFileInfo.fileName(), - Qt::CaseInsensitive) < 0 - ? asc - : !asc; - } - return leftSize < rightSize; - } - return QSortFilterProxyModel::lessThan(left, right); - } - - virtual Qt::ItemFlags flags(const QModelIndex &index) const - { - if (!index.isValid()) - return Qt::NoItemFlags; - - auto sourceIndex = mapToSource(index); - Qt::ItemFlags flags = sourceIndex.flags(); - if (index.column() == 0) - { - flags |= Qt::ItemIsUserCheckable; - if (sourceIndex.model()->hasChildren(sourceIndex)) - { - flags |= Qt::ItemIsTristate; - } - } - - return flags; - } - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - QModelIndex sourceIndex = mapToSource(index); - - if (index.column() == 0 && role == Qt::CheckStateRole) - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto cover = blocked.cover(blockedPath); - if (!cover.isNull()) - { - return QVariant(Qt::Unchecked); - } - else if (blocked.exists(blockedPath)) - { - return QVariant(Qt::PartiallyChecked); - } - else - { - return QVariant(Qt::Checked); - } - } - - return sourceIndex.data(role); - } - - virtual bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) - { - if (index.column() == 0 && role == Qt::CheckStateRole) - { - Qt::CheckState state = static_cast(value.toInt()); - return setFilterState(index, state); - } - - QModelIndex sourceIndex = mapToSource(index); - return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); - } - - QString relPath(const QString &path) const - { - QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot()); - prefix += '/'; - if (!path.startsWith(prefix)) - { - return QString(); - } - return path.mid(prefix.size()); - } - - bool setFilterState(QModelIndex index, Qt::CheckState state) - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - - if (!fsm) - { - return false; - } - - QModelIndex sourceIndex = mapToSource(index); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - bool changed = false; - if (state == Qt::Unchecked) - { - // blocking a path - auto &node = blocked.insert(blockedPath); - // get rid of all blocked nodes below - node.clear(); - changed = true; - } - else if (state == Qt::Checked || state == Qt::PartiallyChecked) - { - if (!blocked.remove(blockedPath)) - { - auto cover = blocked.cover(blockedPath); - qDebug() << "Blocked by cover" << cover; - // uncover - blocked.remove(cover); - // block all contents, except for any cover - QModelIndex rootIndex = - fsm->index(FS::PathCombine(m_instance->instanceRoot(), cover)); - QModelIndex doing = rootIndex; - int row = 0; - QStack todo; - while (1) - { - auto node = doing.child(row, 0); - if (!node.isValid()) - { - if (!todo.size()) - { - break; - } - else - { - doing = todo.pop(); - row = 0; - continue; - } - } - auto relpath = relPath(fsm->filePath(node)); - if (blockedPath.startsWith(relpath)) // cover found? - { - // continue processing cover later - todo.push(node); - } - else - { - // or just block this one. - blocked.insert(relpath); - } - row++; - } - } - changed = true; - } - if (changed) - { - // update the thing - emit dataChanged(index, index, {Qt::CheckStateRole}); - // update everything above index - QModelIndex up = index.parent(); - while (1) - { - if (!up.isValid()) - break; - emit dataChanged(up, up, {Qt::CheckStateRole}); - up = up.parent(); - } - // and everything below the index - QModelIndex doing = index; - int row = 0; - QStack todo; - while (1) - { - auto node = doing.child(row, 0); - if (!node.isValid()) - { - if (!todo.size()) - { - break; - } - else - { - doing = todo.pop(); - row = 0; - continue; - } - } - emit dataChanged(node, node, {Qt::CheckStateRole}); - todo.push(node); - row++; - } - // siblings and unrelated nodes are ignored - } - return true; - } - - bool shouldExpand(QModelIndex index) - { - QModelIndex sourceIndex = mapToSource(index); - QFileSystemModel *fsm = qobject_cast(sourceModel()); - if (!fsm) - { - return false; - } - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto found = blocked.find(blockedPath); - if(found) - { - return !found->leaf(); - } - return false; - } - - void setBlockedPaths(QStringList paths) - { - beginResetModel(); - blocked.clear(); - blocked.insert(paths); - endResetModel(); - } - - const SeparatorPrefixTree<'/'> & blockedPaths() const - { - return blocked; - } + PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent) + { + m_instance = instance; + } + // NOTE: Sadly, we have to do sorting ourselves. + bool lessThan(const QModelIndex &left, const QModelIndex &right) const + { + QFileSystemModel *fsm = qobject_cast(sourceModel()); + if (!fsm) + { + return QSortFilterProxyModel::lessThan(left, right); + } + bool asc = sortOrder() == Qt::AscendingOrder ? true : false; + + QFileInfo leftFileInfo = fsm->fileInfo(left); + QFileInfo rightFileInfo = fsm->fileInfo(right); + + if (!leftFileInfo.isDir() && rightFileInfo.isDir()) + { + return !asc; + } + if (leftFileInfo.isDir() && !rightFileInfo.isDir()) + { + return asc; + } + + // sort and proxy model breaks the original model... + if (sortColumn() == 0) + { + return Strings::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), + Qt::CaseInsensitive) < 0; + } + if (sortColumn() == 1) + { + auto leftSize = leftFileInfo.size(); + auto rightSize = rightFileInfo.size(); + if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) + { + return Strings::naturalCompare(leftFileInfo.fileName(), + rightFileInfo.fileName(), + Qt::CaseInsensitive) < 0 + ? asc + : !asc; + } + return leftSize < rightSize; + } + return QSortFilterProxyModel::lessThan(left, right); + } + + virtual Qt::ItemFlags flags(const QModelIndex &index) const + { + if (!index.isValid()) + return Qt::NoItemFlags; + + auto sourceIndex = mapToSource(index); + Qt::ItemFlags flags = sourceIndex.flags(); + if (index.column() == 0) + { + flags |= Qt::ItemIsUserCheckable; + if (sourceIndex.model()->hasChildren(sourceIndex)) + { + flags |= Qt::ItemIsTristate; + } + } + + return flags; + } + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + QModelIndex sourceIndex = mapToSource(index); + + if (index.column() == 0 && role == Qt::CheckStateRole) + { + QFileSystemModel *fsm = qobject_cast(sourceModel()); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto cover = blocked.cover(blockedPath); + if (!cover.isNull()) + { + return QVariant(Qt::Unchecked); + } + else if (blocked.exists(blockedPath)) + { + return QVariant(Qt::PartiallyChecked); + } + else + { + return QVariant(Qt::Checked); + } + } + + return sourceIndex.data(role); + } + + virtual bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole) + { + if (index.column() == 0 && role == Qt::CheckStateRole) + { + Qt::CheckState state = static_cast(value.toInt()); + return setFilterState(index, state); + } + + QModelIndex sourceIndex = mapToSource(index); + return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); + } + + QString relPath(const QString &path) const + { + QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot()); + prefix += '/'; + if (!path.startsWith(prefix)) + { + return QString(); + } + return path.mid(prefix.size()); + } + + bool setFilterState(QModelIndex index, Qt::CheckState state) + { + QFileSystemModel *fsm = qobject_cast(sourceModel()); + + if (!fsm) + { + return false; + } + + QModelIndex sourceIndex = mapToSource(index); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + bool changed = false; + if (state == Qt::Unchecked) + { + // blocking a path + auto &node = blocked.insert(blockedPath); + // get rid of all blocked nodes below + node.clear(); + changed = true; + } + else if (state == Qt::Checked || state == Qt::PartiallyChecked) + { + if (!blocked.remove(blockedPath)) + { + auto cover = blocked.cover(blockedPath); + qDebug() << "Blocked by cover" << cover; + // uncover + blocked.remove(cover); + // block all contents, except for any cover + QModelIndex rootIndex = + fsm->index(FS::PathCombine(m_instance->instanceRoot(), cover)); + QModelIndex doing = rootIndex; + int row = 0; + QStack todo; + while (1) + { + auto node = doing.child(row, 0); + if (!node.isValid()) + { + if (!todo.size()) + { + break; + } + else + { + doing = todo.pop(); + row = 0; + continue; + } + } + auto relpath = relPath(fsm->filePath(node)); + if (blockedPath.startsWith(relpath)) // cover found? + { + // continue processing cover later + todo.push(node); + } + else + { + // or just block this one. + blocked.insert(relpath); + } + row++; + } + } + changed = true; + } + if (changed) + { + // update the thing + emit dataChanged(index, index, {Qt::CheckStateRole}); + // update everything above index + QModelIndex up = index.parent(); + while (1) + { + if (!up.isValid()) + break; + emit dataChanged(up, up, {Qt::CheckStateRole}); + up = up.parent(); + } + // and everything below the index + QModelIndex doing = index; + int row = 0; + QStack todo; + while (1) + { + auto node = doing.child(row, 0); + if (!node.isValid()) + { + if (!todo.size()) + { + break; + } + else + { + doing = todo.pop(); + row = 0; + continue; + } + } + emit dataChanged(node, node, {Qt::CheckStateRole}); + todo.push(node); + row++; + } + // siblings and unrelated nodes are ignored + } + return true; + } + + bool shouldExpand(QModelIndex index) + { + QModelIndex sourceIndex = mapToSource(index); + QFileSystemModel *fsm = qobject_cast(sourceModel()); + if (!fsm) + { + return false; + } + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto found = blocked.find(blockedPath); + if(found) + { + return !found->leaf(); + } + return false; + } + + void setBlockedPaths(QStringList paths) + { + beginResetModel(); + blocked.clear(); + blocked.insert(paths); + endResetModel(); + } + + const SeparatorPrefixTree<'/'> & blockedPaths() const + { + return blocked; + } protected: - bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const - { - Q_UNUSED(source_parent) + bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const + { + Q_UNUSED(source_parent) - // adjust the columns you want to filter out here - // return false for those that will be hidden - if (source_column == 2 || source_column == 3) - return false; + // adjust the columns you want to filter out here + // return false for those that will be hidden + if (source_column == 2 || source_column == 3) + return false; - return true; - } + return true; + } private: - InstancePtr m_instance; - SeparatorPrefixTree<'/'> blocked; + InstancePtr m_instance; + SeparatorPrefixTree<'/'> blocked; }; ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent) - : QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance) + : QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance) { - ui->setupUi(this); - auto model = new QFileSystemModel(this); - proxyModel = new PackIgnoreProxy(m_instance, this); - loadPackIgnore(); - proxyModel->setSourceModel(model); - auto root = instance->instanceRoot(); - ui->treeView->setModel(proxyModel); - ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); - ui->treeView->sortByColumn(0, Qt::AscendingOrder); - - connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int))); - - model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); - model->setRootPath(root); - auto headerView = ui->treeView->header(); - headerView->setSectionResizeMode(QHeaderView::ResizeToContents); - headerView->setSectionResizeMode(0, QHeaderView::Stretch); + ui->setupUi(this); + auto model = new QFileSystemModel(this); + proxyModel = new PackIgnoreProxy(m_instance, this); + loadPackIgnore(); + proxyModel->setSourceModel(model); + auto root = instance->instanceRoot(); + ui->treeView->setModel(proxyModel); + ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); + ui->treeView->sortByColumn(0, Qt::AscendingOrder); + + connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int))); + + model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + model->setRootPath(root); + auto headerView = ui->treeView->header(); + headerView->setSectionResizeMode(QHeaderView::ResizeToContents); + headerView->setSectionResizeMode(0, QHeaderView::Stretch); } ExportInstanceDialog::~ExportInstanceDialog() { - delete ui; + delete ui; } /// Save icon to instance's folder is needed void SaveIcon(InstancePtr m_instance) { - auto iconKey = m_instance->iconKey(); - auto iconList = MMC->icons(); - auto mmcIcon = iconList->icon(iconKey); - if(mmcIcon) - { - bool saveIcon = false; - switch(mmcIcon->type()) - { - case IconType::FileBased: - case IconType::Transient: - saveIcon = true; - default: - break; - } - if(saveIcon) - { - auto & image = mmcIcon->m_images[mmcIcon->type()]; - auto & icon = image.icon; - auto sizes = icon.availableSizes(); - if(sizes.size() == 0) - { - return; - } - auto areaOf = [](QSize size) - { - return size.width() * size.height(); - }; - QSize largest = sizes[0]; - // find variant with largest area - for(auto size: sizes) - { - if(areaOf(largest) < areaOf(size)) - { - largest = size; - } - } - auto pixmap = icon.pixmap(largest); - pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png")); - } - } + auto iconKey = m_instance->iconKey(); + auto iconList = MMC->icons(); + auto mmcIcon = iconList->icon(iconKey); + if(!mmcIcon || mmcIcon->isBuiltIn()) { + return; + } + auto path = mmcIcon->getFilePath(); + if(!path.isNull()) { + QFileInfo inInfo (path); + FS::copy(path, FS::PathCombine(m_instance->instanceRoot(), inInfo.fileName())) (); + return; + } + auto & image = mmcIcon->m_images[mmcIcon->type()]; + auto & icon = image.icon; + auto sizes = icon.availableSizes(); + if(sizes.size() == 0) + { + return; + } + auto areaOf = [](QSize size) + { + return size.width() * size.height(); + }; + QSize largest = sizes[0]; + // find variant with largest area + for(auto size: sizes) + { + if(areaOf(largest) < areaOf(size)) + { + largest = size; + } + } + auto pixmap = icon.pixmap(largest); + pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png")); } bool ExportInstanceDialog::doExport() { - auto name = FS::RemoveInvalidFilenameChars(m_instance->name()); - - const QString output = QFileDialog::getSaveFileName( - this, tr("Export %1").arg(m_instance->name()), - FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite); - if (output.isEmpty()) - { - return false; - } - if (QFile::exists(output)) - { - int ret = - QMessageBox::question(this, tr("Overwrite?"), - tr("This file already exists. Do you want to overwrite it?"), - QMessageBox::No, QMessageBox::Yes); - if (ret == QMessageBox::No) - { - return false; - } - } - - SaveIcon(m_instance); - - auto & blocked = proxyModel->blockedPaths(); - using std::placeholders::_1; - if (!JlCompress::compressDir(output, m_instance->instanceRoot(), name, std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1))) - { - QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); - return false; - } - return true; + auto name = FS::RemoveInvalidFilenameChars(m_instance->name()); + + const QString output = QFileDialog::getSaveFileName( + this, tr("Export %1").arg(m_instance->name()), + FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite); + if (output.isEmpty()) + { + return false; + } + if (QFile::exists(output)) + { + int ret = + QMessageBox::question(this, tr("Overwrite?"), + tr("This file already exists. Do you want to overwrite it?"), + QMessageBox::No, QMessageBox::Yes); + if (ret == QMessageBox::No) + { + return false; + } + } + + SaveIcon(m_instance); + + auto & blocked = proxyModel->blockedPaths(); + using std::placeholders::_1; + if (!JlCompress::compressDir(output, m_instance->instanceRoot(), name, std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1))) + { + QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); + return false; + } + return true; } void ExportInstanceDialog::done(int result) { - savePackIgnore(); - if (result == QDialog::Accepted) - { - if (doExport()) - { - QDialog::done(QDialog::Accepted); - return; - } - else - { - return; - } - } - QDialog::done(result); + savePackIgnore(); + if (result == QDialog::Accepted) + { + if (doExport()) + { + QDialog::done(QDialog::Accepted); + return; + } + else + { + return; + } + } + QDialog::done(result); } void ExportInstanceDialog::rowsInserted(QModelIndex parent, int top, int bottom) { - //WARNING: possible off-by-one? - for(int i = top; i < bottom; i++) - { - auto node = parent.child(i, 0); - if(proxyModel->shouldExpand(node)) - { - auto expNode = node.parent(); - if(!expNode.isValid()) - { - continue; - } - ui->treeView->expand(node); - } - } + //WARNING: possible off-by-one? + for(int i = top; i < bottom; i++) + { + auto node = parent.child(i, 0); + if(proxyModel->shouldExpand(node)) + { + auto expNode = node.parent(); + if(!expNode.isValid()) + { + continue; + } + ui->treeView->expand(node); + } + } } QString ExportInstanceDialog::ignoreFileName() { - return FS::PathCombine(m_instance->instanceRoot(), ".packignore"); + return FS::PathCombine(m_instance->instanceRoot(), ".packignore"); } void ExportInstanceDialog::loadPackIgnore() { - auto filename = ignoreFileName(); - QFile ignoreFile(filename); - if(!ignoreFile.open(QIODevice::ReadOnly)) - { - return; - } - auto data = ignoreFile.readAll(); - auto string = QString::fromUtf8(data); - proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts)); + auto filename = ignoreFileName(); + QFile ignoreFile(filename); + if(!ignoreFile.open(QIODevice::ReadOnly)) + { + return; + } + auto data = ignoreFile.readAll(); + auto string = QString::fromUtf8(data); + proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts)); } void ExportInstanceDialog::savePackIgnore() { - auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); - auto filename = ignoreFileName(); - try - { - FS::write(filename, data); - } - catch (Exception & e) - { - qWarning() << e.cause(); - } + auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); + auto filename = ignoreFileName(); + try + { + FS::write(filename, data); + } + catch (const Exception &e) + { + qWarning() << e.cause(); + } } #include "ExportInstanceDialog.moc" diff --git a/application/dialogs/ExportInstanceDialog.h b/application/dialogs/ExportInstanceDialog.h index 7b9c6726..aec4cbfb 100644 --- a/application/dialogs/ExportInstanceDialog.h +++ b/application/dialogs/ExportInstanceDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,25 +30,25 @@ class ExportInstanceDialog; class ExportInstanceDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0); - ~ExportInstanceDialog(); + explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0); + ~ExportInstanceDialog(); - virtual void done(int result); + virtual void done(int result); private: - bool doExport(); - void loadPackIgnore(); - void savePackIgnore(); - QString ignoreFileName(); + bool doExport(); + void loadPackIgnore(); + void savePackIgnore(); + QString ignoreFileName(); private: - Ui::ExportInstanceDialog *ui; - InstancePtr m_instance; - PackIgnoreProxy * proxyModel; + Ui::ExportInstanceDialog *ui; + InstancePtr m_instance; + PackIgnoreProxy * proxyModel; private slots: - void rowsInserted(QModelIndex parent, int top, int bottom); + void rowsInserted(QModelIndex parent, int top, int bottom); }; diff --git a/application/dialogs/IconPickerDialog.cpp b/application/dialogs/IconPickerDialog.cpp index 4ffd12bc..7f930717 100644 --- a/application/dialogs/IconPickerDialog.cpp +++ b/application/dialogs/IconPickerDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,138 +25,139 @@ #include "groupview/InstanceDelegate.h" #include "icons/IconList.h" +#include "icons/IconUtils.h" #include IconPickerDialog::IconPickerDialog(QWidget *parent) - : QDialog(parent), ui(new Ui::IconPickerDialog) + : QDialog(parent), ui(new Ui::IconPickerDialog) { - ui->setupUi(this); - setWindowModality(Qt::WindowModal); - - auto contentsWidget = ui->iconView; - contentsWidget->setViewMode(QListView::IconMode); - contentsWidget->setFlow(QListView::LeftToRight); - contentsWidget->setIconSize(QSize(48, 48)); - contentsWidget->setMovement(QListView::Static); - contentsWidget->setResizeMode(QListView::Adjust); - contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection); - contentsWidget->setSpacing(5); - contentsWidget->setWordWrap(false); - contentsWidget->setWrapping(true); - contentsWidget->setUniformItemSizes(true); - contentsWidget->setTextElideMode(Qt::ElideRight); - contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); - contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - contentsWidget->setItemDelegate(new ListViewDelegate()); - - // contentsWidget->setAcceptDrops(true); - contentsWidget->setDropIndicatorShown(true); - contentsWidget->viewport()->setAcceptDrops(true); - contentsWidget->setDragDropMode(QAbstractItemView::DropOnly); - contentsWidget->setDefaultDropAction(Qt::CopyAction); - - contentsWidget->installEventFilter(this); - - contentsWidget->setModel(MMC->icons().get()); - - // NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win. - auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole); - auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole); - - connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon())); - connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon())); - - connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex))); - - connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection))); - - auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole); - connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder); + ui->setupUi(this); + setWindowModality(Qt::WindowModal); + + auto contentsWidget = ui->iconView; + contentsWidget->setViewMode(QListView::IconMode); + contentsWidget->setFlow(QListView::LeftToRight); + contentsWidget->setIconSize(QSize(48, 48)); + contentsWidget->setMovement(QListView::Static); + contentsWidget->setResizeMode(QListView::Adjust); + contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection); + contentsWidget->setSpacing(5); + contentsWidget->setWordWrap(false); + contentsWidget->setWrapping(true); + contentsWidget->setUniformItemSizes(true); + contentsWidget->setTextElideMode(Qt::ElideRight); + contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + contentsWidget->setItemDelegate(new ListViewDelegate()); + + // contentsWidget->setAcceptDrops(true); + contentsWidget->setDropIndicatorShown(true); + contentsWidget->viewport()->setAcceptDrops(true); + contentsWidget->setDragDropMode(QAbstractItemView::DropOnly); + contentsWidget->setDefaultDropAction(Qt::CopyAction); + + contentsWidget->installEventFilter(this); + + contentsWidget->setModel(MMC->icons().get()); + + // NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win. + auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole); + auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole); + + connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon())); + connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon())); + + connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex))); + + connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection))); + + auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole); + connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder); } bool IconPickerDialog::eventFilter(QObject *obj, QEvent *evt) { - if (obj != ui->iconView) - return QDialog::eventFilter(obj, evt); - if (evt->type() != QEvent::KeyPress) - { - return QDialog::eventFilter(obj, evt); - } - QKeyEvent *keyEvent = static_cast(evt); - switch (keyEvent->key()) - { - case Qt::Key_Delete: - removeSelectedIcon(); - return true; - case Qt::Key_Plus: - addNewIcon(); - return true; - default: - break; - } - return QDialog::eventFilter(obj, evt); + if (obj != ui->iconView) + return QDialog::eventFilter(obj, evt); + if (evt->type() != QEvent::KeyPress) + { + return QDialog::eventFilter(obj, evt); + } + QKeyEvent *keyEvent = static_cast(evt); + switch (keyEvent->key()) + { + case Qt::Key_Delete: + removeSelectedIcon(); + return true; + case Qt::Key_Plus: + addNewIcon(); + return true; + default: + break; + } + return QDialog::eventFilter(obj, evt); } void IconPickerDialog::addNewIcon() { - //: The title of the select icons open file dialog - QString selectIcons = tr("Select Icons"); - //: The type of icon files - QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), - tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg)"); - MMC->icons()->installIcons(fileNames); + //: The title of the select icons open file dialog + QString selectIcons = tr("Select Icons"); + //: The type of icon files + auto filter = IconUtils::getIconFilter(); + QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), tr("Icons %1").arg(filter)); + MMC->icons()->installIcons(fileNames); } void IconPickerDialog::removeSelectedIcon() { - MMC->icons()->deleteIcon(selectedIconKey); + MMC->icons()->deleteIcon(selectedIconKey); } void IconPickerDialog::activated(QModelIndex index) { - selectedIconKey = index.data(Qt::UserRole).toString(); - accept(); + selectedIconKey = index.data(Qt::UserRole).toString(); + accept(); } void IconPickerDialog::selectionChanged(QItemSelection selected, QItemSelection deselected) { - if (selected.empty()) - return; + if (selected.empty()) + return; - QString key = selected.first().indexes().first().data(Qt::UserRole).toString(); - if (!key.isEmpty()) - selectedIconKey = key; + QString key = selected.first().indexes().first().data(Qt::UserRole).toString(); + if (!key.isEmpty()) + selectedIconKey = key; } int IconPickerDialog::execWithSelection(QString selection) { - auto list = MMC->icons(); - auto contentsWidget = ui->iconView; - selectedIconKey = selection; - - int index_nr = list->getIconIndex(selection); - auto model_index = list->index(index_nr); - contentsWidget->selectionModel()->select( - model_index, QItemSelectionModel::Current | QItemSelectionModel::Select); - - QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, - Q_ARG(QModelIndex, model_index)); - return QDialog::exec(); + auto list = MMC->icons(); + auto contentsWidget = ui->iconView; + selectedIconKey = selection; + + int index_nr = list->getIconIndex(selection); + auto model_index = list->index(index_nr); + contentsWidget->selectionModel()->select( + model_index, QItemSelectionModel::Current | QItemSelectionModel::Select); + + QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, + Q_ARG(QModelIndex, model_index)); + return QDialog::exec(); } void IconPickerDialog::delayed_scroll(QModelIndex model_index) { - auto contentsWidget = ui->iconView; - contentsWidget->scrollTo(model_index); + auto contentsWidget = ui->iconView; + contentsWidget->scrollTo(model_index); } IconPickerDialog::~IconPickerDialog() { - delete ui; + delete ui; } void IconPickerDialog::openFolder() { - DesktopServices::openDirectory(MMC->icons()->getDirectory(), true); + DesktopServices::openDirectory(MMC->icons()->getDirectory(), true); } diff --git a/application/dialogs/IconPickerDialog.h b/application/dialogs/IconPickerDialog.h index 9053ec61..cb870f44 100644 --- a/application/dialogs/IconPickerDialog.h +++ b/application/dialogs/IconPickerDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,26 +24,26 @@ class IconPickerDialog; class IconPickerDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit IconPickerDialog(QWidget *parent = 0); - ~IconPickerDialog(); - int execWithSelection(QString selection); - QString selectedIconKey; + explicit IconPickerDialog(QWidget *parent = 0); + ~IconPickerDialog(); + int execWithSelection(QString selection); + QString selectedIconKey; protected: - virtual bool eventFilter(QObject *, QEvent *); + virtual bool eventFilter(QObject *, QEvent *); private: - Ui::IconPickerDialog *ui; + Ui::IconPickerDialog *ui; private slots: - void selectionChanged(QItemSelection, QItemSelection); - void activated(QModelIndex); - void delayed_scroll(QModelIndex); - void addNewIcon(); - void removeSelectedIcon(); - void openFolder(); + void selectionChanged(QItemSelection, QItemSelection); + void activated(QModelIndex); + void delayed_scroll(QModelIndex); + void addNewIcon(); + void removeSelectedIcon(); + void openFolder(); }; diff --git a/application/dialogs/LoginDialog.cpp b/application/dialogs/LoginDialog.cpp index b2020372..484cb8e2 100644 --- a/application/dialogs/LoginDialog.cpp +++ b/application/dialogs/LoginDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,89 +22,89 @@ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { - ui->setupUi(this); - ui->progressBar->setVisible(false); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + ui->setupUi(this); + ui->progressBar->setVisible(false); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } LoginDialog::~LoginDialog() { - delete ui; + delete ui; } // Stage 1: User interaction void LoginDialog::accept() { - setUserInputsEnabled(false); - ui->progressBar->setVisible(true); - - // Setup the login task and start it - m_account = MojangAccount::createFromUsername(ui->userTextBox->text()); - m_loginTask = m_account->login(nullptr, ui->passTextBox->text()); - connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed); - connect(m_loginTask.get(), &Task::succeeded, this, - &LoginDialog::onTaskSucceeded); - connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus); - connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress); - m_loginTask->start(); + setUserInputsEnabled(false); + ui->progressBar->setVisible(true); + + // Setup the login task and start it + m_account = MojangAccount::createFromUsername(ui->userTextBox->text()); + m_loginTask = m_account->login(nullptr, ui->passTextBox->text()); + connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed); + connect(m_loginTask.get(), &Task::succeeded, this, + &LoginDialog::onTaskSucceeded); + connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus); + connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress); + m_loginTask->start(); } void LoginDialog::setUserInputsEnabled(bool enable) { - ui->userTextBox->setEnabled(enable); - ui->passTextBox->setEnabled(enable); - ui->buttonBox->setEnabled(enable); + ui->userTextBox->setEnabled(enable); + ui->passTextBox->setEnabled(enable); + ui->buttonBox->setEnabled(enable); } // Enable the OK button only when both textboxes contain something. void LoginDialog::on_userTextBox_textEdited(const QString &newText) { - ui->buttonBox->button(QDialogButtonBox::Ok) - ->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok) + ->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty()); } void LoginDialog::on_passTextBox_textEdited(const QString &newText) { - ui->buttonBox->button(QDialogButtonBox::Ok) - ->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok) + ->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty()); } void LoginDialog::onTaskFailed(const QString &reason) { - // Set message - ui->label->setText("" + reason + ""); + // Set message + ui->label->setText("" + reason + ""); - // Re-enable user-interaction - setUserInputsEnabled(true); - ui->progressBar->setVisible(false); + // Re-enable user-interaction + setUserInputsEnabled(true); + ui->progressBar->setVisible(false); } void LoginDialog::onTaskSucceeded() { - QDialog::accept(); + QDialog::accept(); } void LoginDialog::onTaskStatus(const QString &status) { - ui->label->setText(status); + ui->label->setText(status); } void LoginDialog::onTaskProgress(qint64 current, qint64 total) { - ui->progressBar->setMaximum(total); - ui->progressBar->setValue(current); + ui->progressBar->setMaximum(total); + ui->progressBar->setValue(current); } // Public interface MojangAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg) { - LoginDialog dlg(parent); - dlg.ui->label->setText(msg); - if (dlg.exec() == QDialog::Accepted) - { - return dlg.m_account; - } - return 0; + LoginDialog dlg(parent); + dlg.ui->label->setText(msg); + if (dlg.exec() == QDialog::Accepted) + { + return dlg.m_account; + } + return 0; } diff --git a/application/dialogs/LoginDialog.h b/application/dialogs/LoginDialog.h index 27b97cb0..30fcb760 100644 --- a/application/dialogs/LoginDialog.h +++ b/application/dialogs/LoginDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,32 +27,32 @@ class LoginDialog; class LoginDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - ~LoginDialog(); + ~LoginDialog(); - static MojangAccountPtr newAccount(QWidget *parent, QString message); + static MojangAccountPtr newAccount(QWidget *parent, QString message); private: - explicit LoginDialog(QWidget *parent = 0); + explicit LoginDialog(QWidget *parent = 0); - void setUserInputsEnabled(bool enable); + void setUserInputsEnabled(bool enable); protected slots: - void accept(); + void accept(); - void onTaskFailed(const QString &reason); - void onTaskSucceeded(); - void onTaskStatus(const QString &status); - void onTaskProgress(qint64 current, qint64 total); + void onTaskFailed(const QString &reason); + void onTaskSucceeded(); + void onTaskStatus(const QString &status); + void onTaskProgress(qint64 current, qint64 total); - void on_userTextBox_textEdited(const QString &newText); - void on_passTextBox_textEdited(const QString &newText); + void on_userTextBox_textEdited(const QString &newText); + void on_passTextBox_textEdited(const QString &newText); private: - Ui::LoginDialog *ui; - MojangAccountPtr m_account; - std::shared_ptr m_loginTask; + Ui::LoginDialog *ui; + MojangAccountPtr m_account; + std::shared_ptr m_loginTask; }; diff --git a/application/dialogs/ModEditDialogCommon.cpp b/application/dialogs/ModEditDialogCommon.cpp deleted file mode 100644 index 4201bdad..00000000 --- a/application/dialogs/ModEditDialogCommon.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "ModEditDialogCommon.h" -#include "CustomMessageBox.h" -#include - -bool lastfirst(QModelIndexList &list, int &first, int &last) -{ - if (list.isEmpty()) - return false; - first = last = list[0].row(); - for (auto item : list) - { - int row = item.row(); - if (row < first) - first = row; - if (row > last) - last = row; - } - return true; -} - -void showWebsiteForMod(QWidget *parentDlg, Mod &m) -{ - QString url = m.homeurl(); - if (url.size()) - { - // catch the cases where the protocol is missing - if (!url.startsWith("http")) - { - url = "http://" + url; - } - DesktopServices::openUrl(url); - } - else - { - CustomMessageBox::selectable( - parentDlg, QObject::tr("How sad!"), - QObject::tr("The mod author didn't provide a website link for this mod."), - QMessageBox::Warning); - } -} diff --git a/application/dialogs/ModEditDialogCommon.h b/application/dialogs/ModEditDialogCommon.h deleted file mode 100644 index fc5e3c2b..00000000 --- a/application/dialogs/ModEditDialogCommon.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -#include -#include -#include - -bool lastfirst(QModelIndexList &list, int &first, int &last); - -void showWebsiteForMod(QWidget *parentDlg, Mod &m); diff --git a/application/dialogs/NewComponentDialog.cpp b/application/dialogs/NewComponentDialog.cpp index 514aa938..d0d1d24b 100644 --- a/application/dialogs/NewComponentDialog.cpp +++ b/application/dialogs/NewComponentDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,72 +35,72 @@ #include NewComponentDialog::NewComponentDialog(const QString & initialName, const QString & initialUid, QWidget *parent) - : QDialog(parent), ui(new Ui::NewComponentDialog) + : QDialog(parent), ui(new Ui::NewComponentDialog) { - ui->setupUi(this); - resize(minimumSizeHint()); + ui->setupUi(this); + resize(minimumSizeHint()); - ui->nameTextBox->setText(initialName); - ui->uidTextBox->setText(initialUid); + ui->nameTextBox->setText(initialName); + ui->uidTextBox->setText(initialUid); - connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState); - connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState); + connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState); + connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState); - auto groups = MMC->instances()->getGroups().toSet(); - ui->nameTextBox->setFocus(); + auto groups = MMC->instances()->getGroups().toSet(); + ui->nameTextBox->setFocus(); - originalPlaceholderText = ui->uidTextBox->placeholderText(); - updateDialogState(); + originalPlaceholderText = ui->uidTextBox->placeholderText(); + updateDialogState(); } NewComponentDialog::~NewComponentDialog() { - delete ui; + delete ui; } void NewComponentDialog::updateDialogState() { - auto protoUid = ui->nameTextBox->text().toLower(); - protoUid.remove(QRegularExpression("[^a-z]")); - if(protoUid.isEmpty()) - { - ui->uidTextBox->setPlaceholderText(originalPlaceholderText); - } - else - { - QString suggestedUid = "org.multimc.custom." + protoUid; - ui->uidTextBox->setPlaceholderText(suggestedUid); - } - bool allowOK = !name().isEmpty() && !uid().isEmpty() && !uidBlacklist.contains(uid()); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK); + auto protoUid = ui->nameTextBox->text().toLower(); + protoUid.remove(QRegularExpression("[^a-z]")); + if(protoUid.isEmpty()) + { + ui->uidTextBox->setPlaceholderText(originalPlaceholderText); + } + else + { + QString suggestedUid = "org.multimc.custom." + protoUid; + ui->uidTextBox->setPlaceholderText(suggestedUid); + } + bool allowOK = !name().isEmpty() && !uid().isEmpty() && !uidBlacklist.contains(uid()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK); } QString NewComponentDialog::name() const { - auto result = ui->nameTextBox->text(); - if(result.size()) - { - return result.trimmed(); - } - return QString(); + auto result = ui->nameTextBox->text(); + if(result.size()) + { + return result.trimmed(); + } + return QString(); } QString NewComponentDialog::uid() const { - auto result = ui->uidTextBox->text(); - if(result.size()) - { - return result.trimmed(); - } - result = ui->uidTextBox->placeholderText(); - if(result.size() && result != originalPlaceholderText) - { - return result.trimmed(); - } - return QString(); + auto result = ui->uidTextBox->text(); + if(result.size()) + { + return result.trimmed(); + } + result = ui->uidTextBox->placeholderText(); + if(result.size() && result != originalPlaceholderText) + { + return result.trimmed(); + } + return QString(); } void NewComponentDialog::setBlacklist(QStringList badUids) { - uidBlacklist = badUids; + uidBlacklist = badUids; } diff --git a/application/dialogs/NewComponentDialog.h b/application/dialogs/NewComponentDialog.h index 70caec0f..518f342d 100644 --- a/application/dialogs/NewComponentDialog.h +++ b/application/dialogs/NewComponentDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,22 +27,22 @@ class NewComponentDialog; class NewComponentDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0); - virtual ~NewComponentDialog(); - void setBlacklist(QStringList badUids); + explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0); + virtual ~NewComponentDialog(); + void setBlacklist(QStringList badUids); - QString name() const; - QString uid() const; + QString name() const; + QString uid() const; private slots: - void updateDialogState(); + void updateDialogState(); private: - Ui::NewComponentDialog *ui; + Ui::NewComponentDialog *ui; - QString originalPlaceholderText; - QStringList uidBlacklist; + QString originalPlaceholderText; + QStringList uidBlacklist; }; diff --git a/application/dialogs/NewComponentDialog.ui b/application/dialogs/NewComponentDialog.ui index b30c2431..03b0d222 100644 --- a/application/dialogs/NewComponentDialog.ui +++ b/application/dialogs/NewComponentDialog.ui @@ -14,7 +14,7 @@ - Copy Instance + Add Empty Component diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp index b3ce5c6c..3533763d 100644 --- a/application/dialogs/NewInstanceDialog.cpp +++ b/application/dialogs/NewInstanceDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,178 +39,209 @@ #include #include -NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString & url, QWidget *parent) - : QDialog(parent), ui(new Ui::NewInstanceDialog) -{ - ui->setupUi(this); - - setWindowIcon(MMC->getThemedIcon("new")); - - InstIconKey = "default"; - ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); - - auto groups = MMC->instances()->getGroups().toSet(); - auto groupList = QStringList(groups.toList()); - groupList.sort(Qt::CaseInsensitive); - groupList.removeOne(""); - groupList.push_front(initialGroup); - groupList.push_front(""); - ui->groupBox->addItems(groupList); - int index = groupList.indexOf(initialGroup); - if(index == -1) - { - index = 0; - } - ui->groupBox->setCurrentIndex(index); - ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); - - m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok); - m_buttons->button(QDialogButtonBox::Ok)->setDefault(true); - - m_container = new PageContainer(this); - m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); - m_container->layout()->setContentsMargins(0, 0, 0, 0); - ui->verticalLayout->insertWidget(2, m_container); - - m_container->addButtons(m_buttons); - m_buttons->setFocus(); - - if(!url.isEmpty()) - { - m_container->selectPage("import"); - importPage->setUrl(url); - } - - connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &NewInstanceDialog::accept); - connect(m_buttons->button(QDialogButtonBox::Help), &QPushButton::clicked, m_container, &PageContainer::help); - - updateDialogState(); - - restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray())); +NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString & url, QWidget *parent) + : QDialog(parent), ui(new Ui::NewInstanceDialog) +{ + ui->setupUi(this); + + setWindowIcon(MMC->getThemedIcon("new")); + + InstIconKey = "default"; + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); + + auto groups = MMC->instances()->getGroups().toSet(); + auto groupList = QStringList(groups.toList()); + groupList.sort(Qt::CaseInsensitive); + groupList.removeOne(""); + groupList.push_front(initialGroup); + groupList.push_front(""); + ui->groupBox->addItems(groupList); + int index = groupList.indexOf(initialGroup); + if(index == -1) + { + index = 0; + } + ui->groupBox->setCurrentIndex(index); + ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); + + + // NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not move this below. + m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + m_container = new PageContainer(this); + m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); + m_container->layout()->setContentsMargins(0, 0, 0, 0); + ui->verticalLayout->insertWidget(2, m_container); + + m_container->addButtons(m_buttons); + + // Bonk Qt over its stupid head and make sure it understands which button is the default one... + // See: https://stackoverflow.com/questions/24556831/qbuttonbox-set-default-button + auto OkButton = m_buttons->button(QDialogButtonBox::Ok); + OkButton->setDefault(true); + OkButton->setAutoDefault(true); + connect(OkButton, &QPushButton::clicked, this, &NewInstanceDialog::accept); + + auto CancelButton = m_buttons->button(QDialogButtonBox::Cancel); + CancelButton->setDefault(false); + CancelButton->setAutoDefault(false); + connect(CancelButton, &QPushButton::clicked, this, &NewInstanceDialog::reject); + + auto HelpButton = m_buttons->button(QDialogButtonBox::Help); + HelpButton->setDefault(false); + HelpButton->setAutoDefault(false); + connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help); + + if(!url.isEmpty()) + { + QUrl actualUrl(url); + if(actualUrl.host() == "www.curseforge.com") { + m_container->selectPage("twitch"); + twitchPage->setUrl(url); + } + else { + m_container->selectPage("import"); + importPage->setUrl(url); + } + } + + updateDialogState(); + + restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray())); } void NewInstanceDialog::reject() { - MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); - QDialog::reject(); + MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); + QDialog::reject(); } void NewInstanceDialog::accept() { - MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); - importIconNow(); - QDialog::accept(); + MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); + importIconNow(); + QDialog::accept(); } QList NewInstanceDialog::getPages() { - importPage = new ImportPage(this); - return - { - new VanillaPage(this), - new FTBPage(this), - importPage, - new TwitchPage(this), - new TechnicPage(this) - }; + importPage = new ImportPage(this); + twitchPage = new TwitchPage(this); + return + { + new VanillaPage(this), + importPage, + twitchPage, + new FTBPage(this) + }; } QString NewInstanceDialog::dialogTitle() { - return tr("New Instance"); + return tr("New Instance"); } NewInstanceDialog::~NewInstanceDialog() { - delete ui; + delete ui; } void NewInstanceDialog::setSuggestedPack(const QString& name, InstanceTask* task) { - creationTask.reset(task); - ui->instNameTextBox->setPlaceholderText(name); + creationTask.reset(task); + ui->instNameTextBox->setPlaceholderText(name); + + if(!task) + { + ui->iconButton->setIcon(MMC->icons()->getIcon("default")); + importIcon = false; + } - auto allowOK = task && !instName().isEmpty(); - m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK); + auto allowOK = task && !instName().isEmpty(); + m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK); } void NewInstanceDialog::setSuggestedIconFromFile(const QString &path, const QString &name) { - importIcon = true; - importIconPath = path; - importIconName = name; + importIcon = true; + importIconPath = path; + importIconName = name; - //Hmm, for some reason they can be to small - ui->iconButton->setIcon(QIcon(path)); + //Hmm, for some reason they can be to small + ui->iconButton->setIcon(QIcon(path)); } InstanceTask * NewInstanceDialog::extractTask() { - InstanceTask * extracted = creationTask.get(); - creationTask.release(); - extracted->setName(instName()); - extracted->setGroup(instGroup()); - extracted->setIcon(iconKey()); - return extracted; + InstanceTask * extracted = creationTask.get(); + creationTask.release(); + extracted->setName(instName()); + extracted->setGroup(instGroup()); + extracted->setIcon(iconKey()); + return extracted; } void NewInstanceDialog::updateDialogState() { - auto allowOK = creationTask && !instName().isEmpty(); - m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK); + auto allowOK = creationTask && !instName().isEmpty(); + auto OkButton = m_buttons->button(QDialogButtonBox::Ok); + if(OkButton->isEnabled() != allowOK) + { + OkButton->setEnabled(allowOK); + } } QString NewInstanceDialog::instName() const { - auto result = ui->instNameTextBox->text(); - if(result.size()) - { - return result.trimmed(); - } - result = ui->instNameTextBox->placeholderText(); - if(result.size()) - { - return result.trimmed(); - } - return QString(); + auto result = ui->instNameTextBox->text().trimmed(); + if(result.size()) + { + return result; + } + result = ui->instNameTextBox->placeholderText().trimmed(); + if(result.size()) + { + return result; + } + return QString(); } QString NewInstanceDialog::instGroup() const { - return ui->groupBox->currentText(); + return ui->groupBox->currentText(); } QString NewInstanceDialog::iconKey() const { - return InstIconKey; + return InstIconKey; } void NewInstanceDialog::on_iconButton_clicked() { - importIconNow(); //so the user can switch back - IconPickerDialog dlg(this); - dlg.execWithSelection(InstIconKey); + importIconNow(); //so the user can switch back + IconPickerDialog dlg(this); + dlg.execWithSelection(InstIconKey); - if (dlg.result() == QDialog::Accepted) - { - InstIconKey = dlg.selectedIconKey; - ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); - importIcon = false; - } + if (dlg.result() == QDialog::Accepted) + { + InstIconKey = dlg.selectedIconKey; + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); + importIcon = false; + } } void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1) { - updateDialogState(); + updateDialogState(); } void NewInstanceDialog::importIconNow() { - if(importIcon) { - MMC->icons()->installIcon(importIconPath, importIconName); - InstIconKey = importIconName; - importIcon = false; - } - MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); + if(importIcon) { + MMC->icons()->installIcon(importIconPath, importIconName); + InstIconKey = importIconName; + importIcon = false; + } + MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); } diff --git a/application/dialogs/NewInstanceDialog.h b/application/dialogs/NewInstanceDialog.h index 1448d225..0b8b2fb8 100644 --- a/application/dialogs/NewInstanceDialog.h +++ b/application/dialogs/NewInstanceDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,49 +29,51 @@ class NewInstanceDialog; class PageContainer; class QDialogButtonBox; class ImportPage; +class TwitchPage; class NewInstanceDialog : public QDialog, public BasePageProvider { - Q_OBJECT + Q_OBJECT public: - explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0); - ~NewInstanceDialog(); + explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0); + ~NewInstanceDialog(); - void updateDialogState(); + void updateDialogState(); - void setSuggestedPack(const QString & name = QString(), InstanceTask * task = nullptr); - void setSuggestedIconFromFile(const QString &path, const QString &name); + void setSuggestedPack(const QString & name = QString(), InstanceTask * task = nullptr); + void setSuggestedIconFromFile(const QString &path, const QString &name); - InstanceTask * extractTask(); + InstanceTask * extractTask(); - QString dialogTitle() override; - QList getPages() override; + QString dialogTitle() override; + QList getPages() override; - QString instName() const; - QString instGroup() const; - QString iconKey() const; + QString instName() const; + QString instGroup() const; + QString iconKey() const; public slots: - void accept() override; - void reject() override; + void accept() override; + void reject() override; private slots: - void on_iconButton_clicked(); - void on_instNameTextBox_textChanged(const QString &arg1); + void on_iconButton_clicked(); + void on_instNameTextBox_textChanged(const QString &arg1); private: - Ui::NewInstanceDialog *ui = nullptr; - PageContainer * m_container = nullptr; - QDialogButtonBox * m_buttons = nullptr; + Ui::NewInstanceDialog *ui = nullptr; + PageContainer * m_container = nullptr; + QDialogButtonBox * m_buttons = nullptr; - QString InstIconKey; - ImportPage *importPage = nullptr; - std::unique_ptr creationTask; + QString InstIconKey; + ImportPage *importPage = nullptr; + TwitchPage *twitchPage = nullptr; + std::unique_ptr creationTask; - bool importIcon = false; - QString importIconPath; - QString importIconName; + bool importIcon = false; + QString importIconPath; + QString importIconName; - void importIconNow(); + void importIconNow(); }; diff --git a/application/dialogs/NotificationDialog.cpp b/application/dialogs/NotificationDialog.cpp index 86b03bda..f2a35ae2 100644 --- a/application/dialogs/NotificationDialog.cpp +++ b/application/dialogs/NotificationDialog.cpp @@ -2,85 +2,85 @@ #include "ui_NotificationDialog.h" #include -#include +#include NotificationDialog::NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent) : - QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint), - ui(new Ui::NotificationDialog) + QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint), + ui(new Ui::NotificationDialog) { - ui->setupUi(this); + ui->setupUi(this); - QStyle::StandardPixmap icon; - switch (entry.type) - { - case NotificationChecker::NotificationEntry::Critical: - icon = QStyle::SP_MessageBoxCritical; - break; - case NotificationChecker::NotificationEntry::Warning: - icon = QStyle::SP_MessageBoxWarning; - break; - default: - case NotificationChecker::NotificationEntry::Information: - icon = QStyle::SP_MessageBoxInformation; - break; - } - ui->iconLabel->setPixmap(style()->standardPixmap(icon, 0, this)); - ui->messageLabel->setText(entry.message); + QStyle::StandardPixmap icon; + switch (entry.type) + { + case NotificationChecker::NotificationEntry::Critical: + icon = QStyle::SP_MessageBoxCritical; + break; + case NotificationChecker::NotificationEntry::Warning: + icon = QStyle::SP_MessageBoxWarning; + break; + default: + case NotificationChecker::NotificationEntry::Information: + icon = QStyle::SP_MessageBoxInformation; + break; + } + ui->iconLabel->setPixmap(style()->standardPixmap(icon, 0, this)); + ui->messageLabel->setText(entry.message); - m_dontShowAgainText = tr("Don't show again"); - m_closeText = tr("Close"); + m_dontShowAgainText = tr("Don't show again"); + m_closeText = tr("Close"); - ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime)); - ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime)); + ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime)); + ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime)); - startTimer(1000); + startTimer(1000); } NotificationDialog::~NotificationDialog() { - delete ui; + delete ui; } void NotificationDialog::timerEvent(QTimerEvent *event) { - if (m_dontShowAgainTime > 0) - { - m_dontShowAgainTime--; - if (m_dontShowAgainTime == 0) - { - ui->dontShowAgainBtn->setText(m_dontShowAgainText); - ui->dontShowAgainBtn->setEnabled(true); - } - else - { - ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime)); - } - } - if (m_closeTime > 0) - { - m_closeTime--; - if (m_closeTime == 0) - { - ui->closeBtn->setText(m_closeText); - ui->closeBtn->setEnabled(true); - } - else - { - ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime)); - } - } + if (m_dontShowAgainTime > 0) + { + m_dontShowAgainTime--; + if (m_dontShowAgainTime == 0) + { + ui->dontShowAgainBtn->setText(m_dontShowAgainText); + ui->dontShowAgainBtn->setEnabled(true); + } + else + { + ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime)); + } + } + if (m_closeTime > 0) + { + m_closeTime--; + if (m_closeTime == 0) + { + ui->closeBtn->setText(m_closeText); + ui->closeBtn->setEnabled(true); + } + else + { + ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime)); + } + } - if (m_closeTime == 0 && m_dontShowAgainTime == 0) - { - killTimer(event->timerId()); - } + if (m_closeTime == 0 && m_dontShowAgainTime == 0) + { + killTimer(event->timerId()); + } } void NotificationDialog::on_dontShowAgainBtn_clicked() { - done(DontShowAgain); + done(DontShowAgain); } void NotificationDialog::on_closeBtn_clicked() { - done(Normal); + done(Normal); } diff --git a/application/dialogs/NotificationDialog.h b/application/dialogs/NotificationDialog.h index 27b9e853..e1cbb9fa 100644 --- a/application/dialogs/NotificationDialog.h +++ b/application/dialogs/NotificationDialog.h @@ -11,34 +11,34 @@ class NotificationDialog; class NotificationDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent = 0); - ~NotificationDialog(); + explicit NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent = 0); + ~NotificationDialog(); - enum ExitCode - { - Normal, - DontShowAgain - }; + enum ExitCode + { + Normal, + DontShowAgain + }; protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event); private: - Ui::NotificationDialog *ui; + Ui::NotificationDialog *ui; - int m_dontShowAgainTime = 10; - int m_closeTime = 5; + int m_dontShowAgainTime = 10; + int m_closeTime = 5; - QString m_dontShowAgainText; - QString m_closeText; + QString m_dontShowAgainText; + QString m_closeText; private slots: - void on_dontShowAgainBtn_clicked(); - void on_closeBtn_clicked(); + void on_dontShowAgainBtn_clicked(); + void on_closeBtn_clicked(); }; #endif // NOTIFICATIONDIALOG_H diff --git a/application/dialogs/ProfileSelectDialog.cpp b/application/dialogs/ProfileSelectDialog.cpp index f1b335f9..b64de01a 100644 --- a/application/dialogs/ProfileSelectDialog.cpp +++ b/application/dialogs/ProfileSelectDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,91 +26,91 @@ #include ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWidget *parent) - : QDialog(parent), ui(new Ui::ProfileSelectDialog) + : QDialog(parent), ui(new Ui::ProfileSelectDialog) { - ui->setupUi(this); - - m_accounts = MMC->accounts(); - auto view = ui->listView; - //view->setModel(m_accounts.get()); - //view->hideColumn(MojangAccountList::ActiveColumn); - view->setColumnCount(1); - view->setRootIsDecorated(false); - if(QTreeWidgetItem* header = view->headerItem()) - { - header->setText(0, tr("Name")); - } - else - { - view->setHeaderLabel(tr("Name")); - } - QList items; - for (int i = 0; i < m_accounts->count(); i++) - { - MojangAccountPtr account = m_accounts->at(i); - for (auto profile : account->profiles()) - { - auto profileLabel = profile.name; - if(account->isInUse()) - { - profileLabel += tr(" (in use)"); - } - auto item = new QTreeWidgetItem(view); - item->setText(0, profileLabel); - item->setIcon(0, SkinUtils::getFaceFromCache(profile.id)); - item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account)); - items.append(item); - } - } - view->addTopLevelItems(items); - - // Set the message label. - ui->msgLabel->setVisible(!message.isEmpty()); - ui->msgLabel->setText(message); - - // Flags... - ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox); - ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox); - qDebug() << flags; - - // Select the first entry in the list. - ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0)); - - connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted())); + ui->setupUi(this); + + m_accounts = MMC->accounts(); + auto view = ui->listView; + //view->setModel(m_accounts.get()); + //view->hideColumn(MojangAccountList::ActiveColumn); + view->setColumnCount(1); + view->setRootIsDecorated(false); + if(QTreeWidgetItem* header = view->headerItem()) + { + header->setText(0, tr("Name")); + } + else + { + view->setHeaderLabel(tr("Name")); + } + QList items; + for (int i = 0; i < m_accounts->count(); i++) + { + MojangAccountPtr account = m_accounts->at(i); + for (auto profile : account->profiles()) + { + auto profileLabel = profile.name; + if(account->isInUse()) + { + profileLabel += tr(" (in use)"); + } + auto item = new QTreeWidgetItem(view); + item->setText(0, profileLabel); + item->setIcon(0, SkinUtils::getFaceFromCache(profile.id)); + item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account)); + items.append(item); + } + } + view->addTopLevelItems(items); + + // Set the message label. + ui->msgLabel->setVisible(!message.isEmpty()); + ui->msgLabel->setText(message); + + // Flags... + ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox); + ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox); + qDebug() << flags; + + // Select the first entry in the list. + ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0)); + + connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted())); } ProfileSelectDialog::~ProfileSelectDialog() { - delete ui; + delete ui; } MojangAccountPtr ProfileSelectDialog::selectedAccount() const { - return m_selected; + return m_selected; } bool ProfileSelectDialog::useAsGlobalDefault() const { - return ui->globalDefaultCheck->isChecked(); + return ui->globalDefaultCheck->isChecked(); } bool ProfileSelectDialog::useAsInstDefaullt() const { - return ui->instDefaultCheck->isChecked(); + return ui->instDefaultCheck->isChecked(); } void ProfileSelectDialog::on_buttonBox_accepted() { - QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.size() > 0) - { - QModelIndex selected = selection.first(); - m_selected = selected.data(MojangAccountList::PointerRole).value(); - } - close(); + QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.size() > 0) + { + QModelIndex selected = selection.first(); + m_selected = selected.data(MojangAccountList::PointerRole).value(); + } + close(); } void ProfileSelectDialog::on_buttonBox_rejected() { - close(); + close(); } diff --git a/application/dialogs/ProfileSelectDialog.h b/application/dialogs/ProfileSelectDialog.h index b1268743..40fa0843 100644 --- a/application/dialogs/ProfileSelectDialog.h +++ b/application/dialogs/ProfileSelectDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,63 +28,63 @@ class ProfileSelectDialog; class ProfileSelectDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - enum Flags - { - NoFlags = 0, - - /*! - * Shows a check box on the dialog that allows the user to specify that the account - * they've selected should be used as the global default for all instances. - */ - GlobalDefaultCheckbox, - - /*! - * Shows a check box on the dialog that allows the user to specify that the account - * they've selected should be used as the default for the instance they are currently launching. - * This is not currently implemented. - */ - InstanceDefaultCheckbox, - }; - - /*! - * Constructs a new account select dialog with the given parent and message. - * The message will be shown at the top of the dialog. It is an empty string by default. - */ - explicit ProfileSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0); - ~ProfileSelectDialog(); - - /*! - * Gets a pointer to the account that the user selected. - * This is null if the user clicked cancel or hasn't clicked OK yet. - */ - MojangAccountPtr selectedAccount() const; - - /*! - * Returns true if the user checked the "use as global default" checkbox. - * If the checkbox wasn't shown, this function returns false. - */ - bool useAsGlobalDefault() const; - - /*! - * Returns true if the user checked the "use as instance default" checkbox. - * If the checkbox wasn't shown, this function returns false. - */ - bool useAsInstDefaullt() const; + enum Flags + { + NoFlags = 0, + + /*! + * Shows a check box on the dialog that allows the user to specify that the account + * they've selected should be used as the global default for all instances. + */ + GlobalDefaultCheckbox, + + /*! + * Shows a check box on the dialog that allows the user to specify that the account + * they've selected should be used as the default for the instance they are currently launching. + * This is not currently implemented. + */ + InstanceDefaultCheckbox, + }; + + /*! + * Constructs a new account select dialog with the given parent and message. + * The message will be shown at the top of the dialog. It is an empty string by default. + */ + explicit ProfileSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0); + ~ProfileSelectDialog(); + + /*! + * Gets a pointer to the account that the user selected. + * This is null if the user clicked cancel or hasn't clicked OK yet. + */ + MojangAccountPtr selectedAccount() const; + + /*! + * Returns true if the user checked the "use as global default" checkbox. + * If the checkbox wasn't shown, this function returns false. + */ + bool useAsGlobalDefault() const; + + /*! + * Returns true if the user checked the "use as instance default" checkbox. + * If the checkbox wasn't shown, this function returns false. + */ + bool useAsInstDefaullt() const; public slots: - void on_buttonBox_accepted(); + void on_buttonBox_accepted(); - void on_buttonBox_rejected(); + void on_buttonBox_rejected(); protected: - std::shared_ptr m_accounts; + std::shared_ptr m_accounts; - //! The account that was selected when the user clicked OK. - MojangAccountPtr m_selected; + //! The account that was selected when the user clicked OK. + MojangAccountPtr m_selected; private: - Ui::ProfileSelectDialog *ui; + Ui::ProfileSelectDialog *ui; }; diff --git a/application/dialogs/ProgressDialog.cpp b/application/dialogs/ProgressDialog.cpp index 056a0ffb..0e186fc2 100644 --- a/application/dialogs/ProgressDialog.cpp +++ b/application/dialogs/ProgressDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,117 +23,117 @@ ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ProgressDialog) { - ui->setupUi(this); - this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); - setSkipButton(false); - changeProgress(0, 100); + ui->setupUi(this); + this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); + setSkipButton(false); + changeProgress(0, 100); } void ProgressDialog::setSkipButton(bool present, QString label) { - ui->skipButton->setAutoDefault(false); - ui->skipButton->setDefault(false); - ui->skipButton->setFocusPolicy(Qt::ClickFocus); - ui->skipButton->setEnabled(present); - ui->skipButton->setVisible(present); - ui->skipButton->setText(label); - updateSize(); + ui->skipButton->setAutoDefault(false); + ui->skipButton->setDefault(false); + ui->skipButton->setFocusPolicy(Qt::ClickFocus); + ui->skipButton->setEnabled(present); + ui->skipButton->setVisible(present); + ui->skipButton->setText(label); + updateSize(); } void ProgressDialog::on_skipButton_clicked(bool checked) { - Q_UNUSED(checked); - task->abort(); + Q_UNUSED(checked); + task->abort(); } ProgressDialog::~ProgressDialog() { - delete ui; + delete ui; } void ProgressDialog::updateSize() { QSize qSize = QSize(480, minimumSizeHint().height()); - resize(qSize); + resize(qSize); setFixedSize(qSize); } int ProgressDialog::execWithTask(Task *task) { - this->task = task; - QDialog::DialogCode result; - - if(!task) - { - qDebug() << "Programmer error: progress dialog created with null task."; - return Accepted; - } - - if(handleImmediateResult(result)) - { - return result; - } - - // Connect signals. - connect(task, SIGNAL(started()), SLOT(onTaskStarted())); - connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString))); - connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded())); - connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString &))); - connect(task, SIGNAL(progress(qint64, qint64)), SLOT(changeProgress(qint64, qint64))); - - // if this didn't connect to an already running task, invoke start - if(!task->isRunning()) - { - task->start(); - } - if(task->isRunning()) - { - changeProgress(task->getProgress(), task->getTotalProgress()); - changeStatus(task->getStatus()); - return QDialog::exec(); - } - else if(handleImmediateResult(result)) - { - return result; - } - else - { - return QDialog::Rejected; - } + this->task = task; + QDialog::DialogCode result; + + if(!task) + { + qDebug() << "Programmer error: progress dialog created with null task."; + return Accepted; + } + + if(handleImmediateResult(result)) + { + return result; + } + + // Connect signals. + connect(task, SIGNAL(started()), SLOT(onTaskStarted())); + connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString))); + connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded())); + connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString &))); + connect(task, SIGNAL(progress(qint64, qint64)), SLOT(changeProgress(qint64, qint64))); + + // if this didn't connect to an already running task, invoke start + if(!task->isRunning()) + { + task->start(); + } + if(task->isRunning()) + { + changeProgress(task->getProgress(), task->getTotalProgress()); + changeStatus(task->getStatus()); + return QDialog::exec(); + } + else if(handleImmediateResult(result)) + { + return result; + } + else + { + return QDialog::Rejected; + } } // TODO: only provide the unique_ptr overloads int ProgressDialog::execWithTask(std::unique_ptr &&task) { - connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater); - return execWithTask(task.release()); + connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater); + return execWithTask(task.release()); } int ProgressDialog::execWithTask(std::unique_ptr &task) { - connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater); - return execWithTask(task.release()); + connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater); + return execWithTask(task.release()); } bool ProgressDialog::handleImmediateResult(QDialog::DialogCode &result) { - if(task->isFinished()) - { - if(task->wasSuccessful()) - { - result = QDialog::Accepted; - } - else - { - result = QDialog::Rejected; - } - return true; - } - return false; + if(task->isFinished()) + { + if(task->wasSuccessful()) + { + result = QDialog::Accepted; + } + else + { + result = QDialog::Rejected; + } + return true; + } + return false; } Task *ProgressDialog::getTask() { - return task; + return task; } void ProgressDialog::onTaskStarted() @@ -142,55 +142,55 @@ void ProgressDialog::onTaskStarted() void ProgressDialog::onTaskFailed(QString failure) { - reject(); + reject(); } void ProgressDialog::onTaskSucceeded() { - accept(); + accept(); } void ProgressDialog::changeStatus(const QString &status) { - ui->statusLabel->setText(status); - updateSize(); + ui->statusLabel->setText(status); + updateSize(); } void ProgressDialog::changeProgress(qint64 current, qint64 total) { - ui->taskProgressBar->setMaximum(total); - ui->taskProgressBar->setValue(current); + ui->taskProgressBar->setMaximum(total); + ui->taskProgressBar->setValue(current); } void ProgressDialog::keyPressEvent(QKeyEvent *e) { - if(ui->skipButton->isVisible()) - { - if (e->key() == Qt::Key_Escape) - { - on_skipButton_clicked(true); - return; - } - else if(e->key() == Qt::Key_Tab) - { - ui->skipButton->setFocusPolicy(Qt::StrongFocus); - ui->skipButton->setFocus(); - ui->skipButton->setAutoDefault(true); - ui->skipButton->setDefault(true); - return; - } - } - QDialog::keyPressEvent(e); + if(ui->skipButton->isVisible()) + { + if (e->key() == Qt::Key_Escape) + { + on_skipButton_clicked(true); + return; + } + else if(e->key() == Qt::Key_Tab) + { + ui->skipButton->setFocusPolicy(Qt::StrongFocus); + ui->skipButton->setFocus(); + ui->skipButton->setAutoDefault(true); + ui->skipButton->setDefault(true); + return; + } + } + QDialog::keyPressEvent(e); } void ProgressDialog::closeEvent(QCloseEvent *e) { - if (task && task->isRunning()) - { - e->ignore(); - } - else - { - QDialog::closeEvent(e); - } + if (task && task->isRunning()) + { + e->ignore(); + } + else + { + QDialog::closeEvent(e); + } } diff --git a/application/dialogs/ProgressDialog.h b/application/dialogs/ProgressDialog.h index f27b71e1..a3779e3f 100644 --- a/application/dialogs/ProgressDialog.h +++ b/application/dialogs/ProgressDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,45 +27,45 @@ class ProgressDialog; class ProgressDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit ProgressDialog(QWidget *parent = 0); - ~ProgressDialog(); + explicit ProgressDialog(QWidget *parent = 0); + ~ProgressDialog(); - void updateSize(); + void updateSize(); - int execWithTask(Task *task); - int execWithTask(std::unique_ptr &&task); - int execWithTask(std::unique_ptr &task); + int execWithTask(Task *task); + int execWithTask(std::unique_ptr &&task); + int execWithTask(std::unique_ptr &task); - void setSkipButton(bool present, QString label = QString()); + void setSkipButton(bool present, QString label = QString()); - Task *getTask(); + Task *getTask(); public slots: - void onTaskStarted(); - void onTaskFailed(QString failure); - void onTaskSucceeded(); + void onTaskStarted(); + void onTaskFailed(QString failure); + void onTaskSucceeded(); - void changeStatus(const QString &status); - void changeProgress(qint64 current, qint64 total); + void changeStatus(const QString &status); + void changeProgress(qint64 current, qint64 total); private slots: - void on_skipButton_clicked(bool checked); + void on_skipButton_clicked(bool checked); protected: - virtual void keyPressEvent(QKeyEvent *e); - virtual void closeEvent(QCloseEvent *e); + virtual void keyPressEvent(QKeyEvent *e); + virtual void closeEvent(QCloseEvent *e); private: - bool handleImmediateResult(QDialog::DialogCode &result); + bool handleImmediateResult(QDialog::DialogCode &result); private: - Ui::ProgressDialog *ui; + Ui::ProgressDialog *ui; - Task *task; + Task *task; }; diff --git a/application/dialogs/SkinUploadDialog.cpp b/application/dialogs/SkinUploadDialog.cpp index 93414c6e..7d2ff829 100644 --- a/application/dialogs/SkinUploadDialog.cpp +++ b/application/dialogs/SkinUploadDialog.cpp @@ -9,106 +9,106 @@ void SkinUploadDialog::on_buttonBox_rejected() { - close(); + close(); } void SkinUploadDialog::on_buttonBox_accepted() { - AuthSessionPtr session = std::make_shared(); - auto login = m_acct->login(session); - ProgressDialog prog(this); - if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted) - { - //FIXME: recover with password prompt - CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to login!"), QMessageBox::Warning)->exec(); - close(); - return; - } - QString fileName; - QString input = ui->skinPathTextBox->text(); - QRegExp urlPrefixMatcher("^([a-z]+)://.+$"); - bool isLocalFile = false; - // it has an URL prefix -> it is an URL - if(urlPrefixMatcher.exactMatch(input)) - { - QUrl fileURL = input; - if(fileURL.isValid()) - { - // local? - if(fileURL.isLocalFile()) - { - isLocalFile = true; - fileName = fileURL.toLocalFile(); - } - else - { - CustomMessageBox::selectable( - this, - tr("Skin Upload"), - tr("Using remote URLs for setting skins is not implemented yet."), - QMessageBox::Warning - )->exec(); - close(); - return; - } - } - else - { - CustomMessageBox::selectable( - this, - tr("Skin Upload"), - tr("You cannot use an invalid URL for uploading skins."), - QMessageBox::Warning - )->exec(); - close(); - return; - } - } - else - { - // just assume it's a path then - isLocalFile = true; - fileName = ui->skinPathTextBox->text(); - } - if (isLocalFile && !QFile::exists(fileName)) - { - CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec(); - close(); - return; - } - SkinUpload::Model model = SkinUpload::STEVE; - if (ui->steveBtn->isChecked()) - { - model = SkinUpload::STEVE; - } - else if (ui->alexBtn->isChecked()) - { - model = SkinUpload::ALEX; - } - SkinUploadPtr upload = std::make_shared(this, session, FS::read(fileName), model); - if (prog.execWithTask((Task*)upload.get()) != QDialog::Accepted) - { - CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec(); - close(); - return; - } - CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Success"), QMessageBox::Information)->exec(); - close(); + AuthSessionPtr session = std::make_shared(); + auto login = m_acct->login(session); + ProgressDialog prog(this); + if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted) + { + //FIXME: recover with password prompt + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to login!"), QMessageBox::Warning)->exec(); + close(); + return; + } + QString fileName; + QString input = ui->skinPathTextBox->text(); + QRegExp urlPrefixMatcher("^([a-z]+)://.+$"); + bool isLocalFile = false; + // it has an URL prefix -> it is an URL + if(urlPrefixMatcher.exactMatch(input)) + { + QUrl fileURL = input; + if(fileURL.isValid()) + { + // local? + if(fileURL.isLocalFile()) + { + isLocalFile = true; + fileName = fileURL.toLocalFile(); + } + else + { + CustomMessageBox::selectable( + this, + tr("Skin Upload"), + tr("Using remote URLs for setting skins is not implemented yet."), + QMessageBox::Warning + )->exec(); + close(); + return; + } + } + else + { + CustomMessageBox::selectable( + this, + tr("Skin Upload"), + tr("You cannot use an invalid URL for uploading skins."), + QMessageBox::Warning + )->exec(); + close(); + return; + } + } + else + { + // just assume it's a path then + isLocalFile = true; + fileName = ui->skinPathTextBox->text(); + } + if (isLocalFile && !QFile::exists(fileName)) + { + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec(); + close(); + return; + } + SkinUpload::Model model = SkinUpload::STEVE; + if (ui->steveBtn->isChecked()) + { + model = SkinUpload::STEVE; + } + else if (ui->alexBtn->isChecked()) + { + model = SkinUpload::ALEX; + } + SkinUploadPtr upload = std::make_shared(this, session, FS::read(fileName), model); + if (prog.execWithTask((Task*)upload.get()) != QDialog::Accepted) + { + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec(); + close(); + return; + } + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Success"), QMessageBox::Information)->exec(); + close(); } void SkinUploadDialog::on_skinBrowseBtn_clicked() { - QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png"); - if (raw_path.isEmpty() || !QFileInfo::exists(raw_path)) - { - return; - } - QString cooked_path = FS::NormalizePath(raw_path); - ui->skinPathTextBox->setText(cooked_path); + QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png"); + if (raw_path.isEmpty() || !QFileInfo::exists(raw_path)) + { + return; + } + QString cooked_path = FS::NormalizePath(raw_path); + ui->skinPathTextBox->setText(cooked_path); } SkinUploadDialog::SkinUploadDialog(MojangAccountPtr acct, QWidget *parent) - :QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog) + :QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog) { - ui->setupUi(this); + ui->setupUi(this); } diff --git a/application/dialogs/SkinUploadDialog.h b/application/dialogs/SkinUploadDialog.h index 514eabc8..deb44eac 100644 --- a/application/dialogs/SkinUploadDialog.h +++ b/application/dialogs/SkinUploadDialog.h @@ -5,25 +5,25 @@ namespace Ui { - class SkinUploadDialog; + class SkinUploadDialog; } class SkinUploadDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit SkinUploadDialog(MojangAccountPtr acct, QWidget *parent = 0); - virtual ~SkinUploadDialog() {}; + explicit SkinUploadDialog(MojangAccountPtr acct, QWidget *parent = 0); + virtual ~SkinUploadDialog() {}; public slots: - void on_buttonBox_accepted(); + void on_buttonBox_accepted(); - void on_buttonBox_rejected(); + void on_buttonBox_rejected(); - void on_skinBrowseBtn_clicked(); + void on_skinBrowseBtn_clicked(); protected: - MojangAccountPtr m_acct; + MojangAccountPtr m_acct; private: - Ui::SkinUploadDialog *ui; + Ui::SkinUploadDialog *ui; }; diff --git a/application/dialogs/UpdateDialog.cpp b/application/dialogs/UpdateDialog.cpp index 30c7173d..242a5b70 100644 --- a/application/dialogs/UpdateDialog.cpp +++ b/application/dialogs/UpdateDialog.cpp @@ -10,20 +10,20 @@ UpdateDialog::UpdateDialog(bool hasUpdate, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog) { - ui->setupUi(this); - auto channel = MMC->settings()->get("UpdateChannel").toString(); - if(hasUpdate) - { - ui->label->setText(tr("A new %1 update is available!").arg(channel)); - } - else - { - ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel)); - ui->btnUpdateNow->setHidden(true); - ui->btnUpdateLater->setText(tr("Close")); - } - loadChangelog(); - restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("UpdateDialogGeometry").toByteArray())); + ui->setupUi(this); + auto channel = MMC->settings()->get("UpdateChannel").toString(); + if(hasUpdate) + { + ui->label->setText(tr("A new %1 update is available!").arg(channel)); + } + else + { + ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel)); + ui->btnUpdateNow->setHidden(true); + ui->btnUpdateLater->setText(tr("Close")); + } + loadChangelog(); + restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("UpdateDialogGeometry").toByteArray())); } UpdateDialog::~UpdateDialog() @@ -32,150 +32,150 @@ UpdateDialog::~UpdateDialog() void UpdateDialog::loadChangelog() { - auto channel = MMC->settings()->get("UpdateChannel").toString(); - dljob.reset(new NetJob("Changelog")); - QString url; - if(channel == "stable") - { - url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel); - m_changelogType = CHANGELOG_MARKDOWN; - } - else - { - url = QString("https://api.github.com/repos/MultiMC/MultiMC5/compare/%1...%2").arg(BuildConfig.GIT_COMMIT, channel); - m_changelogType = CHANGELOG_COMMITS; - } - dljob->addNetAction(Net::Download::makeByteArray(QUrl(url), &changelogData)); - connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded); - connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed); - dljob->start(); + auto channel = MMC->settings()->get("UpdateChannel").toString(); + dljob.reset(new NetJob("Changelog")); + QString url; + if(channel == "stable") + { + url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel); + m_changelogType = CHANGELOG_MARKDOWN; + } + else + { + url = QString("https://api.github.com/repos/MultiMC/MultiMC5/compare/%1...%2").arg(BuildConfig.GIT_COMMIT, channel); + m_changelogType = CHANGELOG_COMMITS; + } + dljob->addNetAction(Net::Download::makeByteArray(QUrl(url), &changelogData)); + connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded); + connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed); + dljob->start(); } QString reprocessMarkdown(QByteArray markdown) { - HoeDown hoedown; - QString output = hoedown.process(markdown); + HoeDown hoedown; + QString output = hoedown.process(markdown); - // HACK: easier than customizing hoedown - output.replace(QRegExp("GH-([0-9]+)"), "GH-\\1"); - qDebug() << output; - return output; + // HACK: easier than customizing hoedown + output.replace(QRegExp("GH-([0-9]+)"), "GH-\\1"); + qDebug() << output; + return output; } QString reprocessCommits(QByteArray json) { - auto channel = MMC->settings()->get("UpdateChannel").toString(); - try - { - QString result; - auto document = Json::requireDocument(json); - auto rootobject = Json::requireObject(document); - auto status = Json::requireString(rootobject, "status"); - auto diff_url = Json::requireString(rootobject, "html_url"); + auto channel = MMC->settings()->get("UpdateChannel").toString(); + try + { + QString result; + auto document = Json::requireDocument(json); + auto rootobject = Json::requireObject(document); + auto status = Json::requireString(rootobject, "status"); + auto diff_url = Json::requireString(rootobject, "html_url"); - auto print_commits = [&]() - { - result += ""; - auto commitarray = Json::requireArray(rootobject, "commits"); - for(int i = commitarray.size() - 1; i >= 0; i--) - { - const auto & commitval = commitarray[i]; - auto commitobj = Json::requireObject(commitval); - auto parents_info = Json::ensureArray(commitobj, "parents"); - // NOTE: this ignores merge commits, because they have more than one parent - if(parents_info.size() > 1) - { - continue; - } - auto commit_url = Json::requireString(commitobj, "html_url"); - auto commit_info = Json::requireObject(commitobj, "commit"); - auto commit_message = Json::requireString(commit_info, "message"); - auto lines = commit_message.split('\n'); - QRegularExpression regexp("(?(GH-(?[0-9]+))|(NOISSUE)|(SCRATCH))? *(?.*) *"); - auto match = regexp.match(lines.takeFirst(), 0, QRegularExpression::NormalMatch); - auto issuenr = match.captured("issuenr"); - auto prefix = match.captured("prefix"); - auto rest = match.captured("rest"); - result += ""; - lines.prepend(rest); - result += ""; - } - result += "
"; - if(issuenr.length()) - { - result += QString("GH-%2").arg(issuenr, issuenr); - } - else if(prefix.length()) - { - result += QString("%2").arg(commit_url, prefix); - } - else - { - result += QString("NOISSUE").arg(commit_url); - } - result += "

" + lines.join("
") + "

"; - }; + auto print_commits = [&]() + { + result += ""; + auto commitarray = Json::requireArray(rootobject, "commits"); + for(int i = commitarray.size() - 1; i >= 0; i--) + { + const auto & commitval = commitarray[i]; + auto commitobj = Json::requireObject(commitval); + auto parents_info = Json::ensureArray(commitobj, "parents"); + // NOTE: this ignores merge commits, because they have more than one parent + if(parents_info.size() > 1) + { + continue; + } + auto commit_url = Json::requireString(commitobj, "html_url"); + auto commit_info = Json::requireObject(commitobj, "commit"); + auto commit_message = Json::requireString(commit_info, "message"); + auto lines = commit_message.split('\n'); + QRegularExpression regexp("(?(GH-(?[0-9]+))|(NOISSUE)|(SCRATCH))? *(?.*) *"); + auto match = regexp.match(lines.takeFirst(), 0, QRegularExpression::NormalMatch); + auto issuenr = match.captured("issuenr"); + auto prefix = match.captured("prefix"); + auto rest = match.captured("rest"); + result += ""; + lines.prepend(rest); + result += ""; + } + result += "
"; + if(issuenr.length()) + { + result += QString("GH-%2").arg(issuenr, issuenr); + } + else if(prefix.length()) + { + result += QString("%2").arg(commit_url, prefix); + } + else + { + result += QString("NOISSUE").arg(commit_url); + } + result += "

" + lines.join("
") + "

"; + }; - if(status == "identical") - { - return QObject::tr("

There are no code changes between your current version and latest %1.

").arg(channel); - } - else if(status == "ahead") - { - result += QObject::tr("

Following commits were added since last update:

"); - print_commits(); - } - else if(status == "diverged") - { - auto commit_ahead = Json::requireInteger(rootobject, "ahead_by"); - auto commit_behind = Json::requireInteger(rootobject, "behind_by"); - result += QObject::tr("

The update removes %1 commits and adds the following %2:

").arg(commit_behind).arg(commit_ahead); - print_commits(); - } - result += QObject::tr("

You can look at the changes on github.

").arg(diff_url); - return result; - } - catch (JSONValidationError & e) - { - qWarning() << "Got an unparseable commit log from github:" << e.what(); - qDebug() << json; - } - return QString(); + if(status == "identical") + { + return QObject::tr("

There are no code changes between your current version and latest %1.

").arg(channel); + } + else if(status == "ahead") + { + result += QObject::tr("

Following commits were added since last update:

"); + print_commits(); + } + else if(status == "diverged") + { + auto commit_ahead = Json::requireInteger(rootobject, "ahead_by"); + auto commit_behind = Json::requireInteger(rootobject, "behind_by"); + result += QObject::tr("

The update removes %1 commits and adds the following %2:

").arg(commit_behind).arg(commit_ahead); + print_commits(); + } + result += QObject::tr("

You can look at the changes on github.

").arg(diff_url); + return result; + } + catch (const JSONValidationError &e) + { + qWarning() << "Got an unparseable commit log from github:" << e.what(); + qDebug() << json; + } + return QString(); } void UpdateDialog::changelogLoaded() { - QString result; - switch(m_changelogType) - { - case CHANGELOG_COMMITS: - result = reprocessCommits(changelogData); - break; - case CHANGELOG_MARKDOWN: - result = reprocessMarkdown(changelogData); - break; - } - changelogData.clear(); - ui->changelogBrowser->setHtml(result); + QString result; + switch(m_changelogType) + { + case CHANGELOG_COMMITS: + result = reprocessCommits(changelogData); + break; + case CHANGELOG_MARKDOWN: + result = reprocessMarkdown(changelogData); + break; + } + changelogData.clear(); + ui->changelogBrowser->setHtml(result); } void UpdateDialog::changelogFailed(QString reason) { - ui->changelogBrowser->setHtml(tr("

Failed to fetch changelog... Error: %1

").arg(reason)); + ui->changelogBrowser->setHtml(tr("

Failed to fetch changelog... Error: %1

").arg(reason)); } void UpdateDialog::on_btnUpdateLater_clicked() { - reject(); + reject(); } void UpdateDialog::on_btnUpdateNow_clicked() { - done(UPDATE_NOW); + done(UPDATE_NOW); } void UpdateDialog::closeEvent(QCloseEvent* evt) { - MMC->settings()->set("UpdateDialogGeometry", saveGeometry().toBase64()); - QDialog::closeEvent(evt); + MMC->settings()->set("UpdateDialogGeometry", saveGeometry().toBase64()); + QDialog::closeEvent(evt); } diff --git a/application/dialogs/UpdateDialog.h b/application/dialogs/UpdateDialog.h index 78960c99..6a871b1c 100644 --- a/application/dialogs/UpdateDialog.h +++ b/application/dialogs/UpdateDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,43 +25,43 @@ class UpdateDialog; enum UpdateAction { - UPDATE_LATER = QDialog::Rejected, - UPDATE_NOW = QDialog::Accepted, + UPDATE_LATER = QDialog::Rejected, + UPDATE_NOW = QDialog::Accepted, }; enum ChangelogType { - CHANGELOG_MARKDOWN, - CHANGELOG_COMMITS + CHANGELOG_MARKDOWN, + CHANGELOG_COMMITS }; class UpdateDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0); - ~UpdateDialog(); + explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0); + ~UpdateDialog(); public slots: - void on_btnUpdateNow_clicked(); - void on_btnUpdateLater_clicked(); + void on_btnUpdateNow_clicked(); + void on_btnUpdateLater_clicked(); - /// Starts loading the changelog - void loadChangelog(); + /// Starts loading the changelog + void loadChangelog(); - /// Slot for when the chengelog loads successfully. - void changelogLoaded(); + /// Slot for when the chengelog loads successfully. + void changelogLoaded(); - /// Slot for when the chengelog fails to load... - void changelogFailed(QString reason); + /// Slot for when the chengelog fails to load... + void changelogFailed(QString reason); protected: - void closeEvent(QCloseEvent * ) override; + void closeEvent(QCloseEvent * ) override; private: - Ui::UpdateDialog *ui; - QByteArray changelogData; - NetJobPtr dljob; - ChangelogType m_changelogType = CHANGELOG_MARKDOWN; + Ui::UpdateDialog *ui; + QByteArray changelogData; + NetJobPtr dljob; + ChangelogType m_changelogType = CHANGELOG_MARKDOWN; }; diff --git a/application/dialogs/VersionSelectDialog.cpp b/application/dialogs/VersionSelectDialog.cpp index c7009497..0b6ba87e 100644 --- a/application/dialogs/VersionSelectDialog.cpp +++ b/application/dialogs/VersionSelectDialog.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,109 +33,109 @@ #include VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) - : QDialog(parent) + : QDialog(parent) { - setObjectName(QStringLiteral("VersionSelectDialog")); - resize(400, 347); - m_verticalLayout = new QVBoxLayout(this); - m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + setObjectName(QStringLiteral("VersionSelectDialog")); + resize(400, 347); + m_verticalLayout = new QVBoxLayout(this); + m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(parent); - m_verticalLayout->addWidget(m_versionWidget); + m_versionWidget = new VersionSelectWidget(parent); + m_verticalLayout->addWidget(m_versionWidget); - m_horizontalLayout = new QHBoxLayout(); - m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + m_horizontalLayout = new QHBoxLayout(); + m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); - m_refreshButton = new QPushButton(this); - m_refreshButton->setObjectName(QStringLiteral("refreshButton")); - m_horizontalLayout->addWidget(m_refreshButton); + m_refreshButton = new QPushButton(this); + m_refreshButton->setObjectName(QStringLiteral("refreshButton")); + m_horizontalLayout->addWidget(m_refreshButton); - m_buttonBox = new QDialogButtonBox(this); - m_buttonBox->setObjectName(QStringLiteral("buttonBox")); - m_buttonBox->setOrientation(Qt::Horizontal); - m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - m_horizontalLayout->addWidget(m_buttonBox); + m_buttonBox = new QDialogButtonBox(this); + m_buttonBox->setObjectName(QStringLiteral("buttonBox")); + m_buttonBox->setOrientation(Qt::Horizontal); + m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + m_horizontalLayout->addWidget(m_buttonBox); - m_verticalLayout->addLayout(m_horizontalLayout); + m_verticalLayout->addLayout(m_horizontalLayout); - retranslate(); + retranslate(); - QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - QMetaObject::connectSlotsByName(this); - setWindowModality(Qt::WindowModal); - setWindowTitle(title); + QMetaObject::connectSlotsByName(this); + setWindowModality(Qt::WindowModal); + setWindowTitle(title); - m_vlist = vlist; + m_vlist = vlist; - if (!cancelable) - { - m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); - } + if (!cancelable) + { + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + } } void VersionSelectDialog::retranslate() { - // FIXME: overrides custom title given in constructor! - setWindowTitle(tr("Choose Version")); - m_refreshButton->setToolTip(tr("Reloads the version list.")); - m_refreshButton->setText(tr("&Refresh")); + // FIXME: overrides custom title given in constructor! + setWindowTitle(tr("Choose Version")); + m_refreshButton->setToolTip(tr("Reloads the version list.")); + m_refreshButton->setText(tr("&Refresh")); } void VersionSelectDialog::setCurrentVersion(const QString& version) { - m_currentVersion = version; - m_versionWidget->setCurrentVersion(version); + m_currentVersion = version; + m_versionWidget->setCurrentVersion(version); } void VersionSelectDialog::setEmptyString(QString emptyString) { - m_versionWidget->setEmptyString(emptyString); + m_versionWidget->setEmptyString(emptyString); } void VersionSelectDialog::setEmptyErrorString(QString emptyErrorString) { - m_versionWidget->setEmptyErrorString(emptyErrorString); + m_versionWidget->setEmptyErrorString(emptyErrorString); } void VersionSelectDialog::setResizeOn(int column) { - resizeOnColumn = column; + resizeOnColumn = column; } int VersionSelectDialog::exec() { - QDialog::open(); - m_versionWidget->initialize(m_vlist); - if(resizeOnColumn != -1) - { - m_versionWidget->setResizeOn(resizeOnColumn); - } - return QDialog::exec(); + QDialog::open(); + m_versionWidget->initialize(m_vlist); + if(resizeOnColumn != -1) + { + m_versionWidget->setResizeOn(resizeOnColumn); + } + return QDialog::exec(); } void VersionSelectDialog::selectRecommended() { - m_versionWidget->selectRecommended(); + m_versionWidget->selectRecommended(); } BaseVersionPtr VersionSelectDialog::selectedVersion() const { - return m_versionWidget->selectedVersion(); + return m_versionWidget->selectedVersion(); } void VersionSelectDialog::on_refreshButton_clicked() { - m_versionWidget->loadList(); + m_versionWidget->loadList(); } void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { - m_versionWidget->setExactFilter(role, filter); + m_versionWidget->setExactFilter(role, filter); } void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { - m_versionWidget->setFuzzyFilter(role, filter); + m_versionWidget->setFuzzyFilter(role, filter); } diff --git a/application/dialogs/VersionSelectDialog.h b/application/dialogs/VersionSelectDialog.h index 127a0ee9..14bc4d76 100644 --- a/application/dialogs/VersionSelectDialog.h +++ b/application/dialogs/VersionSelectDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,43 +36,43 @@ class VersionProxyModel; class VersionSelectDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true); - virtual ~VersionSelectDialog() {}; + explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true); + virtual ~VersionSelectDialog() {}; - int exec() override; + int exec() override; - BaseVersionPtr selectedVersion() const; + BaseVersionPtr selectedVersion() const; - void setCurrentVersion(const QString & version); - void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); - void setExactFilter(BaseVersionList::ModelRoles role, QString filter); - void setEmptyString(QString emptyString); - void setEmptyErrorString(QString emptyErrorString); - void setResizeOn(int column); + void setCurrentVersion(const QString & version); + void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactFilter(BaseVersionList::ModelRoles role, QString filter); + void setEmptyString(QString emptyString); + void setEmptyErrorString(QString emptyErrorString); + void setResizeOn(int column); private slots: - void on_refreshButton_clicked(); + void on_refreshButton_clicked(); private: - void retranslate(); - void selectRecommended(); + void retranslate(); + void selectRecommended(); private: - QString m_currentVersion; - VersionSelectWidget *m_versionWidget = nullptr; - QVBoxLayout *m_verticalLayout = nullptr; - QHBoxLayout *m_horizontalLayout = nullptr; - QPushButton *m_refreshButton = nullptr; - QDialogButtonBox *m_buttonBox = nullptr; + QString m_currentVersion; + VersionSelectWidget *m_versionWidget = nullptr; + QVBoxLayout *m_verticalLayout = nullptr; + QHBoxLayout *m_horizontalLayout = nullptr; + QPushButton *m_refreshButton = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; - BaseVersionList *m_vlist = nullptr; + BaseVersionList *m_vlist = nullptr; - VersionProxyModel *m_proxyModel = nullptr; + VersionProxyModel *m_proxyModel = nullptr; - int resizeOnColumn = -1; + int resizeOnColumn = -1; - Task * loadTask = nullptr; + Task * loadTask = nullptr; }; -- cgit v1.2.3