diff options
author | Petr Mrázek <peterix@gmail.com> | 2017-01-05 04:05:08 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2017-01-05 04:05:08 +0100 |
commit | e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa (patch) | |
tree | 2592a85455ff45925eaa19e8023061a5089be89a /application | |
parent | 4c0db2b99decf407b1f5cf0afc6f29db87ac03ca (diff) | |
download | MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.gz MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.lz MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.xz MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.zip |
NOISSUE feature complete setup wizard
Diffstat (limited to 'application')
-rw-r--r-- | application/CMakeLists.txt | 10 | ||||
-rw-r--r-- | application/dialogs/VersionSelectDialog.cpp | 168 | ||||
-rw-r--r-- | application/dialogs/VersionSelectDialog.h | 36 | ||||
-rw-r--r-- | application/dialogs/VersionSelectDialog.ui | 120 | ||||
-rw-r--r-- | application/setupwizard/AnalyticsWizardPage.cpp | 79 | ||||
-rw-r--r-- | application/setupwizard/AnalyticsWizardPage.h | 26 | ||||
-rw-r--r-- | application/setupwizard/BaseWizardPage.h | 33 | ||||
-rw-r--r-- | application/setupwizard/JavaWizardPage.cpp | 327 | ||||
-rw-r--r-- | application/setupwizard/JavaWizardPage.h | 79 | ||||
-rw-r--r-- | application/setupwizard/LanguageWizardPage.cpp | 74 | ||||
-rw-r--r-- | application/setupwizard/LanguageWizardPage.h | 33 | ||||
-rw-r--r-- | application/setupwizard/SetupWizard.cpp | 353 | ||||
-rw-r--r-- | application/setupwizard/SetupWizard.h | 7 | ||||
-rw-r--r-- | application/widgets/ProgressWidget.cpp | 18 | ||||
-rw-r--r-- | application/widgets/VersionSelectWidget.cpp | 181 | ||||
-rw-r--r-- | application/widgets/VersionSelectWidget.h | 76 |
16 files changed, 1069 insertions, 551 deletions
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index e51e6eb1..2814d6be 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -114,6 +114,13 @@ SET(MULTIMC_SOURCES # GUI - setup wizard setupwizard/SetupWizard.h setupwizard/SetupWizard.cpp + setupwizard/AnalyticsWizardPage.cpp + setupwizard/AnalyticsWizardPage.h + setupwizard/BaseWizardPage.h + setupwizard/JavaWizardPage.cpp + setupwizard/JavaWizardPage.h + setupwizard/LanguageWizardPage.cpp + setupwizard/LanguageWizardPage.h # GUI - themes themes/FusionTheme.cpp @@ -246,6 +253,8 @@ SET(MULTIMC_SOURCES widgets/ServerStatus.h widgets/VersionListView.cpp widgets/VersionListView.h + widgets/VersionSelectWidget.cpp + widgets/VersionSelectWidget.h widgets/ProgressWidget.h widgets/ProgressWidget.cpp @@ -289,7 +298,6 @@ SET(MULTIMC_UIS dialogs/CopyInstanceDialog.ui dialogs/NewInstanceDialog.ui dialogs/AboutDialog.ui - dialogs/VersionSelectDialog.ui dialogs/ProgressDialog.ui dialogs/IconPickerDialog.ui dialogs/ProfileSelectDialog.ui diff --git a/application/dialogs/VersionSelectDialog.cpp b/application/dialogs/VersionSelectDialog.cpp index 50b543db..8290d6d6 100644 --- a/application/dialogs/VersionSelectDialog.cpp +++ b/application/dialogs/VersionSelectDialog.cpp @@ -14,9 +14,12 @@ */ #include "VersionSelectDialog.h" -#include "ui_VersionSelectDialog.h" -#include <QHeaderView> +#include <QtWidgets/QButtonGroup> +#include <QtWidgets/QDialogButtonBox> +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QPushButton> +#include <QtWidgets/QVBoxLayout> #include <dialogs/ProgressDialog.h> #include "CustomMessageBox.h" @@ -27,165 +30,102 @@ #include <QDebug> #include "MultiMC.h" #include <VersionProxyModel.h> +#include <widgets/VersionSelectWidget.h> -VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, - bool cancelable) - : QDialog(parent), ui(new Ui::VersionSelectDialog) +VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) + : QDialog(parent) { - ui->setupUi(this); + setObjectName(QStringLiteral("VersionSelectDialog")); + resize(400, 347); + m_verticalLayout = new QVBoxLayout(this); + m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + + m_versionWidget = new VersionSelectWidget(vlist, parent); + m_verticalLayout->addWidget(m_versionWidget); + + 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_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); + + retranslate(); + + 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); m_vlist = vlist; - m_proxyModel = new VersionProxyModel(this); - m_proxyModel->setSourceModel(vlist); - - ui->listView->setModel(m_proxyModel); - ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); - ui->sneakyProgressBar->setHidden(true); - if (!cancelable) { - ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); } } -void VersionSelectDialog::setEmptyString(QString emptyString) +void VersionSelectDialog::retranslate() { - ui->listView->setEmptyString(emptyString); + // FIXME: overrides custom title given in constructor! + setWindowTitle(QApplication::translate("VersionSelectDialog", "Choose Version", Q_NULLPTR)); + m_refreshButton->setToolTip(QApplication::translate("VersionSelectDialog", "Reloads the version list.", Q_NULLPTR)); + m_refreshButton->setText(QApplication::translate("VersionSelectDialog", "&Refresh", Q_NULLPTR)); } -void VersionSelectDialog::setEmptyErrorString(QString emptyErrorString) +void VersionSelectDialog::setEmptyString(QString emptyString) { - ui->listView->setEmptyErrorString(emptyErrorString); + m_versionWidget->setEmptyString(emptyString); } -VersionSelectDialog::~VersionSelectDialog() +void VersionSelectDialog::setEmptyErrorString(QString emptyErrorString) { - delete ui; + m_versionWidget->setEmptyErrorString(emptyErrorString); } void VersionSelectDialog::setResizeOn(int column) { - ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents); - resizeOnColumn = column; - ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); + m_versionWidget->setResizeOn(column); } int VersionSelectDialog::exec() { QDialog::open(); - if (!m_vlist->isLoaded()) - { - loadList(); - } - else - { - if (m_proxyModel->rowCount() == 0) - { - ui->listView->setEmptyMode(VersionListView::String); - } - preselect(); - } + m_versionWidget->initialize(); return QDialog::exec(); } -void VersionSelectDialog::closeEvent(QCloseEvent * event) -{ - if(loadTask) - { - loadTask->abort(); - loadTask->deleteLater(); - loadTask = nullptr; - } - QDialog::closeEvent(event); -} - -void VersionSelectDialog::loadList() -{ - if(loadTask) - { - return; - } - loadTask = m_vlist->getLoadTask(); - if (!loadTask) - { - return; - } - connect(loadTask, &Task::finished, this, &VersionSelectDialog::onTaskFinished); - connect(loadTask, &Task::progress, this, &VersionSelectDialog::changeProgress); - loadTask->start(); - ui->sneakyProgressBar->setHidden(false); -} - -void VersionSelectDialog::onTaskFinished() -{ - if (!loadTask->successful()) - { - CustomMessageBox::selectable(this, tr("Error"), - tr("List update failed:\n%1").arg(loadTask->failReason()), - QMessageBox::Warning)->show(); - if (m_proxyModel->rowCount() == 0) - { - ui->listView->setEmptyMode(VersionListView::ErrorString); - } - } - else if (m_proxyModel->rowCount() == 0) - { - ui->listView->setEmptyMode(VersionListView::String); - } - ui->sneakyProgressBar->setHidden(true); - loadTask->deleteLater(); - loadTask = nullptr; - preselect(); -} - -void VersionSelectDialog::changeProgress(qint64 current, qint64 total) -{ - ui->sneakyProgressBar->setMaximum(total); - ui->sneakyProgressBar->setValue(current); -} - -void VersionSelectDialog::preselect() -{ - if(preselectedAlready) - return; - preselectedAlready = true; - selectRecommended(); -} - void VersionSelectDialog::selectRecommended() { - auto idx = m_proxyModel->getRecommended(); - if(idx.isValid()) - { - ui->listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); - ui->listView->scrollTo(idx, QAbstractItemView::PositionAtCenter); - } + m_versionWidget->selectRecommended(); } BaseVersionPtr VersionSelectDialog::selectedVersion() const { - auto currentIndex = ui->listView->selectionModel()->currentIndex(); - auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole); - return variant.value<BaseVersionPtr>(); + return m_versionWidget->selectedVersion(); } void VersionSelectDialog::on_refreshButton_clicked() { - loadList(); + m_versionWidget->loadList(); } void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, filter, true); + m_versionWidget->setExactFilter(role, filter); } void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, filter, false); + m_versionWidget->setFuzzyFilter(role, filter); } - -#include "VersionSelectDialog.moc" diff --git a/application/dialogs/VersionSelectDialog.h b/application/dialogs/VersionSelectDialog.h index 6b83535e..8916ce59 100644 --- a/application/dialogs/VersionSelectDialog.h +++ b/application/dialogs/VersionSelectDialog.h @@ -18,8 +18,15 @@ #include <QDialog> #include <QSortFilterProxyModel> + #include "BaseVersionList.h" +class QVBoxLayout; +class QHBoxLayout; +class QDialogButtonBox; +class VersionSelectWidget; +class QPushButton; + namespace Ui { class VersionSelectDialog; @@ -32,14 +39,10 @@ class VersionSelectDialog : public QDialog Q_OBJECT public: - explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, - bool cancelable = true); - ~VersionSelectDialog(); - - virtual int exec(); + explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true); + virtual ~VersionSelectDialog() {}; - //! Starts a task that loads the list. - void loadList(); + int exec() override; BaseVersionPtr selectedVersion() const; @@ -50,22 +53,19 @@ public: void setResizeOn(int column); void setUseLatest(const bool useLatest); -protected: - virtual void closeEvent ( QCloseEvent* ); - -private -slots: +private slots: void on_refreshButton_clicked(); - void onTaskFinished(); - void changeProgress(qint64 current, qint64 total); - private: - void preselect(); + void retranslate(); void selectRecommended(); private: - Ui::VersionSelectDialog *ui = nullptr; + VersionSelectWidget *m_versionWidget = nullptr; + QVBoxLayout *m_verticalLayout = nullptr; + QHBoxLayout *m_horizontalLayout = nullptr; + QPushButton *m_refreshButton = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; BaseVersionList *m_vlist = nullptr; @@ -74,6 +74,4 @@ private: int resizeOnColumn = 0; Task * loadTask = nullptr; - - bool preselectedAlready = false; }; diff --git a/application/dialogs/VersionSelectDialog.ui b/application/dialogs/VersionSelectDialog.ui deleted file mode 100644 index 420e853d..00000000 --- a/application/dialogs/VersionSelectDialog.ui +++ /dev/null @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>VersionSelectDialog</class> - <widget class="QDialog" name="VersionSelectDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>347</height> - </rect> - </property> - <property name="windowTitle"> - <string>Choose Version</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="VersionListView" name="listView"> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <attribute name="headerCascadingSectionResizes"> - <bool>true</bool> - </attribute> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - </widget> - </item> - <item> - <widget class="QProgressBar" name="sneakyProgressBar"> - <property name="value"> - <number>24</number> - </property> - <property name="format"> - <string notr="true">%p%</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="refreshButton"> - <property name="toolTip"> - <string>Reloads the version list.</string> - </property> - <property name="text"> - <string>&Refresh</string> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>VersionListView</class> - <extends>QTreeView</extends> - <header>widgets/VersionListView.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>VersionSelectDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>257</x> - <y>290</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>VersionSelectDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>325</x> - <y>290</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/application/setupwizard/AnalyticsWizardPage.cpp b/application/setupwizard/AnalyticsWizardPage.cpp new file mode 100644 index 00000000..40fb0b88 --- /dev/null +++ b/application/setupwizard/AnalyticsWizardPage.cpp @@ -0,0 +1,79 @@ +#include "AnalyticsWizardPage.h" +#include <MultiMC.h> + +#include <QVBoxLayout> +#include <QTextBrowser> +#include <QCheckBox> + +#include <ganalytics.h> + +AnalyticsWizardPage::AnalyticsWizardPage(QWidget *parent) + : BaseWizardPage(parent) +{ + setObjectName(QStringLiteral("analyticsPage")); + verticalLayout_3 = new QVBoxLayout(this); + verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); + textBrowser = new QTextBrowser(this); + textBrowser->setObjectName(QStringLiteral("textBrowser")); + textBrowser->setAcceptRichText(false); + textBrowser->setOpenExternalLinks(true); + verticalLayout_3->addWidget(textBrowser); + + checkBox = new QCheckBox(this); + checkBox->setObjectName(QStringLiteral("checkBox")); + checkBox->setChecked(true); + verticalLayout_3->addWidget(checkBox); + retranslate(); +} + +AnalyticsWizardPage::~AnalyticsWizardPage() +{ +} + +bool AnalyticsWizardPage::validatePage() +{ + auto settings = MMC->settings(); + auto analytics = MMC->analytics(); + auto status = checkBox->isChecked(); + settings->set("AnalyticsSeen", analytics->version()); + settings->set("Analytics", status); + return true; +} + +bool AnalyticsWizardPage::isRequired() +{ + auto settings = MMC->settings(); + auto analytics = MMC->analytics(); + if (!settings->get("Analytics").toBool()) + { + return false; + } + if (settings->get("AnalyticsSeen").toInt() < analytics->version()) + { + return true; + } + return false; +} + +void AnalyticsWizardPage::retranslate() +{ + setTitle(QApplication::translate("AnalyticsWizardPage", "Analytics", Q_NULLPTR)); + setSubTitle(QApplication::translate("AnalyticsWizardPage", "We track some anonymous statistics about users.", Q_NULLPTR)); + textBrowser->setHtml(QApplication::translate( + "AnalyticsWizardPage", + "<html><body>" + "<p>MultiMC sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.</p>" + "<p>The data is processed by Google Analytics, see their <a href=\"https://support.google.com/analytics/answer/6004245?hl=en\">article on the " + "matter</a>.</p>" + "<p>The following data is collected:</p>" + "<ul><li>A random unique ID of the MultiMC installation.<br />It is stored in the application settings (multimc.cfg).</li>" + "<li>Anonymized (partial) IP address.</li>" + "<li>MultiMC version.</li>" + "<li>Operating system name, version and architecture.</li>" + "<li>CPU architecture (kernel architecture on linux).</li>" + "<li>Size of system memory.</li>" + "<li>Java version, architecture and memory settings.</li></ul>" + "<p>If we change the tracked information, you will see this page again.</p></body></html>", + Q_NULLPTR)); + checkBox->setText(QApplication::translate("AnalyticsWizardPage", "Enable Analytics", Q_NULLPTR)); +} diff --git a/application/setupwizard/AnalyticsWizardPage.h b/application/setupwizard/AnalyticsWizardPage.h new file mode 100644 index 00000000..88fbed01 --- /dev/null +++ b/application/setupwizard/AnalyticsWizardPage.h @@ -0,0 +1,26 @@ +#pragma once + +#include "BaseWizardPage.h" + +class QVBoxLayout; +class QTextBrowser; +class QCheckBox; + +class AnalyticsWizardPage : public BaseWizardPage +{ + Q_OBJECT; +public: + explicit AnalyticsWizardPage(QWidget *parent = Q_NULLPTR); + virtual ~AnalyticsWizardPage(); + + bool validatePage() override; + static bool isRequired(); + +protected: + void retranslate() override; + +private: + QVBoxLayout *verticalLayout_3 = nullptr; + QTextBrowser *textBrowser = nullptr; + QCheckBox *checkBox = nullptr; +};
\ No newline at end of file diff --git a/application/setupwizard/BaseWizardPage.h b/application/setupwizard/BaseWizardPage.h new file mode 100644 index 00000000..9ad54e09 --- /dev/null +++ b/application/setupwizard/BaseWizardPage.h @@ -0,0 +1,33 @@ +#pragma once + +#include <QWizardPage> +#include <QEvent> + +class BaseWizardPage : public QWizardPage +{ +public: + explicit BaseWizardPage(QWidget *parent = Q_NULLPTR) + : QWizardPage(parent) + { + } + virtual ~BaseWizardPage() {}; + + virtual bool wantsRefreshButton() + { + return false; + } + virtual void refresh() + { + } + +protected: + virtual void retranslate() = 0; + void changeEvent(QEvent * event) override + { + if (event->type() == QEvent::LanguageChange) + { + retranslate(); + } + QWizardPage::changeEvent(event); + } +}; diff --git a/application/setupwizard/JavaWizardPage.cpp b/application/setupwizard/JavaWizardPage.cpp new file mode 100644 index 00000000..31b8ff71 --- /dev/null +++ b/application/setupwizard/JavaWizardPage.cpp @@ -0,0 +1,327 @@ +#include "JavaWizardPage.h" +#include <MultiMC.h> + +#include <QVBoxLayout> +#include <QGroupBox> +#include <QSpinBox> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <widgets/VersionSelectWidget.h> +#include <widgets/IconLabel.h> +#include <FileSystem.h> + +#include <java/JavaInstall.h> +#include <dialogs/CustomMessageBox.h> +#include <java/JavaUtils.h> +#include <sys.h> +#include <QFileDialog> + + +JavaWizardPage::JavaWizardPage(QWidget *parent) + :BaseWizardPage(parent) +{ + m_availableMemory = Sys::getSystemRam() / (1024ull * 1024ull); + + goodIcon = MMC->getThemedIcon("status-good"); + yellowIcon = MMC->getThemedIcon("status-yellow"); + badIcon = MMC->getThemedIcon("status-bad"); + setupUi(); + + connect(m_minMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int))); + connect(m_maxMemSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int))); + connect(m_permGenSpinBox, SIGNAL(valueChanged(int)), this, SLOT(memoryValueChanged(int))); + connect(m_versionWidget, &VersionSelectWidget::selectedVersionChanged, this, &JavaWizardPage::javaVersionSelected); + connect(m_javaBrowseBtn, &QPushButton::clicked, this, &JavaWizardPage::on_javaBrowseBtn_clicked); + connect(m_javaPathTextBox, &QLineEdit::textEdited, this, &JavaWizardPage::checkJavaPath); +} + +void JavaWizardPage::setupUi() +{ + setObjectName(QStringLiteral("javaPage")); + m_verticalLayout = new QVBoxLayout(this); + m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + + m_versionWidget = new VersionSelectWidget(MMC->javalist().get(), this); + m_versionWidget->setResizeOn(2); + m_verticalLayout->addWidget(m_versionWidget); + + m_horizontalLayout = new QHBoxLayout(); + m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + m_javaPathTextBox = new QLineEdit(this); + m_javaPathTextBox->setObjectName(QStringLiteral("javaPathTextBox")); + + m_horizontalLayout->addWidget(m_javaPathTextBox); + + m_javaBrowseBtn = new QPushButton(this); + m_javaBrowseBtn->setObjectName(QStringLiteral("javaBrowseBtn")); + /* + QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(m_javaBrowseBtn->sizePolicy().hasHeightForWidth()); + m_javaBrowseBtn->setSizePolicy(sizePolicy2); + m_javaBrowseBtn->setMaximumSize(QSize(28, 16777215)); + */ + m_javaBrowseBtn->setText(QStringLiteral("...")); + m_horizontalLayout->addWidget(m_javaBrowseBtn); + + m_javaStatusLabel = new IconLabel(this, badIcon, QSize(16, 16)); + m_horizontalLayout->addWidget(m_javaStatusLabel); + + m_verticalLayout->addLayout(m_horizontalLayout); + + m_memoryGroupBox = new QGroupBox(this); + m_memoryGroupBox->setObjectName(QStringLiteral("memoryGroupBox")); + m_gridLayout_2 = new QGridLayout(m_memoryGroupBox); + m_gridLayout_2->setObjectName(QStringLiteral("gridLayout_2")); + + m_labelMinMem = new QLabel(m_memoryGroupBox); + m_labelMinMem->setObjectName(QStringLiteral("labelMinMem")); + m_gridLayout_2->addWidget(m_labelMinMem, 0, 0, 1, 1); + + m_minMemSpinBox = new QSpinBox(m_memoryGroupBox); + m_minMemSpinBox->setObjectName(QStringLiteral("minMemSpinBox")); + m_minMemSpinBox->setSuffix(QStringLiteral(" MB")); + m_minMemSpinBox->setMinimum(256); + m_minMemSpinBox->setMaximum(m_availableMemory); + m_minMemSpinBox->setSingleStep(128); + m_minMemSpinBox->setValue(256); + m_gridLayout_2->addWidget(m_minMemSpinBox, 0, 1, 1, 1); + + m_labelMaxMem = new QLabel(m_memoryGroupBox); + m_labelMaxMem->setObjectName(QStringLiteral("labelMaxMem")); + m_gridLayout_2->addWidget(m_labelMaxMem, 1, 0, 1, 1); + + m_maxMemSpinBox = new QSpinBox(m_memoryGroupBox); + m_maxMemSpinBox->setObjectName(QStringLiteral("maxMemSpinBox")); + m_maxMemSpinBox->setSuffix(QStringLiteral(" MB")); + m_maxMemSpinBox->setMinimum(512); + m_maxMemSpinBox->setMaximum(m_availableMemory); + m_maxMemSpinBox->setSingleStep(128); + m_maxMemSpinBox->setValue(1024); + m_gridLayout_2->addWidget(m_maxMemSpinBox, 1, 1, 1, 1); + + m_labelPermGen = new QLabel(m_memoryGroupBox); + m_labelPermGen->setObjectName(QStringLiteral("labelPermGen")); + m_labelPermGen->setText(QStringLiteral("PermGen:")); + m_gridLayout_2->addWidget(m_labelPermGen, 2, 0, 1, 1); + m_labelPermGen->setVisible(false); + + m_permGenSpinBox = new QSpinBox(m_memoryGroupBox); + m_permGenSpinBox->setObjectName(QStringLiteral("permGenSpinBox")); + m_permGenSpinBox->setSuffix(QStringLiteral(" MB")); + m_permGenSpinBox->setMinimum(64); + m_permGenSpinBox->setMaximum(m_availableMemory); + m_permGenSpinBox->setSingleStep(8); + m_permGenSpinBox->setValue(128); + m_gridLayout_2->addWidget(m_permGenSpinBox, 2, 1, 1, 1); + m_permGenSpinBox->setVisible(false); + + m_verticalLayout->addWidget(m_memoryGroupBox); + + retranslate(); +} + +void JavaWizardPage::refresh() +{ + m_versionWidget->loadList(); +} + +void JavaWizardPage::initializePage() +{ + m_versionWidget->initialize(); + auto s = MMC->settings(); + // Memory + m_minMemSpinBox->setValue(s->get("MinMemAlloc").toInt()); + m_maxMemSpinBox->setValue(s->get("MaxMemAlloc").toInt()); + m_permGenSpinBox->setValue(s->get("PermGen").toInt()); +} + +bool JavaWizardPage::validatePage() +{ + auto settings = MMC->settings(); + auto path = m_javaPathTextBox->text(); + switch(javaStatus) + { + case JavaStatus::Bad: + { + int button = CustomMessageBox::selectable( + this, + tr("No Java version selected"), + tr("You didn't select a Java version or selected something that doesn't work.\n" + "MultiMC will not be able to start Minecraft.\n" + "Do you wish to proceed without any Java?" + "\n\n" + "You can change the Java version in the settings later.\n" + ), + QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::NoButton + )->exec(); + if(button == QMessageBox::No) + { + return false; + } + } + break; + case JavaStatus::Pending: + { + return false; + } + case JavaStatus::Good: + { + settings->set("JavaPath", path); + } + } + + // Memory + auto s = MMC->settings(); + s->set("MinMemAlloc", m_minMemSpinBox->value()); + s->set("MaxMemAlloc", m_maxMemSpinBox->value()); + if (m_permGenSpinBox->isVisible()) + { + s->set("PermGen", m_permGenSpinBox->value()); + } + else + { + s->reset("PermGen"); + } + return true; +} + +bool JavaWizardPage::isRequired() +{ + QString currentHostName = QHostInfo::localHostName(); + QString oldHostName = MMC->settings()->get("LastHostname").toString(); + if (currentHostName != oldHostName) + { + MMC->settings()->set("LastHostname", currentHostName); + return true; + } + QString currentJavaPath = MMC->settings()->get("JavaPath").toString(); + QString actualPath = FS::ResolveExecutable(currentJavaPath); + if (actualPath.isNull()) + { + return true; + } + return false; +} + +bool JavaWizardPage::wantsRefreshButton() +{ + return true; +} + +void JavaWizardPage::memoryValueChanged(int) +{ + int min = m_minMemSpinBox->value(); + int max = m_maxMemSpinBox->value(); + QObject *obj = sender(); + if (obj == m_minMemSpinBox) + { + if (min > max) + { + m_maxMemSpinBox->setValue(min); + } + } + else if (obj == m_maxMemSpinBox) + { + if (min > max) + { + m_minMemSpinBox->setValue(max); + } + } + checkJavaPath(m_javaPathTextBox->text()); +} + +void JavaWizardPage::javaVersionSelected(BaseVersionPtr version) +{ + auto java = std::dynamic_pointer_cast<JavaInstall>(version); + if(!java) + { + return; + } + auto visible = java->id.requiresPermGen(); + m_labelPermGen->setVisible(visible); + m_permGenSpinBox->setVisible(visible); + m_javaPathTextBox->setText(java->path); + checkJavaPath(java->path); +} + +void JavaWizardPage::on_javaBrowseBtn_clicked() +{ + QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable")); + if(raw_path.isNull()) + { + return; + } + QString cooked_path = FS::NormalizePath(raw_path); + m_javaPathTextBox->setText(cooked_path); + checkJavaPath(cooked_path); +} + +void JavaWizardPage::setJavaStatus(JavaWizardPage::JavaStatus status) +{ + javaStatus = status; + switch(javaStatus) + { + case JavaStatus::Good: + m_javaStatusLabel->setIcon(goodIcon); + break; + case JavaStatus::Pending: + m_javaStatusLabel->setIcon(yellowIcon); + break; + default: + case JavaStatus::Bad: + m_javaStatusLabel->setIcon(badIcon); + break; + } +} + +void JavaWizardPage::checkJavaPath(const QString &path) +{ + auto realPath = FS::ResolveExecutable(path); + if(realPath.isNull()) + { + setJavaStatus(JavaStatus::Bad); + return; + } + setJavaStatus(JavaStatus::Pending); + m_checker.reset(new JavaChecker()); + m_checker->m_path = path; + m_checker->m_minMem = m_minMemSpinBox->value(); + m_checker->m_maxMem = m_maxMemSpinBox->value(); + if(m_permGenSpinBox->isVisible()) + { + m_checker->m_permGen = m_permGenSpinBox->value(); + } + connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaWizardPage::checkFinished); + m_checker->performCheck(); +} + +void JavaWizardPage::checkFinished(JavaCheckResult result) +{ + if(result.valid) + { + setJavaStatus(JavaStatus::Good); + } + else + { + setJavaStatus(JavaStatus::Bad); + } + m_checker.reset(); +} + +void JavaWizardPage::retranslate() +{ + setTitle(QApplication::translate("JavaWizardPage", "Java", Q_NULLPTR)); + setSubTitle(QApplication::translate("JavaWizardPage", "You do not have a working Java set up yet or it went missing.\n" + "Please select one of the following or browse for a java executable.", Q_NULLPTR)); + m_memoryGroupBox->setTitle(QApplication::translate("JavaPage", "Memory", Q_NULLPTR)); + m_maxMemSpinBox->setToolTip(QApplication::translate("JavaPage", "The maximum amount of memory Minecraft is allowed to use.", Q_NULLPTR)); + m_labelMinMem->setText(QApplication::translate("JavaPage", "Minimum memory allocation:", Q_NULLPTR)); + m_labelMaxMem->setText(QApplication::translate("JavaPage", "Maximum memory allocation:", Q_NULLPTR)); + m_minMemSpinBox->setToolTip(QApplication::translate("JavaPage", "The amount of memory Minecraft is started with.", Q_NULLPTR)); + m_permGenSpinBox->setToolTip(QApplication::translate("JavaPage", "The amount of memory available to store loaded Java classes.", Q_NULLPTR)); +} diff --git a/application/setupwizard/JavaWizardPage.h b/application/setupwizard/JavaWizardPage.h new file mode 100644 index 00000000..5a61ff02 --- /dev/null +++ b/application/setupwizard/JavaWizardPage.h @@ -0,0 +1,79 @@ +#pragma once + +#include "BaseWizardPage.h" +#include <BaseVersion.h> +#include <QObjectPtr.h> +#include <java/JavaChecker.h> +#include <QIcon> + +class QLineEdit; +class VersionSelectWidget; +class QSpinBox; +class QPushButton; +class QVBoxLayout; +class QHBoxLayout; +class QGroupBox; +class QGridLayout; +class QLabel; +class IconLabel; + +class JavaWizardPage : public BaseWizardPage +{ + Q_OBJECT; +public: + explicit JavaWizardPage(QWidget *parent = Q_NULLPTR); + + virtual ~JavaWizardPage() + { + }; + + bool wantsRefreshButton() override; + void refresh() override; + void initializePage() override; + bool validatePage() override; + static bool isRequired(); + + enum class JavaStatus + { + Pending, + Good, + Bad + } javaStatus; + +protected slots: + void memoryValueChanged(int); + void javaVersionSelected(BaseVersionPtr version); + void on_javaBrowseBtn_clicked(); + void checkFinished(JavaCheckResult result); + +protected: /* methods */ + void checkJavaPath(const QString &path); + void setJavaStatus(JavaStatus status); + void setupUi(); + void retranslate() override; + +private: /* data */ + VersionSelectWidget *m_versionWidget = nullptr; + QVBoxLayout *m_verticalLayout = nullptr; + + QLineEdit * m_javaPathTextBox = nullptr; + QPushButton * m_javaBrowseBtn = nullptr; + IconLabel * m_javaStatusLabel = nullptr; + QHBoxLayout *m_horizontalLayout = nullptr; + + QGroupBox *m_memoryGroupBox = nullptr; + QGridLayout *m_gridLayout_2 = nullptr; + QSpinBox *m_maxMemSpinBox = nullptr; + QLabel *m_labelMinMem = nullptr; + QLabel *m_labelMaxMem = nullptr; + QSpinBox *m_minMemSpinBox = nullptr; + QLabel *m_labelPermGen = nullptr; + QSpinBox *m_permGenSpinBox = nullptr; + QIcon goodIcon; + QIcon yellowIcon; + QIcon badIcon; + + uint64_t m_availableMemory = 0ull; + shared_qobject_ptr<JavaChecker> m_checker; +}; + diff --git a/application/setupwizard/LanguageWizardPage.cpp b/application/setupwizard/LanguageWizardPage.cpp new file mode 100644 index 00000000..cf427a0d --- /dev/null +++ b/application/setupwizard/LanguageWizardPage.cpp @@ -0,0 +1,74 @@ +#include "LanguageWizardPage.h" +#include <MultiMC.h> +#include <translations/TranslationsModel.h> + +#include <QVBoxLayout> +#include <QListView> + +LanguageWizardPage::LanguageWizardPage(QWidget *parent) + : BaseWizardPage(parent) +{ + setObjectName(QStringLiteral("languagePage")); + verticalLayout = new QVBoxLayout(this); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + languageView = new QListView(this); + languageView->setObjectName(QStringLiteral("languageView")); + verticalLayout->addWidget(languageView); + retranslate(); + + auto translations = MMC->translations(); + auto index = translations->selectedIndex(); + languageView->setModel(translations.get()); + languageView->setCurrentIndex(index); + connect(languageView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &LanguageWizardPage::languageRowChanged); +} + +LanguageWizardPage::~LanguageWizardPage() +{ +} + +bool LanguageWizardPage::wantsRefreshButton() +{ + return true; +} + +void LanguageWizardPage::refresh() +{ + auto translations = MMC->translations(); + translations->downloadIndex(); +} + +bool LanguageWizardPage::validatePage() +{ + auto settings = MMC->settings(); + auto translations = MMC->translations(); + QString key = translations->data(languageView->currentIndex(), Qt::UserRole).toString(); + settings->set("Language", key); + return true; +} + +bool LanguageWizardPage::isRequired() +{ + auto settings = MMC->settings(); + if (settings->get("Language").toString().isEmpty()) + return true; + return false; +} + +void LanguageWizardPage::retranslate() +{ + setTitle(QApplication::translate("LanguageWizardPage", "Language", Q_NULLPTR)); + setSubTitle(QApplication::translate("LanguageWizardPage", "Select the language to use in MultiMC", Q_NULLPTR)); +} + +void LanguageWizardPage::languageRowChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + if (current == previous) + { + return; + } + auto translations = MMC->translations(); + QString key = translations->data(current, Qt::UserRole).toString(); + translations->selectLanguage(key); + translations->updateLanguage(key); +} diff --git a/application/setupwizard/LanguageWizardPage.h b/application/setupwizard/LanguageWizardPage.h new file mode 100644 index 00000000..9c24b29d --- /dev/null +++ b/application/setupwizard/LanguageWizardPage.h @@ -0,0 +1,33 @@ +#pragma once + +#include "BaseWizardPage.h" + +class QVBoxLayout; +class QListView; + +class LanguageWizardPage : public BaseWizardPage +{ + Q_OBJECT; +public: + explicit LanguageWizardPage(QWidget *parent = Q_NULLPTR); + + virtual ~LanguageWizardPage(); + + bool wantsRefreshButton() override; + + void refresh() override; + + bool validatePage() override; + + static bool isRequired(); + +protected: + void retranslate() override; + +protected slots: + void languageRowChanged(const QModelIndex ¤t, const QModelIndex &previous); + +private: + QVBoxLayout *verticalLayout = nullptr; + QListView *languageView = nullptr; +}; diff --git a/application/setupwizard/SetupWizard.cpp b/application/setupwizard/SetupWizard.cpp index 18b8aff9..fc5b2555 100644 --- a/application/setupwizard/SetupWizard.cpp +++ b/application/setupwizard/SetupWizard.cpp @@ -1,336 +1,98 @@ #include "SetupWizard.h" + +#include "LanguageWizardPage.h" +#include "JavaWizardPage.h" +#include "AnalyticsWizardPage.h" + #include "translations/TranslationsModel.h" #include <MultiMC.h> #include <FileSystem.h> #include <ganalytics.h> +#include <QAbstractButton> + enum Page { Language, Java, Analytics, - // Themes, - // Accounts -}; - -#include <QtCore/QVariant> -#include <QtWidgets/QAction> -#include <QtWidgets/QApplication> -#include <QtWidgets/QButtonGroup> -#include <QtWidgets/QCheckBox> -#include <QtWidgets/QHeaderView> -#include <QtWidgets/QListView> -#include <QtWidgets/QTextBrowser> -#include <QtWidgets/QVBoxLayout> -#include <QtWidgets/QWizard> -#include <QtWidgets/QWizardPage> - -class BaseWizardPage : public QWizardPage -{ -public: - explicit BaseWizardPage(QWidget *parent = Q_NULLPTR) - : QWizardPage(parent) - { - } - virtual ~BaseWizardPage() {}; - -protected: - virtual void retranslate() = 0; - void changeEvent(QEvent * event) override - { - if (event->type() == QEvent::LanguageChange) - { - retranslate(); - } - QWizardPage::changeEvent(event); - } }; -class LanguageWizardPage : public BaseWizardPage +SetupWizard::SetupWizard(QWidget *parent) : QWizard(parent) { - Q_OBJECT; -public: - explicit LanguageWizardPage(QWidget *parent = Q_NULLPTR) - : BaseWizardPage(parent) - { - setObjectName(QStringLiteral("languagePage")); - verticalLayout = new QVBoxLayout(this); - verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - languageView = new QListView(this); - languageView->setObjectName(QStringLiteral("languageView")); - verticalLayout->addWidget(languageView); - retranslate(); - - auto translations = MMC->translations(); - auto index = translations->selectedIndex(); - languageView->setModel(translations.get()); - languageView->setCurrentIndex(index); - connect(languageView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &LanguageWizardPage::languageRowChanged); - } + setObjectName(QStringLiteral("SetupWizard")); + resize(615, 659); + // make it ugly everywhere to avoid variability in theming + setWizardStyle(QWizard::ClassicStyle); + setOptions(QWizard::NoCancelButton | QWizard::IndependentPages | QWizard::HaveCustomButton1); - virtual ~LanguageWizardPage() - { - }; + retranslate(); - bool validatePage() override - { - auto settings = MMC->settings(); - auto translations = MMC->translations(); - QString key = translations->data(languageView->currentIndex(), Qt::UserRole).toString(); - settings->set("Language", key); - return true; - } + connect(this, &QWizard::currentIdChanged, this, &SetupWizard::pageChanged); - static bool isRequired() + if (LanguageWizardPage::isRequired()) { - auto settings = MMC->settings(); - if (settings->get("Language").toString().isEmpty()) - return true; - return false; + setPage(Page::Language, new LanguageWizardPage(this)); } - -protected: - void retranslate() override + if (JavaWizardPage::isRequired()) { - setTitle(QApplication::translate("LanguageWizardPage", "Language", Q_NULLPTR)); - setSubTitle(QApplication::translate("LanguageWizardPage", "Select the language to use in MultiMC", Q_NULLPTR)); + setPage(Page::Java, new JavaWizardPage(this)); } - -protected slots: - void languageRowChanged(const QModelIndex ¤t, const QModelIndex &previous) + if(AnalyticsWizardPage::isRequired()) { - if (current == previous) - { - return; - } - auto translations = MMC->translations(); - QString key = translations->data(current, Qt::UserRole).toString(); - translations->selectLanguage(key); - translations->updateLanguage(key); + setPage(Page::Analytics, new AnalyticsWizardPage(this)); } +} -private: - QVBoxLayout *verticalLayout = nullptr; - QListView *languageView = nullptr; -}; - -#include <dialogs/VersionSelectDialog.h> -#include <java/JavaInstall.h> -#include <dialogs/CustomMessageBox.h> -#include <java/JavaUtils.h> - -class JavaWizardPage : public BaseWizardPage +void SetupWizard::retranslate() { - Q_OBJECT; -public: - explicit JavaWizardPage(QWidget *parent = Q_NULLPTR) - : BaseWizardPage(parent) - { - setObjectName(QStringLiteral("javaPage")); - // FIXME: this is dumb and ugly. - qDebug() << "Java path needs resetting, showing Java selection dialog..."; - JavaInstallPtr java; - - VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, false); - vselect.setResizeOn(2); - vselect.exec(); - - if (vselect.selectedVersion()) - { - java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion()); - } - else - { - CustomMessageBox::selectable(this, - tr("Invalid version selected"), - tr("You didn't select a valid Java version, so MultiMC will select the default. You can change this in the settings dialog."), - QMessageBox::Warning)->show(); - JavaUtils ju; - java = ju.GetDefaultJava(); - } - if (java) - { - MMC->settings()->set("JavaPath", java->path); - } - else - { - MMC->settings()->set("JavaPath", QString("java")); - } - retranslate(); - } - - virtual ~JavaWizardPage() - { - }; - - bool validatePage() override - { - auto settings = MMC->settings(); - /* - auto analytics = MMC->analytics(); - auto status = checkBox->isChecked(); - settings->set("AnalyticsSeen", analytics->version()); - settings->set("Analytics", status); - */ - return true; - } - - static bool isRequired() - { - QString currentHostName = QHostInfo::localHostName(); - QString oldHostName = MMC->settings()->get("LastHostname").toString(); - if (currentHostName != oldHostName) - { - MMC->settings()->set("LastHostname", currentHostName); - return true; - } - QString currentJavaPath = MMC->settings()->get("JavaPath").toString(); - QString actualPath = FS::ResolveExecutable(currentJavaPath); - if (actualPath.isNull()) - { - return true; - } - return false; - } - -protected: - void retranslate() override - { - setTitle(QApplication::translate("JavaWizardPage", "Java", Q_NULLPTR)); - setSubTitle(QApplication::translate("JavaWizardPage", "You need to set up Java to proceed.", Q_NULLPTR)); - /* - textBrowser->setHtml(QApplication::translate("JavaWizardPage", - "<html><body>" - "<p>MultiMC sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.</p>" - "<p>The data is processed by Google Analytics, see their <a href=\"https://support.google.com/analytics/answer/6004245?hl=en\">article on the matter</a>.</p>" - "<p>The following data is collected:</p>" - "<ul><li>A random unique ID of the MultiMC installation.<br />It is stored in the application settings (multimc.cfg).</li>" - "<li>Anonymized IP address.<br />Last octet is set to 0 by Google and not stored.</li>" - "<li>MultiMC version.</li>" - "<li>Operating system name, version and architecture.</li>" - "<li>CPU architecture (kernel architecture on linux).</li>" - "<li>Size of system memory.</li>" - "<li>Java version, architecture and memory settings.</li></ul>" - "<p>The analytics will activate on next start, unless you disable them in the settings.</p>" - "<p>If we change the tracked information, analytics won't be active for the first run and you will see this page again.</p></body></html>", Q_NULLPTR)); - checkBox->setText(QApplication::translate("JavaWizardPage", "Enable Analytics", Q_NULLPTR)); - */ - } -private: - /* - QVBoxLayout *verticalLayout_3 = nullptr; - QTextBrowser *textBrowser = nullptr; - QCheckBox *checkBox = nullptr; - */ -}; + setButtonText(QWizard::NextButton, tr("&Next >")); + setButtonText(QWizard::BackButton, tr("< &Back")); + setButtonText(QWizard::FinishButton, tr("&Finish")); + setButtonText(QWizard::CustomButton1, tr("&Refresh")); + setWindowTitle(QApplication::translate("SetupWizard", "MultiMC Quick Setup", Q_NULLPTR)); +} -class AnalyticsWizardPage : public BaseWizardPage +BaseWizardPage * SetupWizard::getBasePage(int id) { - Q_OBJECT; -public: - explicit AnalyticsWizardPage(QWidget *parent = Q_NULLPTR) - : BaseWizardPage(parent) - { - setObjectName(QStringLiteral("analyticsPage")); - verticalLayout_3 = new QVBoxLayout(this); - verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); - textBrowser = new QTextBrowser(this); - textBrowser->setObjectName(QStringLiteral("textBrowser")); - textBrowser->setAcceptRichText(false); - textBrowser->setOpenExternalLinks(true); - verticalLayout_3->addWidget(textBrowser); - - checkBox = new QCheckBox(this); - checkBox->setObjectName(QStringLiteral("checkBox")); - checkBox->setChecked(true); - verticalLayout_3->addWidget(checkBox); - retranslate(); - } - - virtual ~AnalyticsWizardPage() - { - }; - - bool validatePage() override - { - auto settings = MMC->settings(); - auto analytics = MMC->analytics(); - auto status = checkBox->isChecked(); - settings->set("AnalyticsSeen", analytics->version()); - settings->set("Analytics", status); - return true; - } - - static bool isRequired() - { - auto settings = MMC->settings(); - auto analytics = MMC->analytics(); - if(!settings->get("Analytics").toBool()) - { - return false; - } - if(settings->get("AnalyticsSeen").toInt() < analytics->version()) - { - return true; - } - return false; - } + if(id == -1) + return nullptr; + auto pagePtr = page(id); + if(!pagePtr) + return nullptr; + return dynamic_cast<BaseWizardPage *>(pagePtr); +} -protected: - void retranslate() override - { - setTitle(QApplication::translate("AnalyticsWizardPage", "Analytics", Q_NULLPTR)); - setSubTitle(QApplication::translate("AnalyticsWizardPage", "We track some anonymous statistics about users.", Q_NULLPTR)); - textBrowser->setHtml(QApplication::translate("AnalyticsWizardPage", - "<html><body>" - "<p>MultiMC sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.</p>" - "<p>The data is processed by Google Analytics, see their <a href=\"https://support.google.com/analytics/answer/6004245?hl=en\">article on the matter</a>.</p>" - "<p>The following data is collected:</p>" - "<ul><li>A random unique ID of the MultiMC installation.<br />It is stored in the application settings (multimc.cfg).</li>" - "<li>Anonymized IP address.<br />Last octet is set to 0 by Google and not stored.</li>" - "<li>MultiMC version.</li>" - "<li>Operating system name, version and architecture.</li>" - "<li>CPU architecture (kernel architecture on linux).</li>" - "<li>Size of system memory.</li>" - "<li>Java version, architecture and memory settings.</li></ul>" - "<p>The analytics will activate on next start, unless you disable them in the settings.</p>" - "<p>If we change the tracked information, analytics won't be active for the first run and you will see this page again.</p></body></html>", Q_NULLPTR)); - checkBox->setText(QApplication::translate("AnalyticsWizardPage", "Enable Analytics", Q_NULLPTR)); - } -private: - QVBoxLayout *verticalLayout_3 = nullptr; - QTextBrowser *textBrowser = nullptr; - QCheckBox *checkBox = nullptr; -}; +BaseWizardPage * SetupWizard::getCurrentBasePage() +{ + return getBasePage(currentId()); +} -SetupWizard::SetupWizard(QWidget *parent) : QWizard(parent) +void SetupWizard::pageChanged(int id) { - setObjectName(QStringLiteral("SetupWizard")); - resize(615, 659); - // make it ugly everywhere to avoid variability in theming - setWizardStyle(QWizard::ClassicStyle); - setOptions(QWizard::NoCancelButton | QWizard::IndependentPages); - if (LanguageWizardPage::isRequired()) + auto basePagePtr = getBasePage(id); + if(!basePagePtr) { - setPage(Page::Language, new LanguageWizardPage(this)); + return; } - if (JavaWizardPage::isRequired()) + if(basePagePtr->wantsRefreshButton()) { - setPage(Page::Java, new JavaWizardPage(this)); + setButtonLayout({QWizard::CustomButton1, QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton}); + auto customButton = button(QWizard::CustomButton1); + connect(customButton, &QAbstractButton::pressed, [&](){ + auto basePagePtr = getCurrentBasePage(); + if(basePagePtr) + { + basePagePtr->refresh(); + } + }); } - if(AnalyticsWizardPage::isRequired()) + else { - setPage(Page::Analytics, new AnalyticsWizardPage(this)); + setButtonLayout({QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton}); } } -void SetupWizard::retranslate() -{ - setButtonText(QWizard::NextButton, tr("Next >")); - setButtonText(QWizard::BackButton, tr("< Back")); - setButtonText(QWizard::FinishButton, tr("Finish")); - setWindowTitle(QApplication::translate("SetupWizard", "MultiMC Quick Setup", Q_NULLPTR)); -} void SetupWizard::changeEvent(QEvent *event) { @@ -356,4 +118,3 @@ bool SetupWizard::isRequired() return false; } -#include "SetupWizard.moc" diff --git a/application/setupwizard/SetupWizard.h b/application/setupwizard/SetupWizard.h index adf254c7..a1e757d8 100644 --- a/application/setupwizard/SetupWizard.h +++ b/application/setupwizard/SetupWizard.h @@ -22,6 +22,8 @@ namespace Ui class SetupWizard; } +class BaseWizardPage; + class SetupWizard : public QWizard { Q_OBJECT @@ -31,6 +33,11 @@ public: /* con/destructors */ virtual ~SetupWizard(); void changeEvent(QEvent * event) override; + BaseWizardPage *getBasePage(int id); + BaseWizardPage *getCurrentBasePage(); + +private slots: + void pageChanged(int id); public: /* methods */ static bool isRequired(); diff --git a/application/widgets/ProgressWidget.cpp b/application/widgets/ProgressWidget.cpp index 7b51eca0..8b670916 100644 --- a/application/widgets/ProgressWidget.cpp +++ b/application/widgets/ProgressWidget.cpp @@ -1,7 +1,23 @@ // Licensed under the Apache-2.0 license. See README.md for details. #include "ProgressWidget.h" - + /* + textBrowser->setHtml(QApplication::translate("JavaWizardPage", + "<html><body>" + "<p>MultiMC sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.</p>" + "<p>The data is processed by Google Analytics, see their <a href=\"https://support.google.com/analytics/answer/6004245?hl=en\">article on the matter</a>.</p>" + "<p>The following data is collected:</p>" + "<ul><li>A random unique ID of the MultiMC installation.<br />It is stored in the application settings (multimc.cfg).</li>" + "<li>Anonymized IP address.<br />Last octet is set to 0 by Google and not stored.</li>" + "<li>MultiMC version.</li>" + "<li>Operating system name, version and architecture.</li>" + "<li>CPU architecture (kernel architecture on linux).</li>" + "<li>Size of system memory.</li>" + "<li>Java version, architecture and memory settings.</li></ul>" + "<p>The analytics will activate on next start, unless you disable them in the settings.</p>" + "<p>If we change the tracked information, analytics won't be active for the first run and you will see this page again.</p></body></html>", Q_NULLPTR)); + checkBox->setText(QApplication::translate("JavaWizardPage", "Enable Analytics", Q_NULLPTR)); + */ #include <QProgressBar> #include <QLabel> #include <QVBoxLayout> diff --git a/application/widgets/VersionSelectWidget.cpp b/application/widgets/VersionSelectWidget.cpp new file mode 100644 index 00000000..18284a91 --- /dev/null +++ b/application/widgets/VersionSelectWidget.cpp @@ -0,0 +1,181 @@ +#include "VersionSelectWidget.h" +#include <QProgressBar> +#include <QVBoxLayout> +#include "VersionListView.h" +#include <QHeaderView> +#include <VersionProxyModel.h> +#include <dialogs/CustomMessageBox.h> + +VersionSelectWidget::VersionSelectWidget(BaseVersionList* vlist, QWidget* parent) + : QWidget(parent), m_vlist(vlist) +{ + setObjectName(QStringLiteral("VersionSelectWidget")); + verticalLayout = new QVBoxLayout(this); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + verticalLayout->setContentsMargins(0, 0, 0, 0); + + m_proxyModel = new VersionProxyModel(this); + m_proxyModel->setSourceModel(vlist); + + listView = new VersionListView(this); + listView->setObjectName(QStringLiteral("listView")); + listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView->setAlternatingRowColors(true); + listView->setRootIsDecorated(false); + listView->setItemsExpandable(false); + listView->setWordWrap(true); + listView->header()->setCascadingSectionResizes(true); + listView->header()->setStretchLastSection(false); + listView->setModel(m_proxyModel); + listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); + verticalLayout->addWidget(listView); + + sneakyProgressBar = new QProgressBar(this); + sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar")); + sneakyProgressBar->setFormat(QStringLiteral("%p%")); + verticalLayout->addWidget(sneakyProgressBar); + sneakyProgressBar->setHidden(true); + connect(listView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &VersionSelectWidget::currentRowChanged); + + QMetaObject::connectSlotsByName(this); +} + +void VersionSelectWidget::setEmptyString(QString emptyString) +{ + listView->setEmptyString(emptyString); +} + +void VersionSelectWidget::setEmptyErrorString(QString emptyErrorString) +{ + listView->setEmptyErrorString(emptyErrorString); +} + +VersionSelectWidget::~VersionSelectWidget() +{ +} + +void VersionSelectWidget::setResizeOn(int column) +{ + listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents); + resizeOnColumn = column; + listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); +} + +void VersionSelectWidget::initialize() +{ + if (!m_vlist->isLoaded()) + { + loadList(); + } + else + { + if (m_proxyModel->rowCount() == 0) + { + listView->setEmptyMode(VersionListView::String); + } + preselect(); + } +} + +void VersionSelectWidget::closeEvent(QCloseEvent * event) +{ + if(loadTask) + { + loadTask->abort(); + loadTask->deleteLater(); + loadTask = nullptr; + } + QWidget::closeEvent(event); +} + +void VersionSelectWidget::loadList() +{ + if(loadTask) + { + return; + } + loadTask = m_vlist->getLoadTask(); + if (!loadTask) + { + return; + } + connect(loadTask, &Task::finished, this, &VersionSelectWidget::onTaskFinished); + connect(loadTask, &Task::progress, this, &VersionSelectWidget::changeProgress); + loadTask->start(); + sneakyProgressBar->setHidden(false); +} + +void VersionSelectWidget::onTaskFinished() +{ + if (!loadTask->successful()) + { + CustomMessageBox::selectable(this, tr("Error"), + tr("List update failed:\n%1").arg(loadTask->failReason()), + QMessageBox::Warning)->show(); + if (m_proxyModel->rowCount() == 0) + { + listView->setEmptyMode(VersionListView::ErrorString); + } + } + else if (m_proxyModel->rowCount() == 0) + { + listView->setEmptyMode(VersionListView::String); + } + sneakyProgressBar->setHidden(true); + loadTask->deleteLater(); + loadTask = nullptr; + preselect(); +} + +void VersionSelectWidget::changeProgress(qint64 current, qint64 total) +{ + sneakyProgressBar->setMaximum(total); + sneakyProgressBar->setValue(current); +} + +void VersionSelectWidget::currentRowChanged(const QModelIndex& current, const QModelIndex&) +{ + auto variant = m_proxyModel->data(current, BaseVersionList::VersionPointerRole); + emit selectedVersionChanged(variant.value<BaseVersionPtr>()); +} + +void VersionSelectWidget::preselect() +{ + if(preselectedAlready) + return; + preselectedAlready = true; + selectRecommended(); +} + +void VersionSelectWidget::selectRecommended() +{ + auto idx = m_proxyModel->getRecommended(); + if(idx.isValid()) + { + listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + listView->scrollTo(idx, QAbstractItemView::PositionAtCenter); + } +} + +bool VersionSelectWidget::hasVersions() const +{ + return m_proxyModel->rowCount(QModelIndex()) != 0; +} + +BaseVersionPtr VersionSelectWidget::selectedVersion() const +{ + auto currentIndex = listView->selectionModel()->currentIndex(); + auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole); + return variant.value<BaseVersionPtr>(); +} + +void VersionSelectWidget::setExactFilter(BaseVersionList::ModelRoles role, QString filter) +{ + m_proxyModel->setFilter(role, filter, true); +} + +void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) +{ + m_proxyModel->setFilter(role, filter, false); +}
\ No newline at end of file diff --git a/application/widgets/VersionSelectWidget.h b/application/widgets/VersionSelectWidget.h new file mode 100644 index 00000000..0fc9f2e6 --- /dev/null +++ b/application/widgets/VersionSelectWidget.h @@ -0,0 +1,76 @@ +/* Copyright 2013-2017 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <QWidget> +#include <QSortFilterProxyModel> +#include "BaseVersionList.h" + +class VersionProxyModel; +class VersionListView; +class QVBoxLayout; +class QProgressBar; + +class VersionSelectWidget: public QWidget +{ + Q_OBJECT +public: + explicit VersionSelectWidget(BaseVersionList *vlist, QWidget *parent = 0); + ~VersionSelectWidget(); + + //! loads the list if needed. + void initialize(); + + //! Starts a task that loads the list. + void loadList(); + + bool hasVersions() const; + BaseVersionPtr selectedVersion() const; + void selectRecommended(); + + 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 setUseLatest(const bool useLatest); + +signals: + void selectedVersionChanged(BaseVersionPtr version); + +protected: + virtual void closeEvent ( QCloseEvent* ); + +private slots: + void onTaskFinished(); + void changeProgress(qint64 current, qint64 total); + void currentRowChanged(const QModelIndex ¤t, const QModelIndex &); + +private: + void preselect(); + +private: + BaseVersionList *m_vlist = nullptr; + VersionProxyModel *m_proxyModel = nullptr; + int resizeOnColumn = 0; + Task * loadTask = nullptr; + bool preselectedAlready = false; + +private: + QVBoxLayout *verticalLayout = nullptr; + VersionListView *listView = nullptr; + QProgressBar *sneakyProgressBar = nullptr; +}; |