summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2017-01-05 04:05:08 +0100
committerPetr Mrázek <peterix@gmail.com>2017-01-05 04:05:08 +0100
commite1bd1c614519974d7bfc0efc8dcbfafa9418e2fa (patch)
tree2592a85455ff45925eaa19e8023061a5089be89a
parent4c0db2b99decf407b1f5cf0afc6f29db87ac03ca (diff)
downloadMultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar
MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.gz
MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.lz
MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.tar.xz
MultiMC-e1bd1c614519974d7bfc0efc8dcbfafa9418e2fa.zip
NOISSUE feature complete setup wizard
-rw-r--r--api/logic/translations/TranslationsModel.cpp4
-rw-r--r--application/CMakeLists.txt10
-rw-r--r--application/dialogs/VersionSelectDialog.cpp168
-rw-r--r--application/dialogs/VersionSelectDialog.h36
-rw-r--r--application/dialogs/VersionSelectDialog.ui120
-rw-r--r--application/setupwizard/AnalyticsWizardPage.cpp79
-rw-r--r--application/setupwizard/AnalyticsWizardPage.h26
-rw-r--r--application/setupwizard/BaseWizardPage.h33
-rw-r--r--application/setupwizard/JavaWizardPage.cpp327
-rw-r--r--application/setupwizard/JavaWizardPage.h79
-rw-r--r--application/setupwizard/LanguageWizardPage.cpp74
-rw-r--r--application/setupwizard/LanguageWizardPage.h33
-rw-r--r--application/setupwizard/SetupWizard.cpp353
-rw-r--r--application/setupwizard/SetupWizard.h7
-rw-r--r--application/widgets/ProgressWidget.cpp18
-rw-r--r--application/widgets/VersionSelectWidget.cpp181
-rw-r--r--application/widgets/VersionSelectWidget.h76
17 files changed, 1073 insertions, 551 deletions
diff --git a/api/logic/translations/TranslationsModel.cpp b/api/logic/translations/TranslationsModel.cpp
index 1d44484a..868aa98f 100644
--- a/api/logic/translations/TranslationsModel.cpp
+++ b/api/logic/translations/TranslationsModel.cpp
@@ -193,6 +193,10 @@ QString TranslationsModel::selectedLanguage()
void TranslationsModel::downloadIndex()
{
+ if(d->m_index_job || d->m_dl_job)
+ {
+ return;
+ }
qDebug() << "Downloading Translations Index...";
d->m_index_job.reset(new NetJob("Translations Index"));
MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "index");
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>&amp;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 &current, 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 &current, 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 &current, 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 &current, 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;
+};